diff --git a/.agents/skills b/.agents/skills deleted file mode 120000 index c1dd3b0f40d..00000000000 --- a/.agents/skills +++ /dev/null @@ -1 +0,0 @@ -../.claude/plugins/n8n/skills \ No newline at end of file diff --git a/.agents/skills/AGENTS.md b/.agents/skills/AGENTS.md new file mode 100644 index 00000000000..cec17493072 --- /dev/null +++ b/.agents/skills/AGENTS.md @@ -0,0 +1,39 @@ +# Agent Skills + +Shared n8n skills live in `.agents/skills`. These are the canonical source for +skills that should work across Claude Code, OpenCode, and future agent harnesses. + +## Layout + +- Shared skills: `.agents/skills//SKILL.md` +- Claude-specific skills and overrides: `.claude/plugins/n8n/skills//` +- OpenCode-specific skills and overrides: `.opencode/skills//` + +Claude plugin skills should usually be symlinks back to `.agents/skills`. +OpenCode discovers `.agents/skills` directly, so `.opencode/skills` should only +contain OpenCode-specific real-directory overrides. + +Real directories in a harness path are treated as intentional overrides and are +preserved by the sync script. The sync script only prunes symlinks that point +back into `.agents/skills` (stale shared-skill links); hand-placed symlinks +pointing elsewhere are left untouched. + +The Claude plugin links are git symlinks, so a checkout needs symlink support. +On Windows, enable it (`git config core.symlinks true`, plus Developer Mode or +WSL) before checking out — otherwise git writes the links as plain text stubs +and Claude Code fails to load those skills. `--check` reports stubs with an +actionable error. (OpenCode reads `.agents/skills` directly and is unaffected.) + +## Editing + +- Edit shared skills under `.agents/skills`, not through symlinked copies. +- Only put a skill in `.agents/skills` if it can work across supported agent + harnesses. Avoid hardcoded harness tool names, commands, or UI flows unless + the skill includes a clear availability check and fallback. +- Keep harness-specific commands out of shared skills unless guarded by clear + tool availability checks. +- Put harness-specific workflows, such as MCP setup commands, in real + directories under the matching harness path. +- Run `pnpm sync:skill-links` after adding or removing shared skills to update + Claude plugin symlinks. +- Run `pnpm check:skill-links` before submitting changes. diff --git a/.claude/plugins/n8n/skills/community-pr-readiness-check/SKILL.md b/.agents/skills/community-pr-readiness-check/SKILL.md similarity index 75% rename from .claude/plugins/n8n/skills/community-pr-readiness-check/SKILL.md rename to .agents/skills/community-pr-readiness-check/SKILL.md index 7f82941dadd..ab94b73710d 100644 --- a/.claude/plugins/n8n/skills/community-pr-readiness-check/SKILL.md +++ b/.agents/skills/community-pr-readiness-check/SKILL.md @@ -1,4 +1,5 @@ --- +name: n8n:community-pr-readiness-check description: >- Checks if a community pull request is ready for human review. Verifies CLA signature, PR title format, description completeness, test coverage, and @@ -6,7 +7,13 @@ description: >- close. Use when given a PR number or branch name to review, or when the user says /community-pr-readiness-check, or asks to check if a PR is ready for review. -allowed-tools: Bash(gh:*), Bash(git:*), Bash(node:*), Read, Glob, Grep, AskUserQuestion, mcp__linear-server__save_issue, mcp__linear-server__get_issue, mcp__linear-server__list_teams, mcp__linear-server__list_issue_statuses +allowed-tools: Bash(gh:*), Bash(git:*), Bash(node:*), Read, Glob, Grep +compatibility: + requires: + - mcp: linear + description: Required for reading and updating Linear tickets during triage + - cli: gh + description: Required for PR inspection and triage actions. Must be authenticated (gh auth login) --- # Community PR Readiness Check @@ -44,8 +51,8 @@ If `author.login` is one of n8n's internal bots — `n8n-cat-bot` / `app/n8n-cat gh pr edit --repo n8n-io/n8n --remove-label community --add-label "n8n team" ``` 2. Update the linked Linear ticket (extract `GHC-XXXX` per step 5): - - **`n8n-cat-bot`** — cancel: `mcp__linear-server__save_issue` with `state: "Canceled"`, no labels. - - **`aikido-autofix`** — route to Dev Platform: `mcp__linear-server__save_issue` with `team: "Developer Platform"`, `state: "Triage"`, no labels. + - **`n8n-cat-bot`** — cancel: use the available Linear MCP issue-update tool with `state: "Canceled"`, no labels. + - **`aikido-autofix`** — route to Dev Platform: use the available Linear MCP issue-update tool with `team: "Developer Platform"`, `state: "Triage"`, no labels. When reviewing a batch, omit the skipped PR from the output. For a single PR, emit a one-line note (e.g. `Skipped & cleaned up #30591 (n8n-cat-bot): relabeled to n8n team, cancelled GHC-8398.`). @@ -84,7 +91,7 @@ gh api --paginate "repos/n8n-io/n8n/issues//comments" \ ## Step 2.5 — Auto-rejection screen -Per [`CONTRIBUTING.md`](../../../../../CONTRIBUTING.md), two PR patterns should be closed outright rather than reviewed: +Per `CONTRIBUTING.md`, two PR patterns should be closed outright rather than reviewed: - **Typo-only PR** — diff is entirely spelling/grammar fixes with no logic or tests. - **New-node PR** — adds a brand-new node, unless the n8n team has explicitly agreed to take it. @@ -96,8 +103,8 @@ If either matches, set `checks.AutoReject` and skip directly to action **D**. Fu Run when `AutoReject` is `null`. Full rules for each in `reference/checks.md`: - **A. CLA** — `cla-signed` label present. -- **B. Title** — matches the conventional-commit regex. Authoritative rules in [`.github/pull_request_title_conventions.md`](../../../../../.github/pull_request_title_conventions.md). -- **C. Description** — every section heading and checklist item from [`.github/pull_request_template.md`](../../../../../.github/pull_request_template.md) is present in the PR body. The template is read at check time, so changes to it propagate automatically. +- **B. Title** — matches the conventional-commit regex. Authoritative rules in `.github/pull_request_title_conventions.md`. +- **C. Description** — every section heading and checklist item from `.github/pull_request_template.md` is present in the PR body. The template is read at check time, so changes to it propagate automatically. - **D. Tests** — source logic changes have matching test files. Skip for `docs/ci/chore/build` PRs. - **E. cubic-dev-ai** — no unresolved comments (resolved = "Addressed in commit" marker). @@ -111,6 +118,21 @@ n8n-assistant leaves a comment on every community PR containing `This PR has bee If no n8n-assistant comment exists (older PRs that predate the automation), `linearTicket` is `null`. +## Step 5b — Find Linear tickets for issues this PR claims to fix + +The PR body often says `Fixes #NNNN` / `Closes #NNNN` / `Resolves #NNNN` (or links to `https://github.com/n8n-io/n8n/issues/NNNN`). Each of those issues usually has its own GHC ticket (or has already been triaged to a team). Surface those so the assign action can cross-reference them. + +1. Extract every issue number from the PR body matching `\b(?:fix(?:es)?|close[sd]?|resolve[sd]?)\s+#?(\d+)\b` (case-insensitive) **or** URLs matching `github\.com/n8n-io/n8n/issues/(\d+)`. Deduplicate. +2. For each issue number, search Linear with the available Linear MCP issue-search tool (query `github.com/n8n-io/n8n/issues/`, limit 50) and filter the result to issues whose `description` contains the exact URL `https://github.com/n8n-io/n8n/issues/`. The n8n-assistant bot embeds that URL in the description of every community-issue ticket it creates, so the match is reliable. Use the default limit of 50 (not a smaller value): the `query` is a substring search ordered by `updatedAt`, so `issues/` also matches longer issue numbers (e.g. searching `123` matches `1234`) and the exact ticket can sit anywhere in the result set — a tight limit would silently drop it. If 50 results come back full, paginate with `cursor` until the exact match is found or results are exhausted. +3. Collect the matching ticket IDs (e.g. `GHC-1234`, or wherever they've been routed since — `NODE-5678`, `CAT-3338`). Include cancelled/duplicate tickets too — the comment is still useful for traceability. + +Emit the result as `relatedIssueTickets` in the JSON. During the `assign` action the cross-reference is posted **both ways** so both ends carry the link: + +- On each related issue ticket — *"FYI, [community PR #](https://github.com/n8n-io/n8n/pull/) claims to fix the issue tracked here; routed to as ."* +- On the PR's own ticket (`linearTicket`), when it is non-null — a note pointing back to each related issue ticket. + +If no `Fixes/Closes/Resolves` references exist, return `relatedIssueTickets: []`. + ## Step 6 — Output JSON ```json @@ -119,6 +141,7 @@ If no n8n-assistant comment exists (older PRs that predate the automation), `lin "messageForUser": "", "team": "", "linearTicket": "", + "relatedIssueTickets": [<"GHC-1234" | "NODE-5678" | ...>], "checks": { "AutoReject": <"typo-only" | "new-node" | null>, "CLA": , @@ -137,7 +160,7 @@ Emit the JSON first, then take the appropriate action path below. ## Step 7 — Action paths -Use `AskUserQuestion` for each prompt. Sub-agents called for analysis only should stop after step 6 and let the caller drive step 7. +Ask the user for each prompt (presented as the listed options). Sub-agents called for analysis only should stop after step 6 and let the caller drive step 7. ### A — Minor title fix @@ -164,14 +187,12 @@ Destination state: `Review` for NODES, `Triage` for every other team. Label comp On `Yes`: -```python -# 1. Linear -mcp__linear-server__save_issue( - id=linearTicket, - team=, - state=, - labels=, -) +```bash +# 1. Linear — call the available Linear MCP issue-update tool with: +# id = linearTicket +# team = +# state = +# labels = # 2. GitHub (only if Linear succeeded) — see reference/label-flow.md gh pr edit --repo n8n-io/n8n \ --remove-label "triage:in-progress" \ @@ -229,7 +250,7 @@ gh pr edit --repo n8n-io/n8n \ --add-label "triage:complete" ``` -If `linearTicket` is set, also cancel it: `mcp__linear-server__save_issue(id=linearTicket, state="Canceled")`. If `gh pr close` reports the PR is already closed (contributor beat you to it), proceed with the comment, labels, and ticket cancellation anyway. +If `linearTicket` is set, also cancel it with the available Linear MCP issue-update tool (`id=linearTicket`, `state="Canceled"`). If `gh pr close` reports the PR is already closed (contributor beat you to it), proceed with the comment, labels, and ticket cancellation anyway. ## Notes diff --git a/.claude/plugins/n8n/skills/community-pr-readiness-check/reference/checks.md b/.agents/skills/community-pr-readiness-check/reference/checks.md similarity index 89% rename from .claude/plugins/n8n/skills/community-pr-readiness-check/reference/checks.md rename to .agents/skills/community-pr-readiness-check/reference/checks.md index 327e62bb5b0..cb372cedda1 100644 --- a/.claude/plugins/n8n/skills/community-pr-readiness-check/reference/checks.md +++ b/.agents/skills/community-pr-readiness-check/reference/checks.md @@ -18,7 +18,7 @@ The full ruleset for the auto-rejection screen and the five readiness checks. Lo ## Step 2.5 — Auto-rejection screening -Before running the five checks, screen for PRs that the project policy in [`CONTRIBUTING.md`](../../../../../../CONTRIBUTING.md) (section "Community PR Guidelines") says should be rejected outright. If a PR matches one of these patterns, skip the five checks and recommend a polite close instead. +Before running the five checks, screen for PRs that the project policy in `CONTRIBUTING.md` (section "Community PR Guidelines") says should be rejected outright. If a PR matches one of these patterns, skip the five checks and recommend a polite close instead. ### Typo-only PR @@ -54,7 +54,7 @@ Check the PR `labels` returned from `gh pr view`: ### B. PR title format -The authoritative title rules live in [`.github/pull_request_title_conventions.md`](../../../../../../.github/pull_request_title_conventions.md). Read that file at the start of the check — the allowed `type` list and scope rules come from there, not from this skill. +The authoritative title rules live in `.github/pull_request_title_conventions.md`. Read that file at the start of the check — the allowed `type` list and scope rules come from there, not from this skill. The matching regex below is a cached extraction of those rules. If the conventions file disagrees with the regex (a new type, a different scope syntax), trust the file and flag the divergence in your output. @@ -80,7 +80,7 @@ Quick recap of what the regex enforces (full detail in the conventions file): ### C. PR description completeness -The PR template at [`.github/pull_request_template.md`](../../../../../../.github/pull_request_template.md) is the **source of truth** for what a complete PR description looks like. Read it at the start of the check — sections and checklist items shouldn't be hardcoded here. +The PR template at `.github/pull_request_template.md` is the **source of truth** for what a complete PR description looks like. Read it at the start of the check — sections and checklist items shouldn't be hardcoded here. Procedure: diff --git a/.claude/plugins/n8n/skills/community-pr-readiness-check/reference/label-flow.md b/.agents/skills/community-pr-readiness-check/reference/label-flow.md similarity index 100% rename from .claude/plugins/n8n/skills/community-pr-readiness-check/reference/label-flow.md rename to .agents/skills/community-pr-readiness-check/reference/label-flow.md diff --git a/.claude/plugins/n8n/skills/community-pr-readiness-check/reference/re-review.md b/.agents/skills/community-pr-readiness-check/reference/re-review.md similarity index 100% rename from .claude/plugins/n8n/skills/community-pr-readiness-check/reference/re-review.md rename to .agents/skills/community-pr-readiness-check/reference/re-review.md diff --git a/.claude/plugins/n8n/skills/community-pr-readiness-check/reference/teams.md b/.agents/skills/community-pr-readiness-check/reference/teams.md similarity index 97% rename from .claude/plugins/n8n/skills/community-pr-readiness-check/reference/teams.md rename to .agents/skills/community-pr-readiness-check/reference/teams.md index 48717875942..6a3f8ca0694 100644 --- a/.claude/plugins/n8n/skills/community-pr-readiness-check/reference/teams.md +++ b/.agents/skills/community-pr-readiness-check/reference/teams.md @@ -63,7 +63,7 @@ The **GitHub team label** column is what gets applied to the PR after a successf ## Linear ticket label rules -When calling `mcp__linear-server__save_issue` to assign a ticket to a team, pass a `labels` array composed of three pieces: +When calling the available Linear MCP issue-update tool to assign a ticket to a team, pass a `labels` array composed of three pieces: ### Always-on label diff --git a/.claude/plugins/n8n/skills/content-design/SKILL.md b/.agents/skills/content-design/SKILL.md similarity index 100% rename from .claude/plugins/n8n/skills/content-design/SKILL.md rename to .agents/skills/content-design/SKILL.md diff --git a/.claude/plugins/n8n/skills/conventions/SKILL.md b/.agents/skills/conventions/SKILL.md similarity index 100% rename from .claude/plugins/n8n/skills/conventions/SKILL.md rename to .agents/skills/conventions/SKILL.md diff --git a/.claude/plugins/n8n/skills/create-community-node-lint-rule/SKILL.md b/.agents/skills/create-community-node-lint-rule/SKILL.md similarity index 100% rename from .claude/plugins/n8n/skills/create-community-node-lint-rule/SKILL.md rename to .agents/skills/create-community-node-lint-rule/SKILL.md diff --git a/.claude/plugins/n8n/skills/create-community-node-lint-rule/reference.md b/.agents/skills/create-community-node-lint-rule/reference.md similarity index 100% rename from .claude/plugins/n8n/skills/create-community-node-lint-rule/reference.md rename to .agents/skills/create-community-node-lint-rule/reference.md diff --git a/.claude/plugins/n8n/skills/create-issue/SKILL.md b/.agents/skills/create-issue/SKILL.md similarity index 96% rename from .claude/plugins/n8n/skills/create-issue/SKILL.md rename to .agents/skills/create-issue/SKILL.md index f10a2779c23..8d077fa8ab6 100644 --- a/.claude/plugins/n8n/skills/create-issue/SKILL.md +++ b/.agents/skills/create-issue/SKILL.md @@ -123,7 +123,7 @@ Structure the description using markdown headers. Use the appropriate template: If the user provides screenshots, videos, or screen recordings: - **URLs** — embed directly in the description using markdown image syntax (`![description](url)`) -- **File paths** — if the user provides a local file path, ask them to upload it to a hosting service (e.g., GitHub, Imgur) or use `mcp__linear-server__create_attachment` to attach it to the Linear ticket after creation +- **File paths** — if the user provides a local file path, ask them to upload it to a hosting service (e.g., GitHub, Imgur) or use the available Linear MCP attachment tool to attach it to the Linear ticket after creation - **Pasted images in conversation** — describe what the image shows in the ticket description and note that a screenshot was provided. You cannot upload binary data directly. Always mention in the description when visual evidence was provided, even if it cannot be directly embedded. @@ -153,7 +153,7 @@ Always mention in the description when visual evidence was provided, even if it #### Team -- **Try to fetch up-to-date team areas of responsibility from Notion** using `mcp__notion__notion-search` (search for "areas of responsibility" or similar). Use the fetched data to determine the best team for the issue. +- **Try to fetch up-to-date team areas of responsibility from Notion** using the available Notion MCP search tool (search for "areas of responsibility" or similar). Use the fetched data to determine the best team for the issue. - **If Notion MCP is unavailable or the lookup fails**, fall back to these common teams: `Engineering` (N8N), `AI`, `NODES`, `Identity & Access` (IAM), `Catalysts` (CAT), `Lifecycle & Governance` (LIGO), `Cloud Platform`, `Docs` (DOC) - **Always ask the user which team** if not obvious from context or the Notion lookup - If the issue is node-specific, it likely belongs to `NODES` @@ -218,7 +218,7 @@ Only set an estimate if the user provides one or explicitly asks for one. Use t- 3. **Wait for user confirmation** — do not create until the user approves -4. **Create the ticket** using `mcp__linear-server__save_issue`: +4. **Create the ticket** using the available Linear MCP issue-creation tool: ``` title: team: <team name> @@ -237,7 +237,7 @@ Only set an estimate if the user provides one or explicitly asks for one. Use t- - Never apply **triage-state**, **release**, or **docs-automation** labels - Never set **assignee** unless the user explicitly asks - Never set a **cycle** or **milestone** unless the user explicitly asks -- Never create **duplicate issues** — if the user describes something that sounds like it may exist, search first with `mcp__linear-server__list_issues` +- Never create **duplicate issues** — if the user describes something that sounds like it may exist, search first with the available Linear MCP issue-search tool --- diff --git a/.claude/plugins/n8n/skills/create-pr/SKILL.md b/.agents/skills/create-pr/SKILL.md similarity index 95% rename from .claude/plugins/n8n/skills/create-pr/SKILL.md rename to .agents/skills/create-pr/SKILL.md index a5dea8d90f6..c9e14f106f7 100644 --- a/.claude/plugins/n8n/skills/create-pr/SKILL.md +++ b/.agents/skills/create-pr/SKILL.md @@ -53,9 +53,9 @@ Creates GitHub PRs with titles that pass n8n's `check-pr-title` CI validation. git log origin/master..HEAD --oneline ``` -2. **Check for implementation plan**: Look for a plan file in `.claude/plans/` +2. **Check for implementation plan**: Look for a plan file in the repository plan directories (`.claude/plans/` or `.agents/plans/` when present) that matches the current branch's ticket ID (e.g. if branch is - `scdekov/PAY-1234-some-feature`, check for `.claude/plans/PAY-1234.md`). + `scdekov/PAY-1234-some-feature`, check for `PAY-1234.md`). If a plan file exists, ask the user whether they want to include it in the PR description as a collapsible `<details>` section (see Plan Section below). Only include the plan if the user explicitly approves. @@ -163,7 +163,7 @@ Key validation rules: ## Plan Section -If a matching plan file was found in `.claude/plans/` and the user has approved +If a matching plan file was found in a repository plan directory and the user has approved including it, add a collapsible section at the end of the PR body (after the checklist, before `EOF`): diff --git a/.claude/plugins/n8n/skills/create-skill/SKILL.md b/.agents/skills/create-skill/SKILL.md similarity index 79% rename from .claude/plugins/n8n/skills/create-skill/SKILL.md rename to .agents/skills/create-skill/SKILL.md index 080664bde63..7bbb278dbfe 100644 --- a/.claude/plugins/n8n/skills/create-skill/SKILL.md +++ b/.agents/skills/create-skill/SKILL.md @@ -13,13 +13,16 @@ Skills are markdown (plus optional scripts) that teach the agent a focused workf | Location | When to use | |----------|-------------| -| **`.claude/plugins/n8n/skills/<name>/`** | Default for n8n: team-shared, versioned, namespaced under `n8n:`. | +| **`.agents/skills/<name>/`** | Default for n8n: team-shared, versioned, agent-neutral source. | +| `.claude/plugins/n8n/skills/<name>/` | Claude-specific override, or a generated symlink to `.agents/skills/<name>/`. | +| `.opencode/skills/<name>/` | OpenCode-specific override only. Shared skills stay in `.agents/skills/<name>/`. | | `~/.claude/skills/<name>/` | Personal skill for Claude Code across all projects. | +| `~/.config/opencode/skills/<name>/` | Personal skill for OpenCode across all projects. | | `~/.cursor/skills/<name>/` | Optional personal skill for Cursor only, global to your machine. | **Do not** put custom skills in `~/.cursor/skills-cursor/`—that is reserved for Cursor’s built-in skills. -Prefer **plugin `.claude/plugins/n8n/skills/`** for anything that should match how the rest of the team works. +Prefer **`.agents/skills/`** for anything that should match how the rest of the team works. Run `pnpm sync:skill-links` after adding or removing shared skills. ## Before you write: gather requirements @@ -29,7 +32,7 @@ Ask (or infer) briefly: 2. **Triggers** — when should the agent apply this skill? 3. **Gaps** — what does the agent *not* already know (project rules, URLs, formats)? 4. **Outputs** — templates, checklists, or strict formats? -5. **Examples** — follow an existing skill in `.claude/plugins/n8n/skills/` if one fits. +5. **Examples** — follow an existing shared skill in `.agents/skills/` if one fits. Ask the user in plain language when you need more detail. @@ -47,12 +50,16 @@ skill-name/ ```yaml --- -name: skill-name # lowercase, hyphens, max 64 chars +name: n8n:skill-name # n8n:<name> — lowercase, hyphens, max 64 chars description: >- # max 1024 chars, non-empty — see below ... --- ``` +**Name** — shared n8n skills use the `n8n:<name>` form so Claude Code namespaces +them under the `n8n` plugin (invoked as `/n8n:<name>`). The `<name>` part must +match the skill's directory name. + **Description** (discovery is everything — third person, WHAT + WHEN, trigger words): - Good: `Extracts tables from PDFs and fills forms. Use when the user works with PDFs, forms, or document extraction.` @@ -80,7 +87,7 @@ description: >- # max 1024 chars, non-empty — see below - **MCPs are optional per user** — not everyone has the same servers enabled. If a skill **requires** a specific MCP to work as written, say so explicitly: - Put a hint in the **frontmatter description** (e.g. “Requires Linear MCP for …”) so mismatches are obvious early. - Add a short **Prerequisites** (or **Requirements**) block near the top: which integration, what it is used for, and a **fallback** (e.g. web UI, `gh`, or “ask the user to paste …”) when it is missing. -- **Referencing other skills** — use the namespaced invocation name (e.g. `n8n:create-issue`) so the agent resolves the plugin skill. For human-readable links, give the path from the repo root (e.g. `.claude/plugins/n8n/skills/create-issue/SKILL.md`). From a sibling folder, a relative link works too: `[create-issue](../create-issue/SKILL.md)`. Parent skills should delegate steps instead of duplicating long procedures. +- **Referencing other skills** — use the harness-visible invocation name (e.g. `n8n:create-issue` where namespacing is available, otherwise `create-issue`). For human-readable links, give the canonical path from the repo root (e.g. `.agents/skills/create-issue/SKILL.md`). From a sibling folder, a relative link works too: `[create-issue](../create-issue/SKILL.md)`. Parent skills should delegate steps instead of duplicating long procedures. ## Patterns (pick what fits) @@ -109,7 +116,7 @@ description: >- # max 1024 chars, non-empty — see below ```markdown --- -name: my-workflow +name: n8n:my-workflow description: Does X using project convention Y. Use when the user asks for X or mentions Z. --- diff --git a/.claude/plugins/n8n/skills/db-migrations/SKILL.md b/.agents/skills/db-migrations/SKILL.md similarity index 90% rename from .claude/plugins/n8n/skills/db-migrations/SKILL.md rename to .agents/skills/db-migrations/SKILL.md index 41be3831741..f177c58252c 100644 --- a/.claude/plugins/n8n/skills/db-migrations/SKILL.md +++ b/.agents/skills/db-migrations/SKILL.md @@ -19,7 +19,7 @@ description: Authors n8n database migrations. Use when creating or modifying fil - [Cross-database Compatibility](#cross-database-compatibility) - [Tests](#tests) - [General Design Guidance](#general-design-guidance) -- [After authoring](#after-authoring) +- [Schema documentation](#schema-documentation) --- @@ -117,11 +117,13 @@ Run through this before requesting review. Each item is a real, recurring review - [ ] **Sparse-unique columns:** use a partial index `WHERE col IS NOT NULL`. — [Index Management](#index-management) - [ ] **Composite index column order** matches your actual `WHERE` / `ORDER BY` usage. — [Index Management](#index-management) - [ ] **Entity ↔ migration parity**: column types, `notNull`, defaults, FKs, `@Index` decorators all match. — [Schema/Entity Drift](#schemaentity-drift) +- [ ] **If using `addColumns`, `dropColumns`, `addNotNull`, `dropNotNull`, `addEnumCheck`, or `dropEnumCheck`:** verified whether the target table has incoming FKs. If so, either set `withFKsDisabled = true as const` (in a `sqlite/` subclass if this is a `common/` migration) or use raw `ALTER TABLE ADD COLUMN` for nullable/defaulted columns. — [SQLite table recreation risk](#sqlite-table-recreation-risk) - [ ] **No live-app value imports** in the migration body. Inline types/utility code locally. — [Never import entities as values](#never-import-entities-as-values) - [ ] **`async down()` was tested locally**: `pnpm start && pnpm start -- db:revert && pnpm start` on **both** SQLite and Postgres. — [Reversibility](#reversibility) - [ ] **One logical change per migration**; split unrelated table changes into separate files. — [Don't combine independent schema changes](#dont-combine-independent-schema-changes) - [ ] **`up()` / `down()` reads as a list of intentions.** If either body grows past a screen or mixes schema operations with a multi-statement raw-SQL data move, extract the data move into a `private async` method on the same class (e.g. `private async backfillFromX(ctx)`). The top-level should orchestrate, not implement. - [ ] **Precedent is the bar to fix, not perpetuate.** When the checklist conflicts with what an older migration does (e.g. redundant `.primary.notNull`, hand-quoted identifiers, missing `.comment()`), the checklist wins for new code — don't copy the violation forward. Note the old occurrences in the PR if you spotted them. +- [ ] **Regenerated the schema docs** with `pnpm db:schema:docs` and committed the `docs/generated/` changes. The DB Tests CI job fails on stale docs. — [Schema documentation](#schema-documentation) Treat the checklist as a floor, not a ceiling. If any item fails, fix it before opening review. @@ -218,7 +220,7 @@ export class MigrateThing1234567890000 implements IrreversibleMigration { const { schemaBuilder: { addColumns, column, createIndex } } = ctx; // One-liner DSL calls stay inline — naming them adds no information. - await addColumns('my_table', [column('slug').varchar(255)]); + await addColumns('my_table', [column('slug').varchar(255)], { recreatesOnSqlite: true }); // The non-trivial step gets a named method. await this.backfillSlugs(ctx); @@ -350,6 +352,51 @@ export class CreateMyTable1234567890000 implements ReversibleMigration { } ``` +### SQLite table recreation risk + +Six DSL methods trigger **full table recreation** on SQLite — TypeORM internally creates a temp copy, drops the original, and renames: + +| Method | TypeORM internal call | +|---|---| +| `addColumns()` | `queryRunner.addColumns()` | +| `dropColumns()` | `queryRunner.dropColumns()` | +| `addNotNull()` | `queryRunner.changeColumn()` | +| `dropNotNull()` | `queryRunner.changeColumn()` | +| `addEnumCheck()` | `queryRunner.changeColumn()` | +| `dropEnumCheck()` | `queryRunner.changeColumn()` | + +All six require a final options parameter with `recreatesOnSqlite: true` — TypeScript rejects calls that omit it. + +**The danger:** If the target table has incoming FK constraints with `CASCADE` from other tables, the `DROP TABLE` during recreation fires cascading deletes and **wipes rows from those referencing tables**. + +**Decision tree:** + +1. Does the target table have incoming FK constraints from other tables? + - **No** → Safe to use the DSL method directly (with the ack parameter). + - **Yes** → Continue to step 2. +2. Is this an `addColumns` call where every new column is nullable or has a default? + - **Yes** → Use raw `ALTER TABLE ADD COLUMN` instead (avoids table recreation entirely): + ```typescript + await runQuery( + `ALTER TABLE ${escape.tableName('my_table')} ADD COLUMN ${escape.columnName('col')} TEXT`, + ); + ``` + See `1733133775640-AddMockedNodesColumnToTestDefinition.ts` for a real example. + - **No** → Continue to step 3. +3. Set `withFKsDisabled = true as const` on the migration class. For common migrations, create a SQLite subclass in `sqlite/` that extends the common migration and adds the flag: + ```typescript + // sqlite/1234567890000-MyMigration.ts + import { MyMigration1234567890000 as BaseMigration } from '../common/1234567890000-MyMigration'; + + export class MyMigration1234567890000 extends BaseMigration { + withFKsDisabled = true as const; + } + ``` + +**How `withFKsDisabled` works:** The migration wrapper calls `PRAGMA foreign_keys=OFF` before `up()`/`down()`, runs the migration inside a manual transaction, then re-enables foreign keys. This prevents CASCADE from firing during the internal table drop. It also sets `transaction = false` to avoid TypeORM's default transaction (since SQLite can't nest transactions with PRAGMA changes). + +> **Note:** On Postgres, these methods use `ALTER TABLE` directly and don't recreate the table. The risk is SQLite-specific. + ### Column types **Match column type to value semantics.** Never `varchar` as a catch-all for non-string values — storing numbers as strings loses sort order, range queries, and SUM/AVG aggregations. @@ -570,7 +617,11 @@ When a migration both adds a column and backfills data, structure it clearly wit ```typescript export class AddAndBackfillColumn1234567890000 implements IrreversibleMigration { async up(ctx: MigrationContext) { - await ctx.schemaBuilder.addColumns('my_table', [ctx.schemaBuilder.column('newCol').text]); + await ctx.schemaBuilder.addColumns( + 'my_table', + [ctx.schemaBuilder.column('newCol').text], + { recreatesOnSqlite: true }, + ); await this.backfillNewCol(ctx); } @@ -633,7 +684,7 @@ Some migrations override with `transaction = false as const` for big DDL on engi - **Small differences** (a single statement, a CHECK constraint, slightly different syntax): keep one migration in `common/` and branch on `isSqlite` / `isPostgres`. - **Large differences** (different table recreation strategies, different intermediate steps, fundamentally different SQL): write **separate files** in `postgresdb/` and `sqlite/`. A common migration full of `if (isSqlite) { ... }` blocks is harder to read and review than two focused files. -If only Postgres needs the change, just put the file in `postgresdb/`; don't write a no-op SQLite migration with `if (isPostgres)`. SQLite no longer needs separate migrations for column adds (the recreate-table path was fixed) — verify before duplicating. +If only Postgres needs the change, just put the file in `postgresdb/`; don't write a no-op SQLite migration with `if (isPostgres)`. For SQLite column adds, follow the [SQLite table recreation risk](#sqlite-table-recreation-risk) decision tree before deciding whether a common migration is enough or a SQLite subclass/raw `ALTER TABLE` path is needed. ### SQLite supports modern syntax @@ -729,4 +780,18 @@ A "polymorphic" column pair is one column that points at different tables depend - **Separate join tables per relation type** (`credential_external_secret_dependency`, `credential_node_dependency`, …). Each has a real FK. Queries that need "all dependencies" become a UNION. - **One nullable FK per possible target** with a CHECK constraint that exactly one is set. Each column is a real FK. - **Supertype table**: hoist parents into a single `dependency_target` with its own type column, then have one FK to that table. -- + +--- + +## Schema documentation + +The database schema is documented under `docs/generated/` — `docs/generated/sqlite-schema/` and `docs/generated/postgres-schema/`, one Markdown page per table plus a Mermaid ER diagram. These are **auto-generated from the migrations** with [tbls](https://github.com/k1LoW/tbls) (it runs every migration against a throwaway database and introspects the result), so any schema-changing migration makes them stale. + +Regenerate and commit them alongside your migration: + +```sh +pnpm db:schema:docs # rewrites docs/generated/ — requires Docker (and `brew install tbls` locally) +pnpm db:schema:check # verify only; what the DB Tests CI job runs +``` + +The DB Tests CI job fails the PR when the committed docs don't match the migrations (each matrix leg verifies its own database). Don't hand-edit anything under `docs/generated/` — it's overwritten on every regeneration. diff --git a/.claude/plugins/n8n/skills/design-system/SKILL.md b/.agents/skills/design-system/SKILL.md similarity index 100% rename from .claude/plugins/n8n/skills/design-system/SKILL.md rename to .agents/skills/design-system/SKILL.md diff --git a/.claude/plugins/n8n/skills/design-system/rules/web-animation-guidelines.md b/.agents/skills/design-system/rules/web-animation-guidelines.md similarity index 100% rename from .claude/plugins/n8n/skills/design-system/rules/web-animation-guidelines.md rename to .agents/skills/design-system/rules/web-animation-guidelines.md diff --git a/.claude/plugins/n8n/skills/design-system/rules/web-interface-guidelines.md b/.agents/skills/design-system/rules/web-interface-guidelines.md similarity index 100% rename from .claude/plugins/n8n/skills/design-system/rules/web-interface-guidelines.md rename to .agents/skills/design-system/rules/web-interface-guidelines.md diff --git a/.claude/plugins/n8n/skills/experiments/SKILL.md b/.agents/skills/experiments/SKILL.md similarity index 97% rename from .claude/plugins/n8n/skills/experiments/SKILL.md rename to .agents/skills/experiments/SKILL.md index a83d1387fa2..0a51017536c 100644 --- a/.claude/plugins/n8n/skills/experiments/SKILL.md +++ b/.agents/skills/experiments/SKILL.md @@ -1,5 +1,5 @@ --- -name: experiments +name: n8n:experiments description: >- Guides work on `packages/frontend/editor-ui` experiments. Use when creating, extending, wiring, testing, reviewing, or retiring editor-ui experiments, diff --git a/.claude/plugins/n8n/skills/experiments/reference.md b/.agents/skills/experiments/reference.md similarity index 93% rename from .claude/plugins/n8n/skills/experiments/reference.md rename to .agents/skills/experiments/reference.md index cf3f0968f53..3c0af89d4c2 100644 --- a/.claude/plugins/n8n/skills/experiments/reference.md +++ b/.agents/skills/experiments/reference.md @@ -19,6 +19,9 @@ Use this guide for code under `packages/frontend/editor-ui/src/experiments/` and - Use `useStorage` from `@/app/composables/useStorage` for experiment-owned persisted UI state such as dismissed, interacted, or last-seen flags. - Do not use raw `localStorage` for new experiment-owned state unless the experiment must write an existing non-experiment app key. - Keep `"User is part of experiment"` tracking centralized. Add only experiment-specific `track*` helpers in experiment code. +- Use `getExperimentTelemetryPayload()` from `@/experiments/utils` for every experiment-specific telemetry helper that may be used as a PostHog experiment exposure or metric event. +- Custom exposure events must include PostHog's `$feature/<experiment-name>` property with the current variant. The helper adds this property and the human-readable `variant` property. +- Do not hand-roll `$feature/<experiment-name>` or instance group metadata in experiment stores. `usePostHog().init()` calls `posthog.group()` centrally so the PostHog web SDK associates subsequent frontend events with the instance group. ## PostHog flag lookup diff --git a/.claude/plugins/n8n/skills/human-like-code-review/SKILL.md b/.agents/skills/human-like-code-review/SKILL.md similarity index 99% rename from .claude/plugins/n8n/skills/human-like-code-review/SKILL.md rename to .agents/skills/human-like-code-review/SKILL.md index aeaf0552cda..6097ccc6a9c 100644 --- a/.claude/plugins/n8n/skills/human-like-code-review/SKILL.md +++ b/.agents/skills/human-like-code-review/SKILL.md @@ -1,4 +1,5 @@ --- +name: n8n:human-like-code-review description: Reviews a GitHub pull request like a thoughtful human reviewer and writes the feedback to a markdown file. Prioritizes bugs, behavioral regressions, security issues, and missing tests, ordered by severity. Use when given a PR URL to review, or when the user says /human-like-code-review. allowed-tools: Bash(gh:*), Bash(git:*), Read, Glob, Grep --- diff --git a/.claude/plugins/n8n/skills/linear-issue/SKILL.md b/.agents/skills/linear-issue/SKILL.md similarity index 90% rename from .claude/plugins/n8n/skills/linear-issue/SKILL.md rename to .agents/skills/linear-issue/SKILL.md index ea2da3afb95..f869d099107 100644 --- a/.claude/plugins/n8n/skills/linear-issue/SKILL.md +++ b/.agents/skills/linear-issue/SKILL.md @@ -26,12 +26,12 @@ Start work on Linear issue **$ARGUMENTS** This skill depends on external tools. Before proceeding, verify availability: **Required:** -- **Linear MCP** (`mcp__linear`): Must be connected. Without it the skill cannot function at all. +- **Linear MCP**: Must be connected. Without it the skill cannot function at all. - **GitHub CLI** (`gh`): Must be installed and authenticated. Run `gh auth status` to verify. Used to fetch linked PRs and issues. **Optional (graceful degradation):** -- **Notion MCP** (`mcp__notion`): Needed only if the issue links to Notion docs. If unavailable, note the Notion links in the summary and tell the user to check them manually. -- **Loom transcript skill** (`/loom-transcript`): Needed only if the issue contains Loom videos. If unavailable, note the Loom links in the summary for the user to watch. +- **Notion MCP**: Needed only if the issue links to Notion docs. If unavailable, note the Notion links in the summary and tell the user to check them manually. +- **Loom transcript skill**: Needed only if the issue contains Loom videos. If unavailable, note the Loom links in the summary for the user to watch. - **curl**: Used to download images. Almost always available; if missing, skip image downloads and note it. If a required tool is missing, stop and tell the user what needs to be set up before continuing. @@ -42,11 +42,11 @@ Follow these steps to gather comprehensive context about the issue: ### 1. Fetch the Issue and Comments from Linear -Use the Linear MCP tools to fetch the issue details and comments together: +Use the Linear MCP tools available in the active harness to fetch the issue details and comments together: -- Use `mcp__linear__get_issue` with the issue ID to get full details including attachments +- Fetch the issue by ID to get full details including attachments - Include relations to see blocking/related/duplicate issues -- **Immediately after**, use `mcp__linear__list_comments` with the issue ID to fetch all comments +- **Immediately after**, fetch all comments for the issue ID Both calls should be made together in the same step to gather the complete context upfront. @@ -88,14 +88,14 @@ After fetching the issue, immediately check its labels: 1. Scan the issue description AND all comments for Loom URLs (loom.com/share/...) 2. For EACH Loom video found (in description or comments): - - Use the `/loom-transcript` skill to fetch the FULL transcript + - Use the Loom transcript skill to fetch the FULL transcript - Summarize key points, timestamps, and any demonstrated issues 3. Loom videos often contain crucial reproduction steps and context that text alone cannot convey ### 4. Fetch Related Context **Related Linear Issues:** -- Use `mcp__linear__get_issue` for any issues mentioned in relations (blocking, blocked by, related, duplicates) +- Use the Linear MCP issue-fetching tool for any issues mentioned in relations (blocking, blocked by, related, duplicates) - Summarize how they relate to the main issue **GitHub PRs and Issues:** @@ -105,7 +105,7 @@ After fetching the issue, immediately check its labels: - Download images attached to issues: `curl -H "Authorization: token $(gh auth token)" -L <image-url> -o image.png` **Notion Documents:** -- If Notion links are present, use `mcp__notion__notion-fetch` with the Notion URL or page ID to retrieve document content +- If Notion links are present, use the Notion MCP fetch tool with the Notion URL or page ID to retrieve document content - Summarize relevant documentation ### 5. Review Comments diff --git a/.claude/plugins/n8n/skills/loom-transcript/SKILL.md b/.agents/skills/loom-transcript/SKILL.md similarity index 100% rename from .claude/plugins/n8n/skills/loom-transcript/SKILL.md rename to .agents/skills/loom-transcript/SKILL.md diff --git a/.claude/plugins/n8n/skills/node-add-oauth/SKILL.md b/.agents/skills/node-add-oauth/SKILL.md similarity index 100% rename from .claude/plugins/n8n/skills/node-add-oauth/SKILL.md rename to .agents/skills/node-add-oauth/SKILL.md diff --git a/.claude/plugins/n8n/skills/protect-endpoints/SKILL.md b/.agents/skills/protect-endpoints/SKILL.md similarity index 100% rename from .claude/plugins/n8n/skills/protect-endpoints/SKILL.md rename to .agents/skills/protect-endpoints/SKILL.md diff --git a/.claude/plugins/n8n/skills/reproduce-bug/SKILL.md b/.agents/skills/reproduce-bug/SKILL.md similarity index 100% rename from .claude/plugins/n8n/skills/reproduce-bug/SKILL.md rename to .agents/skills/reproduce-bug/SKILL.md diff --git a/.claude/plugins/n8n/skills/spec-driven-development/SKILL.md b/.agents/skills/spec-driven-development/SKILL.md similarity index 91% rename from .claude/plugins/n8n/skills/spec-driven-development/SKILL.md rename to .agents/skills/spec-driven-development/SKILL.md index 955d98003d5..57470f1d431 100644 --- a/.claude/plugins/n8n/skills/spec-driven-development/SKILL.md +++ b/.agents/skills/spec-driven-development/SKILL.md @@ -1,11 +1,11 @@ --- name: n8n:spec-driven-development -description: Keeps implementation and specs in sync. Use when working on a feature that has a spec in .claude/specs/, when the user says /spec, or when starting implementation of a documented feature. Also use when the user asks to verify implementation against a spec or update a spec after changes. +description: Keeps implementation and specs in sync. Use when working on a feature that has a spec in .agents/specs/, when the user says /spec, or when starting implementation of a documented feature. Also use when the user asks to verify implementation against a spec or update a spec after changes. --- # Spec-Driven Development -Specs live in `.claude/specs/`. They are the source of truth for architectural +Specs live in `.agents/specs/`. They are the source of truth for architectural decisions, API contracts, and implementation scope. Implementation and specs must stay in sync — neither leads exclusively. @@ -17,10 +17,10 @@ Read spec → Implement → Verify alignment → Update spec or code → Repeat ## Before Starting Work -1. **Find the spec.** Search `.claude/specs/` for files matching the feature: +1. **Find the spec.** Search `.agents/specs/` for files matching the feature: ```bash -ls .claude/specs/ +ls .agents/specs/ ``` 2. **Read the full spec.** Understand scope, decisions, API contracts, and @@ -63,7 +63,7 @@ Run a spec verification pass: ## Spec File Conventions -- One or more markdown files per feature in `.claude/specs/`. +- One or more markdown files per feature in `.agents/specs/`. - Keep specs concise. Use tables for mappings, code blocks for shapes. - Use `## Implementation TODO` with checkboxes to track progress. - Split into multiple files when it helps (e.g. separate backend/frontend), diff --git a/.aikido b/.aikido new file mode 100644 index 00000000000..1d1b6d78b0b --- /dev/null +++ b/.aikido @@ -0,0 +1,21 @@ +# Aikido scan configuration +# https://help.aikido.dev/code-scanning/scanning-practices/ignore-via-code-with-aikido-files +# Path matching is plain substring against the full file path (no globs), +# so fragment entries below act as suffix/segment wildcards. + +exclude: + paths: + # Machine-generated instance-AI expectation traces. Contain ephemeral + # credential reference IDs (nanoids) that re-trip the secrets scanner + # on every regeneration. No secret material. + - packages/testing/playwright/expectations + + # Test code repo-wide. Fixtures routinely contain synthetic PEM blocks, + # basic-auth strings, and deliberately fake keys (including the secret + # scrubber's own tests). Verified 0/20 true-positive rate to date. + - .test.ts + - __tests__/ + - /test/ + + # Test fixtures by convention. + - .fixture.ts diff --git a/.claude/README.md b/.claude/README.md index 93e84daaf2c..a3eb89474fd 100644 --- a/.claude/README.md +++ b/.claude/README.md @@ -2,9 +2,9 @@ This directory contains shared Claude Code configuration for the n8n team. -All skills, agents, and commands live under the `n8n` plugin at -`.claude/plugins/n8n/` for `n8n:` namespacing. See -[plugin README](plugins/n8n/README.md) for full details. +Agents and commands live under the `n8n` plugin at `.claude/plugins/n8n/` for +`n8n:` namespacing. Shared skills are sourced from `.agents/skills/` and linked +into the plugin. See [plugin README](plugins/n8n/README.md) for full details. ## Setup diff --git a/.claude/plugins/n8n/.claude-plugin/marketplace.json b/.claude/plugins/n8n/.claude-plugin/marketplace.json index df61b27875d..2684019eac2 100644 --- a/.claude/plugins/n8n/.claude-plugin/marketplace.json +++ b/.claude/plugins/n8n/.claude-plugin/marketplace.json @@ -1,12 +1,12 @@ { - "name": "n8n", - "owner": { - "name": "n8n" - }, - "plugins": [ - { - "name": "n8n", - "source": "./" - } - ] + "name": "n8n", + "owner": { + "name": "n8n" + }, + "plugins": [ + { + "name": "n8n", + "source": "./" + } + ] } diff --git a/.claude/plugins/n8n/.claude-plugin/plugin.json b/.claude/plugins/n8n/.claude-plugin/plugin.json index c42d44d59c4..b4fb4cd437e 100644 --- a/.claude/plugins/n8n/.claude-plugin/plugin.json +++ b/.claude/plugins/n8n/.claude-plugin/plugin.json @@ -1,5 +1,5 @@ { - "name": "n8n", - "version": "0.2.0", - "description": "n8n Claude Code plugin — shared skills, commands, and agents for n8n development" + "name": "n8n", + "version": "0.2.0", + "description": "n8n Claude Code plugin — shared skills, commands, and agents for n8n development" } diff --git a/.claude/plugins/n8n/README.md b/.claude/plugins/n8n/README.md index 30d990c05d2..432d35ece05 100644 --- a/.claude/plugins/n8n/README.md +++ b/.claude/plugins/n8n/README.md @@ -1,8 +1,8 @@ # n8n Claude Code Plugin -Shared skills, commands, and agents for n8n development. All items are -namespaced under `n8n:` to avoid collisions with personal or third-party -plugins. +Shared commands and agents for n8n development, plus Claude Code skill links. +All plugin items are namespaced under `n8n:` to avoid collisions with personal +or third-party plugins. ## Usage @@ -15,6 +15,17 @@ plugin directory. Everything gets the `n8n:` namespace prefix automatically. | Command | `commands/plan.md` | `/n8n:plan PAY-XXX` | | Agent | `agents/developer.md` | `n8n:developer` | +Shared skill sources live in `.agents/skills/`. Most entries under +`.claude/plugins/n8n/skills/` are symlinks to those shared sources. Claude-only +skills or overrides remain real directories in this plugin path. + +> **Requires symlink support.** These shared-skill entries are git symlinks. On +> Windows, check out with symlinks enabled (`git config core.symlinks true`, +> plus Developer Mode or WSL) — otherwise git writes them as plain text stubs +> and Claude Code fails to load the affected skills. `node +> scripts/sync-agent-skill-links.mjs --check` flags stubs with an actionable +> error. + ## Plugin Structure ``` @@ -27,10 +38,14 @@ plugin directory. Everything gets the `n8n:` namespace prefix automatically. ├── commands/ │ └── <name>.md # → /n8n:<name> command ├── skills/ -│ └── <name>/SKILL.md # → n8n:<name> skill +│ ├── <shared> -> ../../../../.agents/skills/<shared> +│ └── <claude-only>/SKILL.md └── README.md ``` +Run `pnpm sync:skill-links` after adding or removing shared skills. Run +`pnpm check:skill-links` before submitting changes. + ## Design Decisions ### Why a plugin instead of standalone skills? @@ -39,8 +54,7 @@ To get the `n8n:` namespace prefix, avoiding collisions with personal or third-party plugins. Claude Code only supports colon-namespaced items through the plugin system — standalone `.claude/skills/` entries cannot be namespaced. -### Known Issues +### Skill Frontmatter -- Plugin skill namespacing requires omitting the `name` field from SKILL.md - frontmatter due to a [Claude Code bug](https://github.com/anthropics/claude-code/issues/17271). - The directory name is used as the skill identifier instead. +Shared skills keep `name: n8n:<name>` in `SKILL.md` frontmatter for cross-agent +discovery. Do not remove shared skill names when linking them into this plugin. diff --git a/.claude/plugins/n8n/skills/community-pr-readiness-check b/.claude/plugins/n8n/skills/community-pr-readiness-check new file mode 120000 index 00000000000..208abd3398d --- /dev/null +++ b/.claude/plugins/n8n/skills/community-pr-readiness-check @@ -0,0 +1 @@ +../../../../.agents/skills/community-pr-readiness-check \ No newline at end of file diff --git a/.claude/plugins/n8n/skills/content-design b/.claude/plugins/n8n/skills/content-design new file mode 120000 index 00000000000..6d9e47e38bc --- /dev/null +++ b/.claude/plugins/n8n/skills/content-design @@ -0,0 +1 @@ +../../../../.agents/skills/content-design \ No newline at end of file diff --git a/.claude/plugins/n8n/skills/conventions b/.claude/plugins/n8n/skills/conventions new file mode 120000 index 00000000000..fd5cdf9b16b --- /dev/null +++ b/.claude/plugins/n8n/skills/conventions @@ -0,0 +1 @@ +../../../../.agents/skills/conventions \ No newline at end of file diff --git a/.claude/plugins/n8n/skills/create-community-node-lint-rule b/.claude/plugins/n8n/skills/create-community-node-lint-rule new file mode 120000 index 00000000000..f85c955ee1f --- /dev/null +++ b/.claude/plugins/n8n/skills/create-community-node-lint-rule @@ -0,0 +1 @@ +../../../../.agents/skills/create-community-node-lint-rule \ No newline at end of file diff --git a/.claude/plugins/n8n/skills/create-issue b/.claude/plugins/n8n/skills/create-issue new file mode 120000 index 00000000000..e13006eedb3 --- /dev/null +++ b/.claude/plugins/n8n/skills/create-issue @@ -0,0 +1 @@ +../../../../.agents/skills/create-issue \ No newline at end of file diff --git a/.claude/plugins/n8n/skills/create-pr b/.claude/plugins/n8n/skills/create-pr new file mode 120000 index 00000000000..ddcf56820f2 --- /dev/null +++ b/.claude/plugins/n8n/skills/create-pr @@ -0,0 +1 @@ +../../../../.agents/skills/create-pr \ No newline at end of file diff --git a/.claude/plugins/n8n/skills/create-skill b/.claude/plugins/n8n/skills/create-skill new file mode 120000 index 00000000000..3b5c064515c --- /dev/null +++ b/.claude/plugins/n8n/skills/create-skill @@ -0,0 +1 @@ +../../../../.agents/skills/create-skill \ No newline at end of file diff --git a/.claude/plugins/n8n/skills/db-migrations b/.claude/plugins/n8n/skills/db-migrations new file mode 120000 index 00000000000..b4c873af2d6 --- /dev/null +++ b/.claude/plugins/n8n/skills/db-migrations @@ -0,0 +1 @@ +../../../../.agents/skills/db-migrations \ No newline at end of file diff --git a/.claude/plugins/n8n/skills/design-system b/.claude/plugins/n8n/skills/design-system new file mode 120000 index 00000000000..930eaae214e --- /dev/null +++ b/.claude/plugins/n8n/skills/design-system @@ -0,0 +1 @@ +../../../../.agents/skills/design-system \ No newline at end of file diff --git a/.claude/plugins/n8n/skills/experiments b/.claude/plugins/n8n/skills/experiments new file mode 120000 index 00000000000..e6752201e2f --- /dev/null +++ b/.claude/plugins/n8n/skills/experiments @@ -0,0 +1 @@ +../../../../.agents/skills/experiments \ No newline at end of file diff --git a/.claude/plugins/n8n/skills/human-like-code-review b/.claude/plugins/n8n/skills/human-like-code-review new file mode 120000 index 00000000000..54aa3d97af1 --- /dev/null +++ b/.claude/plugins/n8n/skills/human-like-code-review @@ -0,0 +1 @@ +../../../../.agents/skills/human-like-code-review \ No newline at end of file diff --git a/.claude/plugins/n8n/skills/linear-issue b/.claude/plugins/n8n/skills/linear-issue new file mode 120000 index 00000000000..f1cfff1f892 --- /dev/null +++ b/.claude/plugins/n8n/skills/linear-issue @@ -0,0 +1 @@ +../../../../.agents/skills/linear-issue \ No newline at end of file diff --git a/.claude/plugins/n8n/skills/loom-transcript b/.claude/plugins/n8n/skills/loom-transcript new file mode 120000 index 00000000000..ec611abbd63 --- /dev/null +++ b/.claude/plugins/n8n/skills/loom-transcript @@ -0,0 +1 @@ +../../../../.agents/skills/loom-transcript \ No newline at end of file diff --git a/.claude/plugins/n8n/skills/mutant-diff/SKILL.md b/.claude/plugins/n8n/skills/mutant-diff/SKILL.md deleted file mode 100644 index 1a2c84de32c..00000000000 --- a/.claude/plugins/n8n/skills/mutant-diff/SKILL.md +++ /dev/null @@ -1,126 +0,0 @@ ---- -description: Run Stryker mutation testing on the source files changed in the current branch (vs origin/master) across vitest packages. One command for "did my work hold up under mutation?" before pushing. Triages which files dropped below threshold and offers to invoke n8n:mutant-fix on them. Use when the user says /mutant-diff, "mutate what I changed", "check my changes", or has just finished writing a feature and wants pre-merge feedback. ---- - -# Mutate what I changed - -Closes the local dev loop. Single command to run Stryker against every changed source file the current branch touched (vs `origin/master`) in a mutation-eligible package, then point at any reds that need strengthening. - -## When to use - -- User says `/mutant-diff`, "mutate the files I changed", "check my changes", "did my tests stick" -- Mid-feature: dev wants pre-merge feedback before pushing -- Pre-PR: cheaper than waiting for the nightly cron - -**Don't** use: -- For a single specific file (`/n8n:mutant-score <path>` is faster) -- After the user already ran `/n8n:mutant-fix` (which calls mutant-score internally for verification — running both again is wasted compute) - -Changed files in **jest** packages (`nodes-base`, `cli`, `db`, …) and in `@n8n/expression-runtime` are skipped automatically — see step 1. - -## Inputs - -- **Default base**: `origin/master`. Override with `--base <ref>` if comparing against another branch (e.g. `--base HEAD~5`). -- **Default scope**: `packages/**/src/**/*.ts`, narrowed to mutation-eligible (vitest) packages in step 1. - -## Steps - -### 1. Identify changed, eligible source files - -```bash -git diff --name-only origin/master...HEAD -- 'packages/**/src/**/*.ts' -``` - -(`...` is correct — three-dot means "since the branch diverged from base," which is what we want.) - -If `git fetch` hasn't been run recently, suggest the user `git fetch origin master` first; otherwise the base ref is stale. - -Filter out: -- `**/*.d.ts` (declarations, no behaviour) -- `**/*.stories.ts` (Storybook scaffolding) -- `index.ts` files (barrels) -- `interfaces.ts`, `types.ts`, `constants.ts` (low-value, same filter the picker uses) -- **files in non-eligible packages**: for each changed file, find its package (nearest ancestor dir with a `package.json`). Keep the file only if that package has a `vitest.config.*` **and** is not `@n8n/expression-runtime` (it's the isolated-vm engine — blocked on DEVP-257). Drop jest packages with a one-line note: `skipped (jest): packages/cli/src/...`. - -### 2. Surface the plan to the user - -Print the filtered list before running anything. Each Stryker run is 1–5 minutes; the user should confirm if there are many. - -``` -Found N changed source files to mutate (J skipped: jest / expression-runtime): - - packages/workflow/src/foo.ts - - packages/@n8n/crdt/src/bar.ts - ... - -Estimated runtime: ~M-K minutes (M minutes minimum if every Stryker run is fast). -Proceed? (skill default: yes if N ≤ 3, ask if N > 3) -``` - -If the filtered list is empty: report "No mutation-eligible source files changed vs $base — nothing to mutate." and stop. Exit cleanly. - -If N > 8: refuse and ask the user to narrow scope (a different base ref, or invoke per-file). Running 8+ mutations sequentially is a 30+ minute session that should be a deliberate choice. - -### 3. Run mutation testing per file - -For each file in the plan, invoke `pnpm mutate <repo-relative-path>` (the package is inferred from the path). Capture the score per file from the `✓ / ✗` summary line mutate.mjs prints to stderr — don't re-read `summary.json` (it's overwritten per run, and lives in that file's own package). - -After each run completes, print one line: - -``` -✓ packages/workflow/src/foo.ts 95.12% (39/41 killed) GREEN -✗ packages/@n8n/crdt/src/bar.ts 54.83% (17/31 killed) RED — 13 survivors, top: ConditionalExpression, EqualityOperator -``` - -If a Stryker run hard-fails (exit 3, no `summary.json`), print `! <file> Stryker failed — see stderr` and continue to the next file. Don't abort the whole batch. - -### 4. Summary table - -After all files have been mutated, print one compact table: - -``` -=== Mutation results: N files, M green, K red, J failed === -| File | Score | Verdict | Survivors | -|---------------------------------|---------|---------|-----------| -| packages/workflow/src/foo.ts | 95.12% | GREEN | 2 | -| packages/@n8n/crdt/src/bar.ts | 54.83% | RED | 13 | -| packages/workflow/src/baz.ts | n/a | FAILED | - | -``` - -### 5. Offer the strengthen step on the worst red file - -If any file came back red: - -> The lowest-score red file is `packages/@n8n/crdt/src/bar.ts` (54.83%, 13 survivors). Run `/n8n:mutant-fix <file>` to triage them and write assertion changes? (suggesting; don't auto-invoke) - -Only suggest one file at a time — `n8n:mutant-fix` caps at 5 survivors per invocation, and re-running this skill after edits is cheap. - -If everything is green: report it and stop. No follow-up needed. - -## Output shape - -Three deliverable sections per invocation: - -1. **Plan** (before running) — list of eligible files (+ skipped count), estimated runtime -2. **Per-file progress** (during) — one line per file as it completes -3. **Summary table + recommendation** (after) — compact view - -Don't dump full `summary.json` payloads — each mutate run writes one to `<package>/reports/mutation/` (overwritten per run). The user can read the latest one if they want detail. - -## Constraints - -- **Vitest packages only.** Jest packages and `@n8n/expression-runtime` are filtered out in step 1, not mutated. -- **Max 8 files per invocation.** Above that, ask user to narrow. -- **Don't auto-invoke `/n8n:mutant-fix`.** Suggest, don't act. Same reasoning as the other skills: each pass should be a deliberate human-approved step. -- **No commits.** Edits land in working tree; user reviews. -- **No fabricated scores.** If a Stryker run fails, mark FAILED in the table — never guess a value. - -## Common follow-ups - -- "strengthen them all" → loop the user through `/n8n:mutant-fix`, one file at a time -- "what changed?" → `git diff origin/master...HEAD -- <file>` for the file in question -- "ignore <pattern>" → re-run with the user's exclude added to the filter - -## Related - -- `n8n:mutant-score` — single-file version of this skill -- `n8n:mutant-fix` — the natural next step when reds show up diff --git a/.claude/plugins/n8n/skills/mutant-fix/SKILL.md b/.claude/plugins/n8n/skills/mutant-fix/SKILL.md deleted file mode 100644 index 1ed76ccf338..00000000000 --- a/.claude/plugins/n8n/skills/mutant-fix/SKILL.md +++ /dev/null @@ -1,151 +0,0 @@ ---- -description: Take a Stryker summary.json (from n8n:mutant-score), triage the surviving mutants by user-reachable-behaviour risk, write minimal assertion changes to kill the top 3-5 highest-leverage survivors, then verify by re-running n8n:mutant-score. Use when the user has just run mutation testing and wants to strengthen the test suite, or says "kill the survivors / strengthen tests / fix the red." Pairs with n8n:mutant-score as the inner write side of a single iteration. ---- - -# Strengthen tests — kill the highest-leverage survivors - -The other half of the local mutation-testing loop. `n8n:mutant-score` reports which mutations escaped the tests; this skill picks the ones that matter and writes minimal assertion changes to kill them. - -## When to use - -- User has just run `/n8n:mutant-score <file>` and the verdict was `red` -- User says: "strengthen tests", "kill the survivors", "fix the red", "iterate on the tests for X" -- Mid-loop: this skill's verify step calls `n8n:mutant-score` again, so the loop closes here - -**Don't** use this skill: -- For a `green` verdict — there's nothing to strengthen; if user insists, push back and ask which file actually needs work -- To bulk-kill every survivor — explicitly capped at 5 per invocation. Re-invoke for more. - -## Inputs - -Accepts **either** a source file or an existing summary — whichever you have: - -- **A source file** (a repo-relative path, e.g. `packages/workflow/src/workflow-checksum.ts` — package inferred): self-bootstrapping — there's no summary yet, so step 1 runs `n8n:mutant-score` to produce one, then proceeds. This is the entry point for unattended callers (e.g. cat-bot acting on a ledger gap). -- **An existing summary**: `--summary <path>`. A prior `n8n:mutant-score` run wrote it to that package's `reports/mutation/summary.json` (e.g. `packages/workflow/reports/mutation/summary.json`). Skips the bootstrap. - -## Steps - -### 1. Get a summary (bootstrap if needed) - -- **Given a source file** (or no usable summary on disk): run `n8n:mutant-score` on the file first to generate `<package-dir>/reports/mutation/summary.json`. Then read it. -- **Given/defaulting to a summary path**: read it directly. - -Read the summary (already compact, ~50 KB) and pull: -- `files[0].file` — the source file under test -- `files[0].score` — current mutation score -- `files[0].survivors[]` — every surviving (and no-coverage) mutant with location, replacement, covering test names - -If the verdict is already `green`, stop — nothing to strengthen. - -### 2. Read the source under test, sparingly - -Read the source file referenced in `summary.json`. Read **once**, the whole file (typical source files are 50-500 lines; the cost is bounded). This is the only file read; don't load test files yet. - -### 3. Triage the survivors - -Categorise each survivor into one of three buckets. Use the rubric below — don't apply it mechanically, but lean on it. - -**HIGH leverage — "real regression vector":** mutant guards behaviour that real users actually hit through the public API surface. - -- Type checks against shapes user data routinely takes: `null`, `undefined`, `Date`, `Buffer`, `Uint8Array`, `Array`, plain objects with arbitrary keys -- Conditional branches that gate critical fall-through (e.g. "if this returns early, the wrong code path runs") -- Code paths that handle user-controlled flow: expressions, Code-node behaviour, binary item handling, deep-clone semantics -- Mutants on guard clauses that prevent crashes (`if (value == null) return ...`) - -**MODERATE leverage — "user-observable invariant":** real but lower-frequency user impact. - -- Proxy traps that change `Object.keys` / `in` / `hasOwnProperty` semantics after mutation -- Set-then-delete / re-set-after-delete sequences (Code-node assignment patterns) -- Treating `undefined` assignment as deletion (`obj.foo = undefined` → key removed) -- Edge cases that only fire under specific iteration patterns - -**LOW leverage — "refactor insurance" or noise:** skip these. Document the skip in the output but don't write tests for them. - -- Constructor property checks (`arr.constructor === Array`) unless production code is known to rely on them -- Idempotency invariants only triggered by other library code (Lodash, native spread) -- Equivalent mutants — mutations that produce semantically identical code (e.g. swapping an unused conditional) -- Mutants on internal helpers users can't reach through any public API - -If the summary lists `noCoverage` survivors, treat them as their own bucket: "the test suite doesn't even execute these lines." Triage them by the same rubric, but flag separately since they need a new test case rather than an assertion extension. - -### 4. Pick the work set: up to 5 mutants - -Order: all HIGH first, then MODERATE if budget remains, never LOW. Hard cap at 5 total. If HIGH alone exceeds 5, pick the 5 most distinct (don't pick 5 mutants on the same line — they probably share a fix; pick representatives across the file). - -If fewer than 3 HIGH+MODERATE candidates exist, just do what's there. Don't pad with LOW just to hit a number. - -Write up the work set to the user **before editing**: - -``` -Picked N survivors to address (M skipped as refactor-insurance / low-leverage): - 1. [HIGH] location — original → replacement - plan: assert <X> in <covering test name> - 2. [HIGH] ... - 3. [MODERATE] ... - ... -``` - -This is the user's chance to redirect. Don't write code yet. - -### 5. Read covering tests for the picked survivors - -For each picked survivor, the summary lists the test names that covered the line. Find those tests in the test file (usually `packages/<pkg>/test/<source-basename>.test.ts`, but check) and read **just the relevant `test('...')` blocks** — not the whole file. Use `Grep` + `Read` with line offsets to keep token cost down. - -Goal: understand what the existing test asserts so the new assertion is additive, not contradictory. - -### 6. Write the changes - -Constraints: -- **Prefer extending an existing covering test** over adding a new one. Lower file churn, easier review. -- **Match the existing style** — same assertion library, same matcher idioms (`.toBe` vs `.toEqual` vs `.toStrictEqual`). -- **Minimal additions** — one or two assertions per mutant, not a new it-block per mutant. -- **No fabrication** — only assert what the source code actually does. If you can't tell from the source, stop and ask the user. -- **For `noCoverage` survivors**, add a new test case named after the behaviour being pinned. Place it next to related tests. - -Use `Edit` with exact-string matches. Never rewrite entire test files. - -### 7. Verify - -Re-invoke `n8n:mutant-score` on the same source file. Report: - -``` -Before: red 76.74% (28 survivors) -After: green 82.34% (22 survivors) -Killed: 6 of 5 targeted (1 bonus — fix for #77 also killed #78) -Still surviving: 22 — re-invoke /n8n:mutant-fix for another batch. -``` - -If the score went UP but threshold still not met: the iteration is working, recommend another pass. -If the score went DOWN or stayed the same: at least one new test isn't asserting what we think it asserts. Surface the diff to the user and stop — do not auto-revert. -If a test now fails (not survives — actually fails): we asserted something the code doesn't do. Revert that specific assertion, leave the rest, report which one was wrong. - -## Output shape - -Each invocation produces: - -1. **Work plan** (before edits) — the picked survivors and the plan for each -2. **Diffs** (during edits) — Edit tool calls, visible in transcript -3. **Verify** (after) — re-run + before/after comparison - -Keep prose minimal between sections. The plan and verify steps are the structured outputs; everything else is mechanical. - -## Constraints - -- **5 mutants max per invocation.** Re-invoke for more. Prevents runaway sessions on 30-survivor files. -- **Never fabricate assertions.** If the source doesn't clearly do X, don't claim it does. -- **No new test files unless absolutely necessary.** Extend the existing covering test file. -- **No reverting other people's tests.** Only edit tests in the package being mutated. -- **No re-running mutant-score more than once per invocation.** That's the verify step. Don't loop within a single invocation; let the user re-invoke. -- **No commits.** Edits land in the working tree; user reviews and commits. - -## Common follow-ups - -- User says "go again" → re-invoke this skill. The summary.json now reflects the post-edit state. -- User says "why was #N classified as LOW?" → explain the rubric application for that specific mutant, no re-triage of others. -- User says "kill #N specifically" → override the triage for that mutant, treat it as picked. -- User says "skip the verify step" → don't; the verify step is the contract that the edits actually moved the score. - -## Related - -- `n8n:mutant-score` — the read side of this loop -- `scripts/mutation-health/README.md` — the BQ-backed observability story this slots into diff --git a/.claude/plugins/n8n/skills/mutant-score/SKILL.md b/.claude/plugins/n8n/skills/mutant-score/SKILL.md deleted file mode 100644 index d6cca6d18d5..00000000000 --- a/.claude/plugins/n8n/skills/mutant-score/SKILL.md +++ /dev/null @@ -1,116 +0,0 @@ ---- -description: Run Stryker mutation testing on a single source file and return a structured, token-frugal report that's pipeable to a follow-up "strengthen tests" loop. Use when the user says /mutant-score, "mutation test this file", or has just edited tests and wants to verify they actually assert behaviour. Per-file only — full-package mutation runs are out of scope. ---- - -# Mutation testing — single file - -Wraps `pnpm mutate <file>` and parses `summary.json` into a compact, structured shape suitable for downstream "strengthen the surviving mutants" iteration. Works for any vitest package — `pnpm mutate` infers the package from the path. - -## When to use - -- User explicitly invokes: `/mutant-score <path>`, "mutation test this file", "check my test effectiveness on X" -- User has just edited a test file and wants to know if their assertions are load-bearing -- Follow-up loop after a `red` verdict — feed the structured output back to a "fix" iteration - -**Don't** use this skill for: -- Whole-package or whole-repo mutation runs — single file only -- Coverage % questions (use the existing coverage workflow) -- **jest** packages (`nodes-base`, `cli`, `db`) — Stryker's vitest-runner only covers vitest packages -- `@n8n/expression-runtime` — it's the isolated-vm engine (blocked on DEVP-257) - -## Inputs - -One required argument: the source file to mutate. Prefer a **repo-relative path** — the package is inferred from it: - -- `packages/workflow/src/cron.ts` (package inferred) -- `packages/@n8n/crdt/src/utils.ts` (package inferred) - -A bare package-relative path (`src/cron.ts`) is ambiguous — pass the repo-relative path, or add `--package-dir <pkg>`. Don't guess the package. - -## Steps - -1. **Resolve the target.** Any vitest package works; `pnpm mutate` infers the package from a repo-relative path. If the file is in a jest package or `@n8n/expression-runtime`, say so and stop — don't fabricate output. - -2. **Run Stryker with trimmed output:** - ```bash - pnpm mutate <repo-relative-file> 2>&1 | tail -40 - ``` - `tail -40` discards the Stryker progress bar spam; the relevant numbers + survivor list always land in the last ~30 lines. Exit codes: `0` = pass, `1` = below threshold (still valid, summary.json exists), `2` = usage error, `3` = Stryker failure (no summary.json). - -3. **If exit code 3**, surface the trimmed tail to the user, suggest checking that workspace deps are built (`pnpm build`), and stop. Don't fabricate a report. - -4. **Read the package's `reports/mutation/summary.json`** (e.g. `packages/workflow/reports/mutation/summary.json`) — never `raw.json`. raw.json is 600KB+ and not needed for the strengthen loop. summary.json already contains every surviving mutant with its location, replacement, mutator name, and the names of tests that covered the line. - -5. **Cap covering_tests at 3 per survivor.** If a mutant was covered by more than 3 tests, keep the first 3 and append `+N more` as a count. Names beyond 3 add tokens without adding actionable signal — the strengthen loop only needs to know *which test* to extend, not all of them. - -6. **Compute `minimum_kills_needed`** to reach the threshold: - ``` - killed_now = summary.overall.counts.killed + summary.overall.counts.timeout - valid_total = killed_now + summary.overall.counts.survived + summary.overall.counts.noCoverage - needed = ceil((threshold/100) * valid_total) - killed_now - ``` - This tells the next loop the minimum number of survivors it has to kill to flip `red` → `green`. Cap at the number of survivors. - -7. **Output the structured shape** described below. Keep prose to one headline line; the rest is the JSON block. - -## Output shape - -One headline line, then a fenced JSON block. Nothing else — no preamble, no per-survivor commentary, no risk triage (that's the next loop's job). - -```` -[red|green] <score>% (threshold <T>%) — <N> survivors; need to kill ≥<K> to flip green. - -```json -{ - "verdict": "red", - "target": "packages/workflow/src/augment-object.ts", - "package": "n8n-workflow", - "score": 76.74, - "threshold": 80, - "delta_to_threshold": 3.26, - "minimum_kills_needed": 5, - "counts": { - "killed": 99, - "survived": 28, - "no_coverage": 2, - "timeout": 0 - }, - "survivors": [ - { - "id": "77", - "mutator": "ConditionalExpression", - "location": "src/augment-object.ts:95:6", - "original": "value === null", - "replacement": "false", - "covering_tests": [ - "augmentObject should handle null values", - "augmentObject should handle nested nulls" - ], - "covering_tests_overflow": 0 - } - ] -} -``` -```` - -Order the survivors array by `location` (ascending line number, then column) so the strengthen loop processes them top-to-bottom of the file. - -## Constraints - -- **No raw.json** — never read or surface it. summary.json is the only input. -- **No HTML report** — don't `open` raw.html or paste links to it. If the user wants visual exploration they'll ask. -- **No automatic triage** — don't categorise survivors by "real bug" vs "refactor insurance." That's a separate analysis step that should happen on demand, not by default. Keeps token cost predictable. -- **No "I'll regenerate tests for you now"** — this skill reports the gap. Use `n8n:mutant-fix` if you want assertion edits. - -## Common follow-ups (don't do unless asked) - -- User says "fix these" → start a strengthen loop using the JSON output as input. Read covering_tests source, propose changes per mutant, run the skill again to verify. -- User says "explain survivor #N" → fetch that mutant from summary.json, show its surrounding ~5 lines from the source file, no analysis beyond what summary.json contains. -- User says "what's the threshold?" → 80% provisional; see `scripts/mutation-health/README.md` for the rationale. -- User says "run it on the changed files" → use `n8n:mutant-diff` (mutates the diff vs origin/master). - -## Related - -- `scripts/mutation-health/README.md` — the broader BQ-backed observability story -- `scripts/mutation-health/stryker.default.mjs` — the default Stryker config; a package may override with its own `stryker.config.mjs` (e.g. `packages/workflow` carves out the isolated-vm engine) -- `n8n:mutant-fix` — the strengthen-the-survivors counterpart diff --git a/.claude/plugins/n8n/skills/node-add-oauth b/.claude/plugins/n8n/skills/node-add-oauth new file mode 120000 index 00000000000..be7a6d46309 --- /dev/null +++ b/.claude/plugins/n8n/skills/node-add-oauth @@ -0,0 +1 @@ +../../../../.agents/skills/node-add-oauth \ No newline at end of file diff --git a/.claude/plugins/n8n/skills/protect-endpoints b/.claude/plugins/n8n/skills/protect-endpoints new file mode 120000 index 00000000000..e4920b4d418 --- /dev/null +++ b/.claude/plugins/n8n/skills/protect-endpoints @@ -0,0 +1 @@ +../../../../.agents/skills/protect-endpoints \ No newline at end of file diff --git a/.claude/plugins/n8n/skills/reproduce-bug b/.claude/plugins/n8n/skills/reproduce-bug new file mode 120000 index 00000000000..deb956f4720 --- /dev/null +++ b/.claude/plugins/n8n/skills/reproduce-bug @@ -0,0 +1 @@ +../../../../.agents/skills/reproduce-bug \ No newline at end of file diff --git a/.claude/plugins/n8n/skills/spec-driven-development b/.claude/plugins/n8n/skills/spec-driven-development new file mode 120000 index 00000000000..128e2eb4889 --- /dev/null +++ b/.claude/plugins/n8n/skills/spec-driven-development @@ -0,0 +1 @@ +../../../../.agents/skills/spec-driven-development \ No newline at end of file diff --git a/.claude/skills b/.claude/skills deleted file mode 120000 index 18fd928f1f4..00000000000 --- a/.claude/skills +++ /dev/null @@ -1 +0,0 @@ -plugins/n8n/skills \ No newline at end of file diff --git a/.code-health-baseline.json b/.code-health-baseline.json index 84744f7d80c..4fd32e04709 100644 --- a/.code-health-baseline.json +++ b/.code-health-baseline.json @@ -1,42 +1,36 @@ { "version": 1, - "generated": "2026-05-18T09:49:47.866Z", - "totalViolations": 99, + "generated": "2026-06-04T06:55:45.363Z", + "totalViolations": 148, "violations": { "packages/@n8n/ai-workflow-builder.ee/package.json": [ { "rule": "catalog-violations", - "line": 73, + "line": 76, "message": "langsmith@^0.4.6 should use \"catalog:\" (exists in pnpm-workspace.yaml)", "hash": "6ee5e003d795" }, { "rule": "catalog-violations", - "line": 61, + "line": 63, "message": "@mozilla/readability appears in 5 packages with 2 different versions — add to pnpm-workspace.yaml catalog", "hash": "d2120f012c93" }, { "rule": "catalog-violations", - "line": 70, - "message": "csv-parse appears in 3 packages with 2 different versions — add to pnpm-workspace.yaml catalog", - "hash": "94f80b083b76" - }, - { - "rule": "catalog-violations", - "line": 71, + "line": 74, "message": "jsdom appears in 4 packages with 2 different versions — add to pnpm-workspace.yaml catalog", "hash": "9c770d66baf2" }, { "rule": "catalog-violations", - "line": 77, + "line": 80, "message": "turndown appears in 3 packages with 2 different versions — add to pnpm-workspace.yaml catalog", "hash": "85c311d87491" }, { "rule": "catalog-violations", - "line": 83, + "line": 87, "message": "@types/turndown appears in 3 packages with 2 different versions — add to pnpm-workspace.yaml catalog", "hash": "407c8d1b3428" } @@ -44,7 +38,7 @@ "packages/@n8n/json-schema-to-zod/package.json": [ { "rule": "catalog-violations", - "line": 63, + "line": 64, "message": "zod@^3.25.76 should use \"catalog:\" (exists in pnpm-workspace.yaml)", "hash": "0e18482e8781" } @@ -52,87 +46,81 @@ "packages/@n8n/nodes-langchain/package.json": [ { "rule": "catalog-violations", - "line": 268, + "line": 272, "message": "@n8n/typeorm@0.3.20-16 should use \"catalog:\" (exists in pnpm-workspace.yaml)", "hash": "a7c1bca1c439" }, { "rule": "catalog-violations", - "line": 269, + "line": 273, "message": "mysql2@3.17.0 should use \"catalog:\" (exists in pnpm-workspace.yaml)", "hash": "2d7d1b715d0c" }, { "rule": "catalog-violations", - "line": 295, + "line": 301, "message": "openai@^6.34.0 should use \"catalog:\" (exists in pnpm-workspace.yaml)", "hash": "3c1f53f0afe3" }, { "rule": "catalog-violations", - "line": 302, + "line": 307, "message": "tmp-promise appears in 4 packages with 2 different versions — add to pnpm-workspace.yaml catalog", "hash": "88d67e2ef747" }, { "rule": "catalog-violations", - "line": 261, + "line": 265, "message": "@mozilla/readability appears in 5 packages with 2 different versions — add to pnpm-workspace.yaml catalog", "hash": "69d6fa7e46f9" }, { "rule": "catalog-violations", - "line": 277, + "line": 283, "message": "cheerio appears in 2 packages with 2 different versions — add to pnpm-workspace.yaml catalog", "hash": "8cd029bb871e" }, { "rule": "catalog-violations", - "line": 287, + "line": 293, "message": "jsdom appears in 4 packages with 2 different versions — add to pnpm-workspace.yaml catalog", "hash": "26f20ebea4b1" }, { "rule": "catalog-violations", - "line": 292, + "line": 298, "message": "mongodb appears in 2 packages with 2 different versions — add to pnpm-workspace.yaml catalog", "hash": "46cb48884e22" - }, - { - "rule": "catalog-violations", - "line": 296, - "message": "pdf-parse appears in 2 packages with 2 different versions — add to pnpm-workspace.yaml catalog", - "hash": "0c7d44a9c2e4" } ], "packages/@n8n/tournament/package.json": [ { "rule": "catalog-violations", - "line": 44, + "line": 47, "message": "@types/node@^18.13.0 should use \"catalog:\" (exists in pnpm-workspace.yaml)", "hash": "6368b5d3b924" }, { "rule": "catalog-violations", - "line": 52, + "line": 55, "message": "typescript@^5.0.0 should use \"catalog:\" (exists in pnpm-workspace.yaml)", "hash": "f668021a144e" }, { "rule": "catalog-violations", - "line": 55, + "line": 58, "message": "ast-types appears in 2 packages with 2 different versions — add to pnpm-workspace.yaml catalog", "hash": "27edcbb2b4f8" }, { "rule": "catalog-violations", - "line": 56, + "line": 59, "message": "esprima-next appears in 3 packages with 2 different versions — add to pnpm-workspace.yaml catalog", "hash": "75058f9a4d30" }, { "rule": "catalog-violations", - "line": 57, + "line": 60, "message": "recast appears in 2 packages with 2 different versions — add to pnpm-workspace.yaml catalog", "hash": "5f2b50fef19d" } @@ -140,7 +128,7 @@ "packages/frontend/@n8n/chat/package.json": [ { "rule": "catalog-violations", - "line": 56, + "line": 60, "message": "unplugin-icons@^0.19.0 should use \"catalog:frontend\" (exists in pnpm-workspace.yaml [frontend])", "hash": "a0d24d761026" } @@ -148,7 +136,7 @@ "packages/frontend/@n8n/design-system/package.json": [ { "rule": "catalog-violations", - "line": 73, + "line": 88, "message": "@vueuse/core@* should use \"catalog:frontend\" (exists in pnpm-workspace.yaml [frontend])", "hash": "237e9d17c4ba" } @@ -156,55 +144,43 @@ "packages/cli/package.json": [ { "rule": "catalog-violations", - "line": 98, - "message": "@ai-sdk/anthropic appears in 3 packages with 2 different versions — add to pnpm-workspace.yaml catalog", - "hash": "1e3686e1923b" - }, - { - "rule": "catalog-violations", - "line": 139, + "line": 146, "message": "@opentelemetry/sdk-trace-base appears in 2 packages with 2 different versions — add to pnpm-workspace.yaml catalog", "hash": "1cf7f6bcf5d1" }, { "rule": "catalog-violations", - "line": 140, + "line": 147, "message": "@opentelemetry/sdk-trace-node appears in 2 packages with 2 different versions — add to pnpm-workspace.yaml catalog", "hash": "a3dad0b8dc21" }, { "rule": "catalog-violations", - "line": 150, + "line": 157, "message": "change-case appears in 5 packages with 3 different versions — add to pnpm-workspace.yaml catalog", "hash": "949e802528f7" }, { "rule": "catalog-violations", - "line": 202, + "line": 212, "message": "prettier appears in 3 packages with 3 different versions — add to pnpm-workspace.yaml catalog", "hash": "3cab98902302" }, { "rule": "catalog-violations", - "line": 209, - "message": "semver appears in 4 packages with 2 different versions — add to pnpm-workspace.yaml catalog", - "hash": "5b7e9b03fb10" - }, - { - "rule": "catalog-violations", - "line": 217, + "line": 228, "message": "undici appears in 2 packages with 2 different versions — add to pnpm-workspace.yaml catalog", "hash": "91c29775e961" }, { "rule": "catalog-violations", - "line": 220, + "line": 231, "message": "ws appears in 3 packages with 2 different versions — add to pnpm-workspace.yaml catalog", "hash": "cd07242e8163" }, { "rule": "catalog-violations", - "line": 75, + "line": 80, "message": "@types/psl appears in 2 packages with 2 different versions — add to pnpm-workspace.yaml catalog", "hash": "6e62e0076b0a" } @@ -212,89 +188,33 @@ "packages/@n8n/agents/package.json": [ { "rule": "catalog-violations", - "line": 28, - "message": "@ai-sdk/anthropic appears in 3 packages with 2 different versions — add to pnpm-workspace.yaml catalog", - "hash": "b58f03d0d5c1" - }, - { - "rule": "catalog-violations", - "line": 50, + "line": 76, "message": "@opentelemetry/sdk-trace-base appears in 2 packages with 2 different versions — add to pnpm-workspace.yaml catalog", "hash": "c5c495ac3508" }, { "rule": "catalog-violations", - "line": 51, + "line": 77, "message": "@opentelemetry/sdk-trace-node appears in 2 packages with 2 different versions — add to pnpm-workspace.yaml catalog", "hash": "a77ced903cdf" } ], - "packages/@n8n/instance-ai/package.json": [ - { - "rule": "catalog-violations", - "line": 81, - "message": "@ai-sdk/anthropic appears in 3 packages with 2 different versions — add to pnpm-workspace.yaml catalog", - "hash": "5b2153508e47" - }, - { - "rule": "catalog-violations", - "line": 87, - "message": "@types/psl appears in 2 packages with 2 different versions — add to pnpm-workspace.yaml catalog", - "hash": "56dabb51b433" - }, - { - "rule": "catalog-violations", - "line": 57, - "message": "@mozilla/readability appears in 5 packages with 2 different versions — add to pnpm-workspace.yaml catalog", - "hash": "8fa6b9a8fc91" - }, - { - "rule": "catalog-violations", - "line": 65, - "message": "csv-parse appears in 3 packages with 2 different versions — add to pnpm-workspace.yaml catalog", - "hash": "8f082fc2e8b6" - }, - { - "rule": "catalog-violations", - "line": 72, - "message": "turndown appears in 3 packages with 2 different versions — add to pnpm-workspace.yaml catalog", - "hash": "9a9d97065952" - }, - { - "rule": "catalog-violations", - "line": 88, - "message": "@types/turndown appears in 3 packages with 2 different versions — add to pnpm-workspace.yaml catalog", - "hash": "12e346c47b39" - }, - { - "rule": "catalog-violations", - "line": 51, - "message": "@joplin/turndown-plugin-gfm appears in 2 packages with 2 different versions — add to pnpm-workspace.yaml catalog", - "hash": "a3cf1504b5c2" - }, - { - "rule": "catalog-violations", - "line": 69, - "message": "pdf-parse appears in 2 packages with 2 different versions — add to pnpm-workspace.yaml catalog", - "hash": "283fa9114c03" - } - ], "packages/node-dev/package.json": [ { "rule": "catalog-violations", - "line": 47, + "line": 49, "message": "change-case appears in 5 packages with 3 different versions — add to pnpm-workspace.yaml catalog", "hash": "6988b9f58c92" }, { "rule": "catalog-violations", - "line": 46, + "line": 48, "message": "@oclif/core appears in 4 packages with 2 different versions — add to pnpm-workspace.yaml catalog", "hash": "da9b64834300" }, { "rule": "catalog-violations", - "line": 53, + "line": 55, "message": "tmp-promise appears in 4 packages with 2 different versions — add to pnpm-workspace.yaml catalog", "hash": "632a744e397e" } @@ -302,61 +222,49 @@ "packages/nodes-base/package.json": [ { "rule": "catalog-violations", - "line": 913, + "line": 920, "message": "change-case appears in 5 packages with 3 different versions — add to pnpm-workspace.yaml catalog", "hash": "2d1fab7a5b05" }, { "rule": "catalog-violations", - "line": 963, - "message": "semver appears in 4 packages with 2 different versions — add to pnpm-workspace.yaml catalog", - "hash": "2daf37aa14e4" - }, - { - "rule": "catalog-violations", - "line": 968, + "line": 976, "message": "tmp-promise appears in 4 packages with 2 different versions — add to pnpm-workspace.yaml catalog", "hash": "3f93c404ae9c" }, { "rule": "catalog-violations", - "line": 902, + "line": 909, "message": "@mozilla/readability appears in 5 packages with 2 different versions — add to pnpm-workspace.yaml catalog", "hash": "ca4ac788adc6" }, { "rule": "catalog-violations", - "line": 914, + "line": 921, "message": "cheerio appears in 2 packages with 2 different versions — add to pnpm-workspace.yaml catalog", "hash": "1a1b5bbc50c9" }, { "rule": "catalog-violations", - "line": 917, - "message": "csv-parse appears in 3 packages with 2 different versions — add to pnpm-workspace.yaml catalog", - "hash": "781db4a1e068" - }, - { - "rule": "catalog-violations", - "line": 919, + "line": 926, "message": "eventsource appears in 2 packages with 2 different versions — add to pnpm-workspace.yaml catalog", "hash": "9795e6c6d9e9" }, { "rule": "catalog-violations", - "line": 932, + "line": 940, "message": "jsdom appears in 4 packages with 2 different versions — add to pnpm-workspace.yaml catalog", "hash": "02341f2b5e3e" }, { "rule": "catalog-violations", - "line": 943, + "line": 951, "message": "mongodb appears in 2 packages with 2 different versions — add to pnpm-workspace.yaml catalog", "hash": "f688907d087a" }, { "rule": "catalog-violations", - "line": 894, + "line": 901, "message": "eslint-plugin-n8n-nodes-base appears in 2 packages with 2 different versions — add to pnpm-workspace.yaml catalog", "hash": "ac254baa61f9" } @@ -364,25 +272,25 @@ "packages/@n8n/node-cli/package.json": [ { "rule": "catalog-violations", - "line": 52, + "line": 53, "message": "change-case appears in 5 packages with 3 different versions — add to pnpm-workspace.yaml catalog", "hash": "da74ed210d07" }, { "rule": "catalog-violations", - "line": 59, + "line": 60, "message": "prettier appears in 3 packages with 3 different versions — add to pnpm-workspace.yaml catalog", "hash": "188baf266f61" }, { "rule": "catalog-violations", - "line": 51, + "line": 52, "message": "@oclif/core appears in 4 packages with 2 different versions — add to pnpm-workspace.yaml catalog", "hash": "9711a9b00bf9" }, { "rule": "catalog-violations", - "line": 55, + "line": 56, "message": "eslint-plugin-n8n-nodes-base appears in 2 packages with 2 different versions — add to pnpm-workspace.yaml catalog", "hash": "6a9e12780943" } @@ -390,53 +298,39 @@ "packages/frontend/editor-ui/package.json": [ { "rule": "catalog-violations", - "line": 69, + "line": 71, "message": "change-case appears in 5 packages with 3 different versions — add to pnpm-workspace.yaml catalog", "hash": "bd9a2eeb072b" }, { "rule": "catalog-violations", - "line": 91, + "line": 93, "message": "prettier appears in 3 packages with 3 different versions — add to pnpm-workspace.yaml catalog", "hash": "9e9c7ec09a0b" }, { "rule": "catalog-violations", - "line": 93, - "message": "semver appears in 4 packages with 2 different versions — add to pnpm-workspace.yaml catalog", - "hash": "d8c606e42c92" - }, - { - "rule": "catalog-violations", - "line": 78, + "line": 80, "message": "esprima-next appears in 3 packages with 2 different versions — add to pnpm-workspace.yaml catalog", "hash": "62156c2613b2" } ], - "packages/@n8n/scan-community-package/package.json": [ - { - "rule": "catalog-violations", - "line": 20, - "message": "semver appears in 4 packages with 2 different versions — add to pnpm-workspace.yaml catalog", - "hash": "ac0e4301d694" - } - ], "packages/@n8n/ai-utilities/package.json": [ { "rule": "catalog-violations", - "line": 69, + "line": 107, "message": "undici appears in 2 packages with 2 different versions — add to pnpm-workspace.yaml catalog", "hash": "c14cd05614e8" }, { "rule": "catalog-violations", - "line": 65, + "line": 102, "message": "tmp-promise appears in 4 packages with 2 different versions — add to pnpm-workspace.yaml catalog", "hash": "884a45bdbcf2" }, { "rule": "catalog-violations", - "line": 72, + "line": 110, "message": "n8n-workflow appears in 2 packages with 2 different versions — add to pnpm-workspace.yaml catalog", "hash": "ea4fbfff30ba" } @@ -444,37 +338,37 @@ "packages/@n8n/mcp-browser/package.json": [ { "rule": "catalog-violations", - "line": 36, + "line": 37, "message": "ws appears in 3 packages with 2 different versions — add to pnpm-workspace.yaml catalog", "hash": "9650c1b55f3c" }, { "rule": "catalog-violations", - "line": 28, + "line": 29, "message": "@mozilla/readability appears in 5 packages with 2 different versions — add to pnpm-workspace.yaml catalog", "hash": "0c97891a24f4" }, { "rule": "catalog-violations", - "line": 30, + "line": 31, "message": "jsdom appears in 4 packages with 2 different versions — add to pnpm-workspace.yaml catalog", "hash": "8466b03b1044" }, { "rule": "catalog-violations", - "line": 35, + "line": 36, "message": "turndown appears in 3 packages with 2 different versions — add to pnpm-workspace.yaml catalog", "hash": "f23a9d3d7aa2" }, { "rule": "catalog-violations", - "line": 42, + "line": 44, "message": "@types/turndown appears in 3 packages with 2 different versions — add to pnpm-workspace.yaml catalog", "hash": "3f9e46e56803" }, { "rule": "catalog-violations", - "line": 26, + "line": 27, "message": "@joplin/turndown-plugin-gfm appears in 2 packages with 2 different versions — add to pnpm-workspace.yaml catalog", "hash": "743e3a7dbb32" } @@ -482,15 +376,47 @@ "packages/@n8n/task-runner/package.json": [ { "rule": "catalog-violations", - "line": 50, + "line": 51, "message": "ws appears in 3 packages with 2 different versions — add to pnpm-workspace.yaml catalog", "hash": "51cb5069f382" } ], + "packages/@n8n/instance-ai/package.json": [ + { + "rule": "catalog-violations", + "line": 89, + "message": "@types/psl appears in 2 packages with 2 different versions — add to pnpm-workspace.yaml catalog", + "hash": "56dabb51b433" + }, + { + "rule": "catalog-violations", + "line": 56, + "message": "@mozilla/readability appears in 5 packages with 2 different versions — add to pnpm-workspace.yaml catalog", + "hash": "8fa6b9a8fc91" + }, + { + "rule": "catalog-violations", + "line": 76, + "message": "turndown appears in 3 packages with 2 different versions — add to pnpm-workspace.yaml catalog", + "hash": "9a9d97065952" + }, + { + "rule": "catalog-violations", + "line": 90, + "message": "@types/turndown appears in 3 packages with 2 different versions — add to pnpm-workspace.yaml catalog", + "hash": "12e346c47b39" + }, + { + "rule": "catalog-violations", + "line": 55, + "message": "@joplin/turndown-plugin-gfm appears in 2 packages with 2 different versions — add to pnpm-workspace.yaml catalog", + "hash": "a3cf1504b5c2" + } + ], "packages/@n8n/benchmark/package.json": [ { "rule": "catalog-violations", - "line": 36, + "line": 38, "message": "@oclif/core appears in 4 packages with 2 different versions — add to pnpm-workspace.yaml catalog", "hash": "67f9d81d9528" } @@ -498,7 +424,7 @@ "packages/@n8n/cli/package.json": [ { "rule": "catalog-violations", - "line": 74, + "line": 75, "message": "@oclif/core appears in 4 packages with 2 different versions — add to pnpm-workspace.yaml catalog", "hash": "733c3960022e" } @@ -506,7 +432,7 @@ "packages/@n8n/computer-use/package.json": [ { "rule": "catalog-violations", - "line": 47, + "line": 48, "message": "eventsource appears in 2 packages with 2 different versions — add to pnpm-workspace.yaml catalog", "hash": "f50c1eee2ed6" } @@ -514,19 +440,19 @@ "packages/workflow/package.json": [ { "rule": "catalog-violations", - "line": 58, + "line": 64, "message": "ast-types appears in 2 packages with 2 different versions — add to pnpm-workspace.yaml catalog", "hash": "1c7d7cf0b0fe" }, { "rule": "catalog-violations", - "line": 60, + "line": 66, "message": "esprima-next appears in 3 packages with 2 different versions — add to pnpm-workspace.yaml catalog", "hash": "627a716b5d23" }, { "rule": "catalog-violations", - "line": 68, + "line": 74, "message": "recast appears in 2 packages with 2 different versions — add to pnpm-workspace.yaml catalog", "hash": "b660317b5f6f" } @@ -534,7 +460,7 @@ "packages/@n8n/eslint-plugin-community-nodes/package.json": [ { "rule": "catalog-violations", - "line": 47, + "line": 49, "message": "n8n-workflow appears in 2 packages with 2 different versions — add to pnpm-workspace.yaml catalog", "hash": "c5830b76ff8e" } @@ -542,107 +468,595 @@ "packages/@n8n/stylelint-config/package.json": [ { "rule": "catalog-violations", - "line": 29, + "line": 30, "message": "stylelint appears in 2 packages with 2 different versions — add to pnpm-workspace.yaml catalog", "hash": "955f3fe044c7" }, { "rule": "catalog-violations", - "line": 45, + "line": 46, "message": "stylelint appears in 2 packages with 2 different versions — add to pnpm-workspace.yaml catalog", "hash": "955f3fe044c7" } ], + "packages/@n8n/db/src/migrations/common/1690000000030-RemoveResetPasswordColumns.ts": [ + { + "rule": "migration-timestamp", + "line": 1, + "message": "1690000000030-RemoveResetPasswordColumns.ts (1690000000030) is at or below the highest existing migration timestamp (1784000000025). New migrations must be strictly ordered — pick a timestamp greater than 1784000000025.", + "hash": "c524a9ca4292" + } + ], + "packages/@n8n/db/src/migrations/common/1690000000040-AddMfaColumns.ts": [ + { + "rule": "migration-timestamp", + "line": 1, + "message": "1690000000040-AddMfaColumns.ts (1690000000040) is at or below the highest existing migration timestamp (1784000000025). New migrations must be strictly ordered — pick a timestamp greater than 1784000000025.", + "hash": "9d571251376b" + } + ], + "packages/@n8n/db/src/migrations/common/1693491613982-ExecutionSoftDelete.ts": [ + { + "rule": "migration-timestamp", + "line": 1, + "message": "1693491613982-ExecutionSoftDelete.ts (1693491613982) is at or below the highest existing migration timestamp (1784000000025). New migrations must be strictly ordered — pick a timestamp greater than 1784000000025.", + "hash": "7ade19d27ea8" + } + ], + "packages/@n8n/db/src/migrations/common/1693554410387-DisallowOrphanExecutions.ts": [ + { + "rule": "migration-timestamp", + "line": 1, + "message": "1693554410387-DisallowOrphanExecutions.ts (1693554410387) is at or below the highest existing migration timestamp (1784000000025). New migrations must be strictly ordered — pick a timestamp greater than 1784000000025.", + "hash": "d46b0ae69b38" + } + ], + "packages/@n8n/db/src/migrations/common/1695128658538-AddWorkflowMetadata.ts": [ + { + "rule": "migration-timestamp", + "line": 1, + "message": "1695128658538-AddWorkflowMetadata.ts (1695128658538) is at or below the highest existing migration timestamp (1784000000025). New migrations must be strictly ordered — pick a timestamp greater than 1784000000025.", + "hash": "52c9ad1e00dc" + } + ], + "packages/@n8n/db/src/migrations/common/1695829275184-ModifyWorkflowHistoryNodesAndConnections.ts": [ + { + "rule": "migration-timestamp", + "line": 1, + "message": "1695829275184-ModifyWorkflowHistoryNodesAndConnections.ts (1695829275184) is at or below the highest existing migration timestamp (1784000000025). New migrations must be strictly ordered — pick a timestamp greater than 1784000000025.", + "hash": "e05c9af6e2f9" + } + ], + "packages/@n8n/db/src/migrations/common/1705429061930-DropRoleMapping.ts": [ + { + "rule": "migration-timestamp", + "line": 1, + "message": "1705429061930-DropRoleMapping.ts (1705429061930) is at or below the highest existing migration timestamp (1784000000025). New migrations must be strictly ordered — pick a timestamp greater than 1784000000025.", + "hash": "8d325473bce5" + } + ], + "packages/@n8n/db/src/migrations/common/1712044305787-RemoveNodesAccess.ts": [ + { + "rule": "migration-timestamp", + "line": 1, + "message": "1712044305787-RemoveNodesAccess.ts (1712044305787) is at or below the highest existing migration timestamp (1784000000025). New migrations must be strictly ordered — pick a timestamp greater than 1784000000025.", + "hash": "8d2bbe7bc09d" + } + ], + "packages/@n8n/db/src/migrations/common/1714133768519-CreateProject.ts": [ + { + "rule": "migration-timestamp", + "line": 1, + "message": "1714133768519-CreateProject.ts (1714133768519) is at or below the highest existing migration timestamp (1784000000025). New migrations must be strictly ordered — pick a timestamp greater than 1784000000025.", + "hash": "cdd159d80c55" + } + ], + "packages/@n8n/db/src/migrations/common/1714133768521-MakeExecutionStatusNonNullable.ts": [ + { + "rule": "migration-timestamp", + "line": 1, + "message": "1714133768521-MakeExecutionStatusNonNullable.ts (1714133768521) is at or below the highest existing migration timestamp (1784000000025). New migrations must be strictly ordered — pick a timestamp greater than 1784000000025.", + "hash": "7e726215f602" + } + ], + "packages/@n8n/db/src/migrations/common/1724951148974-AddApiKeysTable.ts": [ + { + "rule": "migration-timestamp", + "line": 1, + "message": "1724951148974-AddApiKeysTable.ts (1724951148974) is at or below the highest existing migration timestamp (1784000000025). New migrations must be strictly ordered — pick a timestamp greater than 1784000000025.", + "hash": "3eaa3fa96ad1" + } + ], + "packages/@n8n/db/src/migrations/common/1727427440136-SeparateExecutionCreationFromStart.ts": [ + { + "rule": "migration-timestamp", + "line": 1, + "message": "1727427440136-SeparateExecutionCreationFromStart.ts (1727427440136) is at or below the highest existing migration timestamp (1784000000025). New migrations must be strictly ordered — pick a timestamp greater than 1784000000025.", + "hash": "702281e1c037" + } + ], + "packages/@n8n/db/src/migrations/common/1729607673464-UpdateProcessedDataValueColumnToText.ts": [ + { + "rule": "migration-timestamp", + "line": 1, + "message": "1729607673464-UpdateProcessedDataValueColumnToText.ts (1729607673464) is at or below the highest existing migration timestamp (1784000000025). New migrations must be strictly ordered — pick a timestamp greater than 1784000000025.", + "hash": "cf281457e81a" + } + ], + "packages/@n8n/db/src/migrations/common/1729607673469-AddProjectIcons.ts": [ + { + "rule": "migration-timestamp", + "line": 1, + "message": "1729607673469-AddProjectIcons.ts (1729607673469) is at or below the highest existing migration timestamp (1784000000025). New migrations must be strictly ordered — pick a timestamp greater than 1784000000025.", + "hash": "d3c84ea555a6" + } + ], + "packages/@n8n/db/src/migrations/common/1731404028106-AddDescriptionToTestDefinition.ts": [ + { + "rule": "migration-timestamp", + "line": 1, + "message": "1731404028106-AddDescriptionToTestDefinition.ts (1731404028106) is at or below the highest existing migration timestamp (1784000000025). New migrations must be strictly ordered — pick a timestamp greater than 1784000000025.", + "hash": "c0b12dc71971" + } + ], + "packages/@n8n/db/src/migrations/common/1742918400000-AddScopesColumnToApiKeys.ts": [ + { + "rule": "migration-timestamp", + "line": 1, + "message": "1742918400000-AddScopesColumnToApiKeys.ts (1742918400000) is at or below the highest existing migration timestamp (1784000000025). New migrations must be strictly ordered — pick a timestamp greater than 1784000000025.", + "hash": "1bd84c6e2704" + } + ], + "packages/@n8n/db/src/migrations/common/1750252139168-LinkRoleToUserTable.ts": [ + { + "rule": "migration-timestamp", + "line": 1, + "message": "1750252139168-LinkRoleToUserTable.ts (1750252139168) is at or below the highest existing migration timestamp (1784000000025). New migrations must be strictly ordered — pick a timestamp greater than 1784000000025.", + "hash": "ae1fdf257787" + } + ], + "packages/@n8n/db/src/migrations/common/1750252139170-RemoveOldRoleColumn.ts": [ + { + "rule": "migration-timestamp", + "line": 1, + "message": "1750252139170-RemoveOldRoleColumn.ts (1750252139170) is at or below the highest existing migration timestamp (1784000000025). New migrations must be strictly ordered — pick a timestamp greater than 1784000000025.", + "hash": "121d2727ab80" + } + ], + "packages/@n8n/db/src/migrations/common/1752669793000-AddInputsOutputsToTestCaseExecution.ts": [ + { + "rule": "migration-timestamp", + "line": 1, + "message": "1752669793000-AddInputsOutputsToTestCaseExecution.ts (1752669793000) is at or below the highest existing migration timestamp (1784000000025). New migrations must be strictly ordered — pick a timestamp greater than 1784000000025.", + "hash": "01857ec1a3d0" + } + ], + "packages/@n8n/db/src/migrations/common/1756906557570-AddTimestampsToRoleAndRoleIndexes.ts": [ + { + "rule": "migration-timestamp", + "line": 1, + "message": "1756906557570-AddTimestampsToRoleAndRoleIndexes.ts (1756906557570) is at or below the highest existing migration timestamp (1784000000025). New migrations must be strictly ordered — pick a timestamp greater than 1784000000025.", + "hash": "3170ea3366de" + } + ], + "packages/@n8n/db/src/migrations/common/1758731786132-AddAudienceColumnToApiKey.ts": [ + { + "rule": "migration-timestamp", + "line": 1, + "message": "1758731786132-AddAudienceColumnToApiKey.ts (1758731786132) is at or below the highest existing migration timestamp (1784000000025). New migrations must be strictly ordered — pick a timestamp greater than 1784000000025.", + "hash": "d52a1dd1e54e" + } + ], + "packages/@n8n/db/src/migrations/common/1760020000000-CreateChatHubAgentTable.ts": [ + { + "rule": "migration-timestamp", + "line": 1, + "message": "1760020000000-CreateChatHubAgentTable.ts (1760020000000) is at or below the highest existing migration timestamp (1784000000025). New migrations must be strictly ordered — pick a timestamp greater than 1784000000025.", + "hash": "f8b39208c141" + } + ], + "packages/@n8n/db/src/migrations/common/1760965142113-DropUnusedChatHubColumns.ts": [ + { + "rule": "migration-timestamp", + "line": 1, + "message": "1760965142113-DropUnusedChatHubColumns.ts (1760965142113) is at or below the highest existing migration timestamp (1784000000025). New migrations must be strictly ordered — pick a timestamp greater than 1784000000025.", + "hash": "55d389c0489c" + } + ], + "packages/@n8n/db/src/migrations/common/1761773155024-AddAttachmentsToChatHubMessages.ts": [ + { + "rule": "migration-timestamp", + "line": 1, + "message": "1761773155024-AddAttachmentsToChatHubMessages.ts (1761773155024) is at or below the highest existing migration timestamp (1784000000025). New migrations must be strictly ordered — pick a timestamp greater than 1784000000025.", + "hash": "5f07b3ecd092" + } + ], + "packages/@n8n/db/src/migrations/common/1761830340990-AddToolsColumnToChatHubTables.ts": [ + { + "rule": "migration-timestamp", + "line": 1, + "message": "1761830340990-AddToolsColumnToChatHubTables.ts (1761830340990) is at or below the highest existing migration timestamp (1784000000025). New migrations must be strictly ordered — pick a timestamp greater than 1784000000025.", + "hash": "77e018405eed" + } + ], + "packages/@n8n/db/src/migrations/common/1762177736257-AddWorkflowDescriptionColumn.ts": [ + { + "rule": "migration-timestamp", + "line": 1, + "message": "1762177736257-AddWorkflowDescriptionColumn.ts (1762177736257) is at or below the highest existing migration timestamp (1784000000025). New migrations must be strictly ordered — pick a timestamp greater than 1784000000025.", + "hash": "f660693c50e8" + } + ], + "packages/@n8n/db/src/migrations/common/1762763704614-BackfillMissingWorkflowHistoryRecords.ts": [ + { + "rule": "migration-timestamp", + "line": 1, + "message": "1762763704614-BackfillMissingWorkflowHistoryRecords.ts (1762763704614) is at or below the highest existing migration timestamp (1784000000025). New migrations must be strictly ordered — pick a timestamp greater than 1784000000025.", + "hash": "9918ff139099" + } + ], + "packages/@n8n/db/src/migrations/common/1762847206508-AddWorkflowHistoryAutoSaveFields.ts": [ + { + "rule": "migration-timestamp", + "line": 1, + "message": "1762847206508-AddWorkflowHistoryAutoSaveFields.ts (1762847206508) is at or below the highest existing migration timestamp (1784000000025). New migrations must be strictly ordered — pick a timestamp greater than 1784000000025.", + "hash": "806cf49b747e" + } + ], + "packages/@n8n/db/src/migrations/common/1763047800000-AddActiveVersionIdColumn.ts": [ + { + "rule": "migration-timestamp", + "line": 1, + "message": "1763047800000-AddActiveVersionIdColumn.ts (1763047800000) is at or below the highest existing migration timestamp (1784000000025). New migrations must be strictly ordered — pick a timestamp greater than 1784000000025.", + "hash": "35d686155538" + } + ], + "packages/@n8n/db/src/migrations/common/1764276827837-AddCreatorIdToProjectTable.ts": [ + { + "rule": "migration-timestamp", + "line": 1, + "message": "1764276827837-AddCreatorIdToProjectTable.ts (1764276827837) is at or below the highest existing migration timestamp (1784000000025). New migrations must be strictly ordered — pick a timestamp greater than 1784000000025.", + "hash": "1ed16ec75965" + } + ], + "packages/@n8n/db/src/migrations/common/1765459448000-AddResolvableFieldsToCredentials.ts": [ + { + "rule": "migration-timestamp", + "line": 1, + "message": "1765459448000-AddResolvableFieldsToCredentials.ts (1765459448000) is at or below the highest existing migration timestamp (1784000000025). New migrations must be strictly ordered — pick a timestamp greater than 1784000000025.", + "hash": "94d3e53d35b4" + } + ], + "packages/@n8n/db/src/migrations/common/1765788427674-AddIconToAgentTable.ts": [ + { + "rule": "migration-timestamp", + "line": 1, + "message": "1765788427674-AddIconToAgentTable.ts (1765788427674) is at or below the highest existing migration timestamp (1784000000025). New migrations must be strictly ordered — pick a timestamp greater than 1784000000025.", + "hash": "8886bd530de2" + } + ], + "packages/@n8n/db/src/migrations/common/1766068346315-AddChatMessageIndices.ts": [ + { + "rule": "migration-timestamp", + "line": 1, + "message": "1766068346315-AddChatMessageIndices.ts (1766068346315) is at or below the highest existing migration timestamp (1784000000025). New migrations must be strictly ordered — pick a timestamp greater than 1784000000025.", + "hash": "dc5d53f65c2a" + } + ], + "packages/@n8n/db/src/migrations/common/1769000000000-AddPublishedVersionIdToWorkflowDependency.ts": [ + { + "rule": "migration-timestamp", + "line": 1, + "message": "1769000000000-AddPublishedVersionIdToWorkflowDependency.ts (1769000000000) is at or below the highest existing migration timestamp (1784000000025). New migrations must be strictly ordered — pick a timestamp greater than 1784000000025.", + "hash": "e6f6c0d42f7f" + } + ], + "packages/@n8n/db/src/migrations/common/1770000000000-CreateChatHubToolsTable.ts": [ + { + "rule": "migration-timestamp", + "line": 1, + "message": "1770000000000-CreateChatHubToolsTable.ts (1770000000000) is at or below the highest existing migration timestamp (1784000000025). New migrations must be strictly ordered — pick a timestamp greater than 1784000000025.", + "hash": "61f4de8f7db3" + } + ], + "packages/@n8n/db/src/migrations/common/1771500000002-AddFilesColumnToChatHubAgents.ts": [ + { + "rule": "migration-timestamp", + "line": 1, + "message": "1771500000002-AddFilesColumnToChatHubAgents.ts (1771500000002) is at or below the highest existing migration timestamp (1784000000025). New migrations must be strictly ordered — pick a timestamp greater than 1784000000025.", + "hash": "5ee6be686a28" + } + ], + "packages/@n8n/db/src/migrations/common/1772000000000-AddSuggestedPromptsToAgentTable.ts": [ + { + "rule": "migration-timestamp", + "line": 1, + "message": "1772000000000-AddSuggestedPromptsToAgentTable.ts (1772000000000) is at or below the highest existing migration timestamp (1784000000025). New migrations must be strictly ordered — pick a timestamp greater than 1784000000025.", + "hash": "48bcd6bfe745" + } + ], + "packages/@n8n/db/src/migrations/common/1772619247761-AddRoleColumnToProjectSecretsProviderAccess.ts": [ + { + "rule": "migration-timestamp", + "line": 1, + "message": "1772619247761-AddRoleColumnToProjectSecretsProviderAccess.ts (1772619247761) is at or below the highest existing migration timestamp (1784000000025). New migrations must be strictly ordered — pick a timestamp greater than 1784000000025.", + "hash": "acc7cac40f87" + } + ], + "packages/@n8n/db/src/migrations/common/1772700000000-AddTypeToChatHubSessions.ts": [ + { + "rule": "migration-timestamp", + "line": 1, + "message": "1772700000000-AddTypeToChatHubSessions.ts (1772700000000) is at or below the highest existing migration timestamp (1784000000025). New migrations must be strictly ordered — pick a timestamp greater than 1784000000025.", + "hash": "0279dc26f034" + } + ], + "packages/@n8n/db/src/migrations/common/1774280963551-AddRestoreFieldsToWorkflowBuilderSession.ts": [ + { + "rule": "migration-timestamp", + "line": 1, + "message": "1774280963551-AddRestoreFieldsToWorkflowBuilderSession.ts (1774280963551) is at or below the highest existing migration timestamp (1784000000025). New migrations must be strictly ordered — pick a timestamp greater than 1784000000025.", + "hash": "5bb3e906cdbb" + } + ], + "packages/@n8n/db/src/migrations/common/1775740765000-ChangeWorkflowPublishHistoryVersionIdToSetNull.ts": [ + { + "rule": "migration-timestamp", + "line": 1, + "message": "1775740765000-ChangeWorkflowPublishHistoryVersionIdToSetNull.ts (1775740765000) is at or below the highest existing migration timestamp (1784000000025). New migrations must be strictly ordered — pick a timestamp greater than 1784000000025.", + "hash": "c7e78794aefa" + } + ], + "packages/@n8n/db/src/migrations/common/1777045000000-AddTracingContextToExecution.ts": [ + { + "rule": "migration-timestamp", + "line": 1, + "message": "1777045000000-AddTracingContextToExecution.ts (1777045000000) is at or below the highest existing migration timestamp (1784000000025). New migrations must be strictly ordered — pick a timestamp greater than 1784000000025.", + "hash": "41a43f631a32" + } + ], + "packages/@n8n/db/src/migrations/common/1777100000000-AddLangsmithIdsToInstanceAiRunSnapshots.ts": [ + { + "rule": "migration-timestamp", + "line": 1, + "message": "1777100000000-AddLangsmithIdsToInstanceAiRunSnapshots.ts (1777100000000) is at or below the highest existing migration timestamp (1784000000025). New migrations must be strictly ordered — pick a timestamp greater than 1784000000025.", + "hash": "b541b874f037" + } + ], + "packages/@n8n/db/src/migrations/common/1778000000000-AddExecutionDeduplicationKey.ts": [ + { + "rule": "migration-timestamp", + "line": 1, + "message": "1778000000000-AddExecutionDeduplicationKey.ts (1778000000000) is at or below the highest existing migration timestamp (1784000000025). New migrations must be strictly ordered — pick a timestamp greater than 1784000000025.", + "hash": "278684d916e8" + } + ], + "packages/@n8n/db/src/migrations/common/1778100002000-AddEvaluationConfigColumnsToTestRun.ts": [ + { + "rule": "migration-timestamp", + "line": 1, + "message": "1778100002000-AddEvaluationConfigColumnsToTestRun.ts (1778100002000) is at or below the highest existing migration timestamp (1784000000025). New migrations must be strictly ordered — pick a timestamp greater than 1784000000025.", + "hash": "f61392909be0" + } + ], + "packages/@n8n/db/src/migrations/common/1778496086558-CreateEvaluationCollection.ts": [ + { + "rule": "migration-timestamp", + "line": 1, + "message": "1778496086558-CreateEvaluationCollection.ts (1778496086558) is at or below the highest existing migration timestamp (1784000000025). New migrations must be strictly ordered — pick a timestamp greater than 1784000000025.", + "hash": "7a5d5dd7ac85" + } + ], + "packages/@n8n/db/src/migrations/common/1784000000002-DropAgentExecutionWorkingMemory.ts": [ + { + "rule": "migration-timestamp", + "line": 1, + "message": "1784000000002-DropAgentExecutionWorkingMemory.ts (1784000000002) is at or below the highest existing migration timestamp (1784000000025). New migrations must be strictly ordered — pick a timestamp greater than 1784000000025.", + "hash": "88c53222237a" + } + ], + "packages/@n8n/db/src/migrations/common/1784000000006-AddNodeGroupsColumnToWorkflowAndHistory.ts": [ + { + "rule": "migration-timestamp", + "line": 1, + "message": "1784000000006-AddNodeGroupsColumnToWorkflowAndHistory.ts (1784000000006) is at or below the highest existing migration timestamp (1784000000025). New migrations must be strictly ordered — pick a timestamp greater than 1784000000025.", + "hash": "e946194f33ec" + } + ], + "packages/@n8n/db/src/migrations/common/1784000000007-CreateInstanceAiCheckpointTable.ts": [ + { + "rule": "migration-timestamp", + "line": 1, + "message": "1784000000007-CreateInstanceAiCheckpointTable.ts (1784000000007) is at or below the highest existing migration timestamp (1784000000025). New migrations must be strictly ordered — pick a timestamp greater than 1784000000025.", + "hash": "e5ea3b8289ec" + } + ], + "packages/@n8n/db/src/migrations/common/1784000000011-CreateAgentHistoryTable.ts": [ + { + "rule": "migration-timestamp", + "line": 1, + "message": "1784000000011-CreateAgentHistoryTable.ts (1784000000011) is at or below the highest existing migration timestamp (1784000000025). New migrations must be strictly ordered — pick a timestamp greater than 1784000000025.", + "hash": "696e69444d0a" + } + ], + "packages/@n8n/db/src/migrations/common/1784000000014-PersistInstanceAiPendingConfirmations.ts": [ + { + "rule": "migration-timestamp", + "line": 1, + "message": "1784000000014-PersistInstanceAiPendingConfirmations.ts (1784000000014) is at or below the highest existing migration timestamp (1784000000025). New migrations must be strictly ordered — pick a timestamp greater than 1784000000025.", + "hash": "bd255e8eeb5b" + } + ], + "packages/@n8n/db/src/migrations/common/1784000000015-AddSourceWorkflowIdToWorkflow.ts": [ + { + "rule": "migration-timestamp", + "line": 1, + "message": "1784000000015-AddSourceWorkflowIdToWorkflow.ts (1784000000015) is at or below the highest existing migration timestamp (1784000000025). New migrations must be strictly ordered — pick a timestamp greater than 1784000000025.", + "hash": "45b35ca6fa25" + } + ], + "packages/@n8n/db/src/migrations/common/1784000000017-AddLastUsedAtToApiKey.ts": [ + { + "rule": "migration-timestamp", + "line": 1, + "message": "1784000000017-AddLastUsedAtToApiKey.ts (1784000000017) is at or below the highest existing migration timestamp (1784000000025). New migrations must be strictly ordered — pick a timestamp greater than 1784000000025.", + "hash": "bc7d45e6e54e" + } + ], + "packages/@n8n/db/src/migrations/common/1784000000018-CreateAgentFilesTable.ts": [ + { + "rule": "migration-timestamp", + "line": 1, + "message": "1784000000018-CreateAgentFilesTable.ts (1784000000018) is at or below the highest existing migration timestamp (1784000000025). New migrations must be strictly ordered — pick a timestamp greater than 1784000000025.", + "hash": "11a6b05559ae" + } + ], + "packages/@n8n/db/src/migrations/common/1784000000019-AddCustomTelemetryTagsToProject.ts": [ + { + "rule": "migration-timestamp", + "line": 1, + "message": "1784000000019-AddCustomTelemetryTagsToProject.ts (1784000000019) is at or below the highest existing migration timestamp (1784000000025). New migrations must be strictly ordered — pick a timestamp greater than 1784000000025.", + "hash": "357263c229a1" + } + ], + "packages/@n8n/db/src/migrations/common/1784000000021-CreateAgentTaskDefinitionTable.ts": [ + { + "rule": "migration-timestamp", + "line": 1, + "message": "1784000000021-CreateAgentTaskDefinitionTable.ts (1784000000021) is at or below the highest existing migration timestamp (1784000000025). New migrations must be strictly ordered — pick a timestamp greater than 1784000000025.", + "hash": "a161a7d7e616" + } + ], + "packages/@n8n/db/src/migrations/common/1784000000022-AddSubAgentLinkageToAgentExecutionThreads.ts": [ + { + "rule": "migration-timestamp", + "line": 1, + "message": "1784000000022-AddSubAgentLinkageToAgentExecutionThreads.ts (1784000000022) is at or below the highest existing migration timestamp (1784000000025). New migrations must be strictly ordered — pick a timestamp greater than 1784000000025.", + "hash": "287b98643496" + } + ], + "packages/@n8n/db/src/migrations/common/1784000000024-AddResourceToOAuthAuthorizationCodes.ts": [ + { + "rule": "migration-timestamp", + "line": 1, + "message": "1784000000024-AddResourceToOAuthAuthorizationCodes.ts (1784000000024) is at or below the highest existing migration timestamp (1784000000025). New migrations must be strictly ordered — pick a timestamp greater than 1784000000025.", + "hash": "f3aa84779924" + } + ], + "packages/@n8n/db/src/migrations/postgresdb/1758794506893-AddProjectIdToVariableTable.ts": [ + { + "rule": "migration-timestamp", + "line": 1, + "message": "1758794506893-AddProjectIdToVariableTable.ts (1758794506893) is at or below the highest existing migration timestamp (1784000000025). New migrations must be strictly ordered — pick a timestamp greater than 1784000000025.", + "hash": "7aebfa806bd9" + } + ], + "packages/@n8n/db/src/migrations/sqlite/1764276827837-AddCreatorIdToProjectTable.ts": [ + { + "rule": "migration-timestamp", + "line": 1, + "message": "1764276827837-AddCreatorIdToProjectTable.ts (1764276827837) is at or below the highest existing migration timestamp (1784000000025). New migrations must be strictly ordered — pick a timestamp greater than 1784000000025.", + "hash": "e50608c0e078" + } + ], + "packages/@n8n/db/src/migrations/sqlite/1764689448000-AddResolvableFieldsToCredentials.ts": [ + { + "rule": "migration-timestamp", + "line": 1, + "message": "1764689448000-AddResolvableFieldsToCredentials.ts (1764689448000) is at or below the highest existing migration timestamp (1784000000025). New migrations must be strictly ordered — pick a timestamp greater than 1784000000025.", + "hash": "ac2493848228" + } + ], "package.json": [ { "rule": "stale-overrides", - "line": 100, + "line": 107, "message": "Override \"@azure/identity\" duplicates a catalog entry for @azure/identity — set the override to \"catalog:\" or remove it", "hash": "ef24d04a4347" }, { "rule": "stale-overrides", - "line": 101, + "line": 108, "message": "Override \"@lezer/common\" duplicates a catalog entry for @lezer/common — set the override to \"catalog:\" or remove it", "hash": "1e5d2fb72ef8" }, { "rule": "stale-overrides", - "line": 104, + "line": 111, "message": "Override \"@types/node\" duplicates a catalog entry for @types/node — set the override to \"catalog:\" or remove it", "hash": "d3577ed2e92d" }, { "rule": "stale-overrides", - "line": 105, + "line": 112, "message": "Override \"chokidar\" duplicates a catalog entry for chokidar — set the override to \"catalog:\" or remove it", "hash": "8496c5755ef0" }, { "rule": "stale-overrides", - "line": 115, + "line": 122, "message": "Override \"vue-tsc\" duplicates a catalog entry for vue-tsc — set the override to \"catalog:frontend\" or remove it", "hash": "5414a6c2842f" }, { "rule": "stale-overrides", - "line": 121, + "line": 128, "message": "Override \"form-data\" duplicates a catalog entry for form-data — set the override to \"catalog:\" or remove it", "hash": "ec13014b18ab" }, { "rule": "stale-overrides", - "line": 123, + "line": 131, "message": "Override \"nodemailer\" duplicates a catalog entry for nodemailer — set the override to \"catalog:\" or remove it", "hash": "1a696378ebfc" }, { "rule": "stale-overrides", - "line": 125, + "line": 133, "message": "Override \"zod\" duplicates a catalog entry for zod — set the override to \"catalog:\" or remove it", "hash": "6224a1e7997d" }, { "rule": "stale-overrides", - "line": 135, + "line": 142, "message": "Override \"@rudderstack/rudder-sdk-node@<=3.0.0\" duplicates a catalog entry for @rudderstack/rudder-sdk-node — set the override to \"catalog:\" or remove it", "hash": "71f703e2c449" }, { "rule": "stale-overrides", - "line": 146, + "line": 153, "message": "Override \"lodash\" duplicates a catalog entry for lodash — set the override to \"catalog:\" or remove it", "hash": "3cbb69cc0ff8" }, { "rule": "stale-overrides", - "line": 155, + "line": 161, "message": "Override \"flatted\" duplicates a catalog entry for flatted — set the override to \"catalog:\" or remove it", "hash": "7fe03ed5fec2" }, { "rule": "stale-overrides", - "line": 164, - "message": "Override \"langsmith\" duplicates a catalog entry for langsmith — set the override to \"catalog:\" or remove it", - "hash": "170e854b445c" - }, - { - "rule": "stale-overrides", - "line": 165, + "line": 170, "message": "Override \"yaml@<=2.8.3\" duplicates a catalog entry for yaml — set the override to \"catalog:\" or remove it", "hash": "a5ab421c217c" }, { "rule": "stale-overrides", - "line": 166, + "line": 171, "message": "Override \"axios\" duplicates a catalog entry for axios — set the override to \"catalog:\" or remove it", "hash": "3bd62181cb8d" }, { "rule": "stale-overrides", - "line": 170, + "line": 175, "message": "Override \"uuid@<=13.0.1\" duplicates a catalog entry for uuid — set the override to \"catalog:\" or remove it", "hash": "abd23b6d69fe" + }, + { + "rule": "stale-overrides", + "line": 184, + "message": "Override \"langsmith\" duplicates a catalog entry for langsmith — set the override to \"catalog:\" or remove it", + "hash": "170e854b445c" } ] } diff --git a/.github/WORKFLOWS.md b/.github/WORKFLOWS.md index 48aa5a9bbcb..57a43315358 100644 --- a/.github/WORKFLOWS.md +++ b/.github/WORKFLOWS.md @@ -181,23 +181,26 @@ These only run if specific files changed: | `packages/@n8n/ai-workflow-builder.ee/evaluations/programmatic/python/**` | `test-evals-python.yml` | any | | `packages/@n8n/benchmark/**` | `build-benchmark-image.yml` | master | | `packages/cli/src/public-api/**/*.{css,yaml,yml}` | `util-sync-api-docs.yml` | master | +| `packages/@n8n/instance-ai/src/**`, `packages/@n8n/instance-ai/evaluations/**`, `packages/cli/src/modules/instance-ai/**`, `packages/core/src/execution-engine/eval-mock-helpers.ts` | `ci-instance-ai-evals.yml` | on PR `opened` / `reopened` / `ready_for_review` | ### On PR Review | Event | Workflow | Condition | |----------------------------|-----------------------------|------------------------------------------------------| | Review approved | `test-visual-chromatic.yml` | + design files changed | -| Review approved | `ci-instance-ai-evals.yml` | + Instance AI source/eval paths changed (see below) | | Comment with `@claude` | `util-claude.yml` | mention in any comment | | Any review | `util-notify-pr-status.yml` | not community-labeled | -**Why Instance AI evals fire on approval, not push:** the workflow eval is the most -expensive job in PR CI (LLM-bound builds against ~70 unique scenarios). Running it -on every push made cost untenable. With approval-only triggering, the eval acts as -a merge gate — fires when the reviewer approves; if it fails, branch protection blocks -the merge. `dismiss_stale_reviews_on_push: true` on master forces re-approval (and a -fresh eval) if the author pushes between approval and merge, so the gate stays honest. -The lighter `test-evals-discovery.yml` still runs on every push as part of ci-pull-requests.yml. +**Why Instance AI evals fire once per PR state-change, not per push:** the +workflow eval is the most expensive job in PR CI (LLM-bound builds). Running it +on every push made cost untenable; firing on every review approval cascaded +through the dismiss-stale-on-push → re-approve loop, which also blew up. +The current trigger fires once per `opened` / `reopened` / `ready_for_review` +on a PR touching the eval surface, and runs the `pr` test-case dataset (~6 +high-reliability, capability-diverse cases) instead of the full ~14. To re-run +after pushing a fix, use the workflow's manual dispatch button — also lets you +override `tier` to `full` for broader coverage on a specific PR. The lighter +`test-evals-discovery.yml` still runs on every push as part of `ci-pull-requests.yml`. ### On PR Close/Merge @@ -362,8 +365,8 @@ Runs on push to `master` or `1.x`: ``` Push to master/1.x ├─ build-github (populate cache) -├─ unit-test (matrix: Node 22.x, 24.15.0, 26.x) -│ └─ Coverage only on 24.15.0 +├─ unit-test (matrix: Node 22.x, 24.16.0, 26.x) +│ └─ Coverage only on 24.16.0 ├─ lint └─ notify-on-failure (Slack #alerts-build) ``` @@ -403,7 +406,7 @@ Composite actions in `.github/actions/`: ```yaml inputs: - node-version: # default: '24.15.0' + node-version: # default: '24.16.0' enable-docker-cache: # default: 'false' (Blacksmith Buildx) build-command: # default: 'pnpm build' ``` @@ -506,7 +509,7 @@ Team ownership mappings in `CODEOWNERS`: | `blacksmith-2vcpu-ubuntu-2204` | 2 | Standard builds, E2E shards | | `blacksmith-4vcpu-ubuntu-2204` | 4 | Unit tests, typecheck, lint | | `blacksmith-8vcpu-ubuntu-2204` | 8 | Heavy parallel workloads | -| `blacksmith-4vcpu-ubuntu-2204-arm` | 4 | ARM64 Docker builds | +| `blacksmith-8vcpu-ubuntu-2204-arm` | 8 | ARM64 Docker builds | ### Selection Guidelines @@ -574,7 +577,7 @@ Supply chain security ensures artifacts haven't been tampered with. We provide t - **Runs on:** stable/nightly/rc Docker builds - **Scans:** n8n image, runners image -- **Output:** Slack `#updates-security` when vulnerabilities are detected +- **Output:** GitHub Actions step summary (`$GITHUB_STEP_SUMMARY`) and run logs ### SBOM diff --git a/.github/actionlint.yml b/.github/actionlint.yml index 6c682e673e4..1a9d09e67cb 100644 --- a/.github/actionlint.yml +++ b/.github/actionlint.yml @@ -3,6 +3,6 @@ self-hosted-runner: - blacksmith-2vcpu-ubuntu-2204 - blacksmith-4vcpu-ubuntu-2204 - blacksmith-2vcpu-ubuntu-2204-arm - - blacksmith-4vcpu-ubuntu-2204-arm - blacksmith-8vcpu-ubuntu-2204 + - blacksmith-8vcpu-ubuntu-2204-arm - ubuntu-slim diff --git a/.github/actions/ci-filter/__tests__/ci-filter.test.ts b/.github/actions/ci-filter/__tests__/ci-filter.test.ts index a2845f9373f..2fde3d0599a 100644 --- a/.github/actions/ci-filter/__tests__/ci-filter.test.ts +++ b/.github/actions/ci-filter/__tests__/ci-filter.test.ts @@ -4,7 +4,14 @@ import { execFileSync } from 'node:child_process'; import { mkdtempSync, rmSync, writeFileSync } from 'node:fs'; import { tmpdir } from 'node:os'; import { join } from 'node:path'; -import { matchGlob, parseFilters, evaluateFilter, runValidate, getChangedFiles, getMergeBase } from '../ci-filter.mjs'; +import { + matchGlob, + parseFilters, + evaluateFilter, + runValidate, + getChangedFiles, + getMergeBase, +} from '../ci-filter.mjs'; // --- matchGlob --- @@ -43,7 +50,9 @@ describe('matchGlob', () => { }); it('scoped package pattern does not match other packages', () => { - assert.ok(!matchGlob('packages/@n8n/config/src/index.ts', 'packages/@n8n/task-runner-python/**')); + assert.ok( + !matchGlob('packages/@n8n/config/src/index.ts', 'packages/@n8n/task-runner-python/**'), + ); }); it('* matches single-level only', () => { @@ -147,10 +156,7 @@ describe('evaluateFilter', () => { }); it('mixed python and non-python returns true', () => { - const files = [ - 'packages/@n8n/task-runner-python/src/main.py', - 'packages/cli/src/index.ts', - ]; + const files = ['packages/@n8n/task-runner-python/src/main.py', 'packages/cli/src/index.ts']; const patterns = ['**', '!packages/@n8n/task-runner-python/**']; assert.equal(evaluateFilter(files, patterns), true); }); @@ -186,7 +192,11 @@ describe('evaluateFilter', () => { it('last matching pattern wins (gitignore semantics)', () => { const files = ['packages/@n8n/task-runner-python/src/main.py']; - const patterns = ['**', '!packages/@n8n/task-runner-python/**', 'packages/@n8n/task-runner-python/**']; + const patterns = [ + '**', + '!packages/@n8n/task-runner-python/**', + 'packages/@n8n/task-runner-python/**', + ]; assert.equal(evaluateFilter(files, patterns), true); }); }); @@ -321,6 +331,113 @@ describe('getChangedFiles', () => { }); }); +// --- getChangedFiles deep merge-base (shallow clone, stale base) --- + +describe('getChangedFiles (shallow clone, stale base)', () => { + const builderDir = mkdtempSync(join(tmpdir(), 'ci-filter-build-')); + const remoteDir = mkdtempSync(join(tmpdir(), 'ci-filter-remote-shallow-')); + const repoDir = mkdtempSync(join(tmpdir(), 'ci-filter-shallow-')); + const originalCwd = process.cwd(); + const originalStep = process.env.CI_FILTER_DEEPEN_STEP; + const git = (args: string[], cwd: string) => + execFileSync('git', args, { cwd, stdio: 'pipe' }).toString().trim(); + + before(() => { + execFileSync('git', ['init', '--bare', '-b', 'main', remoteDir], { stdio: 'pipe' }); + git(['init', '-b', 'main'], builderDir); + git(['config', 'user.email', 'test@test.local'], builderDir); + git(['config', 'user.name', 'test'], builderDir); + git(['remote', 'add', 'origin', remoteDir], builderDir); + + // Common ancestor (the merge base the PR diverged from) + writeFileSync(join(builderDir, 'shared.ts'), 'shared\n'); + git(['add', '.'], builderDir); + git(['commit', '-m', 'root'], builderDir); + git(['push', 'origin', 'main'], builderDir); + + // PR branch off root, adds a file + git(['checkout', '-b', 'pr-branch'], builderDir); + writeFileSync(join(builderDir, 'pr-only.ts'), 'pr\n'); + git(['add', '.'], builderDir); + git(['commit', '-m', 'PR change'], builderDir); + git(['push', 'origin', 'pr-branch'], builderDir); + + // master drifts forward, burying the merge base behind several commits + git(['checkout', 'main'], builderDir); + for (let i = 1; i <= 6; i++) { + writeFileSync(join(builderDir, 'shared.ts'), `shared\ndrift ${i}\n`); + git(['commit', '-am', `drift ${i}`], builderDir); + } + git(['push', 'origin', 'main'], builderDir); + + // Shallow checkout of the PR side, mirroring CI's depth-1 clone + git(['clone', '--depth=1', '--branch', 'pr-branch', `file://${remoteDir}`, repoDir], originalCwd); + git(['config', 'user.email', 'test@test.local'], repoDir); + git(['config', 'user.name', 'test'], repoDir); + // Tiny step so the deepen loop has to iterate to reach the merge base + process.env.CI_FILTER_DEEPEN_STEP = '1'; + process.chdir(repoDir); + }); + + after(() => { + process.chdir(originalCwd); + if (originalStep === undefined) delete process.env.CI_FILTER_DEEPEN_STEP; + else process.env.CI_FILTER_DEEPEN_STEP = originalStep; + rmSync(builderDir, { recursive: true, force: true }); + rmSync(remoteDir, { recursive: true, force: true }); + rmSync(repoDir, { recursive: true, force: true }); + }); + + it('resolves PR-only files when the merge base is beyond the shallow boundary', () => { + assert.equal(git(['rev-parse', '--is-shallow-repository'], repoDir), 'true'); + const changed = getChangedFiles('main'); + assert.deepEqual(changed, ['pr-only.ts']); + }); +}); + +// --- getChangedFiles unrelated histories --- + +describe('getChangedFiles (unrelated histories)', () => { + const remoteDir = mkdtempSync(join(tmpdir(), 'ci-filter-remote-unrelated-')); + const repoDir = mkdtempSync(join(tmpdir(), 'ci-filter-unrelated-')); + const originalCwd = process.cwd(); + const git = (args: string[], cwd: string = repoDir) => + execFileSync('git', args, { cwd, stdio: 'pipe' }).toString().trim(); + + before(() => { + execFileSync('git', ['init', '--bare', '-b', 'main', remoteDir], { stdio: 'pipe' }); + git(['init', '-b', 'main'], repoDir); + git(['config', 'user.email', 'test@test.local']); + git(['config', 'user.name', 'test']); + git(['remote', 'add', 'origin', remoteDir]); + + // Remote main has its own root + writeFileSync(join(repoDir, 'main.ts'), 'main\n'); + git(['add', '.']); + git(['commit', '-m', 'main root']); + git(['push', 'origin', 'main']); + + // Local HEAD is an orphan branch sharing no ancestor with main + git(['checkout', '--orphan', 'feature']); + git(['rm', '-q', '-rf', '.']); + writeFileSync(join(repoDir, 'feature.ts'), 'feature\n'); + git(['add', '.']); + git(['commit', '-m', 'feature root']); + + process.chdir(repoDir); + }); + + after(() => { + process.chdir(originalCwd); + rmSync(remoteDir, { recursive: true, force: true }); + rmSync(repoDir, { recursive: true, force: true }); + }); + + it('throws once history is exhausted with no common ancestor', () => { + assert.throws(() => getChangedFiles('main'), /unrelated histories/); + }); +}); + // --- runValidate --- describe('runValidate', () => { @@ -330,7 +447,9 @@ describe('runValidate', () => { let exitCode: number | null = null; process.env.INPUT_JOB_RESULTS = JSON.stringify(jobResults); - process.exit = ((code: number) => { exitCode = code; }) as never; + process.exit = ((code: number) => { + exitCode = code; + }) as never; try { runValidate(); @@ -343,42 +462,57 @@ describe('runValidate', () => { } it('passes when all jobs succeed', () => { - assert.equal(runWithResults({ - 'install-and-build': { result: 'success' }, - 'unit-test': { result: 'success' }, - typecheck: { result: 'success' }, - lint: { result: 'success' }, - }), null); + assert.equal( + runWithResults({ + 'install-and-build': { result: 'success' }, + 'unit-test': { result: 'success' }, + typecheck: { result: 'success' }, + lint: { result: 'success' }, + }), + null, + ); }); it('passes when some jobs are skipped (filtered out)', () => { - assert.equal(runWithResults({ - 'install-and-build': { result: 'success' }, - 'unit-test': { result: 'success' }, - 'security-checks': { result: 'skipped' }, - }), null); + assert.equal( + runWithResults({ + 'install-and-build': { result: 'success' }, + 'unit-test': { result: 'success' }, + 'security-checks': { result: 'skipped' }, + }), + null, + ); }); it('fails when a job fails', () => { - assert.equal(runWithResults({ - 'install-and-build': { result: 'success' }, - 'unit-test': { result: 'failure' }, - typecheck: { result: 'success' }, - }), 1); + assert.equal( + runWithResults({ + 'install-and-build': { result: 'success' }, + 'unit-test': { result: 'failure' }, + typecheck: { result: 'success' }, + }), + 1, + ); }); it('fails when a job is cancelled', () => { - assert.equal(runWithResults({ - 'install-and-build': { result: 'success' }, - 'unit-test': { result: 'cancelled' }, - }), 1); + assert.equal( + runWithResults({ + 'install-and-build': { result: 'success' }, + 'unit-test': { result: 'cancelled' }, + }), + 1, + ); }); it('fails when multiple jobs have problems', () => { - assert.equal(runWithResults({ - 'unit-test': { result: 'failure' }, - typecheck: { result: 'cancelled' }, - lint: { result: 'success' }, - }), 1); + assert.equal( + runWithResults({ + 'unit-test': { result: 'failure' }, + typecheck: { result: 'cancelled' }, + lint: { result: 'success' }, + }), + 1, + ); }); }); diff --git a/.github/actions/ci-filter/ci-filter.mjs b/.github/actions/ci-filter/ci-filter.mjs index 1f9a20e034d..9bc52469c98 100644 --- a/.github/actions/ci-filter/ci-filter.mjs +++ b/.github/actions/ci-filter/ci-filter.mjs @@ -1,5 +1,5 @@ import { execSync } from 'node:child_process'; -import { appendFileSync } from 'node:fs'; +import { appendFileSync, readFileSync } from 'node:fs'; import { fileURLToPath } from 'node:url'; import { resolve } from 'node:path'; @@ -104,7 +104,7 @@ export function getChangedFiles(baseRef) { // direction, so files added to base-branch after the PR diverged show up as // "changed" — spuriously triggering path-filtered jobs. The merge base // scopes the diff to PR-only changes. - execSync(`git fetch --no-tags --prune --deepen=200 origin ${baseRef}`, { stdio: 'pipe' }); + fetchUntilMergeBase(baseRef); const output = execSync('git diff --name-only --merge-base FETCH_HEAD HEAD', { encoding: 'utf-8', }); @@ -114,6 +114,71 @@ export function getChangedFiles(baseRef) { .filter(Boolean); } +/** + * Deepen the shallow clone until the merge base between the fetched base ref + * (FETCH_HEAD) and HEAD is reliably reachable. + * + * A single fixed deepen is not enough for stale PRs whose divergence point is + * older than the shallow boundary. We fetch with an exponentially growing + * window (doubling each round) until the merge base resolves, or until the full + * history has been fetched — at which point no common ancestor means the + * histories are unrelated. + */ +function fetchUntilMergeBase(baseRef) { + let step = Number(process.env.CI_FILTER_DEEPEN_STEP) || 200; + execSync(`git fetch --no-tags --prune --deepen=${step} origin ${baseRef}`, { stdio: 'pipe' }); + + while (!hasReliableMergeBase()) { + if (!isShallow()) { + throw new Error( + `No merge base between FETCH_HEAD and HEAD after fetching the full history of "${baseRef}" (unrelated histories).`, + ); + } + step *= 2; + execSync(`git fetch --no-tags --prune --deepen=${step} origin ${baseRef}`, { stdio: 'pipe' }); + } +} + +function isShallow() { + return ( + execSync('git rev-parse --is-shallow-repository', { encoding: 'utf-8' }).trim() === 'true' + ); +} + +/** + * True when a merge base exists AND does not sit on the shallow boundary. + * In a shallow repo `git merge-base` can return a grafted boundary commit whose + * sub-history is truncated; that result is unreliable, so we must deepen further + * before trusting it. + */ +function hasReliableMergeBase() { + let base; + try { + base = execSync('git merge-base FETCH_HEAD HEAD', { encoding: 'utf-8' }).trim(); + } catch { + return false; // no common ancestor reachable yet + } + if (!base) return false; + return !readShallowBoundaries().has(base); +} + +function readShallowBoundaries() { + try { + const shallowPath = execSync('git rev-parse --git-path shallow', { + encoding: 'utf-8', + }).trim(); + const content = readFileSync(shallowPath, 'utf-8'); + return new Set( + content + .split('\n') + .map((l) => l.trim()) + .filter(Boolean), + ); + } catch { + return new Set(); // no shallow file => complete repo + } +} + /** * Resolve the merge-base SHA between FETCH_HEAD and HEAD. * Used to give downstream tools (e.g. janitor's AST diff) a stable, PR-only diff --git a/.github/actions/setup-nodejs/action.yml b/.github/actions/setup-nodejs/action.yml index 6bc7f3cc9ea..b4e3d3d6192 100644 --- a/.github/actions/setup-nodejs/action.yml +++ b/.github/actions/setup-nodejs/action.yml @@ -7,9 +7,9 @@ description: 'Configures Node.js with pnpm, installs Aikido SafeChain for supply inputs: node-version: - description: 'Node.js version to use. Pinned to 24.15.0 by default for reproducible builds.' + description: 'Node.js version to use. Pinned to 24.16.0 by default for reproducible builds.' required: false - default: '24.15.0' + default: '24.16.0' enable-docker-cache: description: 'Whether to set up Blacksmith Buildx for Docker layer caching (Blacksmith runners only).' required: false @@ -95,7 +95,7 @@ runs: # docker-cluster, unit, lint, typecheck, ...) hit the cache instead of # the GH release CDN. Layered with retry below — cache reduces blast # radius across jobs, retry covers the first-job-per-key case where the - # CDN must be hit. Keep the version in sync with the install step below. + # CDN must be hit. Keep the version in sync with the download step below. - name: Restore Aikido SafeChain Binary id: cache-safe-chain uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 @@ -103,7 +103,12 @@ runs: path: ~/.safe-chain/bin key: safe-chain-1.5.7-${{ runner.os }}-${{ runner.arch }} - - name: Install Aikido SafeChain + # Download + install the SafeChain binary. This is the expensive, + # CDN-backed part and the only part worth gating on the cache. The install + # script also runs `setup-ci`, so on a cache miss this both downloads AND + # activates; the Activate step below then re-runs `setup-ci` idempotently. + - name: Download Aikido SafeChain + if: steps.cache-safe-chain.outputs.cache-hit != 'true' run: | VERSION="1.5.7" EXPECTED_SHA256="07ab512fd8795ce41b2275be369aced4c9a93cc7bca9b397951507891a955239" @@ -112,48 +117,142 @@ runs: echo "${EXPECTED_SHA256} install-safe-chain.sh" | sha256sum -c - # Wrap the install in retry too — it internally fetches the # safe-chain binary from the GH release CDN, which has hit - # transient 404s. The install script no-ops the binary download - # when the cached binary is already present. + # transient 404s. node .github/scripts/retry.mjs --attempts 3 --delay 10 -- \ sh install-safe-chain.sh --ci rm install-safe-chain.sh shell: bash - # Capture pnpm's combined stdout+stderr through `tee` so the ERR_PNPM_* code - # and offending package survive even when `timeout` terminates the process - # group. Stderr-only capture misses the failure footer because pnpm's - # default reporter routes it through stdout; `--reporter=append-only` is - # set explicitly so we don't drift if pnpm changes its CI default again. - # `--loglevel=debug` and `DEBUG=pnpm:*` add registry/store/fetch traces. + # ALWAYS runs, even on a cache hit. `setup-ci` installs SafeChain's + # executable shims and exposes them to subsequent steps via $GITHUB_PATH. + # That PATH wiring is per-job runtime state — it is NOT captured by the + # binary cache above. On a cache hit the download step is skipped, so this + # is the only thing that puts SafeChain on PATH for the install/build steps; + # without it the package managers run unwrapped and protection is inert. + # Runs the cached binary directly to avoid a redundant CDN round-trip. + - name: Activate Aikido SafeChain + run: | + "$HOME/.safe-chain/bin/safe-chain" setup-ci + shell: bash + + # Fail fast if activation did not take effect, mirroring the Node/pnpm + # verify guards above. We use SafeChain's own `safe-chain-verify` command, + # which runs *through* the wrapped package manager and prints + # "OK: Safe-chain works!" only when the shim is active. + # Kept as a step after Activate: `setup-ci` exposes the shims via + # $GITHUB_PATH, which only reaches PATH between steps. + - name: Verify SafeChain is active + shell: bash + run: node .github/scripts/verify-safechain.mjs + + # `--loglevel` CLI flag does NOT override `.npmrc` for that path, but + # `--config.loglevel` does — so the failing script's real output reaches us. + # (Confirmed on CI across Blacksmith + GitHub-hosted, through the SafeChain + # shim and the real pnpm binary) + # + # Layered so the cause survives even failure modes pnpm can't report itself: + # 1. `--config.loglevel=info` un-suppresses lifecycle output (the actual fix). + # `--reporter=append-only` is pinned so we don't drift if pnpm changes its + # CI default; combined stdout+stderr is streamed live AND persisted to + # `$INSTALL_LOG` via `tee`; `${PIPESTATUS[0]}` preserves pnpm's exit code. + # 2. `--config.logs-dir` routes pnpm's own `ERR_PNPM_*` diagnostic logs into + # a dir we always collect. + # 3. On failure we dump an environment snapshot written by *this* shell — + # node/pnpm versions, the resolved pnpm binary, SafeChain wiring, free + # memory, disk, and kernel OOM lines — so OOM / wrong-binary deaths that + # produce no pnpm output at all are still diagnosable. + # 4. Everything is uploaded as an artifact by the next step, so the full log + # survives even when the live console stream is truncated by the runner. + # # `SAFE_CHAIN_LOGGING=verbose` surfaces safe-chain's proxy decisions, which # are otherwise buffered (and lost on failure) while pnpm is in flight. - # `${PIPESTATUS[0]}` preserves pnpm's real exit code through the pipe. - name: Install Dependencies if: ${{ inputs.install-command != '' }} + id: install-deps env: INSTALL_COMMAND: ${{ inputs.install-command }} INSTALL_LOG: ${{ runner.temp }}/pnpm-install.log + PNPM_DIAG_DIR: ${{ runner.temp }}/pnpm-diagnostics SAFE_CHAIN_LOGGING: verbose - DEBUG: pnpm:* + GITHUB_TOKEN: ${{ github.token }} run: | + # Stable, artifact-name-safe id for the upload step (written first so it + # exists even if the install dies immediately). + DIAG_ID="$(printf '%s' "${GITHUB_JOB}-${RUNNER_NAME}-${GITHUB_RUN_ATTEMPT}-${RANDOM}" | tr -c 'A-Za-z0-9._-' '-')" + echo "diag-id=$DIAG_ID" >> "$GITHUB_OUTPUT" + mkdir -p "$PNPM_DIAG_DIR/pnpm-logs" + set +o pipefail timeout --kill-after=30s 300s $INSTALL_COMMAND \ - --reporter=append-only --loglevel=debug 2>&1 | tee "$INSTALL_LOG" + --config.logs-dir="$PNPM_DIAG_DIR/pnpm-logs" \ + --reporter=append-only --config.loglevel=info 2>&1 | tee "$INSTALL_LOG" rc=${PIPESTATUS[0]} set -o pipefail - if [ $rc -ne 0 ]; then - echo "::group::pnpm install full output (captured)" - cat "$INSTALL_LOG" 2>/dev/null || echo "(no captured log)" + + if [ "$rc" -ne 0 ]; then + # Self-emitted environment snapshot — cannot be swallowed by pnpm. + { + echo "exit_code=$rc" + echo "date=$(date -u +%FT%TZ)" + echo "install_command=$INSTALL_COMMAND" + echo "node=$(node --version 2>&1)" + echo "pnpm=$(pnpm --version 2>&1)" + echo "pnpm_resolved=$(command -v pnpm 2>&1) -> $(readlink -f "$(command -v pnpm 2>/dev/null)" 2>&1)" + echo "pnpm_on_path=$(which -a pnpm 2>&1 | tr '\n' ' ')" + echo "safe_chain_bin=$(ls -la "$HOME/.safe-chain/bin" 2>&1 | tr '\n' ' ')" + echo "mem_mb=$(free -m 2>/dev/null | tr '\n' ' ' || echo 'free unavailable')" + echo "disk=$(df -h "$PWD" 2>/dev/null | tail -1)" + echo "oom=$(dmesg 2>/dev/null | grep -iE 'killed process|out of memory' | tail -5 || true)" + } > "$PNPM_DIAG_DIR/environment.txt" 2>&1 + cp "$INSTALL_LOG" "$PNPM_DIAG_DIR/" 2>/dev/null || true + + echo "::error::pnpm install failed (exit $rc). Full output + diagnostics below; also uploaded as artifact 'pnpm-install-logs-${DIAG_ID}'." + echo "::group::Environment diagnostics" + cat "$PNPM_DIAG_DIR/environment.txt" echo "::endgroup::" - case $rc in + echo "::group::pnpm install combined output ($INSTALL_LOG)" + cat "$INSTALL_LOG" 2>/dev/null || echo "(combined log empty — pnpm produced no capturable output; see environment diagnostics and the uploaded artifact)" + echo "::endgroup::" + echo "::group::pnpm diagnostic logs ($PNPM_DIAG_DIR/pnpm-logs)" + find "$PNPM_DIAG_DIR/pnpm-logs" -type f -exec sh -c 'echo "----- $1 -----"; cat "$1"' _ {} \; 2>/dev/null || echo "(none)" + echo "::endgroup::" + case "$rc" in 124) echo "::error::pnpm install timed out after 300s (exit 124)" ;; 137) echo "::error::pnpm install received SIGKILL (exit 137 — likely OOM or kill-after timeout)" ;; esac fi - exit $rc + exit "$rc" shell: bash + # Persist the full combined log + diagnostics so the real cause survives even + # when the runner truncates the live console stream. Scoped to the install + # step's own failure so unrelated step failures don't trigger an empty upload. + - name: Upload pnpm install diagnostics + if: ${{ failure() && steps.install-deps.outcome == 'failure' }} + uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 + with: + name: pnpm-install-logs-${{ steps.install-deps.outputs.diag-id }} + path: | + ${{ runner.temp }}/pnpm-install.log + ${{ runner.temp }}/pnpm-diagnostics/** + if-no-files-found: ignore + retention-days: 7 + + # When setup-nodejs is nested inside another setup-nodejs invocation + # (e.g. load-n8n-docker's rebuild fallback → build-n8n-docker), a turbo + # cache server is already running and its TURBO_API env is already + # exported, so the nested builds can just use it. Starting a second + # server overwrites TURBOGHA_PORT, which both post-runs then read: the + # first post shuts the second server down, and the other post fails the + # job with a bare `fetch failed` — and the first server's caches are + # never saved. + - name: Check for running Turborepo cache server + id: turbo-server + shell: bash + run: echo "running=${TURBOGHA_PORT:+true}" >> "$GITHUB_OUTPUT" + - name: Configure Turborepo Cache + if: steps.turbo-server.outputs.running != 'true' uses: rharkor/caching-for-turbo@5d14fba18e450c09393333cfd4242e8b3cb455a6 # v2.4.2 with: server-port: 0 diff --git a/.github/actions/setup-nodejs/safe-chain.config.json b/.github/actions/setup-nodejs/safe-chain.config.json index 42bda807904..b5799a3681f 100644 --- a/.github/actions/setup-nodejs/safe-chain.config.json +++ b/.github/actions/setup-nodejs/safe-chain.config.json @@ -3,6 +3,7 @@ "minimumPackageAgeExclusions": [ "@n8n/*", "@n8n_io/*", + "eslint-plugin-n8n-nodes-base", "n8n", "n8n-containers", "n8n-core", diff --git a/.github/scripts/attest-image-sbom.mjs b/.github/scripts/attest-image-sbom.mjs new file mode 100644 index 00000000000..186b741e8e8 --- /dev/null +++ b/.github/scripts/attest-image-sbom.mjs @@ -0,0 +1,89 @@ +#!/usr/bin/env node +/** + * Per-image SBOM attestation for the release Docker images. For each built image: + * cdxgen scans it (OS + npm), enrich-sbom resolves licenses, check-sbom-licenses + * gates the npm components, and the result is attested to the image digest via + * cosign — the same mechanism as the VEX/provenance attestations. + * + * Image refs + digests come from the environment (set by docker-build-push.yml). + * An image with no digest (not built for this release type) is skipped. + * + * Usage: node .github/scripts/attest-image-sbom.mjs (run from the repo root) + */ +import { execFileSync } from 'node:child_process'; +import path from 'node:path'; +import { fileURLToPath, pathToFileURL } from 'node:url'; + +const scriptDir = path.dirname(fileURLToPath(import.meta.url)); +const REPO_ROOT = path.resolve(scriptDir, '..', '..'); +const CDXGEN = path.join(scriptDir, 'node_modules', '.bin', 'cdxgen'); +const ENRICH = path.join(REPO_ROOT, 'scripts', 'licenses', 'enrich-sbom.mjs'); +const CHECK = path.join(REPO_ROOT, 'scripts', 'licenses', 'check-sbom-licenses.mjs'); +const ALLOW_REFS = [ + '--allow-ref=LicenseRef-n8n-sustainable-use', + '--allow-ref=LicenseRef-n8n-enterprise', +]; + +export function parseTargets(env) { + return [ + { label: 'n8n', image: env.N8N_IMAGE, digest: env.N8N_DIGEST }, + { label: 'runners', image: env.RUNNERS_IMAGE, digest: env.RUNNERS_DIGEST }, + { label: 'runners-distroless', image: env.DISTROLESS_IMAGE, digest: env.DISTROLESS_DIGEST }, + ].filter((t) => t.image && t.digest); +} + +function run(cmd, args, extraEnv) { + execFileSync(cmd, args, { + stdio: 'inherit', + env: extraEnv ? { ...process.env, ...extraEnv } : process.env, + }); +} + +function attest({ label, image, digest }) { + const ref = `${image}@${digest}`; + const out = path.join(REPO_ROOT, `sbom-${label}.cdx.json`); + console.log(`::group::SBOM for ${label} (${ref})`); + + // Pull the (host-arch) image and scan its filesystem: OS packages + npm. + run('docker', ['pull', ref]); + // FETCH_LICENSE=true would make cdxgen call the npm registry for every package + // to resolve missing license data. In practice it resolves nothing — packages + // without a license field in their tarball also have no license in the registry — + // and adds hundreds of sequential HTTP requests. License gaps are covered by + // enrich-sbom.mjs (license-overrides.json + first-party detection) below. + run( + CDXGEN, + ['-t', 'docker', '--no-install-deps', '--profile', 'license-compliance', '--spec-version', '1.6', '-o', out, ref], + { CDXGEN_NO_BANNER: '1' }, + ); + + // Resolve first-party + override licenses (lenient: this image holds only a + // subset of the npm closure, so absent overrides are not stale pins) and drop + // cdxgen filesystem-scan phantoms. + run(process.execPath, [ENRICH, out, '--lenient-config', '--drop-phantom-npm']); + + // Release-blocking gate, scoped to npm — OS packages carry upstream-distro + // license strings we don't control, so they're inventoried but not gated. + run(process.execPath, [CHECK, out, ...ALLOW_REFS, '--enforce-prefix=pkg:npm/']); + + run('cosign', ['attest', '--yes', '--type', 'cyclonedx', '--predicate', out, ref]); + console.log('::endgroup::'); +} + +function main() { + const targets = parseTargets(process.env); + if (targets.length === 0) { + console.log('No images with digests to attest — skipping.'); + return; + } + for (const target of targets) attest(target); +} + +if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) { + try { + main(); + } catch (err) { + console.error(err.message); + process.exit(1); + } +} diff --git a/.github/scripts/attest-image-sbom.test.mjs b/.github/scripts/attest-image-sbom.test.mjs new file mode 100644 index 00000000000..efae33bc2f1 --- /dev/null +++ b/.github/scripts/attest-image-sbom.test.mjs @@ -0,0 +1,37 @@ +import { describe, it } from 'node:test'; +import assert from 'node:assert/strict'; +import { parseTargets } from './attest-image-sbom.mjs'; + +describe('parseTargets', () => { + it('builds a target per image when both ref and digest are present', () => { + const targets = parseTargets({ + N8N_IMAGE: 'ghcr.io/n8n-io/n8n', + N8N_DIGEST: 'sha256:aaa', + RUNNERS_IMAGE: 'ghcr.io/n8n-io/runners', + RUNNERS_DIGEST: 'sha256:bbb', + DISTROLESS_IMAGE: 'ghcr.io/n8n-io/runners', + DISTROLESS_DIGEST: 'sha256:ccc', + }); + assert.deepEqual( + targets.map((t) => t.label), + ['n8n', 'runners', 'runners-distroless'], + ); + }); + + it('skips an image with no digest (not built for this release type)', () => { + const targets = parseTargets({ + N8N_IMAGE: 'ghcr.io/n8n-io/n8n', + N8N_DIGEST: 'sha256:aaa', + RUNNERS_IMAGE: 'ghcr.io/n8n-io/runners', + RUNNERS_DIGEST: '', + }); + assert.deepEqual( + targets.map((t) => t.label), + ['n8n'], + ); + }); + + it('returns nothing when no digests are present', () => { + assert.deepEqual(parseTargets({}), []); + }); +}); diff --git a/.github/scripts/bump-versions.mjs b/.github/scripts/bump-versions.mjs index 31694d460af..09dcf499015 100644 --- a/.github/scripts/bump-versions.mjs +++ b/.github/scripts/bump-versions.mjs @@ -260,6 +260,8 @@ async function bumpVersions() { propagateDirtyTransitively(packageMap, depsByPackage); + // Always mark the `cli` package as dirty, so it's version always gets incremented + packageMap["n8n"].isDirty = true; // Keep the monorepo version up to date with the released version packageMap['monorepo-root'].version = packageMap['n8n'].version; diff --git a/.github/scripts/determine-release-candidate-branch-for-track.mjs b/.github/scripts/determine-release-candidate-branch-for-track.mjs index 4924b2d8297..08d201eea82 100644 --- a/.github/scripts/determine-release-candidate-branch-for-track.mjs +++ b/.github/scripts/determine-release-candidate-branch-for-track.mjs @@ -29,9 +29,14 @@ function main() { .filter((commit) => commit.trim().length > 0); const actionableCommitList = filterActionableCommits(commitList); + // `force` lets a dispatch create the PR even without actionable commits, + // but never when there are literally no commits between versions. + const force = process.env.FORCE === 'true'; + const shouldCreatePr = commitList.length > 0 && (actionableCommitList.length > 0 || force); + const output = { release_candidate_branch: releaseCandidateBranch, - should_update: actionableCommitList.length > 0 ? 'true' : 'false', + should_create_pr: shouldCreatePr ? 'true' : 'false', }; console.log(output); diff --git a/.github/scripts/docker/docker-config.mjs b/.github/scripts/docker/docker-config.mjs index 972631c9e5f..5e370c5e1b8 100644 --- a/.github/scripts/docker/docker-config.mjs +++ b/.github/scripts/docker/docker-config.mjs @@ -88,7 +88,7 @@ class BuildContext { buildMatrix(platforms) { const runners = { 'linux/amd64': 'blacksmith-4vcpu-ubuntu-2204', - 'linux/arm64': 'blacksmith-4vcpu-ubuntu-2204-arm', + 'linux/arm64': 'blacksmith-8vcpu-ubuntu-2204-arm', }; const matrix = { diff --git a/.github/scripts/github-helpers.mjs b/.github/scripts/github-helpers.mjs index f6c5b110798..dcead8050a7 100644 --- a/.github/scripts/github-helpers.mjs +++ b/.github/scripts/github-helpers.mjs @@ -407,6 +407,124 @@ export async function getChangedFiles(pullRequestNumber) { ]); } +/** + * Returns all files changed in a PR with full metadata including line counts. + * + * @param { number } pullRequestNumber + * @returns { Promise<Array<{ filename: string, additions: number, deletions: number, previous_filename?: string }>> } + * */ +export async function getPrFiles(pullRequestNumber) { + const { octokit, owner, repo } = initGithub(); + + return await octokit.paginate(octokit.rest.pulls.listFiles, { + owner, + repo, + pull_number: pullRequestNumber, + per_page: 100, + }); +} + +/** + * Post a PR comment, or update the existing one if a previous run already + * left one identified by the provided bot marker. + * + * @param { number } pullRequestNumber + * @param { string } body + * @param { string } botMarker + */ +export async function postOrUpdateComment(pullRequestNumber, body, botMarker) { + const { octokit, owner, repo } = initGithub(); + + const comments = await octokit.paginate(octokit.rest.issues.listComments, { + owner, + repo, + issue_number: pullRequestNumber, + per_page: 100, + }); + + const existing = comments.find((c) => c.body?.includes(botMarker)); + + if (existing) { + await octokit.rest.issues.updateComment({ + owner, + repo, + comment_id: existing.id, + body, + }); + } else { + await octokit.rest.issues.createComment({ + owner, + repo, + issue_number: pullRequestNumber, + body, + }); + } +} + +/** + * Request review from the given GitHub teams on a PR. + * + * Team slugs are the part after the org, e.g. `catalysts` for + * `@n8n-io/catalysts`. Re-requesting an already-requested team is a no-op on + * GitHub's side, so this is safe to call on every PR update. + * + * @param { number } pullRequestNumber + * @param { string[] } teamSlugs + */ +export async function requestTeamReviewers(pullRequestNumber, teamSlugs) { + if (teamSlugs.length === 0) return; + + const { octokit, owner, repo } = initGithub(); + + await octokit.rest.pulls.requestReviewers({ + owner, + repo, + pull_number: pullRequestNumber, + team_reviewers: teamSlugs, + }); +} + +/** + * Add a label to a PR (issue). Adding a label that is already present is a + * no-op on GitHub's side. + * + * @param { number } pullRequestNumber + * @param { string } label + */ +export async function addLabel(pullRequestNumber, label) { + const { octokit, owner, repo } = initGithub(); + + await octokit.rest.issues.addLabels({ + owner, + repo, + issue_number: pullRequestNumber, + labels: [label], + }); +} + +/** + * Remove a label from a PR (issue). Removing a label that is not present + * returns 404 from GitHub; that case is swallowed so the call is idempotent. + * + * @param { number } pullRequestNumber + * @param { string } label + */ +export async function removeLabel(pullRequestNumber, label) { + const { octokit, owner, repo } = initGithub(); + + try { + await octokit.rest.issues.removeLabel({ + owner, + repo, + issue_number: pullRequestNumber, + name: label, + }); + } catch (ex) { + if (ex?.status === 404) return; + throw ex; + } +} + /** * @param {string} tag */ diff --git a/.github/scripts/github-helpers.test.mjs b/.github/scripts/github-helpers.test.mjs new file mode 100644 index 00000000000..16c36318a6b --- /dev/null +++ b/.github/scripts/github-helpers.test.mjs @@ -0,0 +1,90 @@ +import { afterEach, beforeEach, describe, it, mock } from 'node:test'; +import assert from 'node:assert/strict'; + +/** + * Run these tests by running + * + * node --test --experimental-test-module-mocks ./.github/scripts/github-helpers.test.mjs + * */ + +let octokitImpl; + +mock.module('@actions/github', { + namedExports: { + getOctokit: () => octokitImpl(), + }, +}); + +const { postOrUpdateComment } = await import('./github-helpers.mjs'); + +const ORIGINAL_ENV = { ...process.env }; + +describe('postOrUpdateComment', () => { + beforeEach(() => { + process.env.GITHUB_TOKEN = 'token'; + process.env.GITHUB_REPOSITORY = 'n8n-io/n8n'; + }); + + afterEach(() => { + process.env = { ...ORIGINAL_ENV }; + }); + + it('creates a new comment when no existing bot-marker comment is found', async () => { + const createComment = mock.fn(async () => {}); + const updateComment = mock.fn(async () => {}); + const paginate = mock.fn(async () => [{ id: 1, body: 'unrelated comment' }]); + octokitImpl = () => ({ + paginate, + rest: { + issues: { + listComments: {}, + createComment, + updateComment, + }, + }, + }); + + await postOrUpdateComment(123, 'new body', '<!-- marker -->'); + + assert.equal(updateComment.mock.calls.length, 0); + assert.equal(createComment.mock.calls.length, 1); + assert.deepEqual(createComment.mock.calls[0].arguments[0], { + owner: 'n8n-io', + repo: 'n8n', + issue_number: 123, + body: 'new body', + }); + assert.deepEqual(paginate.mock.calls[0].arguments[1], { + owner: 'n8n-io', + repo: 'n8n', + issue_number: 123, + per_page: 100, + }); + }); + + it('updates the existing comment when a bot-marker comment is found', async () => { + const createComment = mock.fn(async () => {}); + const updateComment = mock.fn(async () => {}); + octokitImpl = () => ({ + paginate: mock.fn(async () => [{ id: 42, body: '<!-- marker -->\nold body' }]), + rest: { + issues: { + listComments: {}, + createComment, + updateComment, + }, + }, + }); + + await postOrUpdateComment(123, 'updated body', '<!-- marker -->'); + + assert.equal(createComment.mock.calls.length, 0); + assert.equal(updateComment.mock.calls.length, 1); + assert.deepEqual(updateComment.mock.calls[0].arguments[0], { + owner: 'n8n-io', + repo: 'n8n', + comment_id: 42, + body: 'updated body', + }); + }); +}); diff --git a/.github/scripts/jsconfig.json b/.github/scripts/jsconfig.json index ae12830a9d6..1288b589d14 100644 --- a/.github/scripts/jsconfig.json +++ b/.github/scripts/jsconfig.json @@ -1,10 +1,9 @@ { - "compilerOptions": { - "module": "esnext", - "target": "esnext", - "checkJs": true, - "moduleResolution": "bundler" - }, - "exclude": ["node_modules"] + "compilerOptions": { + "module": "esnext", + "target": "esnext", + "checkJs": true, + "moduleResolution": "bundler" + }, + "exclude": ["node_modules"] } - diff --git a/.github/scripts/owners-assign-reviewers.mjs b/.github/scripts/owners-assign-reviewers.mjs new file mode 100644 index 00000000000..c79d5cf3780 --- /dev/null +++ b/.github/scripts/owners-assign-reviewers.mjs @@ -0,0 +1,104 @@ +/** + * Opt-in reviewer auto-assignment. + * + * When a PR carries the `Auto-assign reviewers` label, request review from + * every team that owns a changed file (per .github/OWNERS). This is strictly + * opt-in: without the label the script is a no-op, so it never adds friction + * to PRs that don't want it. + * + * Assignment happens once: after requesting reviewers the trigger label is + * swapped for the `Reviewers auto-assigned` marker, and any PR already carrying + * that marker is skipped. This stops later `synchronize` events from + * re-requesting (and re-notifying) the same teams. + * + * Complements `owners-review-recommendations.mjs`, which only *suggests* + * reviewer teams in a comment — this one actually requests them. + */ + +import { + addLabel, + ensureEnvVar, + getChangedFiles, + readPrLabels, + removeLabel, + requestTeamReviewers, +} from './github-helpers.mjs'; +import { assignOwnership, ownershipsToAllocations, parseOwnersFile } from './owners.mjs'; + +export const AUTO_ASSIGN_LABEL = 'Auto-assign reviewers'; +export const ASSIGNED_LABEL = 'Reviewers auto-assigned'; + +/** + * Convert an OWNERS team handle (`@n8n-io/catalysts`) into the GitHub team slug + * (`catalysts`) expected by the requestReviewers API. + * + * @param { string } team + * @returns { string } + */ +export function teamHandleToSlug(team) { + return team.replace(/^@[^/]+\//, ''); +} + +/** + * @param { string[] } labels + * @returns { boolean } + */ +export function hasAutoAssignLabel(labels) { + return labels.includes(AUTO_ASSIGN_LABEL); +} + +/** + * Determine the team slugs that own files in the changeset, de-duplicated and + * stable-ordered (largest ownership first, matching allocation order). + * + * @param { Set<string> } changedFiles + * @returns { string[] } + */ +export function resolveOwnerTeamSlugs(changedFiles) { + const owners = parseOwnersFile(); + const ownerships = assignOwnership(changedFiles, owners); + const allocations = ownershipsToAllocations(ownerships); + + return allocations.map((allocation) => teamHandleToSlug(allocation.team)); +} + +/** + * @param { number } pullRequestNumber + */ +export async function run(pullRequestNumber) { + const labels = readPrLabels(); + + if (labels.includes(ASSIGNED_LABEL)) { + console.log( + `PR #${pullRequestNumber} already carries the "${ASSIGNED_LABEL}" label; reviewers were already assigned.`, + ); + return; + } + + if (!hasAutoAssignLabel(labels)) { + console.log( + `PR #${pullRequestNumber} is missing the "${AUTO_ASSIGN_LABEL}" label; skipping reviewer assignment.`, + ); + return; + } + + const changedFiles = await getChangedFiles(pullRequestNumber); + const teamSlugs = resolveOwnerTeamSlugs(changedFiles); + + if (teamSlugs.length === 0) { + console.log(`No owning teams matched for PR #${pullRequestNumber}; nothing to assign.`); + return; + } + + console.log(`Requesting review from team(s): ${teamSlugs.join(', ')}`); + await requestTeamReviewers(pullRequestNumber, teamSlugs); + + // Swap the trigger label for the done-marker so later runs no-op. + await addLabel(pullRequestNumber, ASSIGNED_LABEL); + await removeLabel(pullRequestNumber, AUTO_ASSIGN_LABEL); +} + +if (import.meta.url === `file://${process.argv[1]}`) { + const pullRequestNumber = parseInt(ensureEnvVar('PULL_REQUEST_NUMBER')); + await run(pullRequestNumber); +} diff --git a/.github/scripts/owners-assign-reviewers.test.mjs b/.github/scripts/owners-assign-reviewers.test.mjs new file mode 100644 index 00000000000..2114c96bb35 --- /dev/null +++ b/.github/scripts/owners-assign-reviewers.test.mjs @@ -0,0 +1,174 @@ +import { beforeEach, describe, it, mock } from 'node:test'; +import assert from 'node:assert/strict'; + +/** + * Run these tests by running + * + * node --test --experimental-test-module-mocks ./.github/scripts/owners-assign-reviewers.test.mjs + * */ + +/** @type {() => string[]} */ +let readPrLabelsImpl = () => []; +/** @type {(pullRequestNumber: number) => Promise<Set<string>>} */ +let getChangedFilesImpl = async () => new Set(); +/** @type {(pullRequestNumber: number, teamSlugs: string[]) => Promise<void>} */ +let requestTeamReviewersImpl = async () => {}; +/** @type {(pullRequestNumber: number, label: string) => Promise<void>} */ +let addLabelImpl = async () => {}; +/** @type {(pullRequestNumber: number, label: string) => Promise<void>} */ +let removeLabelImpl = async () => {}; + +mock.module('./github-helpers.mjs', { + namedExports: { + ensureEnvVar: () => {}, // no-op in tests + readPrLabels: () => readPrLabelsImpl(), + getChangedFiles: (n) => getChangedFilesImpl(n), + requestTeamReviewers: (pullRequestNumber, teamSlugs) => + requestTeamReviewersImpl(pullRequestNumber, teamSlugs), + addLabel: (pullRequestNumber, label) => addLabelImpl(pullRequestNumber, label), + removeLabel: (pullRequestNumber, label) => removeLabelImpl(pullRequestNumber, label), + }, +}); + +/** @type {() => Array<{ filepath: string, team: string }>} */ +let parseOwnersFileImpl = () => []; +/** @type {(files: Set<string>, owners: Array<{ filepath: string, team: string }>) => Map<string, string[]>} */ +let assignOwnershipImpl = () => new Map(); +/** @type {(ownerships: Map<string, string[]>) => Array<{ team: string, fileCount: number }>} */ +let ownershipsToAllocationsImpl = () => []; + +mock.module('./owners.mjs', { + namedExports: { + parseOwnersFile: () => parseOwnersFileImpl(), + assignOwnership: (files, owners) => assignOwnershipImpl(files, owners), + ownershipsToAllocations: (ownerships) => ownershipsToAllocationsImpl(ownerships), + }, +}); + +const { + AUTO_ASSIGN_LABEL, + ASSIGNED_LABEL, + teamHandleToSlug, + hasAutoAssignLabel, + resolveOwnerTeamSlugs, + run, +} = await import('./owners-assign-reviewers.mjs'); + +describe('teamHandleToSlug', () => { + it('strips the org prefix from an OWNERS team handle', () => { + assert.equal(teamHandleToSlug('@n8n-io/catalysts'), 'catalysts'); + }); + + it('leaves a bare slug untouched', () => { + assert.equal(teamHandleToSlug('catalysts'), 'catalysts'); + }); + + it('only strips the first segment', () => { + assert.equal(teamHandleToSlug('@n8n-io/migrations-review'), 'migrations-review'); + }); +}); + +describe('hasAutoAssignLabel', () => { + it('returns true when the label is present', () => { + assert.equal(hasAutoAssignLabel(['bug', AUTO_ASSIGN_LABEL]), true); + }); + + it('returns false when the label is absent', () => { + assert.equal(hasAutoAssignLabel(['bug', 'enhancement']), false); + }); + + it('returns false for an empty label set', () => { + assert.equal(hasAutoAssignLabel([]), false); + }); +}); + +describe('resolveOwnerTeamSlugs', () => { + beforeEach(() => { + parseOwnersFileImpl = () => []; + assignOwnershipImpl = () => new Map(); + ownershipsToAllocationsImpl = () => []; + }); + + it('maps allocations to team slugs in allocation order', () => { + ownershipsToAllocationsImpl = () => [ + { team: '@n8n-io/catalysts', fileCount: 3 }, + { team: '@n8n-io/qa-dx', fileCount: 1 }, + ]; + + assert.deepEqual(resolveOwnerTeamSlugs(new Set(['a.ts'])), ['catalysts', 'qa-dx']); + }); + + it('returns an empty array when no team owns a file', () => { + assert.deepEqual(resolveOwnerTeamSlugs(new Set(['a.ts'])), []); + }); +}); + +describe('run', () => { + let requestTeamReviewers; + let addLabel; + let removeLabel; + + beforeEach(() => { + readPrLabelsImpl = () => [AUTO_ASSIGN_LABEL]; + getChangedFilesImpl = async () => new Set(['a.ts']); + parseOwnersFileImpl = () => []; + assignOwnershipImpl = () => new Map(); + ownershipsToAllocationsImpl = () => [{ team: '@n8n-io/catalysts', fileCount: 1 }]; + requestTeamReviewers = mock.fn(async () => {}); + requestTeamReviewersImpl = requestTeamReviewers; + addLabel = mock.fn(async () => {}); + addLabelImpl = addLabel; + removeLabel = mock.fn(async () => {}); + removeLabelImpl = removeLabel; + }); + + it('requests review from the owning team slugs when the label is present', async () => { + ownershipsToAllocationsImpl = () => [ + { team: '@n8n-io/catalysts', fileCount: 2 }, + { team: '@n8n-io/qa-dx', fileCount: 1 }, + ]; + + await run(42); + + assert.equal(requestTeamReviewers.mock.calls.length, 1); + assert.equal(requestTeamReviewers.mock.calls[0].arguments[0], 42); + assert.deepEqual(requestTeamReviewers.mock.calls[0].arguments[1], ['catalysts', 'qa-dx']); + }); + + it('swaps the trigger label for the done-marker after assigning', async () => { + await run(42); + + assert.deepEqual(addLabel.mock.calls[0].arguments, [42, ASSIGNED_LABEL]); + assert.deepEqual(removeLabel.mock.calls[0].arguments, [42, AUTO_ASSIGN_LABEL]); + }); + + it('is a no-op when the trigger label is absent', async () => { + readPrLabelsImpl = () => ['bug']; + + await run(42); + + assert.equal(requestTeamReviewers.mock.calls.length, 0); + assert.equal(addLabel.mock.calls.length, 0); + assert.equal(removeLabel.mock.calls.length, 0); + }); + + it('is a no-op when the done-marker label is already present', async () => { + readPrLabelsImpl = () => [AUTO_ASSIGN_LABEL, ASSIGNED_LABEL]; + + await run(42); + + assert.equal(requestTeamReviewers.mock.calls.length, 0); + assert.equal(addLabel.mock.calls.length, 0); + assert.equal(removeLabel.mock.calls.length, 0); + }); + + it('does not request reviewers or relabel when no team owns a changed file', async () => { + ownershipsToAllocationsImpl = () => []; + + await run(42); + + assert.equal(requestTeamReviewers.mock.calls.length, 0); + assert.equal(addLabel.mock.calls.length, 0); + assert.equal(removeLabel.mock.calls.length, 0); + }); +}); diff --git a/.github/scripts/owners-review-recommendations.mjs b/.github/scripts/owners-review-recommendations.mjs index dfdc1e0732f..e054efc3584 100644 --- a/.github/scripts/owners-review-recommendations.mjs +++ b/.github/scripts/owners-review-recommendations.mjs @@ -1,104 +1,254 @@ -import { ensureEnvVar, getChangedFiles, initGithub } from "./github-helpers.mjs"; -import { assignOwnership, ownershipsToAllocations, parseOwnersFile } from "./owners.mjs"; +/** + * PR recommendations entry point. + * + * Posts (or updates) a single PR comment that combines: + * - Recommended reviewer teams based on file ownership + * - A breakdown of changed lines by category (source code, test files, misc) + * + * Advisory only — does not gate merging. + */ + +import { minimatch } from 'minimatch'; +import { ensureEnvVar, getPrFiles, postOrUpdateComment } from './github-helpers.mjs'; +import { assignOwnership, ownershipsToAllocations, parseOwnersFile } from './owners.mjs'; +import { MISC_PATTERNS, SIZE_LIMIT, TEST_PATTERNS } from './quality/check-pr-size.mjs'; /** @typedef {import('./owners.mjs').Allocation} Allocation */ /** - * @param { number } pullRequestNumber - * */ -export async function getReviewRecommendations(pullRequestNumber) { - const changedFiles = await getChangedFiles(pullRequestNumber); - const owners = parseOwnersFile(); + * @typedef {{ + * sourceCodeAdded: number, sourceCodeRemoved: number, + * testFilesAdded: number, testFilesRemoved: number, + * miscAdded: number, miscRemoved: number, + * }} LineStats + */ - const ownerships = assignOwnership(changedFiles, owners); - const allocations = ownershipsToAllocations(ownerships); +const BOT_MARKER = '<!-- pr-recommendations -->'; - const topAllocations = allocations.sort((a, b) => b.fileCount - a.fileCount).slice(0, 3); - - await commentOnPrWithRecommendations(pullRequestNumber, topAllocations, changedFiles); +function createEmptyLineStats() { + return { + sourceCodeAdded: 0, + sourceCodeRemoved: 0, + testFilesAdded: 0, + testFilesRemoved: 0, + miscAdded: 0, + miscRemoved: 0, + }; } -const BOT_MARKER = "<!-- owners-review-recommendations -->"; +/** + * @param { LineStats } stats + * @param {{ filename: string, additions: number, deletions: number }} file + */ +function addFileToLineStats(stats, file) { + const isTest = TEST_PATTERNS.some((p) => minimatch(file.filename, p)); + const isMisc = !isTest && MISC_PATTERNS.some((p) => minimatch(file.filename, p)); + + if (isTest) { + stats.testFilesAdded += file.additions; + stats.testFilesRemoved += file.deletions; + } else if (isMisc) { + stats.miscAdded += file.additions; + stats.miscRemoved += file.deletions; + } else { + stats.sourceCodeAdded += file.additions; + stats.sourceCodeRemoved += file.deletions; + } +} /** - * Build the PR comment body listing the top reviewer teams with their share - * of ownership over the changed files. + * Compute line addition and deletion counts categorised as source code, + * test files, or misc. + * + * @param { Array<{ filename: string, additions: number, deletions: number }> } files + * @returns { LineStats } + */ +export function computeLineStats(files) { + const stats = createEmptyLineStats(); + + for (const file of files) { + addFileToLineStats(stats, file); + } + + return stats; +} + +/** + * Compute line stats for each owner allocation. Renamed files can be owned by + * either their previous or current filename, but are counted only once per team. + * + * @param { Allocation[] } allocations + * @param { Map<string, string[]> } ownerships + * @param { Array<{ filename: string, previous_filename?: string, additions: number, deletions: number }> } files + * @returns { Map<string, LineStats> } + */ +export function computeAllocationLineStats(allocations, ownerships, files) { + const statsByTeam = new Map(); + + for (const { team } of allocations) { + const stats = createEmptyLineStats(); + const ownedFiles = new Set(ownerships.get(team) ?? []); + + for (const file of files) { + if (ownedFiles.has(file.filename) || ownedFiles.has(file.previous_filename)) { + addFileToLineStats(stats, file); + } + } + + statsByTeam.set(team, stats); + } + + return statsByTeam; +} + +/** + * @param { LineStats } lineStats + * @param {'sourceCode' | 'testFiles' | 'misc'} key + * @returns { string } + */ +function formatLineStatsCell(lineStats, key) { + return `+${lineStats[`${key}Added`].toLocaleString()} / -${lineStats[`${key}Removed`].toLocaleString()}`; +} + +/** + * @param { LineStats } lineStats + * @returns { number } + */ +function totalLineChanges(lineStats) { + return ( + lineStats.sourceCodeAdded + + lineStats.sourceCodeRemoved + + lineStats.testFilesAdded + + lineStats.testFilesRemoved + + lineStats.miscAdded + + lineStats.miscRemoved + ); +} + +/** + * @param { LineStats } target + * @param { LineStats } source + */ +function addLineStats(target, source) { + target.sourceCodeAdded += source.sourceCodeAdded; + target.sourceCodeRemoved += source.sourceCodeRemoved; + target.testFilesAdded += source.testFilesAdded; + target.testFilesRemoved += source.testFilesRemoved; + target.miscAdded += source.miscAdded; + target.miscRemoved += source.miscRemoved; +} + +/** + * @param { Allocation[] } allocations + * @param { Map<string, LineStats> } lineStatsByTeam + * @returns { LineStats } + */ +function aggregateLineStats(allocations, lineStatsByTeam) { + const stats = createEmptyLineStats(); + + for (const { team } of allocations) { + addLineStats(stats, lineStatsByTeam.get(team) ?? createEmptyLineStats()); + } + + return stats; +} + +/** + * Build an ownership-first overview table with line stats grouped by team. * * @param { Allocation[] } allocations * @param { Set<string> } changedFiles + * @param { LineStats } totalLineStats + * @param { Map<string, LineStats> } lineStatsByTeam + * @param { Allocation[] } [otherAllocations] * @returns { string } - * */ -export function buildRecommendationsBody(allocations, changedFiles) { + */ +export function buildOverviewTable(allocations, changedFiles, totalLineStats, lineStatsByTeam, otherAllocations = []) { const total = changedFiles.size; + const rows = allocations.length > 0 && total > 0 + ? allocations.map(({ team, fileCount }) => { + const pct = Math.round((fileCount / total) * 100); + const teamLineStats = lineStatsByTeam.get(team) ?? createEmptyLineStats(); + return `| ${team} | ${fileCount} | ${pct}% | ${formatLineStatsCell(teamLineStats, 'sourceCode')} | ${formatLineStatsCell(teamLineStats, 'testFiles')} | ${formatLineStatsCell(teamLineStats, 'misc')} |`; + }) + : [`| _No owning teams matched_ | 0 | 0% | ${formatLineStatsCell(totalLineStats, 'sourceCode')} | ${formatLineStatsCell(totalLineStats, 'testFiles')} | ${formatLineStatsCell(totalLineStats, 'misc')} |`]; - if (allocations.length === 0 || total === 0) { - return [ - BOT_MARKER, - "## Recommended reviewers", - "", - "_No owning teams matched the files changed in this PR._", - ].join("\n"); + if (otherAllocations.length > 0 && total > 0) { + const otherFileCount = otherAllocations.reduce((sum, { fileCount }) => sum + fileCount, 0); + const otherPct = Math.round((otherFileCount / total) * 100); + const otherLineStats = aggregateLineStats(otherAllocations, lineStatsByTeam); + rows.push(`| Other teams | ${otherFileCount} | ${otherPct}% | ${formatLineStatsCell(otherLineStats, 'sourceCode')} | ${formatLineStatsCell(otherLineStats, 'testFiles')} | ${formatLineStatsCell(otherLineStats, 'misc')} |`); } - const rows = allocations.map(({ team, fileCount }) => { - const pct = Math.round((fileCount / total) * 100); - return `| ${team} | ${fileCount} | ${pct}% |`; - }); - return [ - BOT_MARKER, - "## Recommended reviewers", - "", - `Based on ownership of the ${total} changed file${total === 1 ? "" : "s"} in this PR:`, - "", - "| Team | Files owned | Share |", - "| --- | ---: | ---: |", + '## PR review overview', + '', + `Based on ownership of the ${total} changed file${total === 1 ? '' : 's'} in this PR:`, + '', + '| Ownership | Files owned | Share | Source code | Test files | Misc |', + '| --- | ---: | ---: | ---: | ---: | ---: |', ...rows, - ].join("\n"); + `| **Total** | **${total.toLocaleString()}** | **${total === 0 ? 0 : 100}%** | **${formatLineStatsCell(totalLineStats, 'sourceCode')}** | **${formatLineStatsCell(totalLineStats, 'testFiles')}** | **${formatLineStatsCell(totalLineStats, 'misc')}** |`, + ].join('\n'); } /** - * Post the recommendations as a PR comment, or update the existing one if a - * previous run already left one (identified by BOT_MARKER). + * Construct the full PR comment body from reviewer allocations and line stats. * - * @param { number } pullRequestNumber * @param { Allocation[] } allocations * @param { Set<string> } changedFiles - * */ -export async function commentOnPrWithRecommendations(pullRequestNumber, allocations, changedFiles) { - const { octokit, owner, repo } = initGithub(); + * @param { LineStats } lineStats + * @param { Map<string, LineStats> } lineStatsByTeam + * @param { Allocation[] } [otherAllocations] + * @returns { string } + */ +export function buildComment(allocations, changedFiles, lineStats, lineStatsByTeam = new Map(), otherAllocations = []) { + const body = [ + BOT_MARKER, + buildOverviewTable(allocations, changedFiles, lineStats, lineStatsByTeam, otherAllocations), + ]; - const body = buildRecommendationsBody(allocations, changedFiles); - - const comments = await octokit.paginate(octokit.rest.issues.listComments, { - owner, - repo, - issue_number: pullRequestNumber, - per_page: 100, - }); - - const existing = comments.find(c => c.body?.includes(BOT_MARKER)); - - if (existing) { - await octokit.rest.issues.updateComment({ - owner, - repo, - comment_id: existing.id, - body, - }); - } else { - await octokit.rest.issues.createComment({ - owner, - repo, - issue_number: pullRequestNumber, - body, - }); + if (lineStats.sourceCodeAdded > SIZE_LIMIT) { + body.push('', `❗ Source code additions (${lineStats.sourceCodeAdded.toLocaleString()}) exceed the ${SIZE_LIMIT.toLocaleString()}-line limit.`); } + + return body.join('\n'); +} + +/** + * @param { number } pullRequestNumber + */ +export async function run(pullRequestNumber) { + const files = await getPrFiles(pullRequestNumber); + + const changedFiles = new Set([ + ...files.map((f) => f.filename), + ...files.filter((f) => f.previous_filename).map((f) => f.previous_filename), + ]); + + const lineStats = computeLineStats(files); + + const owners = parseOwnersFile(); + const ownerships = assignOwnership(changedFiles, owners); + const allocations = ownershipsToAllocations(ownerships); + const lineStatsByTeam = computeAllocationLineStats(allocations, ownerships, files); + const sortedAllocations = allocations + .toSorted((a, b) => { + const lineChangeDiff = + totalLineChanges(lineStatsByTeam.get(b.team) ?? createEmptyLineStats()) - + totalLineChanges(lineStatsByTeam.get(a.team) ?? createEmptyLineStats()); + + return lineChangeDiff || b.fileCount - a.fileCount; + }); + const topAllocations = sortedAllocations.slice(0, 3); + const otherAllocations = sortedAllocations.slice(3); + + const body = buildComment(topAllocations, changedFiles, lineStats, lineStatsByTeam, otherAllocations); + + await postOrUpdateComment(pullRequestNumber, body, BOT_MARKER); } -// only run when executed directly, not when imported by tests if (import.meta.url === `file://${process.argv[1]}`) { - const pullRequestNumber = parseInt(ensureEnvVar("PULL_REQUEST_NUMBER")); - - await getReviewRecommendations(pullRequestNumber); + const pullRequestNumber = parseInt(ensureEnvVar('PULL_REQUEST_NUMBER')); + await run(pullRequestNumber); } diff --git a/.github/scripts/owners-review-recommendations.test.mjs b/.github/scripts/owners-review-recommendations.test.mjs index d8d304a9882..5826e559970 100644 --- a/.github/scripts/owners-review-recommendations.test.mjs +++ b/.github/scripts/owners-review-recommendations.test.mjs @@ -1,4 +1,4 @@ -import { describe, it, mock } from 'node:test'; +import { beforeEach, describe, it, mock } from 'node:test'; import assert from 'node:assert/strict'; /** @@ -7,71 +7,382 @@ import assert from 'node:assert/strict'; * node --test --experimental-test-module-mocks ./.github/scripts/owners-review-recommendations.test.mjs * */ -// mock.module must be called before the module under test is imported, -// because static imports are hoisted and resolve before any code runs. +/** @type {(pullRequestNumber: number) => Promise<Array<{ filename: string, additions: number, deletions: number, previous_filename?: string }>>} */ +let getPrFilesImpl = async () => []; +/** @type {(pullRequestNumber: number, body: string, botMarker: string) => Promise<void>} */ +let postOrUpdateCommentImpl = async () => {}; + mock.module('./github-helpers.mjs', { namedExports: { ensureEnvVar: () => {}, // no-op in tests initGithub: () => {}, // no-op in tests - getChangedFiles: () => Promise.resolve(new Set()), // no-op in tests + getChangedFiles: () => Promise.resolve(new Set()), + getEventFromGithubEventPath: () => ({}), + getPrFiles: (n) => getPrFilesImpl(n), + postOrUpdateComment: (pullRequestNumber, body, botMarker) => + postOrUpdateCommentImpl(pullRequestNumber, body, botMarker), }, }); -/** @type { (allocations: { team: string, fileCount: number }[], changedFiles: Set<string>) => string } */ -let buildRecommendationsBody; -const { buildRecommendationsBody: imported } = await import('./owners-review-recommendations.mjs'); -buildRecommendationsBody = imported; +/** @type {() => Array<{ filepath: string, team: string }>} */ +let parseOwnersFileImpl = () => []; +/** @type {(files: Set<string>, owners: Array<{ filepath: string, team: string }>) => Map<string, string[]>} */ +let assignOwnershipImpl = () => new Map(); +/** @type {(ownerships: Map<string, string[]>) => Array<{ team: string, fileCount: number }>} */ +let ownershipsToAllocationsImpl = () => []; -describe('buildRecommendationsBody', () => { - const marker = '<!-- owners-review-recommendations -->'; +mock.module('./owners.mjs', { + namedExports: { + parseOwnersFile: () => parseOwnersFileImpl(), + assignOwnership: (files, owners) => assignOwnershipImpl(files, owners), + ownershipsToAllocations: (ownerships) => ownershipsToAllocationsImpl(ownerships), + }, +}); - it('returns the fallback message when there are no allocations', () => { - const body = buildRecommendationsBody([], new Set(['a.ts'])); +const { buildOverviewTable, buildComment, computeAllocationLineStats, computeLineStats, run } = + await import('./owners-review-recommendations.mjs'); - assert.ok(body.startsWith(marker), 'body must start with the bot marker'); - assert.match(body, /No owning teams matched/); - }); +const BOT_MARKER = '<!-- pr-recommendations -->'; +const EMPTY_LINE_STATS = { + sourceCodeAdded: 0, + sourceCodeRemoved: 0, + testFilesAdded: 0, + testFilesRemoved: 0, + miscAdded: 0, + miscRemoved: 0, +}; - it('returns the fallback message when no files changed', () => { - const body = buildRecommendationsBody( - [{ team: '@n8n-io/cli-team', fileCount: 0 }], - new Set(), - ); - - assert.match(body, /No owning teams matched/); - }); - - it('renders a table with team name, file count, and rounded percentage', () => { - const body = buildRecommendationsBody( +describe('buildOverviewTable', () => { + it('renders an ownership-first table with per-team line stats', () => { + const table = buildOverviewTable( [ - { team: '@n8n-io/cli-team', fileCount: 6 }, - { team: '@n8n-io/catalysts', fileCount: 3 }, - { team: '@n8n-io/ai-team', fileCount: 1 }, + { team: '@n8n-io/cli-team', fileCount: 2 }, + { team: '@n8n-io/editor-ui-team', fileCount: 1 }, ], - new Set(['1', '2', '3', '4', '5', '6', '7', '8', '9', '10']), + new Set(['a.ts', 'b.test.ts', 'README.md']), + { + sourceCodeAdded: 10, + sourceCodeRemoved: 2, + testFilesAdded: 5, + testFilesRemoved: 1, + miscAdded: 3, + miscRemoved: 0, + }, + new Map([ + [ + '@n8n-io/cli-team', + { + sourceCodeAdded: 10, + sourceCodeRemoved: 2, + testFilesAdded: 5, + testFilesRemoved: 1, + miscAdded: 0, + miscRemoved: 0, + }, + ], + [ + '@n8n-io/editor-ui-team', + { + sourceCodeAdded: 0, + sourceCodeRemoved: 0, + testFilesAdded: 0, + testFilesRemoved: 0, + miscAdded: 3, + miscRemoved: 0, + }, + ], + ]), ); - assert.ok(body.startsWith(marker)); - assert.match(body, /\| @n8n-io\/cli-team \| 6 \| 60% \|/); - assert.match(body, /\| @n8n-io\/catalysts \| 3 \| 30% \|/); - assert.match(body, /\| @n8n-io\/ai-team \| 1 \| 10% \|/); + assert.match(table, /## PR review overview/); + assert.match(table, /\| Ownership \| Files owned \| Share \| Source code \| Test files \| Misc \|/); + assert.match(table, /\| @n8n-io\/cli-team \| 2 \| 67% \| \+10 \/ -2 \| \+5 \/ -1 \| \+0 \/ -0 \|/); + assert.match(table, /\| @n8n-io\/editor-ui-team \| 1 \| 33% \| \+0 \/ -0 \| \+0 \/ -0 \| \+3 \/ -0 \|/); + assert.match(table, /\| \*\*Total\*\* \| \*\*3\*\* \| \*\*100%\*\* \| \*\*\+10 \/ -2\*\* \| \*\*\+5 \/ -1\*\* \| \*\*\+3 \/ -0\*\* \|/); + }); + + it('renders a no-owner row when no owners matched', () => { + const table = buildOverviewTable( + [], + new Set(['a.ts']), + { ...EMPTY_LINE_STATS, sourceCodeAdded: 12, sourceCodeRemoved: 1 }, + new Map(), + ); + + assert.match(table, /\| _No owning teams matched_ \| 0 \| 0% \| \+12 \/ -1 \| \+0 \/ -0 \| \+0 \/ -0 \|/); }); it('uses singular "file" when exactly one file changed', () => { - const body = buildRecommendationsBody( + const table = buildOverviewTable( [{ team: '@n8n-io/cli-team', fileCount: 1 }], new Set(['only.ts']), + EMPTY_LINE_STATS, + new Map(), ); - assert.match(body, /ownership of the 1 changed file in this PR/); + assert.match(table, /ownership of the 1 changed file in this PR/); }); - it('uses plural "files" for more than one changed file', () => { - const body = buildRecommendationsBody( - [{ team: '@n8n-io/cli-team', fileCount: 2 }], + it('uses plural "files" for more than one file changed', () => { + const table = buildOverviewTable( + [{ team: '@n8n-io/cli-team', fileCount: 1 }], new Set(['a.ts', 'b.ts']), + EMPTY_LINE_STATS, + new Map(), ); - assert.match(body, /ownership of the 2 changed files in this PR/); + assert.match(table, /ownership of the 2 changed files in this PR/); + }); + + it('renders an aggregate row for allocations outside the displayed teams', () => { + const table = buildOverviewTable( + [{ team: '@n8n-io/cli-team', fileCount: 2 }], + new Set(['a.ts', 'b.ts', 'c.ts']), + { ...EMPTY_LINE_STATS, sourceCodeAdded: 13, sourceCodeRemoved: 3 }, + new Map([ + ['@n8n-io/cli-team', { ...EMPTY_LINE_STATS, sourceCodeAdded: 10, sourceCodeRemoved: 1 }], + ['@n8n-io/team-a', { ...EMPTY_LINE_STATS, sourceCodeAdded: 2, sourceCodeRemoved: 1 }], + ['@n8n-io/team-b', { ...EMPTY_LINE_STATS, sourceCodeAdded: 1, sourceCodeRemoved: 1 }], + ]), + [ + { team: '@n8n-io/team-a', fileCount: 1 }, + { team: '@n8n-io/team-b', fileCount: 1 }, + ], + ); + + assert.match(table, /\| Other teams \| 2 \| 67% \| \+3 \/ -2 \| \+0 \/ -0 \| \+0 \/ -0 \|/); + }); +}); + +describe('buildComment', () => { + it('starts with the bot marker', () => { + const body = buildComment([], new Set(['a.ts']), EMPTY_LINE_STATS); + + assert.ok(body.startsWith(BOT_MARKER), 'body must start with the bot marker'); + }); + + it('includes the overview table', () => { + const body = buildComment( + [{ team: '@n8n-io/cli-team', fileCount: 1 }], + new Set(['a.ts']), + { ...EMPTY_LINE_STATS, sourceCodeAdded: 42 }, + ); + + assert.match(body, /## PR review overview/); + assert.match(body, /\| @n8n-io\/cli-team \| 1 \| 100% \|/); + }); + + it('shows a warning below the table when source code additions exceed the size limit', () => { + const body = buildComment([], new Set(['a.ts']), { ...EMPTY_LINE_STATS, sourceCodeAdded: 1001 }); + + assert.match(body, /❗ Source code additions \(1[,.]001\) exceed the 1[,.]000-line limit\./); + }); +}); + +describe('computeLineStats', () => { + it('returns all zeros for an empty file list', () => { + assert.deepEqual(computeLineStats([]), EMPTY_LINE_STATS); + }); + + it('categorises a plain source file as source code', () => { + const stats = computeLineStats([{ filename: 'src/foo.ts', additions: 10, deletions: 3 }]); + + assert.equal(stats.sourceCodeAdded, 10); + assert.equal(stats.sourceCodeRemoved, 3); + assert.equal(stats.testFilesAdded, 0); + assert.equal(stats.miscAdded, 0); + }); + + describe('test file patterns', () => { + for (const [label, filename] of [ + ['*.test.ts', 'src/foo.test.ts'], + ['*.test.js', 'src/foo.test.js'], + ['*.test.mjs', 'src/foo.test.mjs'], + ['*.spec.ts', 'src/foo.spec.ts'], + ['*.spec.js', 'src/foo.spec.js'], + ['*.spec.mjs', 'src/foo.spec.mjs'], + ['test/ directory', 'packages/cli/test/helpers.ts'], + ['tests/ directory', 'packages/cli/tests/helpers.ts'], + ['__tests__/ directory', 'src/__tests__/foo.ts'], + ['__snapshots__/ directory', 'src/__snapshots__/foo.snap'], + ['*.snap extension', 'src/foo.snap'], + ['fixtures/ directory', 'src/fixtures/data.json'], + ['__mocks__/ directory', 'src/__mocks__/axios.ts'], + ['packages/testing/**', 'packages/testing/playwright/spec.ts'], + ]) { + it(`classifies ${label} as testFiles`, () => { + const stats = computeLineStats([{ filename, additions: 7, deletions: 2 }]); + + assert.equal(stats.testFilesAdded, 7, `expected ${filename} to be a test file`); + assert.equal(stats.testFilesRemoved, 2); + assert.equal(stats.sourceCodeAdded, 0); + assert.equal(stats.miscAdded, 0); + }); + } + }); + + describe('misc file patterns', () => { + for (const [label, filename] of [ + ['pnpm-lock.yaml', 'pnpm-lock.yaml'], + ['*.md', 'README.md'], + ['nested *.md', 'packages/cli/CHANGELOG.md'], + ['*.mdx', 'docs/guide.mdx'], + ['nested *.mdx', 'packages/editor-ui/docs/page.mdx'], + ]) { + it(`classifies ${label} as misc`, () => { + const stats = computeLineStats([{ filename, additions: 3, deletions: 1 }]); + + assert.equal(stats.miscAdded, 3, `expected ${filename} to be misc`); + assert.equal(stats.miscRemoved, 1); + assert.equal(stats.sourceCodeAdded, 0); + assert.equal(stats.testFilesAdded, 0); + }); + } + }); + + it('sums additions and deletions across multiple files per category', () => { + const stats = computeLineStats([ + { filename: 'src/a.ts', additions: 10, deletions: 5 }, + { filename: 'src/b.ts', additions: 15, deletions: 3 }, + { filename: 'src/a.test.ts', additions: 5, deletions: 1 }, + { filename: 'src/b.spec.ts', additions: 8, deletions: 2 }, + { filename: 'pnpm-lock.yaml', additions: 100, deletions: 50 }, + { filename: 'README.md', additions: 20, deletions: 10 }, + ]); + + assert.equal(stats.sourceCodeAdded, 25); + assert.equal(stats.sourceCodeRemoved, 8); + assert.equal(stats.testFilesAdded, 13); + assert.equal(stats.testFilesRemoved, 3); + assert.equal(stats.miscAdded, 120); + assert.equal(stats.miscRemoved, 60); + }); +}); + +describe('computeAllocationLineStats', () => { + it('computes line stats per owner allocation', () => { + const statsByTeam = computeAllocationLineStats( + [ + { team: '@n8n-io/cli-team', fileCount: 2 }, + { team: '@n8n-io/docs-team', fileCount: 1 }, + ], + new Map([ + ['@n8n-io/cli-team', ['src/a.ts', 'src/a.test.ts']], + ['@n8n-io/docs-team', ['README.md']], + ]), + [ + { filename: 'src/a.ts', additions: 10, deletions: 1 }, + { filename: 'src/a.test.ts', additions: 5, deletions: 2 }, + { filename: 'README.md', additions: 3, deletions: 1 }, + ], + ); + + assert.deepEqual(statsByTeam.get('@n8n-io/cli-team'), { + sourceCodeAdded: 10, + sourceCodeRemoved: 1, + testFilesAdded: 5, + testFilesRemoved: 2, + miscAdded: 0, + miscRemoved: 0, + }); + assert.deepEqual(statsByTeam.get('@n8n-io/docs-team'), { + sourceCodeAdded: 0, + sourceCodeRemoved: 0, + testFilesAdded: 0, + testFilesRemoved: 0, + miscAdded: 3, + miscRemoved: 1, + }); + }); + + it('matches renamed files by previous filename', () => { + const statsByTeam = computeAllocationLineStats( + [{ team: '@n8n-io/cli-team', fileCount: 1 }], + new Map([['@n8n-io/cli-team', ['old-name.ts']]]), + [{ filename: 'new-name.ts', previous_filename: 'old-name.ts', additions: 7, deletions: 3 }], + ); + + assert.equal(statsByTeam.get('@n8n-io/cli-team').sourceCodeAdded, 7); + assert.equal(statsByTeam.get('@n8n-io/cli-team').sourceCodeRemoved, 3); + }); +}); + +describe('run', () => { + let postOrUpdateComment; + + beforeEach(() => { + getPrFilesImpl = async () => []; + postOrUpdateComment = mock.fn(async () => {}); + postOrUpdateCommentImpl = postOrUpdateComment; + parseOwnersFileImpl = () => []; + assignOwnershipImpl = () => new Map(); + ownershipsToAllocationsImpl = () => []; + }); + + it('calls postOrUpdateComment with the PR number, generated body, and bot marker', async () => { + await run(42); + + assert.equal(postOrUpdateComment.mock.calls.length, 1, 'postOrUpdateComment should be called once'); + assert.equal(postOrUpdateComment.mock.calls[0].arguments[0], 42); + assert.ok(postOrUpdateComment.mock.calls[0].arguments[1].includes(BOT_MARKER)); + assert.equal(postOrUpdateComment.mock.calls[0].arguments[2], BOT_MARKER); + }); + + it('includes renamed files in the changed files set', async () => { + getPrFilesImpl = async () => [ + { filename: 'new-name.ts', additions: 5, deletions: 0, previous_filename: 'old-name.ts' }, + ]; + + let capturedChangedFiles = new Set(); + assignOwnershipImpl = (files) => { + capturedChangedFiles = files; + return new Map(); + }; + + await run(42); + + assert.ok(capturedChangedFiles.has('new-name.ts'), 'new filename must be included'); + assert.ok(capturedChangedFiles.has('old-name.ts'), 'previous filename must be included'); + }); + + it('limits recommendations to the top 3 allocations by total line changes', async () => { + getPrFilesImpl = async () => [ + { filename: 'a.ts', additions: 1, deletions: 0 }, + { filename: 'b.ts', additions: 50, deletions: 50 }, + { filename: 'c.ts', additions: 20, deletions: 20 }, + { filename: 'd.ts', additions: 10, deletions: 10 }, + ]; + assignOwnershipImpl = () => + new Map([ + ['@n8n-io/team-a', ['a.ts']], + ['@n8n-io/team-b', ['b.ts']], + ['@n8n-io/team-c', ['c.ts']], + ['@n8n-io/team-d', ['d.ts']], + ]); + ownershipsToAllocationsImpl = () => [ + { team: '@n8n-io/team-a', fileCount: 1 }, + { team: '@n8n-io/team-b', fileCount: 1 }, + { team: '@n8n-io/team-c', fileCount: 1 }, + { team: '@n8n-io/team-d', fileCount: 1 }, + ]; + + await run(42); + + const body = postOrUpdateComment.mock.calls[0].arguments[1]; + assert.match(body, /@n8n-io\/team-b[\s\S]*@n8n-io\/team-c[\s\S]*@n8n-io\/team-d/); + assert.doesNotMatch(body, /@n8n-io\/team-a/); + assert.match(body, /\| Other teams \| 1 \| 25% \| \+1 \/ -0 \| \+0 \/ -0 \| \+0 \/ -0 \|/); + }); + + it('posted comment body includes the ownership-first overview table', async () => { + getPrFilesImpl = async () => [{ filename: 'src/foo.ts', additions: 50, deletions: 5 }]; + ownershipsToAllocationsImpl = () => [{ team: '@n8n-io/cli-team', fileCount: 1 }]; + assignOwnershipImpl = () => new Map([['@n8n-io/cli-team', ['src/foo.ts']]]); + + await run(42); + + const body = postOrUpdateComment.mock.calls[0].arguments[1]; + assert.match(body, /## PR review overview/); + assert.match(body, /\| @n8n-io\/cli-team \| 1 \| 100% \| \+50 \/ -5 \|/); }); }); diff --git a/.github/scripts/package.json b/.github/scripts/package.json index 1162b4e718e..b43f87e8d00 100644 --- a/.github/scripts/package.json +++ b/.github/scripts/package.json @@ -2,9 +2,11 @@ "name": "workflow-scripts", "scripts": { "test": "node --test --experimental-test-module-mocks ./*.test.mjs ./quality/*.test.mjs ./slack/*.test.mjs ./stale/*.test.mjs ../../scripts/licenses/*.test.mjs", - "generate-sbom": "FETCH_LICENSE=true cdxgen -t pnpm --no-install-deps --profile license-compliance -o ../../sbom-source.cdx.json ../../compiled/", + "generate-sbom": "FETCH_LICENSE=true cdxgen -t pnpm --no-install-deps --profile license-compliance --spec-version 1.6 -o ../../sbom-source.cdx.json ../../compiled/", + "enrich-sbom": "node ../../scripts/licenses/enrich-sbom.mjs ../../sbom-source.cdx.json", "render-licenses-md": "node ../../scripts/licenses/render-licenses-md.mjs ../../sbom-source.cdx.json ../../packages/cli/THIRD_PARTY_LICENSES.md ../../compiled/node_modules", - "generate-licenses": "pnpm generate-sbom && pnpm render-licenses-md" + "check-licenses": "node ../../scripts/licenses/check-sbom-licenses.mjs ../../sbom-source.cdx.json --allow-ref=LicenseRef-n8n-sustainable-use --allow-ref=LicenseRef-n8n-enterprise", + "generate-licenses": "pnpm generate-sbom && pnpm enrich-sbom && pnpm render-licenses-md && pnpm check-licenses" }, "dependencies": { "@actions/github": "9.0.0", @@ -20,5 +22,10 @@ }, "devDependencies": { "conventional-changelog-angular": "8.3.0" + }, + "pnpm": { + "overrides": { + "brace-expansion@5": "^5.0.5" + } } } diff --git a/.github/scripts/pnpm-lock.yaml b/.github/scripts/pnpm-lock.yaml index 1ebe05e063d..281dba0dc79 100644 --- a/.github/scripts/pnpm-lock.yaml +++ b/.github/scripts/pnpm-lock.yaml @@ -4,6 +4,9 @@ settings: autoInstallPeers: true excludeLinksFromLockfile: false +overrides: + brace-expansion@5: ^5.0.5 + importers: .: @@ -365,8 +368,8 @@ packages: boolbase@1.0.0: resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} - brace-expansion@5.0.4: - resolution: {integrity: sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg==} + brace-expansion@5.0.6: + resolution: {integrity: sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==} engines: {node: 18 || 20 || >=22} byte-counter@0.1.0: @@ -1567,7 +1570,7 @@ snapshots: boolbase@1.0.0: {} - brace-expansion@5.0.4: + brace-expansion@5.0.6: dependencies: balanced-match: 4.0.4 @@ -2029,7 +2032,7 @@ snapshots: minimatch@10.2.4: dependencies: - brace-expansion: 5.0.4 + brace-expansion: 5.0.6 minimist@1.2.8: {} diff --git a/.github/scripts/quality/check-pr-size.mjs b/.github/scripts/quality/check-pr-size.mjs index a3505864128..2ed56a6f528 100644 --- a/.github/scripts/quality/check-pr-size.mjs +++ b/.github/scripts/quality/check-pr-size.mjs @@ -18,7 +18,7 @@ import { initGithub, getEventFromGithubEventPath } from '../github-helpers.mjs'; export const SIZE_LIMIT = 1000; export const OVERRIDE_COMMAND = '/size-limit-override'; -export const EXCLUDE_PATTERNS = [ +export const TEST_PATTERNS = [ // Test files (by extension) '**/*.test.ts', '**/*.test.js', @@ -38,12 +38,17 @@ export const EXCLUDE_PATTERNS = [ '**/__mocks__/**', // Dedicated testing package 'packages/testing/**', +]; + +export const MISC_PATTERNS = [ // Lock file (can produce massive diffs on dependency changes) 'pnpm-lock.yaml', '**/*.md', - '**/*.mdx' + '**/*.mdx', ]; +export const EXCLUDE_PATTERNS = [...TEST_PATTERNS, ...MISC_PATTERNS]; + const BOT_MARKER = '<!-- pr-size-check -->'; /** diff --git a/.github/scripts/send-metrics.mjs b/.github/scripts/send-metrics.mjs index c9f504ddce3..8c2551aa7fb 100644 --- a/.github/scripts/send-metrics.mjs +++ b/.github/scripts/send-metrics.mjs @@ -19,16 +19,21 @@ export function metric(name, value, unit, dimensions = {}) { /** Build git/ci/runner context from environment variables. */ export function buildContext(benchmarkName = null) { - const ref = process.env.GITHUB_REF ?? ''; + // Use `||` (not `??`) when falling back across GitHub env vars: on `push` and + // `merge_group` events GITHUB_HEAD_REF is set to '' (empty string, not undefined), + // so `??` would never fall through to GITHUB_REF_NAME and every non-PR row would + // land in BigQuery with git_branch = ''. The same applies to any other GITHUB_* + // var whose intended fallback is null — preserve null, not ''. + const ref = process.env.GITHUB_REF || ''; const prMatch = ref.match(/refs\/pull\/(\d+)/); - const runId = process.env.GITHUB_RUN_ID ?? null; + const runId = process.env.GITHUB_RUN_ID || null; return { timestamp: new Date().toISOString(), benchmark_name: benchmarkName, git: { - sha: process.env.GITHUB_SHA?.slice(0, 8) ?? null, - branch: process.env.GITHUB_HEAD_REF ?? process.env.GITHUB_REF_NAME ?? null, + sha: process.env.GITHUB_SHA?.slice(0, 8) || null, + branch: process.env.GITHUB_HEAD_REF || process.env.GITHUB_REF_NAME || null, pr: prMatch ? parseInt(prMatch[1], 10) : null, }, ci: { @@ -37,8 +42,8 @@ export function buildContext(benchmarkName = null) { runId && process.env.GITHUB_REPOSITORY ? `https://github.com/${process.env.GITHUB_REPOSITORY}/actions/runs/${runId}` : null, - job: process.env.GITHUB_JOB ?? null, - workflow: process.env.GITHUB_WORKFLOW ?? null, + job: process.env.GITHUB_JOB || null, + workflow: process.env.GITHUB_WORKFLOW || null, attempt: process.env.GITHUB_RUN_ATTEMPT ? parseInt(process.env.GITHUB_RUN_ATTEMPT, 10) : null, diff --git a/.github/scripts/verify-safechain.mjs b/.github/scripts/verify-safechain.mjs new file mode 100644 index 00000000000..77f2b3542e9 --- /dev/null +++ b/.github/scripts/verify-safechain.mjs @@ -0,0 +1,67 @@ +#!/usr/bin/env node +/** + * Verify that Aikido SafeChain is active by running `safe-chain-verify` + * *through* each wrapped package manager. SafeChain's shim prints + * "OK: Safe-chain works!" only when it is intercepting the call — a truer + * check than matching the resolved binary path. + * + * SafeChain's CI shims are bare executables on Unix but `.cmd`/`.ps1` on Windows; running + * the command with `shell: true` delegates to the platform shell + * (`/bin/sh` / `cmd.exe`), so each OS resolves its own shim form and a + * single code path covers both. + * + * Note: this must run as a *separate* step after `safe-chain setup-ci`. + * `setup-ci` exposes the shims via `$GITHUB_PATH`, which the runner only + * applies to `PATH` between steps — so the shims are not on this process's + * PATH until the activation step has finished. + * + * Exits 0 only when every package manager reports OK; 1 otherwise. + */ +import { spawnSync } from 'node:child_process'; +import { pathToFileURL } from 'node:url'; + +const PACKAGE_MANAGERS = ['npm', 'pnpm']; + +/** + * @param {string} pm Package manager to probe (e.g. 'npm', 'pnpm') + * @param {typeof spawnSync} spawnFn Injectable for testing + * @returns {{ pm: string, ok: boolean, output: string }} + */ +export function verifyPackageManager(pm, spawnFn = spawnSync) { + const { status, stdout, stderr } = spawnFn(pm, ['safe-chain-verify'], { + shell: true, + encoding: 'utf8', + }); + const output = `${stdout ?? ''}${stderr ?? ''}`; + const ok = status === 0 && output.includes('OK: Safe-chain works!'); + + return { pm, ok, output }; +} + +/** + * Verify Safe Chain for each package manager defined in PACKAGE_MANAGERS + * + * @param {typeof spawnSync} spawnFn Injectable for testing + * @returns {boolean} true when all package managers report OK + */ +export function verifySafeChain(spawnFn = spawnSync) { + let allOk = true; + for (const pm of PACKAGE_MANAGERS) { + const { ok, output } = verifyPackageManager(pm, spawnFn); + process.stdout.write(output.endsWith('\n') ? output : `${output}\n`); + + if (!ok) { + console.error( + `::error::SafeChain inactive: '${pm} safe-chain-verify' failed or returned unexpected output`, + ); + allOk = false; + } + } + return allOk; +} + +// only run when executed directly, not when imported by tests +if (import.meta.url === pathToFileURL(process.argv[1]).href) { + console.log("Verifying SafeChain"); + process.exit(verifySafeChain() ? 0 : 1); +} diff --git a/.github/scripts/verify-safechain.test.mjs b/.github/scripts/verify-safechain.test.mjs new file mode 100644 index 00000000000..b5de48aef40 --- /dev/null +++ b/.github/scripts/verify-safechain.test.mjs @@ -0,0 +1,57 @@ +import { describe, it } from 'node:test'; +import assert from 'node:assert/strict'; + +import { verifyPackageManager, verifySafeChain } from './verify-safechain.mjs'; + +/** + * Run these tests by running + * + * node --test ./.github/scripts/verify-safechain.test.mjs + * */ + +// Build a fake spawnSync that returns a canned result per package manager. +const fakeSpawn = (resultsByPm) => (pm) => resultsByPm[pm] ?? { status: 127, stdout: '', stderr: '' }; + +describe('verifyPackageManager', () => { + it('is ok when status is 0 and output contains OK: Safe-chain works!', () => { + const spawn = fakeSpawn({ npm: { status: 0, stdout: 'OK: Safe-chain works!\n', stderr: '' } }); + assert.deepEqual(verifyPackageManager('npm', spawn), { + pm: 'npm', + ok: true, + output: 'OK: Safe-chain works!\n', + }); + }); + + it('is not ok when the command exits non-zero', () => { + const spawn = fakeSpawn({ npm: { status: 1, stdout: '', stderr: 'command not found' } }); + assert.equal(verifyPackageManager('npm', spawn).ok, false); + }); + + it('is not ok when exit is 0 but OK marker is missing (unwrapped pm)', () => { + const spawn = fakeSpawn({ npm: { status: 0, stdout: 'Unknown command: safe-chain-verify', stderr: '' } }); + assert.equal(verifyPackageManager('npm', spawn).ok, false); + }); + + it('reads the marker from stderr too', () => { + const spawn = fakeSpawn({ npm: { status: 0, stdout: '', stderr: 'OK: Safe-chain works!' } }); + assert.equal(verifyPackageManager('npm', spawn).ok, true); + }); +}); + +describe('verifySafeChain', () => { + it('returns true only when every package manager reports OK', () => { + const spawn = fakeSpawn({ + npm: { status: 0, stdout: 'OK: Safe-chain works!\n', stderr: '' }, + pnpm: { status: 0, stdout: 'OK: Safe-chain works!\n', stderr: '' }, + }); + assert.equal(verifySafeChain(spawn), true); + }); + + it('returns false when any package manager fails', () => { + const spawn = fakeSpawn({ + npm: { status: 0, stdout: 'OK: Safe-chain works!\n', stderr: '' }, + pnpm: { status: 1, stdout: '', stderr: 'nope' }, + }); + assert.equal(verifySafeChain(spawn), false); + }); +}); diff --git a/.github/test-metrics/e2e-impact-map.json b/.github/test-metrics/e2e-impact-map.json index 1274e5add43..244db28e171 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/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/langchain-agents.spec.ts","tests/e2e/ai/langchain-chains.spec.ts","tests/e2e/ai/langchain-vectorstores.spec.ts","tests/e2e/ai/workflow-builder.spec.ts","tests/e2e/api/wait-form-resume.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/app-config/security-notifications.spec.ts","tests/e2e/app-config/versions.spec.ts","tests/e2e/auth/admin-smoke.spec.ts","tests/e2e/auth/authenticated.spec.ts","tests/e2e/auth/oidc.spec.ts","tests/e2e/auth/signin.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/node-details-configuration.spec.ts","tests/e2e/building-blocks/user-service.spec.ts","tests/e2e/building-blocks/workflow-entry-points.spec.ts","tests/e2e/capabilities/proxy-server.spec.ts","tests/e2e/capabilities/task-runner.spec.ts","tests/e2e/chat-hub/chat-hub-attachment.spec.ts","tests/e2e/chat-hub/chat-hub-basic.spec.ts","tests/e2e/chat-hub/chat-hub-chat-user.spec.ts","tests/e2e/chat-hub/chat-hub-personal-agent.spec.ts","tests/e2e/chat-hub/chat-hub-settings.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/credentials/global.spec.ts","tests/e2e/credentials/oauth.spec.ts","tests/e2e/data-tables/details.spec.ts","tests/e2e/data-tables/tables.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-chat-basics.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-sidebar.spec.ts","tests/e2e/instance-ai/instance-ai-timeline.spec.ts","tests/e2e/instance-ai/instance-ai-workflow-execution.spec.ts","tests/e2e/instance-ai/instance-ai-workflow-preview.spec.ts","tests/e2e/instance-ai/instance-ai-workflow-setup.spec.ts","tests/e2e/mcp-registry/mcp-registry.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/email-send-node.spec.ts","tests/e2e/nodes/form-trigger-node.spec.ts","tests/e2e/nodes/http-request-node.spec.ts","tests/e2e/nodes/if-node.spec.ts","tests/e2e/nodes/kafka-nodes.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-advanced.spec.ts","tests/e2e/projects/folders-basic.spec.ts","tests/e2e/projects/folders-operations.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/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-4462-template-setup-experiment.spec.ts","tests/e2e/regression/AI-1401-sub-nodes-input-panel.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-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/sentry/sentry-baseline.spec.ts","tests/e2e/settings/community-nodes/community-nodes.spec.ts","tests/e2e/settings/environments/variables.spec.ts","tests/e2e/settings/external-secrets/secret-providers-connections-ui.spec.ts","tests/e2e/settings/log-streaming/log-streaming-ui-e2e.spec.ts","tests/e2e/settings/log-streaming/log-streaming.spec.ts","tests/e2e/settings/personal/personal.spec.ts","tests/e2e/settings/personal/two-factor-authentication.spec.ts","tests/e2e/settings/users/users.spec.ts","tests/e2e/settings/workers/workers.spec.ts","tests/e2e/sharing/access-control.spec.ts","tests/e2e/sharing/credential-sharing.spec.ts","tests/e2e/sharing/credential-visibility.spec.ts","tests/e2e/sharing/workflow-sharing.spec.ts","tests/e2e/workflows/checklist/production-checklist.spec.ts","tests/e2e/workflows/demo-diff.spec.ts","tests/e2e/workflows/demo-executable-chat-trigger.spec.ts","tests/e2e/workflows/editor/canvas/actions.spec.ts","tests/e2e/workflows/editor/canvas/canvas-nodes.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/node-groups.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/executions-list-infinite-scroll.spec.ts","tests/e2e/workflows/editor/execution/inject-previous.spec.ts","tests/e2e/workflows/editor/execution/logs.spec.ts","tests/e2e/workflows/editor/execution/partial.spec.ts","tests/e2e/workflows/editor/expressions/inline.spec.ts","tests/e2e/workflows/editor/expressions/mapping.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/ndv-data-display.spec.ts","tests/e2e/workflows/editor/ndv/ndv-floating-nodes.spec.ts","tests/e2e/workflows/editor/ndv/ndv-parameters.spec.ts","tests/e2e/workflows/editor/ndv/paired-item.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/routing.spec.ts","tests/e2e/workflows/editor/subworkflows/debugging.spec.ts","tests/e2e/workflows/editor/subworkflows/extraction.spec.ts","tests/e2e/workflows/editor/subworkflows/workflow-selector.spec.ts","tests/e2e/workflows/editor/tags.spec.ts","tests/e2e/workflows/editor/viewer-permissions.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/list/import.spec.ts","tests/e2e/workflows/list/workflows.spec.ts","tests/e2e/workflows/templates/credentials-setup.spec.ts","tests/e2e/workflows/templates/templates.spec.ts","tests/e2e/ai/rag-callout.spec.ts"],"files":{"packages/@n8n/api-types/src/agents/agent-integration.schema.ts":{"3":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"16":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/@n8n/api-types/src/dto/data-table/list-data-table-query.dto.ts":{"32":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/@n8n/api-types/src/dto/pagination/pagination.dto.ts":{"18":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"55":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/@n8n/api-types/src/schemas/password.schema.ts":{"13":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/@n8n/chat-hub/src/constants.ts":{"50":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/@n8n/chat/src/composables/useChat.ts":{"6":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/@n8n/chat/src/utils/event-bus.ts":{"11":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"22":[6,7,8,9,81,102,117],"36":[6,7,8,9,81,102,117],"40":[6,7,8,9,81,102,117]},"packages/@n8n/codemirror-lang-sql/src/sql.ts":{"19":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"26":[111],"61":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"76":[111],"80":[111],"140":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"157":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"195":[111]},"packages/@n8n/codemirror-lang-sql/src/tokens.ts":{"33":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"80":[111],"88":[111],"113":[111],"122":[111],"141":[111],"164":[111],"171":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"221":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"240":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"241":[111]},"packages/@n8n/composables/src/structuralComputed.ts":{"21":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,34,37,38,42,45,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,90,91,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"27":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146]},"packages/@n8n/composables/src/useDeviceSupport.ts":{"3":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"26":[6,7,9,81,84,102,104,105,106,107,108,109,117,129,135],"28":[1,2,4,5,7,21,23,27,37,40,47,51,53,57,64,69,70,71,74,77,80,82,83,84,85,88,89,97,98,102,103,104,105,107,108,109,111,116,117,119,121,122,123,124,125,126,127,129,133,135,138,139,140,141,142,143,144,145,146]},"packages/@n8n/composables/src/useDocumentTitle.ts":{"28":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"37":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"42":[139],"47":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/@n8n/composables/src/useShortKeyPress.ts":{"6":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"22":[147],"33":[1,4,5,147,105,111,119,122,127,129,130,131]},"packages/@n8n/composables/src/useThrottleWithReactiveDelay.ts":{"7":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"12":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/@n8n/design-system/src/components/AskAssistantButton/AskAssistantButton.vue":{"8":[1,2,3],"26":[1,2,3]},"packages/@n8n/design-system/src/components/AskAssistantChat/AskAssistantChat.vue":{"25":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"62":[1],"77":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"78":[1,2,3,4,5,10],"86":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"87":[1,2,3,4,5,10],"99":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"133":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"272":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"275":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"287":[1,2,3,4,5,10],"303":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,37,38,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,90,91,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"307":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"311":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"315":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"321":[1,2,3,4,5,10],"327":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"332":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"345":[5],"360":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,37,38,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,90,91,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"364":[10],"378":[1],"382":[1,4,5,10],"391":[5,10],"395":[5,10],"399":[1,4,5,10],"403":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"405":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"422":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"439":[1,2,3,4],"443":[1,2,3,4,5,10],"456":[1,2,3,4,5,10],"464":[1,2,3,4,5,10],"469":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"500":[1,2,3,4,5,10],"507":[1,2,3,4,5,10],"534":[2],"535":[2],"538":[5],"554":[1,2,4],"562":[1],"563":[1,2,4],"597":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"602":[5,10],"614":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/@n8n/design-system/src/components/AskAssistantChat/messages/BaseMessage.vue":{"16":[1,2,3,4,5,10],"26":[1,2,3,4,5,10]},"packages/@n8n/design-system/src/components/AskAssistantChat/messages/MessageWrapper.vue":{"22":[1,2,3,4,5,10],"30":[1,2,3,4,5,10],"33":[1,2,3,4,5,10],"47":[2],"48":[2]},"packages/@n8n/design-system/src/components/AskAssistantChat/messages/TextMessage.vue":{"31":[4],"40":[1,2,3,4,5,10],"42":[1,2,3,4,5,10],"52":[1,2,3,4,5,10],"53":[1,2,3,4,5,10],"58":[1,2,3,4,5,10],"80":[1,2,3,4,5,10],"89":[1,2,3,4,5,10],"137":[4]},"packages/@n8n/design-system/src/components/AskAssistantChat/messages/ThinkingMessage.vue":{"14":[1,2,3,4,5,10],"21":[1,2,3,4,5,10],"23":[1,2,3,4,5,10],"32":[1,2,3,4,5,10],"38":[1,2,3,4,5,10],"48":[1,2,3,4,5,10],"64":[1,2,3,4,5,10],"65":[1,2,3,4,5,10]},"packages/@n8n/design-system/src/components/AskAssistantChat/messages/helpers.ts":{"10":[1,2,3,4,5,10]},"packages/@n8n/design-system/src/components/AskAssistantChat/messages/useMarkdown.ts":{"6":[1,2,3,4,5,10],"20":[1,2,3,4,5,10]},"packages/@n8n/design-system/src/components/AskAssistantIcon/AssistantIcon.vue":{"4":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"22":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"30":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/@n8n/design-system/src/components/AskAssistantText/AssistantText.vue":{"9":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/@n8n/design-system/src/components/BlinkingCursor/BlinkingCursor.vue":{"2":[1,2,3,4,5]},"packages/@n8n/design-system/src/components/ConditionalRouterLink/CondtionalRouterLink.vue":{"16":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"27":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,35,36,38,39,40,41,42,43,44,45,46,47,48,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,104,105,106,107,108,110,111,112,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,131,132,134,135,136,137,138,139,140,141,143,144,145,146],"32":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/@n8n/design-system/src/components/InlineAskAssistantButton/InlineAskAssistantButton.vue":{"8":[1,2,3,4],"37":[1,2,3,4],"39":[1,2,3],"42":[1,2,3,4]},"packages/@n8n/design-system/src/components/N8nActionBox/ActionBox.vue":{"33":[3,15,23,33,35,36,37,38,39,40,41,68,69,70,71,72,87,88,89,90,91,95,97,98,138,144],"46":[3,23,33,36,37,38,39,40,41,68,69,70,72,87,88,89,90,91,95,97,98],"51":[3,15,23,33,35,36,37,38,39,40,41,71,72,87,88,89,91,95,97,98,138,144],"59":[3,23,36,37,38,39,40,41,68,69,70,72,87,88,89,90,91,95,97,98],"67":[23,39,41,88,89,90,91]},"packages/@n8n/design-system/src/components/N8nActionDropdown/ActionDropdown.vue":{"14":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,29,30,31,32,34,35,36,37,38,40,41,42,45,47,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,94,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"49":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,29,30,31,32,34,35,36,37,38,40,41,42,45,47,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,94,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"54":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,29,30,31,32,34,35,36,37,38,40,41,42,45,47,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,94,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"59":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,29,30,31,32,34,35,36,37,38,40,41,42,45,47,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,94,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"67":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,29,30,31,32,34,35,36,37,38,40,41,42,45,47,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,94,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"68":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,29,30,31,32,34,35,36,37,38,40,41,42,45,47,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,94,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"86":[1,2,4,27,32,40,47,64,68,74,77,83,84,85,94,96,99,109,117,124,125,127,129,133,139,143],"87":[1,2,4,27,32,40,47,64,68,74,77,83,84,85,94,96,99,109,117,124,125,127,129,133,139,143],"97":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,29,30,31,32,34,35,36,37,38,40,41,42,45,47,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,94,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"104":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,29,30,31,32,34,35,36,37,38,40,41,42,45,47,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,94,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"128":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,29,30,31,32,34,35,36,37,38,40,41,42,45,47,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,94,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"141":[1,2,4,27,32,40,47,64,68,74,77,83,84,85,94,96,99,109,117,124,125,127,129,133,139,143],"149":[1,2,4,27,32,40,47,64,68,74,77,83,84,85,94,96,99,109,117,124,125,127,129,133,139,143],"151":[1,2,4,27,32,40,47,64,68,74,77,83,84,85,96,99,117,124,125,127,139,143],"156":[1,2,4,27,32,40,47,64,68,74,77,83,84,85,94,96,99,109,117,124,125,127,129,133,139,143]},"packages/@n8n/design-system/src/components/N8nActionToggle/ActionToggle.vue":{"31":[1,2,3,4,5,7,8,9,11,12,15,16,18,19,20,21,22,23,24,26,27,28,30,33,34,35,37,38,39,40,41,49,51,52,53,55,57,58,60,61,62,65,66,67,68,69,70,71,72,73,74,75,76,79,80,81,82,83,84,85,87,88,89,90,91,93,94,96,97,98,100,103,104,105,106,109,110,111,112,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,144,145,146],"52":[1,2,3,4,5,7,8,9,11,12,15,16,18,19,20,21,22,23,24,26,27,28,30,33,34,35,37,38,39,40,41,49,51,52,53,55,57,58,60,61,62,65,66,67,68,69,70,71,72,73,74,75,76,79,80,81,82,83,84,85,87,88,89,90,91,93,94,96,97,98,100,103,104,105,106,109,110,111,112,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,144,145,146],"53":[1,2,3,4,5,7,8,9,11,12,15,16,18,19,20,21,22,23,24,26,27,28,30,33,34,35,37,38,39,40,41,49,51,52,53,55,57,58,60,61,62,65,66,67,68,69,70,71,72,73,74,75,76,79,80,81,82,83,84,85,87,88,89,90,91,93,94,96,97,98,100,103,104,105,106,109,110,111,112,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,144,145,146],"62":[33,41,68,69,70,72,87,89,91,94,131,144],"63":[33,41,68,69,70,72,87,89,91,94,131,144],"92":[1,2,3,4,5,7,8,9,11,12,15,16,18,19,20,21,22,23,24,26,27,28,30,33,34,35,37,38,39,40,41,49,51,52,53,55,57,58,60,61,62,65,66,67,68,69,70,71,72,73,74,75,76,79,80,81,82,83,84,85,87,88,89,90,91,93,94,96,97,98,100,103,104,105,106,109,110,111,112,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,144,145,146],"99":[33,41,68,69,70,72,87,89,91,94,131,144],"117":[1,2,3,4,5,7,8,9,11,12,15,16,18,19,20,21,22,23,24,26,27,28,30,33,34,35,37,38,39,40,41,49,51,52,53,55,57,58,60,61,62,65,66,67,68,69,70,71,72,73,74,75,76,79,80,81,82,83,84,85,87,88,89,90,91,93,94,96,97,98,100,103,104,105,106,109,110,111,112,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,144,145,146],"130":[69],"132":[69],"139":[33,41,68,69,70,72,87,89,91,94,131,144]},"packages/@n8n/design-system/src/components/N8nBlockUi/BlockUi.vue":{"12":[1,2,3,4,6,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,102,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"13":[1,2,3,4,6,7,8,9,11,12,14,21,22,23,24,27,28,38,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,102,104,105,106,110,111,114,116,117,118,119,120,121,122,123,124,125,126,127,128,131,132,134,135,136,138,140,144]},"packages/@n8n/design-system/src/components/N8nButton/Button.vue":{"9":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"25":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"31":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"37":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"43":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"48":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"53":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"55":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"81":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,20,21,22,23,24,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,96,97,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"84":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"103":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,38,39,40,41,42,43,44,45,46,47,48,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,104,105,106,107,108,110,111,112,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,131,132,134,135,136,137,138,139,140,141,143,144,145,146],"105":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/@n8n/design-system/src/components/N8nCallout/Callout.vue":{"9":[3,7,8,14,23,29,30,33,34,36,37,38,39,42,44,45,46,48,49,50,51,52,53,55,66,76,80,82,88,89,97,98,100,103,111,113,114,119,120,121,122,123,124,125,126,127,128,129,130,131,132,136,139,140,144,145],"33":[3,7,8,14,23,29,30,33,34,36,37,38,39,42,44,45,46,48,49,50,51,52,53,55,66,76,80,82,88,89,97,98,100,103,111,113,114,119,120,121,122,123,124,125,126,127,128,129,130,131,132,136,139,140,144,145],"42":[7,8,14,29,30,34,36,37,42,44,45,46,48,49,50,52,55,66,76,80,82,88,89,100,103,111,113,114,119,120,121,122,123,125,126,127,128,129,132,136,139,140,144],"46":[7,8,14,29,30,34,36,37,42,44,45,46,48,49,50,52,55,66,76,80,82,88,89,100,103,111,113,114,119,120,121,122,123,125,126,127,128,129,132,136,139,140,144],"55":[3,7,8,14,23,29,30,33,34,36,37,38,39,42,44,45,46,48,49,50,51,52,53,55,66,76,80,82,88,89,97,98,100,103,111,113,114,119,120,121,122,123,124,125,126,127,128,129,130,131,132,136,139,140,144,145],"64":[3,7,8,14,23,29,30,33,34,36,37,38,39,42,44,45,46,48,49,50,51,52,53,55,66,76,80,82,88,89,97,98,100,103,111,113,114,119,120,121,122,123,124,125,126,127,128,129,130,131,132,136,139,140,144,145]},"packages/@n8n/design-system/src/components/N8nCommandBar/CommandBar.vue":{"34":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"42":[144],"43":[144],"46":[144],"50":[144],"57":[144],"62":[144],"85":[144],"90":[144],"103":[144],"110":[144],"115":[144],"122":[144],"126":[144],"127":[144],"155":[144],"163":[144],"189":[144],"202":[1,2,4,5,7,10,21,23,27,37,40,47,51,53,54,57,64,69,70,71,72,74,75,77,80,82,83,84,85,88,89,90,93,97,98,103,104,105,107,108,109,111,116,117,119,120,121,122,123,124,125,126,127,129,130,131,133,135,137,138,139,140,141,142,143,144,145,146],"252":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,21,22,23,24,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,45,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"260":[144],"265":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"270":[93,112,115,117,141,142],"274":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"279":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,38,39,40,41,42,43,44,45,46,47,48,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,104,105,106,107,108,110,111,112,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,131,132,134,135,136,137,138,139,140,141,143,144,145,146],"280":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,38,39,40,41,42,43,44,45,46,47,48,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,104,105,106,107,108,110,111,112,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,131,132,134,135,136,137,138,139,140,141,143,144,145,146],"293":[144],"313":[144],"325":[144],"327":[144],"340":[144]},"packages/@n8n/design-system/src/components/N8nDropdownMenu/DropdownMenu.typeguards.ts":{"6":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,45,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,93,94,96,97,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"8":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,45,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,93,94,96,97,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/@n8n/design-system/src/components/N8nDropdownMenu/DropdownMenu.vue":{"27":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,45,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,93,94,96,97,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"55":[30,31,32,68,69,70],"93":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,45,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,93,94,96,97,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"101":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,45,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,93,94,96,97,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"110":[1,2,3,4,24,27,30,31,32,33,37,40,41,47,64,67,68,69,70,72,74,77,83,84,85,87,89,91,94,96,99,109,117,124,125,127,129,131,133,139,143,144],"121":[30,31,32],"147":[30,31,32,68,69,70],"176":[1,2,3,4,24,27,30,31,32,33,37,40,41,47,64,67,68,69,70,72,74,77,83,84,85,87,89,91,94,96,99,109,117,124,125,127,129,131,133,139,143,144],"190":[1,2,3,4,6,7,8,9,11,12,15,18,19,20,21,22,23,24,27,28,30,31,32,33,34,37,38,40,41,42,47,50,51,52,53,55,57,60,62,64,65,66,67,68,69,70,71,72,73,74,76,77,79,80,81,82,83,84,85,87,89,91,93,94,96,97,98,99,100,102,103,104,105,106,109,110,111,112,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,135,138,139,140,141,142,143,144,145,146],"197":[1,2,3,4,7,8,11,12,21,22,24,27,28,30,31,32,33,37,38,40,41,47,52,55,60,62,64,65,67,68,69,70,72,74,76,77,79,82,83,84,85,87,89,91,94,96,99,100,103,104,105,109,110,111,112,113,114,117,118,119,120,121,122,123,124,125,126,127,128,129,131,132,133,135,138,139,140,143,144],"204":[1,2,3,4,7,8,11,12,22,24,27,28,30,31,32,33,37,38,40,41,47,52,60,62,64,67,68,69,70,72,74,76,77,79,82,83,84,85,87,89,91,94,96,99,100,103,104,105,109,110,111,112,113,114,117,118,119,120,121,122,123,124,125,126,127,128,129,131,132,133,138,139,140,143,144],"218":[1,2,3,4,24,27,30,31,32,33,37,40,41,47,64,67,68,69,70,72,74,77,83,84,85,87,89,91,94,96,99,109,117,124,125,127,129,131,133,139,143,144],"225":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,45,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,93,94,96,97,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"226":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,45,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,93,94,96,97,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"239":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,45,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,93,94,96,97,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"240":[1,2,3,4,5,7,8,10,11,12,15,21,23,24,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,45,49,51,52,53,54,55,56,57,58,60,61,62,64,65,66,67,68,69,70,72,74,76,77,80,82,83,84,85,89,90,94,96,97,98,99,100,103,104,105,108,109,110,111,112,113,114,115,117,118,119,120,121,122,124,125,126,127,129,130,131,132,133,136,137,138,139,140,141,142,143,144,145,146],"246":[1,3,4,6,7,8,9,11,12,15,18,19,20,21,22,23,24,28,30,32,33,34,37,38,40,41,42,47,50,51,52,53,55,57,60,62,65,66,67,68,69,70,71,72,73,76,79,80,81,82,83,84,85,87,89,91,93,94,96,97,98,100,102,103,104,105,106,109,110,111,112,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,135,138,139,140,141,142,144,145,146],"255":[1,2,3,4,24,27,30,31,32,33,37,40,41,47,64,67,68,69,70,72,74,77,83,84,85,87,89,91,94,96,99,109,117,124,125,127,129,131,133,139,143,144],"285":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,45,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,93,94,96,97,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"289":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,29,30,31,32,33,34,35,36,38,39,40,41,42,45,47,48,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,93,94,96,97,98,99,100,102,104,105,106,107,108,110,111,112,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,131,132,134,135,136,137,138,139,140,141,143,144,145,146],"290":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,45,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,93,94,96,97,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"319":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,45,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,93,94,96,97,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"334":[1,2,3,4,24,27,30,31,32,33,40,41,47,64,67,68,69,70,72,74,77,83,84,85,87,89,91,94,96,99,117,124,125,127,131,139,143,144],"375":[1,2,3,4,24,27,30,31,32,33,37,40,41,47,64,67,68,69,70,72,74,77,83,84,85,87,89,91,94,96,99,109,117,124,125,127,129,131,133,139,143,144],"377":[1,2,3,4,24,27,30,31,32,33,40,41,47,64,67,68,69,70,72,74,77,83,84,85,87,89,91,94,96,99,117,124,125,127,131,139,143,144],"384":[30,31,32,68,69,70],"387":[1,2,4,27,30,31,32,40,47,64,68,74,77,83,84,85,94,96,99,109,117,124,125,127,129,133,139,143],"390":[1,2,4,27,30,31,32,40,47,64,68,69,70,74,77,83,84,85,94,96,99,109,117,124,125,127,129,133,139,143],"393":[1,2,4,27,30,31,32,33,40,41,47,64,68,69,70,72,74,77,83,84,85,87,89,91,94,96,99,109,117,124,125,127,129,131,133,139,143,144]},"packages/@n8n/design-system/src/components/N8nDropdownMenu/DropdownMenuItem.vue":{"25":[1,2,3,4,24,27,30,31,32,33,37,40,41,47,64,67,68,69,70,72,74,77,83,84,85,87,89,91,94,96,99,109,117,124,125,127,129,131,133,139,143,144],"81":[1,2,3,4,24,27,30,31,32,33,37,40,41,47,64,67,68,69,70,72,74,77,83,84,85,87,89,91,94,96,99,109,117,124,125,127,129,131,133,139,143,144],"82":[1,2,3,4,24,27,30,31,32,33,37,40,41,47,64,67,68,69,70,72,74,77,83,84,85,87,89,91,94,96,99,109,117,124,125,127,129,131,133,139,143,144],"84":[30,31,32,68,69,70],"110":[1,2,3,4,24,27,30,31,32,33,37,40,41,47,64,67,68,69,70,72,74,77,83,84,85,87,89,91,94,96,99,109,117,124,125,127,129,131,133,139,143,144],"114":[1,2,3,4,24,27,30,31,32,33,37,40,41,47,64,67,68,69,70,72,74,77,83,84,85,87,89,91,94,96,99,109,117,124,125,127,129,131,133,139,143,144],"118":[1,2,3,4,24,27,30,31,32,33,37,40,41,47,64,67,68,69,70,72,74,77,83,84,85,87,89,91,94,96,99,109,117,124,125,127,129,131,133,139,143,144],"122":[3,24,33,37,41,67,68,69,70,72,87,89,91,94,131,144],"124":[30,31,32],"128":[1,2,3,4,24,27,30,31,32,33,37,40,41,47,64,67,68,69,70,72,74,77,83,84,85,87,89,91,94,96,99,109,117,124,125,127,129,131,133,139,143,144],"135":[1,2,3,4,24,27,30,31,32,33,37,40,41,47,64,67,68,69,70,72,74,77,83,84,85,87,89,91,94,96,99,109,117,124,125,127,129,131,133,139,143,144],"143":[1,2,3,4,24,27,30,31,32,33,37,40,41,47,64,67,68,69,70,72,74,77,83,84,85,87,89,91,94,96,99,109,117,124,125,127,129,131,133,139,143,144],"144":[1,2,3,4,24,27,30,31,32,33,37,40,41,47,64,67,68,69,70,72,74,77,83,84,85,87,89,91,94,96,99,109,117,124,125,127,129,131,133,139,143,144],"152":[1,2,3,4,24,27,30,31,32,33,37,40,41,47,64,67,68,69,70,72,74,77,83,84,85,87,89,91,94,96,99,109,117,124,125,127,129,131,133,139,143,144],"162":[30,31,32,68,69,70],"167":[30,31,32,68,69,70],"175":[68,69,70],"205":[30,31,32,68,69,70],"212":[30,31,32],"238":[30,31,32],"240":[30,31,32],"248":[30,31,32],"251":[30,31,32],"254":[30,31,32],"280":[1,2,3,4,24,27,30,31,32,33,37,40,41,47,64,67,68,69,70,72,74,77,83,84,85,87,89,91,94,96,99,109,117,124,125,127,129,131,133,139,143,144],"282":[1,2,3,4,24,27,30,31,32,33,37,41,64,67,68,69,70,72,74,77,83,84,85,87,89,91,94,96,99,109,117,124,125,127,129,131,133,139,143,144],"294":[3,24,33,37,41,67,68,69,70,72,87,89,91,94,131,144],"299":[3,24,33,41,67,68,69,70,72,87,89,91,94,131,144]},"packages/@n8n/design-system/src/components/N8nDropdownMenu/composables/useMenuKeyboardNavigation.ts":{"23":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,45,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,93,94,96,97,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"110":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,45,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,93,94,96,97,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/@n8n/design-system/src/components/N8nFormInput/validators.ts":{"7":[15,18,20,25,35,41,71,88,89,92,93,98,138,144],"36":[88],"67":[20,25,92,93],"97":[88],"109":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"139":[15,18,20,25,35,41,71,88,89,92,93,98,138,144]},"packages/@n8n/design-system/src/components/N8nHeading/Heading.vue":{"27":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"34":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"50":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"52":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"56":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,38,39,40,41,42,43,44,45,46,47,48,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,104,105,106,107,108,110,111,112,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,131,132,134,135,136,137,138,139,140,141,143,144,145,146]},"packages/@n8n/design-system/src/components/N8nIcon/Icon.vue":{"21":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"28":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"38":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"50":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"77":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"93":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"95":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"97":[0,1,2,3,4,5,6,7,8,9,11,12,13,14,21,22,23,24,26,27,28,34,37,38,42,45,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,79,80,81,82,83,84,85,89,96,97,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,146],"104":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"110":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/@n8n/design-system/src/components/N8nIcon/custom/bolt-filled.svg":{"9":[0,1,2,3,4,5,6,7,8,9,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146]},"packages/@n8n/design-system/src/components/N8nIcon/custom/filled-square.svg":{"10":[1,2,3,4,5,10]},"packages/@n8n/design-system/src/components/N8nIcon/custom/node-ellipsis.svg":{"11":[0,1,2,3,4,5,6,7,8,9,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146]},"packages/@n8n/design-system/src/components/N8nIcon/custom/node-play.svg":{"11":[0,1,2,3,4,5,6,7,8,9,11,12,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146]},"packages/@n8n/design-system/src/components/N8nIcon/custom/node-power.svg":{"11":[0,1,2,3,4,5,6,7,8,9,11,12,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146]},"packages/@n8n/design-system/src/components/N8nIcon/custom/node-trash.svg":{"11":[0,1,2,3,4,5,6,7,8,9,11,12,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146]},"packages/@n8n/design-system/src/components/N8nIcon/custom/node-validation-error.svg":{"11":[1,2,3,4,5,7,8,11,12,21,22,23,24,37,38,52,53,55,57,58,60,61,67,74,76,78,79,80,83,96,98,100,103,105,111,113,114,117,120,124,126,127,128,129,130,132,136,140,141,142,143,145,146]},"packages/@n8n/design-system/src/components/N8nIcon/custom/pop-out.svg":{"8":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/@n8n/design-system/src/components/N8nIcon/custom/spinner.svg":{"9":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/@n8n/design-system/src/components/N8nIcon/custom/toolbox.svg":{"10":[1,3,7,8,11,12,21,23,28,37,38,54,55,56,58,60,61,67,80,82,83,96,98,100,103,104,105,109,110,111,113,116,119,120,121,122,124,125,127,129,130,131,132,133,136,140]},"packages/@n8n/design-system/src/components/N8nIcon/icons.ts":{"771":[0,1,2,3,4,5,6,7,8,9,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"775":[0,1,2,3,4,5,6,7,8,9,11,12,13,14,21,22,23,24,26,27,28,34,37,38,42,45,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,79,80,81,82,83,84,85,89,96,97,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146]},"packages/@n8n/design-system/src/components/N8nIcon/nodes/chat-trigger.svg":{"11":[1,3,6,7,8,9,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,80,81,82,83,96,98,99,100,102,103,104,105,109,110,111,113,114,117,119,120,121,122,124,126,127,129,130,131,132,133,136,138,140,142,144]},"packages/@n8n/design-system/src/components/N8nIcon/nodes/form-trigger.svg":{"11":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,119,120,121,122,124,126,127,129,130,131,132,133,136,138,140,142,144]},"packages/@n8n/design-system/src/components/N8nIcon/nodes/manual-trigger.svg":{"11":[0,1,2,3,4,7,8,9,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,77,79,80,82,83,84,85,96,98,99,100,101,103,104,105,107,109,110,111,112,113,114,115,116,117,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,141,142,144]},"packages/@n8n/design-system/src/components/N8nIcon/nodes/schedule-trigger.svg":{"11":[1,3,5,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,76,80,82,83,96,98,99,100,103,104,105,106,109,110,111,113,114,117,118,119,120,121,122,124,126,127,129,130,131,132,133,136,138,139,140,142,143,144]},"packages/@n8n/design-system/src/components/N8nIcon/nodes/sub-workflow-trigger.svg":{"11":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,119,120,121,122,124,126,127,129,130,131,132,133,136,138,140,142,144]},"packages/@n8n/design-system/src/components/N8nIcon/nodes/webhook.svg":{"11":[1,3,7,8,11,12,14,21,23,24,26,28,37,38,52,53,54,55,56,57,58,60,61,62,65,66,67,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,118,119,120,121,122,124,126,127,129,130,131,132,133,136,138,140,142,144]},"packages/@n8n/design-system/src/components/N8nIconButton/IconButton.vue":{"6":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"7":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,38,39,40,41,42,43,44,45,46,47,48,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,104,105,106,107,108,110,111,112,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,131,132,134,135,136,137,138,139,140,141,143,144,145,146]},"packages/@n8n/design-system/src/components/N8nInfoTip/InfoTip.vue":{"14":[1,2,3,7,8,9,11,15,16,18,19,20,22,23,26,27,30,33,37,38,39,40,41,49,51,58,60,61,62,65,66,67,68,69,70,71,72,73,75,80,85,88,89,90,91,93,94,96,97,98,110,111,113,114,116,117,118,119,120,121,122,123,124,125,127,128,129,130,131,133,134,135,138,139,144,145,146],"57":[1,2,3,7,8,9,11,15,16,18,19,20,22,23,26,27,30,33,37,38,39,40,41,49,51,58,60,61,62,65,66,67,68,69,70,71,72,73,75,80,85,88,89,90,91,93,94,96,97,98,110,111,113,114,116,117,118,119,120,121,122,123,124,125,127,128,129,130,131,133,134,135,138,139,144,145,146],"63":[1,2,3,7,8,9,11,15,16,18,19,20,22,23,26,27,30,33,37,38,39,40,41,49,51,58,60,61,62,65,66,67,68,69,70,71,72,73,75,80,85,88,89,90,91,93,94,96,97,98,110,111,113,114,116,117,118,119,120,121,122,123,124,125,127,128,129,130,131,133,134,135,138,139,144,145,146]},"packages/@n8n/design-system/src/components/N8nInlineTextEdit/InlineTextEdit.vue":{"16":[0,1,2,3,4,5,6,7,8,9,10,11,12,14,21,22,23,24,26,27,28,30,33,34,36,37,38,39,40,41,42,45,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,74,75,76,77,78,79,80,81,82,83,84,85,89,90,91,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"35":[0,1,2,3,4,5,6,7,8,9,10,11,12,14,21,22,23,24,26,27,28,30,33,34,36,37,38,39,40,41,42,45,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,74,75,76,77,78,79,80,81,82,83,84,85,89,90,91,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"38":[0,1,2,3,4,5,6,7,8,9,10,11,12,14,21,22,23,24,26,27,28,30,33,34,36,37,38,39,40,41,42,45,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,74,75,76,77,78,79,80,81,82,83,84,85,89,90,91,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"44":[0,1,2,3,4,5,6,7,8,9,10,11,12,14,21,22,23,24,26,27,28,30,33,34,36,37,38,39,40,41,42,45,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,74,75,76,77,78,79,80,81,82,83,84,85,89,90,91,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"47":[0,1,2,3,4,5,6,7,8,9,10,11,12,14,21,22,23,24,26,27,28,30,33,34,36,37,38,39,40,41,42,45,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,74,75,76,77,78,79,80,81,82,83,84,85,89,90,91,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"57":[0,1,2,3,4,5,6,7,8,9,10,11,12,14,21,22,23,24,26,27,28,30,33,34,36,37,38,39,40,41,42,45,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,74,75,76,77,78,79,80,81,82,83,84,85,89,90,91,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"68":[1,2,4,23,27,37,38,40,51,64,69,70,74,77,83,84,85,89,90,91,97,98,99,107,117,124,125,127,129,133,143,144,145],"74":[1,2,4,27,38,64,69,74,77,83,84,85,99,117,124,125,127,129,133,137,139,143,144],"81":[1,2,4,23,27,37,38,40,51,64,69,70,74,77,83,84,85,89,90,91,97,98,99,107,117,124,125,127,129,133,143,144,145],"92":[1,2,4,23,27,37,38,40,51,64,69,70,74,77,83,84,85,89,90,91,97,98,99,107,117,124,125,127,129,133,143,144,145],"96":[1,2,4,23,27,37,38,40,51,64,69,70,74,77,83,84,85,89,90,91,97,98,99,107,117,124,125,127,129,133,137,139,143,144,145],"103":[0,1,2,3,4,5,6,7,8,9,10,11,12,14,21,22,23,24,26,27,28,30,33,34,36,37,38,39,40,41,42,45,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,74,75,76,77,78,79,80,81,82,83,84,85,89,90,91,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"122":[0,1,2,3,4,5,6,7,8,9,10,11,12,14,21,22,23,24,26,27,28,30,33,34,36,38,39,40,41,42,45,48,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,74,75,76,77,78,79,80,81,82,83,84,85,89,90,91,96,97,98,99,100,104,105,106,107,108,110,111,112,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,131,132,134,135,136,137,138,139,140,141,143,144,145,146],"127":[0,1,2,3,4,5,6,7,8,9,10,11,12,14,21,22,23,24,26,27,28,30,33,34,36,38,39,40,41,42,45,48,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,74,75,76,77,78,79,80,81,82,83,84,85,89,90,91,96,97,98,99,100,104,105,106,107,108,110,111,112,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,131,132,134,135,136,137,138,139,140,141,143,144,145,146],"143":[1,2,4,23,27,37,38,40,51,64,69,70,74,77,83,84,85,89,90,91,97,98,99,107,117,124,125,127,129,133,143,144,145]},"packages/@n8n/design-system/src/components/N8nInput/Input.vue":{"20":[1,2,3,4,5,6,7,8,9,11,12,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,55,57,58,60,61,62,65,66,67,68,69,70,71,72,73,74,75,76,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,96,97,98,100,102,103,104,105,106,108,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,143,144,145,146],"49":[1,2,3,4,5,6,7,8,9,11,12,14,15,16,18,19,20,21,22,23,24,25,26,27,28,30,32,33,34,35,37,38,39,40,41,49,51,52,53,55,57,58,60,61,62,65,66,67,68,69,70,71,72,73,74,75,76,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,96,97,98,100,102,103,104,105,106,108,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,143,144,145,146],"58":[1,2,3,4,5,6,7,8,9,11,12,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,55,57,58,60,61,62,65,66,67,68,69,70,71,72,73,74,75,76,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,96,97,98,100,102,103,104,105,106,108,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,143,144,145,146],"68":[1,2,3,4,5,6,7,8,9,11,12,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,55,57,58,60,61,62,65,66,67,68,69,70,71,72,73,74,75,76,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,96,97,98,100,102,103,104,105,106,108,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,143,144,145,146],"87":[1,2,3,4,5,6,7,8,9,11,12,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,55,57,58,60,61,62,65,66,67,68,69,70,71,72,73,74,75,76,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,96,97,98,100,102,103,104,105,106,108,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,143,144,145,146],"90":[1,2,3,4,5,6,7,8,9,11,12,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,55,57,58,60,61,62,65,66,67,68,69,70,71,72,73,74,75,76,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,96,97,98,100,102,103,104,105,106,108,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,143,144,145,146],"92":[1,2,3,4,5,6,7,8,9,11,12,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,55,57,58,60,61,62,65,66,67,68,69,70,71,72,73,74,75,76,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,96,97,98,100,102,103,104,105,106,108,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,143,144,145,146],"106":[1,2,3,4,5,6,7,8,9,11,12,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,55,57,58,60,61,62,65,66,67,68,69,70,71,72,73,74,75,76,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,96,97,98,100,102,103,104,105,106,108,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,143,144,145,146],"120":[4,7,8,11,12,15,20,23,24,27,29,30,31,32,34,35,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,60,61,62,67,69,71,80,87,88,89,90,91,92,93,94,97,98,110,113,120,123,124,125,127,130,131,136,137,138,143,144,145,146],"127":[4,7,8,11,12,15,20,23,24,27,29,30,31,32,34,35,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,60,61,62,66,67,68,71,80,87,88,89,90,91,92,93,94,97,98,100,106,109,110,113,120,123,124,125,127,130,131,135,136,137,138,139,140,143,144,145],"133":[4,7,8,11,12,15,18,20,23,24,27,29,30,31,32,34,35,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,60,61,62,66,67,68,69,71,80,87,88,89,90,91,92,93,94,97,98,100,106,109,110,113,120,123,124,125,127,130,131,135,136,137,138,139,140,143,144,145,146],"139":[4,37,40,69,71,88,90,93,109,120,123,124,127,137,144],"144":[11,12,24,27,51,60,61,69,94,109,120,127,130,131,136,144],"155":[1,2,3,4,5,6,7,8,9,11,12,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,55,57,58,60,61,62,65,66,67,68,69,70,71,72,73,74,75,76,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,96,97,98,100,102,103,104,105,106,108,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,143,144,145,146],"181":[15,29,30,31,32,34,35,41,42,43,44,45,46,47,48,49,50,51,71,88,89,98,138,144],"199":[15,29,30,31,32,34,35,41,42,43,44,45,46,47,48,49,50,51,71,88,89,98,138,144],"241":[1,3,4,6,7,8,9,11,12,15,18,19,20,21,22,23,24,28,29,30,31,32,33,34,35,37,38,40,41,42,43,44,45,46,47,48,49,50,51,52,53,55,57,60,62,65,66,67,68,69,70,71,72,73,75,76,79,80,81,82,83,84,87,88,89,91,93,94,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,135,136,137,138,139,140,143,144,145,146],"248":[15,29,30,31,32,34,35,41,42,43,44,45,46,47,48,49,50,51,71,88,89,98,138,144],"261":[1,2,3,4,5,6,7,8,9,11,12,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,55,57,58,60,61,62,65,66,67,68,69,70,71,72,73,74,75,76,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,96,97,98,100,102,103,104,105,106,108,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,143,144,145,146],"267":[1,3,4,6,7,8,9,11,12,15,18,19,20,21,22,23,24,28,30,32,33,34,35,37,38,40,41,42,43,44,45,46,47,48,49,50,51,52,53,55,57,60,62,65,66,67,68,69,70,71,72,73,75,76,79,80,81,82,83,84,87,88,89,91,93,94,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,135,136,137,138,139,140,143,144,145,146],"272":[1,2,3,4,5,6,7,8,9,11,12,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,55,57,58,60,61,62,65,66,67,68,69,70,71,72,73,74,75,76,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,96,97,98,100,102,103,104,105,106,108,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,143,144,145,146],"273":[1,4,7,8,11,12,14,15,20,21,22,23,24,25,27,29,30,31,32,33,34,35,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,53,58,60,61,62,66,67,68,69,71,75,76,80,81,85,87,88,89,90,91,92,93,94,97,98,105,106,110,113,114,116,117,118,120,123,124,125,126,127,128,129,130,131,135,136,137,138,143,144,145,146],"282":[1,2,3,4,5,6,7,8,9,11,12,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,55,57,58,60,61,62,65,66,67,68,69,70,71,72,73,74,75,76,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,96,97,98,100,102,103,104,105,106,108,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,143,144,145,146],"292":[4,7,8,11,12,15,18,20,23,24,27,29,30,31,32,34,35,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,60,61,62,67,68,69,71,80,88,89,90,91,93,94,97,98,106,109,113,120,123,124,125,127,130,131,135,136,137,138,143,144,145],"293":[124,130],"294":[15,40,41,66,71,98,100,123,125,135,138,139,140,144],"297":[1,2,3,4,5,6,7,8,9,11,12,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,55,57,58,60,61,62,65,66,67,68,69,70,71,72,73,74,75,76,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,96,97,98,100,102,103,104,105,106,108,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,143,144,145,146]},"packages/@n8n/design-system/src/components/N8nInputLabel/InputLabel.vue":{"31":[1,2,3,4,5,7,8,9,11,12,14,15,18,20,21,22,23,24,25,27,28,30,32,33,34,35,37,38,39,40,41,49,51,52,53,55,57,58,60,61,62,65,66,67,71,74,75,76,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,144,145],"33":[1,2,3,4,5,7,8,9,11,12,14,15,18,20,21,22,23,24,25,27,28,30,32,33,34,35,37,38,39,40,41,49,51,52,53,55,57,58,60,61,62,65,66,67,71,74,75,76,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,144,145],"65":[1,2,3,4,5,7,8,9,11,12,14,18,20,21,22,23,24,25,27,28,30,32,33,34,37,38,39,40,41,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,144,145],"69":[3,7,8,25,30,32,33,39,40,41,51,66,80,88,89,92,93,100,127,139,140,144,145]},"packages/@n8n/design-system/src/components/N8nInputNumber/InputNumber.vue":{"15":[1,3,7,9,11,14,24,33,53,55,65,67,75,76,82,89,90,100,104,109,111,114,116,117,118,119,120,121,122,124,125,126,127,128,129,130,131,132,133,140,145],"31":[1,3,7,9,11,14,24,33,53,55,65,67,75,76,82,89,90,100,104,109,111,114,116,117,118,119,120,121,122,124,125,126,127,128,129,130,131,132,133,140,145],"32":[1,3,7,9,11,14,24,33,53,55,65,67,75,76,82,89,90,100,104,109,111,114,116,117,118,119,120,121,122,124,125,126,127,128,129,130,131,132,133,140,145]},"packages/@n8n/design-system/src/components/N8nLink/Link.vue":{"31":[0,1,2,3,4,5,6,7,8,9,10,11,12,14,15,16,18,19,20,21,22,23,24,25,26,27,28,30,33,36,37,38,39,40,41,42,45,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"32":[0,1,2,3,4,5,6,7,8,9,10,11,12,14,15,16,18,19,20,21,22,23,24,25,26,27,28,30,33,36,38,39,40,41,42,45,48,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,104,105,106,107,108,110,111,112,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,131,132,134,135,136,137,138,139,140,141,143,144,145,146],"34":[0,1,2,3,4,5,6,7,8,9,10,11,12,14,15,16,18,19,20,21,22,23,24,25,26,27,28,30,33,36,38,39,40,41,42,45,48,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,104,105,106,107,108,110,111,112,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,131,132,134,135,136,137,138,139,140,141,143,144,145,146]},"packages/@n8n/design-system/src/components/N8nLoading/Loading.vue":{"38":[1,3,7,8,11,12,15,16,18,19,20,21,22,23,24,26,28,33,37,38,39,40,41,52,53,54,55,56,57,58,60,61,62,65,67,68,69,70,71,72,73,80,82,83,87,88,89,93,94,96,97,98,99,100,103,104,105,109,110,111,112,113,114,115,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,139,140,142,144,145,146],"47":[1,3,7,8,11,12,15,16,18,19,20,21,22,23,24,26,28,33,37,38,39,40,41,52,53,54,55,56,57,58,60,61,62,65,67,68,69,70,71,72,73,80,82,83,87,88,89,93,94,96,97,98,99,100,103,104,105,109,110,111,112,113,114,115,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,139,140,142,144,145,146],"49":[33,40,41,145],"60":[1,3,7,8,11,12,15,16,18,19,20,21,22,23,24,26,28,33,37,38,39,40,41,52,53,54,55,56,57,58,60,61,62,65,67,68,69,70,71,72,73,80,82,83,87,88,89,93,94,96,97,98,99,100,103,104,105,109,110,111,112,113,114,115,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,139,140,142,144,145,146]},"packages/@n8n/design-system/src/components/N8nMenuItem/MenuItem.vue":{"15":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"29":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"45":[16,32,33,38,40,41,72,89,93,97,98,109,133,138],"52":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"64":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"73":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"89":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"92":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"99":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"117":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,38,39,40,41,42,43,44,45,46,47,48,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,104,105,106,107,108,110,111,112,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,131,132,134,135,136,137,138,139,140,141,143,144,145,146],"126":[16,109],"135":[3,7,8,16,19,23,25,29,30,31,32,33,34,35,36,37,38,39,41,51,58,72,80,87,89,90,91,92,93,94,95,97,98,109,127,130,138,145]},"packages/@n8n/design-system/src/components/N8nNavigationDropdown/NavigationDropdown.vue":{"42":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"56":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"58":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"59":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"60":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"84":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,74,75,76,77,79,80,81,82,83,84,85,88,89,93,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"89":[15,41,71,73,98,133,138,144],"94":[15,41,71,98,138,144],"103":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"113":[15,41,71,98,133,138,144],"117":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"126":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"128":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"130":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,35,36,38,39,40,41,42,43,44,45,46,47,48,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,104,105,106,107,108,110,111,112,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,131,132,134,135,136,137,138,139,140,141,143,144,145,146],"141":[5,15,21,23,26,35,37,39,40,41,53,54,56,57,58,60,61,62,64,67,68,69,70,71,72,74,75,76,77,79,80,81,82,83,85,88,89,96,98,99,103,104,106,109,111,112,113,118,119,120,121,122,127,129,130,131,136,138,144],"143":[5,15,21,23,26,35,37,39,40,41,53,54,56,57,58,60,61,62,64,67,68,69,70,71,72,74,75,76,77,79,80,81,82,83,85,88,89,96,98,99,103,104,106,109,111,112,113,118,119,120,121,122,127,129,130,131,136,138,144],"161":[5,15,21,23,26,35,37,39,40,41,53,54,56,57,58,60,61,62,64,67,68,69,70,71,72,74,75,76,77,79,80,81,82,83,85,88,89,96,98,99,103,104,106,109,111,112,113,118,119,120,121,122,127,129,130,131,136,138,144],"163":[5,15,21,23,26,35,39,40,41,53,54,56,57,58,60,61,62,64,67,68,69,70,71,72,74,75,76,77,79,80,81,82,83,85,88,89,96,98,99,104,106,111,112,118,119,120,121,122,127,131,136,138,144],"166":[5,15,21,23,26,35,39,40,41,53,54,56,57,58,60,61,62,64,67,68,69,70,71,72,74,75,76,77,79,80,81,82,83,85,88,89,96,98,99,104,106,111,112,118,119,120,121,122,127,131,136,138,144],"170":[144],"171":[5,15,21,23,26,35,37,39,40,41,53,54,56,57,58,60,61,62,64,67,68,69,70,71,72,74,75,76,77,79,80,81,82,83,85,88,89,96,98,99,103,104,106,109,111,112,113,118,119,120,121,122,127,129,130,131,136,138,144],"172":[5,15,21,23,26,35,37,39,40,41,53,54,56,57,58,60,61,62,64,67,68,69,70,71,72,74,75,76,77,79,80,81,82,83,85,88,89,96,98,99,103,104,106,109,111,112,113,118,119,120,121,122,127,129,130,131,136,138,144],"208":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"212":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,35,36,38,39,40,41,42,43,44,45,46,47,48,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,104,105,106,107,108,110,111,112,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,131,132,134,135,136,137,138,139,140,141,143,144,145,146]},"packages/@n8n/design-system/src/components/N8nNodeCreatorNode/NodeCreatorNode.vue":{"32":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"33":[1,3,7,8,11,12,21,23,24,28,38,52,53,54,55,56,57,58,60,61,62,65,67,80,82,83,96,98,99,100,104,105,110,111,114,116,119,120,121,122,124,125,126,127,131,132,136,138,140,144],"58":[7,23,37,56,62,96,98,104,111,124,127,140],"61":[7,52,126]},"packages/@n8n/design-system/src/components/N8nNodeIcon/IconContent.vue":{"20":[0,1,2,3,4,5,6,7,8,9,11,12,13,14,21,22,23,24,26,27,28,29,30,31,32,33,34,35,37,38,39,42,45,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,72,74,75,76,77,78,79,80,81,82,83,84,85,89,96,97,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"34":[0,1,2,3,4,5,6,7,8,9,11,12,13,14,21,22,23,24,26,27,28,34,37,38,42,45,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,79,80,81,82,83,84,85,89,96,97,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"53":[0,1,2,3,4,5,6,7,8,9,11,12,13,14,21,22,23,24,26,27,28,34,37,38,42,45,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,79,80,81,82,83,84,85,89,96,97,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"56":[0,1,2,3,4,5,6,7,8,9,11,12,13,14,21,22,23,24,26,27,28,29,30,31,32,33,34,35,37,38,39,42,45,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,72,74,75,76,77,78,79,80,81,82,83,84,85,89,96,97,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146]},"packages/@n8n/design-system/src/components/N8nNodeIcon/NodeIcon.vue":{"24":[0,1,2,3,4,5,6,7,8,9,11,12,13,14,21,22,23,24,26,27,28,29,30,31,32,33,34,35,37,38,39,42,45,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,72,74,75,76,77,78,79,80,81,82,83,84,85,89,96,97,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"28":[0,1,2,3,4,5,6,7,8,9,11,12,13,14,21,22,23,24,26,27,28,29,30,31,32,33,34,35,37,38,39,42,45,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,72,74,75,76,77,78,79,80,81,82,83,84,85,89,96,97,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"43":[0,1,2,3,4,5,6,7,8,9,11,12,13,14,21,22,23,24,26,27,28,29,30,31,32,33,34,35,37,38,39,42,45,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,72,74,75,76,77,78,79,80,81,82,83,84,85,89,96,97,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"59":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145,146]},"packages/@n8n/design-system/src/components/N8nNotice/Notice.vue":{"16":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,51,53,55,60,61,65,67,76,78,80,82,83,84,89,96,98,100,103,104,105,109,110,111,113,114,117,118,119,120,121,122,123,124,126,127,129,130,133,134,135,136,140,144,145],"30":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,51,53,55,60,61,65,67,76,78,80,82,83,84,89,96,98,100,103,104,105,109,110,111,113,114,117,118,119,120,121,122,123,124,126,127,129,130,133,134,135,136,140,144,145],"34":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,51,53,55,60,61,65,67,76,80,82,83,84,89,96,98,100,103,104,105,109,110,111,113,114,117,118,119,120,121,122,123,124,126,127,129,130,133,134,140,144,145],"50":[127],"66":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,51,53,55,60,61,65,67,76,78,80,82,83,84,89,96,98,100,103,104,105,109,110,111,113,114,117,118,119,120,121,122,123,124,126,127,129,130,133,134,135,136,140,144,145],"75":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,38,51,53,55,60,61,65,67,76,78,80,82,83,84,89,96,98,100,104,105,110,111,114,117,118,119,120,121,122,123,124,126,127,134,135,136,140,144,145]},"packages/@n8n/design-system/src/components/N8nOption/Option.vue":{"12":[1,2,3,4,5,7,8,9,11,12,14,15,16,18,19,20,21,22,23,24,25,26,27,28,30,31,33,34,35,37,38,39,40,41,49,51,52,53,55,57,58,60,61,62,65,66,67,68,69,70,71,72,73,74,75,76,79,80,81,82,83,84,85,88,89,90,91,92,93,94,96,97,98,99,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,144,145,146],"13":[1,2,3,4,5,7,8,9,11,12,14,15,16,18,19,20,21,22,23,24,25,26,27,28,30,31,33,34,35,38,39,40,41,51,52,53,55,57,58,60,61,62,65,66,67,68,69,70,71,72,73,74,75,76,79,80,81,82,83,84,85,88,89,90,91,92,93,94,96,97,98,99,100,104,105,106,110,111,114,116,117,118,119,120,121,122,123,124,125,126,127,128,131,132,134,135,136,137,138,139,140,141,144,145,146],"16":[1,2,3,4,5,7,8,9,11,12,14,15,16,18,19,20,21,22,23,24,25,26,27,28,30,31,33,34,35,38,39,40,41,51,52,53,55,57,58,60,61,62,65,66,67,68,69,70,71,72,73,74,75,76,79,80,81,82,83,84,85,88,89,90,91,92,93,94,96,97,98,99,100,104,105,106,110,111,114,116,117,118,119,120,121,122,123,124,125,126,127,128,131,132,134,135,136,137,138,139,140,141,144,145,146]},"packages/@n8n/design-system/src/components/N8nPopover/Popover.vue":{"84":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,29,30,31,32,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"105":[16,40,89,93,100,106,109,111,119,120,121,122,124,127,128,129,130,131,136,139,141,144],"111":[40,89,93,100,106,109,111,119,120,121,122,124,127,130,131,136,139,144],"125":[40,89,100,106,109,111,119,120,121,122,127,129,130,131,136,139,141,144],"133":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,29,30,31,32,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"134":[40,89,100,106,111,119,120,121,122,124,127,128,129,130,131,136,139],"143":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,29,30,31,32,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"146":[16,40,89,93,100,106,109,111,119,120,121,122,127,129,130,131,136,139,141,144],"147":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,29,30,31,32,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"148":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,29,30,31,32,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"151":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,29,30,31,32,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"167":[16,40,89,93,100,106,111,119,120,121,122,124,127,128,131,136,139,141,144],"174":[16,40,93,100,106,109,139,141,144]},"packages/@n8n/design-system/src/components/N8nPromptInput/N8nPromptInput.vue":{"68":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"74":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"83":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"84":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"93":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"97":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"106":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"111":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"183":[1,4,5,10],"189":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"191":[1,4,5,10],"200":[1,4,5,10],"204":[1,4,5,10],"208":[1,4,5,10],"214":[1,4,5,10],"221":[10],"228":[1,4,5,10],"265":[1,2,3,4,5,10],"270":[1,2,4,5,10],"275":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"279":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"281":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"291":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"295":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,38,39,40,41,42,43,44,45,46,47,48,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,104,105,106,107,108,110,111,112,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,131,132,134,135,136,137,138,139,140,141,143,144,145,146],"324":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"332":[1,4,5]},"packages/@n8n/design-system/src/components/N8nPromptInputSuggestions/N8nPromptInputSuggestions.vue":{"10":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"20":[10],"23":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"41":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"46":[10]},"packages/@n8n/design-system/src/components/N8nRadioButtons/RadioButton.vue":{"22":[0,1,2,3,4,5,6,7,8,9,10,11,12,14,21,22,23,24,26,27,28,30,33,36,37,38,39,49,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,89,90,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/@n8n/design-system/src/components/N8nRadioButtons/RadioButtons.vue":{"20":[0,1,2,3,4,5,6,7,8,9,10,11,12,14,21,22,23,24,26,27,28,30,33,36,37,38,39,49,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,89,90,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"33":[7,79,89,105,113,114,115,117,119,120,121,122,123,124,125,127,128,129,130,131,136,141,142],"41":[0,1,2,3,4,5,6,7,8,9,10,11,12,14,21,22,23,24,26,27,28,30,33,36,37,38,39,49,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,89,90,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"50":[0,1,2,3,4,5,6,7,8,9,10,11,12,14,21,22,23,24,26,27,28,30,33,36,38,39,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,89,90,96,97,98,99,100,101,102,104,105,106,107,108,110,111,112,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,131,132,134,135,136,137,138,139,140,141,143,144,145,146],"58":[7,79,89,105,113,114,115,117,119,120,121,122,123,124,125,127,128,129,130,131,136,141,142],"59":[0,1,2,3,4,5,6,7,8,9,10,11,12,14,21,22,23,24,26,27,28,30,33,36,37,38,39,49,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,89,90,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/@n8n/design-system/src/components/N8nResizeWrapper/ResizeWrapper.vue":{"6":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"72":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"91":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"141":[1,3,4,7,8,9,11,12,21,22,28,32,37,38,42,47,50,52,53,55,57,60,62,65,67,69,76,79,80,81,82,83,84,93,96,98,100,103,104,105,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,131,132,133,135,138,139,140,141,142,144,145,146],"167":[1,3,4,7,8,9,11,12,21,22,28,32,37,38,42,47,50,52,53,55,57,60,62,65,67,69,76,79,80,81,82,83,84,93,96,98,100,103,104,105,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,131,132,133,135,138,139,140,141,142,144,145,146],"195":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"201":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/@n8n/design-system/src/components/N8nRoute/Route.vue":{"13":[0,1,2,3,4,5,6,7,8,9,10,11,12,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"15":[0,1,2,3,4,5,6,7,8,9,10,11,12,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"28":[0,1,2,3,4,5,6,7,8,9,10,11,12,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"29":[0,1,2,3,4,5,6,7,8,9,10,11,12,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"38":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/@n8n/design-system/src/components/N8nScrollArea/N8nScrollArea.vue":{"50":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"68":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"82":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"104":[5,10],"144":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"163":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"172":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,38,39,40,41,42,43,44,45,46,47,48,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,104,105,106,107,108,110,111,112,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,131,132,134,135,136,137,138,139,140,141,143,144,145,146],"174":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"181":[29,30,45,46,51]},"packages/@n8n/design-system/src/components/N8nSelect/Select.vue":{"11":[1,2,3,4,5,7,8,9,11,12,14,15,16,18,19,20,21,22,23,24,25,26,27,28,30,31,33,34,35,37,38,39,40,41,49,51,52,53,55,57,58,60,61,62,65,66,67,68,69,70,71,72,73,74,75,76,79,80,81,82,83,84,85,88,89,90,91,92,93,94,96,97,98,99,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,144,145,146],"63":[1,2,3,4,5,7,8,9,11,12,14,15,16,18,19,20,21,22,23,24,25,26,27,28,30,31,33,34,35,37,38,39,40,41,49,51,52,53,55,57,58,60,61,62,65,66,67,68,69,70,71,72,73,74,75,76,79,80,81,82,83,84,85,88,89,90,91,92,93,94,96,97,98,99,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,144,145,146],"64":[1,2,3,4,5,7,8,9,11,12,14,15,16,18,19,20,21,22,23,24,25,26,27,28,30,31,33,34,35,37,38,39,40,41,49,51,52,53,55,57,58,60,61,62,65,66,67,68,69,70,71,72,73,74,75,76,79,80,81,82,83,84,85,88,89,90,91,92,93,94,96,97,98,99,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,144,145,146],"72":[1,2,3,4,5,7,8,9,11,12,14,15,16,18,19,20,21,22,23,24,25,26,27,28,30,31,33,34,35,37,38,39,40,41,49,51,52,53,55,57,58,60,61,62,65,66,67,68,69,70,71,72,73,74,75,76,79,80,81,82,83,84,85,88,89,90,91,92,93,94,96,97,98,99,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,144,145,146],"85":[1,2,3,4,5,7,8,9,11,12,14,15,16,18,19,20,21,22,23,24,25,26,27,28,30,31,33,34,35,37,38,39,40,41,49,51,52,53,55,57,58,60,61,62,65,66,67,68,69,70,71,72,73,74,75,76,79,80,81,82,83,84,85,88,89,90,91,92,93,94,96,97,98,99,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,144,145,146],"89":[3,23,37,38,39,89,97,98],"93":[7,8,127],"97":[11,24,34,37,38,55,58,60,67,110,127,137],"113":[1,2,3,4,5,7,8,9,11,12,14,15,16,18,19,20,21,22,23,24,25,26,27,28,30,31,33,34,35,37,38,39,40,41,49,51,52,53,55,57,58,60,61,62,65,66,67,68,69,70,71,72,73,74,75,76,79,80,81,82,83,84,85,88,89,90,91,92,93,94,96,97,98,99,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,144,145,146],"134":[1,2,3,4,5,7,8,9,11,12,14,15,16,18,19,20,21,22,23,24,25,26,27,28,30,31,33,34,35,37,38,39,40,41,49,51,52,53,55,57,58,60,61,62,65,66,67,68,69,70,71,72,73,74,75,76,79,80,81,82,83,84,85,88,89,90,91,92,93,94,96,97,98,99,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,144,145,146],"136":[3,8,15,23,33,35,37,38,39,41,70,71,72,79,80,88,89,94,97,98,99,117,120,123,124,125,127,128,138,141,144],"142":[5,7,8,22,23,31,33,34,37,38,51,60,67,80,96,98,117,127,130,145],"145":[5,7,8,22,23,31,33,34,37,38,51,60,67,80,96,98,117,127,130,145]},"packages/@n8n/design-system/src/components/N8nSendStopButton/N8nSendStopButton.vue":{"5":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"26":[1,4,5],"30":[10],"32":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"58":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,38,39,40,41,42,43,44,45,46,47,48,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,104,105,106,107,108,110,111,112,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,131,132,134,135,136,137,138,139,140,141,143,144,145,146]},"packages/@n8n/design-system/src/components/N8nSpinner/Spinner.vue":{"20":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/@n8n/design-system/src/components/N8nSuggestedActions/SuggestedActions.vue":{"39":[0,1,2,3,4,5,6,7,8,9,10,11,12,22,26,27,28,37,42,45,49,50,52,59,60,61,62,63,64,65,66,67,68,69,74,75,76,79,81,82,85,96,98,99,100,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,131,133,134,135,136,137,138,139,140,141,142,144,145,146],"50":[0,1,2,3,4,5,6,7,8,9,10,11,12,22,26,27,28,37,42,45,49,50,52,59,60,61,62,63,64,65,66,67,68,69,74,75,76,79,81,82,85,96,98,99,100,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,131,133,134,135,136,137,138,139,140,141,142,144,145,146],"52":[100],"58":[100],"60":[100],"64":[0,1,2,3,4,5,6,7,8,9,10,11,12,22,26,27,28,37,42,45,49,50,52,59,60,61,62,63,64,65,66,67,68,69,74,75,76,79,81,82,85,96,98,99,100,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,131,133,134,135,136,137,138,139,140,141,142,144,145,146],"74":[100,139],"76":[0,1,2,3,4,5,6,7,8,9,10,11,12,22,26,27,28,37,42,45,49,50,52,59,60,61,62,63,64,65,66,67,68,69,74,75,76,79,81,82,85,96,98,99,100,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,131,133,134,135,136,137,138,139,140,141,142,144,145,146],"84":[100,139],"86":[100,139],"89":[100,139],"100":[100],"108":[100,139],"112":[100,139],"121":[100,139],"131":[100],"132":[100,139],"142":[100],"143":[100,139]},"packages/@n8n/design-system/src/components/N8nTabs/Tabs.vue":{"25":[1,2,3,4,7,8,9,11,12,14,15,16,18,19,20,21,22,23,24,26,27,28,34,35,37,38,39,40,41,49,52,53,55,57,58,60,61,62,65,66,67,68,69,70,71,72,73,74,75,76,79,80,81,82,83,84,85,88,89,93,94,96,97,98,100,103,104,105,106,109,110,111,112,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,144,146],"30":[1,2,3,4,7,8,9,11,12,14,15,16,18,19,20,21,22,23,24,26,27,28,34,35,37,38,39,40,41,49,52,53,55,57,58,60,61,62,65,66,67,68,69,70,71,72,73,74,75,76,79,80,81,82,83,84,85,88,89,93,94,96,97,98,100,103,104,105,106,109,110,111,112,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,144,146],"40":[1,2,3,4,7,8,9,11,12,14,15,16,18,19,20,21,22,23,24,26,27,28,34,35,37,38,39,40,41,49,52,53,55,57,58,60,61,62,65,66,67,68,69,70,71,72,73,74,75,76,79,80,81,82,83,84,85,88,89,93,94,96,97,98,100,103,104,105,106,109,110,111,112,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,144,146],"53":[1,3,4,7,8,9,11,12,15,18,19,20,21,22,28,34,37,38,40,41,52,53,55,57,60,62,65,67,69,71,72,73,76,79,80,81,82,83,84,93,94,96,98,100,103,104,105,106,109,110,111,112,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,131,132,133,135,138,139,140,144],"63":[124,128],"73":[1,2,3,4,7,8,9,11,12,14,15,16,18,19,20,21,22,23,24,26,27,28,34,35,37,38,39,40,41,49,52,53,55,57,58,60,61,62,65,66,67,68,69,70,71,72,73,74,75,76,79,80,81,82,83,84,85,88,89,93,94,96,97,98,100,103,104,105,106,109,110,111,112,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,144,146],"92":[1,2,3,4,7,8,9,11,12,14,15,16,18,19,20,21,22,23,24,26,27,28,34,35,38,39,40,41,52,53,55,57,58,60,61,62,65,66,67,68,69,70,71,72,73,74,75,76,79,80,81,82,83,84,85,88,89,93,94,96,97,98,100,104,105,106,110,111,112,114,116,117,118,119,120,121,122,123,124,125,126,127,128,131,132,134,135,136,138,139,140,144,146],"101":[1,2,3,4,7,8,9,11,12,14,15,16,18,19,20,21,22,23,24,26,27,28,34,35,37,38,39,40,41,49,52,53,55,57,58,60,61,62,65,66,67,68,69,70,71,72,73,74,75,76,79,80,81,82,83,84,85,88,89,93,94,96,97,98,100,103,104,105,106,109,110,111,112,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,144,146],"125":[3,15,16,18,19,20,22,23,26,35,37,38,39,40,41,68,69,70,71,72,73,88,89,93,94,96,97,98,133,138,139,144,146],"142":[124,128]},"packages/@n8n/design-system/src/components/N8nTag/Tag.vue":{"15":[0,1,2,3,4,5,6,7,8,9,10,11,12,22,25,26,27,28,33,36,37,42,45,49,50,52,59,60,61,62,63,64,65,66,67,68,69,74,75,76,79,81,82,84,85,87,89,90,91,92,93,94,95,96,98,99,100,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,131,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/@n8n/design-system/src/components/N8nText/Text.vue":{"18":[0,1,2,3,4,5,6,7,8,9,10,11,12,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"26":[0,1,2,3,4,5,6,7,8,9,10,11,12,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"46":[0,1,2,3,4,5,6,7,8,9,10,11,12,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"48":[0,1,2,3,4,5,6,7,8,9,10,11,12,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"52":[0,1,2,3,4,5,6,7,8,9,10,11,12,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,38,39,40,41,42,43,44,45,46,47,48,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,104,105,106,107,108,110,111,112,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,131,132,134,135,136,137,138,139,140,141,143,144,145,146]},"packages/@n8n/design-system/src/components/N8nTooltip/Tooltip.vue":{"20":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"33":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"41":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"42":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"44":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"53":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"58":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"59":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"69":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"71":[0,1,3,4,6,7,8,9,11,12,16,21,22,23,24,26,27,28,30,34,35,36,37,38,40,41,47,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,72,74,76,79,80,81,82,83,84,85,87,93,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,141,142,143,144],"73":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"84":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,38,39,40,41,42,43,44,45,46,47,48,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,104,105,106,107,108,110,111,112,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,131,132,134,135,136,137,138,139,140,141,143,144,145,146],"86":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"89":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"97":[6,7,8,9,12,26,60,67,81,110,114,117,146]},"packages/@n8n/design-system/src/composables/useCharacterLimit.ts":{"15":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"19":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"23":[1,4,5,10],"25":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/@n8n/design-system/src/composables/useI18n.ts":{"4":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"6":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/@n8n/design-system/src/composables/useTooltipAppendTo.ts":{"7":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"11":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"14":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/@n8n/design-system/src/directives/n8n-html.ts":{"19":[1,2,3,4,5,6,7,8,9,10,11,12,14,15,21,22,23,24,27,28,30,33,34,36,37,38,39,40,41,49,51,52,53,55,57,58,60,61,62,65,66,67,72,74,75,76,78,79,80,81,82,83,84,85,87,88,89,90,91,96,97,98,100,102,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145,146],"31":[1,2,3,4,5,6,7,8,9,10,11,12,14,15,21,22,23,24,27,28,30,33,34,36,37,38,39,40,41,49,51,52,53,55,57,58,60,61,62,65,66,67,72,74,75,76,78,79,80,81,82,83,84,85,87,88,89,90,91,96,97,98,100,102,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145,146]},"packages/@n8n/design-system/src/locale/format.ts":{"8":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"12":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/@n8n/design-system/src/locale/index.ts":{"16":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"36":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"38":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/@n8n/design-system/src/plugin.ts":{"8":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/@n8n/design-system/src/types/assistant.ts":{"165":[1,2,3,4,5,10],"221":[1,2,3,4,5,10],"227":[1,2,3,4,5,10],"239":[1,2,3,4,5,10]},"packages/@n8n/design-system/src/utils/cn.ts":{"4":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/@n8n/design-system/src/utils/typeguards.ts":{"1":[1,2,3,4,5,7,8,9,11,12,14,15,16,18,19,20,21,22,23,24,25,26,27,28,30,31,33,34,35,37,38,39,40,41,49,51,52,53,55,57,58,60,61,62,65,66,67,68,69,70,71,72,73,74,75,76,79,80,81,82,83,84,85,88,89,90,91,92,93,94,96,97,98,99,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,144,145,146]},"packages/@n8n/design-system/src/utils/uid.ts":{"6":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/@n8n/i18n/src/index.ts":{"36":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"48":[0,1,2,3,4,5,6,7,8,9,11,12,14,21,22,23,24,26,27,28,34,37,38,45,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,79,80,81,82,83,84,85,90,91,96,98,99,100,102,103,104,105,106,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,141,142,144],"63":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"93":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"101":[0,1,2,3,4,5,6,7,8,9,11,12,14,21,22,23,24,26,27,28,30,33,34,37,38,39,45,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,79,80,81,82,83,84,85,89,90,91,96,97,98,99,100,102,103,104,105,106,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,141,142,144,145],"105":[6,7,8,9,81,102,105,113,114,115,117,141,142],"138":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"145":[3,7,8,23,30,33,37,38,39,51,58,80,89,97,98,127,130,145],"153":[3,7,8,23,30,33,37,38,39,51,58,80,89,97,98,127,130,145],"170":[3,7,8,23,30,33,37,38,39,51,58,80,89,97,98,127,130,145],"180":[3,7,8,23,30,33,37,38,39,51,58,80,89,97,98,127,130,145],"190":[3,7,8,23,30,33,37,38,39,51,58,80,89,97,98,127,130,145],"203":[3,7,8,23,30,33,37,38,39,51,58,80,89,97,98,127,130,145],"216":[3,7,8,23,30,33,37,38,39,51,58,80,89,97,98,127,130,145],"229":[0,1,2,3,4,5,6,7,8,9,11,12,14,21,22,23,24,26,27,28,30,33,34,37,38,39,45,49,50,51,52,53,55,57,58,59,60,61,62,63,64,65,66,67,74,75,76,79,80,81,82,83,84,85,89,90,91,96,97,98,100,102,103,104,105,106,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,141,142,144,145],"238":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,30,33,34,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,90,91,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145],"250":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,34,37,38,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,90,91,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"262":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,34,37,38,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,90,91,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"277":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,34,37,38,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,90,91,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"295":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,34,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,90,91,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"317":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,34,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"340":[120,124,125,128],"373":[12,60],"380":[0,1,2,4,6,7,8,9,11,12,26,27,28,38,45,49,50,59,60,61,62,63,64,65,66,67,74,75,79,81,82,85,102,103,104,105,110,112,113,114,115,116,117,118,120,124,125,128,129,131,134,141,142],"389":[1,2,3,4,5,7,8,11,12,21,23,24,27,28,37,38,52,53,54,55,56,57,58,60,61,62,64,65,67,74,77,78,80,82,83,84,85,96,98,99,100,103,104,105,108,109,110,111,113,114,116,117,119,120,121,122,124,125,126,127,129,130,131,132,133,135,136,138,140,142,143,144,145,146],"407":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/@n8n/i18n/src/utils.ts":{"9":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,30,33,34,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,90,91,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145],"29":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,30,33,34,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,90,91,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145],"31":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,30,33,34,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,90,91,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145],"34":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,30,33,34,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,90,91,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145],"41":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,30,33,34,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,90,91,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145],"49":[1,3,4,7,11,12,22,24,27,53,60,62,65,66,67,76,81,85,100,104,106,109,114,117,118,119,120,121,122,124,125,127,128,129,131,132,133,134,140],"57":[1,3,4,7,11,12,22,24,27,53,60,62,65,66,67,76,81,85,100,104,106,109,114,117,118,119,120,121,122,124,125,127,128,129,131,132,133,134,140],"58":[1,3,4,7,11,12,22,24,27,53,60,62,65,66,67,76,81,85,100,104,106,109,114,117,118,119,120,121,122,124,125,127,128,129,131,132,133,134,140]},"packages/@n8n/permissions/src/roles/all-roles.ts":{"58":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"62":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/@n8n/permissions/src/scope-information.ts":{"4":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"5":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"6":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"14":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"15":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"16":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/@n8n/permissions/src/utilities/combine-scopes.ee.ts":{"16":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"18":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/@n8n/permissions/src/utilities/get-resource-permissions.ee.ts":{"14":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"15":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"18":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/@n8n/permissions/src/utilities/get-role-scopes.ee.ts":{"5":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"16":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/@n8n/permissions/src/utilities/has-scope.ee.ts":{"11":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"20":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"21":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/@n8n/stores/src/metaTagConfig.ts":{"1":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"8":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"34":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/@n8n/stores/src/useAgentRequestStore.ts":{"18":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"64":[0,9,49,79,81,103,114,118,119,121],"78":[0,1,2,8,9,27,49,61,65,67,75,79,81,103,110,114,117,118,119,120,121,122,124,125,128,129,131]},"packages/@n8n/stores/src/useRootStore.ts":{"38":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"69":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"71":[12,14,21,24,37,53,60,67,114,118,124,129,130,144],"73":[12,14,21,24,37,53,60,67,114,118,124,129,130,144],"75":[117],"79":[12,14,21,24,37,53,60,67,114,118,124,129,130,144],"81":[6,7,8,9,12,14,21,24,37,53,60,67,81,102,114,117,118,124,129,130,144],"89":[12,14,21,24,37,53,60,67,114,118,124,129,130,144],"91":[12,14,21,24,37,53,60,67,114,118,124,129,130,144],"93":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"95":[0,1,2,4,6,7,8,9,11,12,26,27,28,38,49,50,59,60,61,62,63,64,65,66,67,74,75,79,81,82,85,102,103,104,105,110,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135,141,142,146],"97":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"99":[1,2,7,8,113,117,124],"103":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"105":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"107":[3,37,39,130,145],"111":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"113":[100],"115":[100],"117":[100],"119":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"130":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"135":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"140":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"144":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"148":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"152":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"156":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"160":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"164":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"168":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"172":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"177":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"181":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"185":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"189":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"193":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"201":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"205":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"209":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"213":[112,117,141,142]},"packages/@n8n/tournament/src/ExpressionBuilder.ts":{"25":[0,1,2,3,4,5,6,7,8,9,12,14,21,22,23,24,26,27,37,38,42,45,48,49,50,52,53,55,57,60,61,62,63,66,67,74,75,76,77,78,79,80,81,82,83,85,89,96,98,100,102,103,104,105,106,107,109,111,112,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,143,144,145],"29":[1,2,3,4,5,6,7,8,9,12,14,21,22,23,24,26,27,37,38,42,45,48,49,50,52,53,55,57,60,61,62,63,66,67,74,75,76,77,78,79,80,81,82,83,85,89,96,98,102,103,104,105,106,107,109,111,112,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145],"33":[0,5,6,7,8,9,14,21,24,26,37,52,53,66,67,77,79,80,81,100,102,103,104,109,114,117,118,120,122,124,125,126,127,128,129,130,131,134,135,136,143,144],"37":[119,121],"50":[0,1,2,3,4,5,6,7,8,9,12,14,21,22,23,24,26,27,37,38,42,45,48,49,50,52,53,55,57,60,61,62,63,66,67,74,75,76,77,78,79,80,81,82,83,85,89,96,98,100,102,103,104,105,106,107,109,111,112,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,143,144,145],"54":[77,104,125],"62":[0,6,7,8,9,14,21,24,26,37,52,66,67,77,79,80,81,100,102,103,104,109,114,117,118,120,124,125,126,127,128,129,143,144],"71":[0,1,2,3,4,5,6,7,8,9,12,14,21,22,23,24,26,27,37,38,42,45,48,49,50,52,53,55,57,60,61,62,63,66,67,74,75,76,77,78,79,80,81,82,83,85,89,96,98,100,102,103,104,105,106,107,109,111,112,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,143,144,145],"75":[79,100,104,114,117,126],"88":[0,1,2,3,4,5,6,7,8,9,12,14,21,22,23,24,26,27,37,38,42,45,48,49,50,52,53,55,57,60,61,62,63,66,67,74,75,76,77,78,79,80,81,82,83,85,89,96,98,100,102,103,104,105,106,107,109,111,112,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,143,144,145],"103":[0,1,2,3,4,5,6,7,8,9,12,14,21,22,23,24,26,27,37,38,42,45,48,49,50,52,53,55,57,60,61,62,63,66,67,74,75,76,77,78,79,80,81,82,83,85,89,96,98,100,102,103,104,105,106,107,109,111,112,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,143,144,145],"110":[5,76,77,81,104,114,120,122,124,125],"136":[0,1,2,3,4,5,6,7,8,9,12,14,21,22,23,24,26,27,37,38,42,45,48,49,50,52,53,55,57,60,61,62,63,66,67,74,75,76,77,78,79,80,81,82,83,85,89,96,98,100,102,103,104,105,106,107,109,111,112,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,143,144,145],"137":[79,100,104,114,117,126],"141":[79,100,104,114,117,126],"157":[0,1,2,3,4,5,6,7,8,9,12,14,21,22,23,24,26,27,37,38,42,45,48,49,50,52,53,55,57,60,61,62,63,66,67,74,75,76,77,78,79,80,81,82,83,85,89,96,98,100,102,103,104,105,106,107,109,111,112,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,143,144,145],"158":[0,1,2,3,4,5,6,7,8,9,12,14,21,22,23,24,26,27,37,38,42,45,48,49,50,52,53,55,57,60,61,62,63,66,67,74,75,76,77,78,79,80,81,82,83,85,89,96,98,100,102,103,104,105,106,107,109,111,112,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,143,144,145],"171":[0,1,2,3,4,5,6,7,8,9,12,14,21,22,23,24,26,27,37,38,42,45,48,49,50,52,53,55,57,60,61,62,63,66,67,74,75,76,77,78,79,80,81,82,83,85,89,96,98,100,102,103,104,105,106,107,109,111,112,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,143,144,145],"188":[0,1,2,3,4,5,6,7,8,9,12,14,21,22,23,24,26,27,37,38,42,45,48,49,50,52,53,55,57,60,61,62,63,66,67,74,75,76,77,78,79,80,81,82,83,85,89,96,98,100,102,103,104,105,106,107,109,111,112,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,143,144,145],"197":[0,1,2,3,4,5,6,7,8,9,12,14,21,22,23,24,26,27,37,38,42,45,48,49,50,52,53,55,57,60,61,62,63,66,67,74,75,76,77,78,79,80,81,82,83,85,89,96,98,100,102,103,104,105,106,107,109,111,112,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,143,144,145],"198":[0,1,2,3,4,5,6,7,8,9,12,14,21,22,23,24,26,27,37,38,42,45,48,49,50,52,53,55,57,60,61,62,63,66,67,74,75,76,77,78,79,80,81,82,83,85,89,96,98,100,102,103,104,105,106,107,109,111,112,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,143,144,145],"263":[5,76,77,81,104,114,120,122,124,125]},"packages/@n8n/tournament/src/ExpressionSplitter.ts":{"19":[0,1,2,3,4,5,6,7,8,9,12,14,21,22,23,24,26,27,37,38,42,45,48,49,50,52,53,55,57,60,61,62,63,66,67,74,75,76,77,78,79,80,81,82,83,85,89,96,98,100,102,103,104,105,106,107,109,111,112,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,143,144,145],"23":[0,1,2,3,4,5,6,7,8,9,12,14,21,22,23,24,26,27,37,38,42,45,48,49,50,52,53,55,57,60,61,62,63,66,67,74,75,76,77,78,79,80,81,82,83,85,89,96,98,100,102,103,104,105,106,107,109,111,112,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,143,144,145],"27":[0,1,2,3,4,5,6,7,8,9,12,14,21,22,23,24,26,27,37,38,42,45,48,49,50,52,53,55,57,60,61,62,63,66,67,74,75,76,77,78,79,80,81,82,83,85,89,96,98,100,102,103,104,105,106,107,109,111,112,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,143,144,145]},"packages/@n8n/tournament/src/FunctionEvaluator.ts":{"8":[0,1,2,3,4,5,6,7,8,9,12,14,21,22,23,24,26,27,37,38,42,45,48,49,50,52,53,55,57,60,61,62,63,66,67,74,75,76,77,78,79,80,81,82,83,85,89,96,98,100,102,103,104,105,106,107,109,111,112,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,143,144,145],"18":[0,1,2,3,4,5,6,7,8,9,12,14,21,22,23,24,26,27,37,38,42,45,48,49,50,52,53,55,57,60,61,62,63,66,67,74,75,76,77,78,79,80,81,82,83,85,89,96,98,100,102,103,104,105,106,107,109,111,112,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,143,144,145]},"packages/@n8n/tournament/src/Parser.ts":{"5":[0,1,2,3,4,5,6,7,8,9,12,14,21,22,23,24,26,27,37,38,42,45,48,49,50,52,53,55,57,60,61,62,63,66,67,74,75,76,77,78,79,80,81,82,83,85,89,96,98,100,102,103,104,105,106,107,109,111,112,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,143,144,145]},"packages/@n8n/tournament/src/VariablePolyfill.ts":{"12":[7,8,37,52,79,80,103,126],"22":[0,1,2,3,4,5,6,7,8,9,12,14,21,22,23,24,26,27,37,38,42,45,48,49,50,52,53,55,57,60,61,62,63,66,67,74,75,76,77,78,79,80,81,82,83,85,89,96,98,100,102,103,104,105,106,107,109,111,112,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,143,144,145],"33":[0,1,2,3,4,5,6,7,8,9,12,14,21,22,23,24,26,27,37,38,42,45,48,49,50,52,53,55,57,60,61,62,63,66,67,74,75,76,77,78,79,80,81,82,83,85,89,96,98,100,102,103,104,105,106,107,109,111,112,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,143,144,145],"46":[0,1,2,3,4,5,6,7,8,9,12,14,21,22,23,24,26,27,37,38,42,45,48,49,50,52,53,55,57,60,61,62,63,66,67,74,75,76,77,78,79,80,81,82,83,85,89,96,98,100,102,103,104,105,106,107,109,111,112,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,143,144,145],"73":[0,1,2,3,4,5,6,7,8,9,12,14,21,22,23,24,26,27,37,38,42,45,48,49,50,52,53,55,57,60,61,62,63,66,67,74,75,76,77,78,79,80,81,82,83,85,89,96,98,100,102,103,104,105,106,107,109,111,112,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,143,144,145],"83":[0,6,7,8,9,14,21,24,26,37,52,66,67,77,79,80,81,100,102,103,104,109,114,117,118,119,120,121,124,125,126,127,128,129,143,144],"107":[0,7,8,9,14,21,24,26,37,52,66,67,77,79,80,100,103,104,109,114,117,118,120,124,125,126,127,128,129,143,144],"114":[0,1,2,3,4,5,6,7,8,9,12,14,21,22,23,24,26,27,37,38,42,45,48,49,50,52,53,55,57,60,61,62,63,66,67,74,75,76,77,78,79,80,81,82,83,85,89,96,98,100,102,103,104,105,106,107,109,111,112,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,143,144,145],"122":[0,1,2,3,4,5,6,7,8,9,12,14,21,22,23,24,26,27,37,38,42,45,48,49,50,52,53,55,57,60,61,62,63,66,67,74,75,76,77,78,79,80,81,82,83,85,89,96,98,100,102,103,104,105,106,107,109,111,112,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,143,144,145]},"packages/@n8n/tournament/src/index.ts":{"16":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"25":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"29":[0,1,2,3,4,5,6,7,8,9,12,14,21,22,23,24,26,27,37,38,42,45,48,49,50,52,53,55,57,60,61,62,63,66,67,74,75,76,77,78,79,80,81,82,83,85,89,96,98,100,102,103,104,105,106,107,109,111,112,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,143,144,145],"33":[0,1,2,3,4,5,6,7,8,9,12,14,21,22,23,24,26,27,37,38,42,45,48,49,50,52,53,55,57,60,61,62,63,66,67,74,75,76,77,78,79,80,81,82,83,85,89,96,98,100,102,103,104,105,106,107,109,111,112,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,143,144,145]},"packages/@n8n/utils/src/event-bus.ts":{"43":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"50":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"60":[93,144],"61":[93,144],"68":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,20,21,22,23,24,26,27,28,30,31,33,34,36,37,38,39,40,41,42,45,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,93,94,96,97,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"75":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,20,21,22,23,24,26,27,28,30,31,33,36,37,38,39,42,45,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,72,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"78":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,20,21,22,23,24,26,27,28,33,36,37,38,39,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,72,74,75,76,77,78,79,80,81,82,83,84,85,87,89,90,91,92,93,94,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/@n8n/utils/src/event-queue.ts":{"7":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,87,95,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"17":[0,1,2,3,4,5,6,7,8,9,10,11,12,22,26,27,28,37,38,42,45,49,50,52,59,60,61,62,63,64,65,66,67,68,69,74,75,76,79,81,82,85,96,98,99,100,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,131,133,134,135,136,137,138,139,140,141,142,144,145,146],"44":[0,1,2,3,4,5,6,7,8,9,10,11,12,22,26,27,28,37,38,42,45,49,50,52,59,60,61,62,63,64,65,66,67,68,69,74,75,76,79,81,82,85,96,98,99,100,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,131,133,134,135,136,137,138,139,140,141,142,144,145,146]},"packages/@n8n/utils/src/search/reRankSearchResults.ts":{"1":[1,3,7,8,147,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,144],"6":[1,3,7,8,147,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,144],"9":[1,3,7,8,147,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,144],"23":[1,3,7,8,147,11,21,23,24,28,37,53,56,57,58,62,65,67,80,96,98,100,103,104,105,109,110,111,119,120,121,122,124,126,127,129,132,133,140,144]},"packages/@n8n/utils/src/search/sublimeSearch.ts":{"25":[1,3,7,8,147,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,144],"41":[1,3,7,8,147,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,144],"182":[1,3,7,8,147,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,144],"205":[1,3,7,8,147,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,144],"222":[1,3,7,8,147,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,144],"227":[1,3,7,8,147,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,144],"229":[1,3,7,8,147,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,144],"233":[1,3,7,8,147,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,144],"243":[1,3,7,8,147,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,144],"277":[1,3,7,8,147,11,21,23,24,28,37,53,56,57,58,62,65,67,80,96,98,100,103,104,105,109,110,111,119,120,121,122,124,126,127,129,132,133,140,144]},"packages/@n8n/utils/src/sort/sortByProperty.ts":{"1":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"6":[5,21,23,26,37,39,41,53,57,58,60,61,64,68,69,70,71,72,74,75,77,80,81,82,83,85,88,96,98,99,103,104,106,109,111,113,118,119,120,121,122,127,130,131,136,138,144]},"packages/frontend/editor-ui/src/Interface.ts":{"390":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/app/App.vue":{"32":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"52":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"61":[1,2,7,8,9,11,12,24,37,49,60,67,104,109,110,111,113,118,119,120,121,122,123,124,125,126,127,128,129,131,132,136],"63":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"69":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"75":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"76":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"83":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"95":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"102":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"107":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"115":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"118":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/app/api/favorites.ts":{"16":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"20":[147],"31":[147]},"packages/frontend/editor-ui/src/app/api/workflows.ts":{"22":[1,2,3,4,5,7,8,147,10,11,12,13,14,21,23,24,26,27,28,36,37,38,52,53,54,55,56,57,58,60,61,62,64,65,67,68,69,74,77,78,80,82,83,84,85,96,98,99,100,101,102,103,104,105,108,109,110,111,112,113,114,117,119,120,121,122,124,125,126,127,129,130,131,132,133,136,137,138,139,140,141,142,143,144,145,146],"35":[0,1,2,6,7,8,9,147,22,26,27,28,42,45,48,49,50,59,60,62,63,64,66,67,68,69,70,72,74,75,76,79,81,82,85,96,98,99,100,104,105,106,107,110,112,114,115,116,117,118,119,120,123,124,125,126,127,128,129,133,134,135,138,139,141,142,144,145,146],"39":[1,2,3,4,5,7,8,147,10,11,12,21,23,24,26,27,28,36,37,38,52,53,54,55,56,57,58,60,61,62,64,65,67,69,74,77,80,82,83,84,85,96,98,99,100,103,104,105,108,109,110,111,113,114,117,119,120,121,122,124,125,126,127,129,130,131,132,133,136,137,138,139,140,142,143,144],"43":[147,100,144],"57":[147,87],"68":[147,15,16,18,19,20,22,26,40,41,68,69,70,71,72,73,93,94,96,98,133,135,136,138,139,144,146],"84":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,36,37,38,40,41,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,93,94,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"106":[0,1,2,4,6,7,8,9,147,11,26,27,28,38,45,49,50,59,60,61,62,63,64,65,66,67,74,75,79,81,82,85,102,103,104,105,110,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135,141,142],"119":[0,6,7,9,147,22,26,59,60,62,63,66,68,75,76,79,81,96,98,104,105,106,107,112,114,115,116,117,118,120,123,124,125,126,127,128,133,134,135,138,139,141,142,144,145,146],"130":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,22,26,27,28,37,38,42,45,48,49,50,52,59,60,61,62,63,64,65,66,67,68,69,74,75,76,79,81,82,85,96,98,99,100,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,131,133,134,135,136,137,138,139,140,141,142,144,145,146]},"packages/frontend/editor-ui/src/app/components/Banner.vue":{"22":[3,7,8,23,30,33,37,38,39,51,58,80,89,97,98,127,130,145],"47":[3,7,8,23,30,33,37,38,39,51,58,80,89,97,98,127,130,145],"53":[3,7,8,23,30,33,37,38,39,51,58,80,89,97,98,127,130,145],"58":[3,7,8,23,30,33,37,38,39,51,58,80,89,97,98,127,130,145],"62":[3,7,8,23,30,33,38,39,51,58,80,89,97,98,127,145],"71":[89]},"packages/frontend/editor-ui/src/app/components/BottomMenu.vue":{"23":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,29,30,31,32,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"33":[16,109],"36":[16,109],"78":[16,93,109],"82":[93],"84":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,29,30,31,32,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"104":[16,109],"106":[16,109],"118":[16,109],"129":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"134":[16,109],"146":[93],"148":[93],"168":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,29,30,31,32,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"173":[93]},"packages/frontend/editor-ui/src/app/components/BreakpointsObserver.vue":{"30":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"37":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"53":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"72":[68,115],"76":[68,115],"84":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"88":[42,50,68,112,133,139],"91":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/app/components/ConnectionTracker.vue":{"26":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,95,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/app/components/CopyInput.vue":{"37":[114],"54":[3,37,39,67,114,130,145]},"packages/frontend/editor-ui/src/app/components/Draggable.vue":{"40":[1,2,3,4,6,7,8,9,11,12,14,15,16,18,20,21,22,23,24,27,28,37,38,40,41,49,52,53,55,57,58,60,61,62,65,66,67,68,69,70,71,72,74,75,76,79,80,81,82,83,84,85,96,98,100,102,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,144,146],"44":[68,69,70,72,120,123,125,128,138,144],"78":[68,120],"105":[68,120],"115":[68,69,70,72,120,144],"127":[68,69,70,72,120,144],"135":[1,4,6,7,8,9,11,12,15,21,22,27,28,37,38,40,41,52,53,55,57,60,61,62,65,67,68,69,70,71,72,75,76,79,80,81,82,83,84,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,131,132,133,135,138,140,144],"149":[1,2,3,4,6,7,8,9,11,12,14,15,16,18,20,21,22,23,24,27,28,37,38,40,41,49,52,53,55,57,58,60,61,62,65,66,67,68,69,70,71,72,74,75,76,79,80,81,82,83,84,85,96,98,100,102,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,144,146]},"packages/frontend/editor-ui/src/app/components/DraggableTarget.vue":{"15":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,34,37,38,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,90,91,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"31":[1,2,3,4,5,7,8,9,11,12,21,22,23,24,27,28,34,37,38,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,90,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"32":[120],"34":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,34,37,38,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,90,91,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"37":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,34,37,38,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,90,91,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"39":[120],"49":[1,3,5,7,8,11,12,14,21,22,23,24,27,28,34,37,38,51,55,58,60,61,67,76,82,83,89,103,104,105,109,110,111,114,116,117,118,119,120,121,122,124,125,127,128,129,130,131,133,134,136,138],"53":[1,3,7,8,11,12,14,21,22,23,24,27,28,34,37,38,51,55,58,60,61,67,76,82,83,89,103,104,105,109,110,111,114,116,117,118,119,120,121,122,124,125,127,128,129,130,131,133,134,136,138],"57":[7,11,12,22,24,27,34,37,38,51,55,58,60,61,67,89,110,111,118,119,120,121,122,124,127,128,129,130,131,136],"64":[120],"79":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,34,37,38,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,90,91,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144]},"packages/frontend/editor-ui/src/app/components/DynamicModalLoader.vue":{"9":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"17":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"23":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"29":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"44":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"46":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"54":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"58":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,38,39,40,41,42,43,44,45,46,47,48,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,104,105,106,107,108,110,111,112,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,131,132,134,135,136,137,138,139,140,141,143,144,145,146],"60":[31,32,33,34,40,41]},"packages/frontend/editor-ui/src/app/components/EnterpriseEdition.ee.vue":{"17":[3,7,8,23,30,33,37,38,39,51,58,70,72,80,89,96,97,98,99,127,130,144,145],"18":[3,7,8,23,30,33,37,38,39,51,58,70,72,80,89,96,97,98,99,127,130,144,145]},"packages/frontend/editor-ui/src/app/components/FocusSidebar.vue":{"28":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"47":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"48":[68,84,106],"49":[0,1,2,3,4,5,6,7,8,9,10,11,12,14,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145],"51":[68,84,106],"53":[68,84,106],"57":[0,1,2,3,4,5,6,7,8,9,10,11,12,14,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145],"65":[84,106],"69":[68],"74":[68],"81":[68,84,106],"85":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"89":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"90":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"101":[0,1,2,3,4,5,6,7,8,9,10,11,12,14,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145],"119":[68],"125":[68],"129":[7,42,50,68,100,105,112,113,114,115,117,133,139,141,142,146],"132":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"154":[84,106]},"packages/frontend/editor-ui/src/app/components/FreeAiCreditsCallout.vue":{"21":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,30,33,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145],"55":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,30,33,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145],"57":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,30,33,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145],"63":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,30,33,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145]},"packages/frontend/editor-ui/src/app/components/KeyboardShortcutTooltip.vue":{"21":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,26,27,28,29,30,31,32,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/app/components/MainHeader/ActionsDropdownMenu.vue":{"44":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"74":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"78":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"86":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"88":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"92":[1,2,4,27,64,68,74,77,83,84,85,117,124,125,127,129,133,143],"96":[1,2,4,27,64,68,74,77,83,84,85,117,124,125,127,129,133,143],"118":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"246":[1,2,4,27,64,68,74,77,83,84,85,96,99,109,117,124,125,127,129,133,139,143],"420":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"428":[1,2,4,27,64,68,74,77,83,84,85,117,124,125,127,129,133,143]},"packages/frontend/editor-ui/src/app/components/MainHeader/MainHeader.vue":{"60":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"68":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"69":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"74":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"75":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"76":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"77":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"78":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"80":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"83":[68],"86":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"94":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"104":[1,2,3,4,5,7,8,9,10,11,12,21,22,23,24,27,28,37,38,52,53,55,57,58,60,61,62,64,65,66,67,68,69,74,75,76,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,144,145,146],"108":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"112":[42,50,68,112,133,139],"116":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"121":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"128":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"138":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"158":[7,68,105,113,114,115,117,141,142],"179":[7,68,105,142],"210":[7,68,105,113,114,115,117,141,142],"236":[68],"254":[68],"258":[68]},"packages/frontend/editor-ui/src/app/components/MainHeader/TabBar.vue":{"22":[7,68,105,113,114,115,117,141,142],"24":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/app/components/MainHeader/WorkflowDetails.vue":{"47":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"93":[68,137],"99":[68],"102":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"106":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"110":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"115":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"120":[68,84,133,137,138,139,143,145,146],"122":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"134":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"135":[68,133,139],"142":[68,137],"150":[68,137],"157":[68,137],"186":[68],"191":[68],"197":[1,2,4,27,38,64,68,69,74,77,83,84,85,99,117,124,125,127,129,133,143,144],"223":[68,139],"267":[68],"288":[68],"324":[68,139],"334":[68,139],"386":[68],"388":[68],"394":[1,2,4,27,64,68,74,77,83,84,85,117,124,125,127,129,133,143],"400":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"409":[42,50,68,112,133,139],"417":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"428":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"434":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,104,105,106,107,108,110,111,112,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,131,132,134,135,136,137,138,139,140,141,143,144,145,146],"493":[139],"500":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/app/components/MainHeader/WorkflowHeaderDraftPublishActions.vue":{"65":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"80":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"87":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"89":[68],"98":[1,2,4,27,64,68,74,77,83,84,85,117,124,125,127,129,133,143],"100":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"104":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"108":[0,1,2,3,4,5,6,7,8,9,10,11,12,22,26,27,28,37,38,42,45,48,49,50,52,53,59,60,61,62,63,64,65,66,67,68,69,74,75,76,79,80,81,82,85,96,98,99,100,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"112":[1,3,5,6,7,8,9,12,21,24,26,37,52,53,60,65,66,67,68,76,78,80,81,100,104,106,109,114,117,118,119,120,121,122,124,126,127,129,130,132,133,139,140,143,144,145,146],"122":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"146":[0,1,2,3,4,5,6,7,8,9,10,11,12,22,26,27,28,37,38,42,45,48,49,50,52,59,60,61,62,63,64,65,66,67,68,69,74,75,76,79,81,82,85,96,98,99,100,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,131,133,134,135,136,137,138,139,140,141,142,144,145,146],"147":[0,1,2,3,4,5,6,7,8,9,10,11,12,22,26,27,28,37,38,42,45,48,49,50,52,59,60,61,62,63,64,65,66,67,68,69,74,75,76,79,81,82,85,96,98,99,100,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,131,133,134,135,136,137,138,139,140,141,142,144,145,146],"148":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"149":[26,66,68,100,139,140,144],"151":[1,2,3,4,5,7,8,10,11,12,21,23,24,26,27,28,36,37,38,52,53,54,55,56,57,58,60,61,62,64,65,67,68,69,74,77,78,80,82,83,84,85,96,98,99,100,103,104,105,108,109,110,111,113,114,117,119,120,121,122,124,125,126,127,129,130,131,132,133,136,137,138,139,140,142,143,144,145,146],"157":[68,144],"182":[66,68,100,139,140,144],"198":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"309":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"314":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"323":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"325":[68],"332":[68],"337":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"342":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"344":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"379":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"384":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"387":[68],"412":[68],"447":[68],"457":[68],"477":[68],"502":[68],"503":[68],"508":[68],"512":[68],"517":[68],"523":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"528":[42,50,68,112,133,139],"536":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"571":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"581":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,104,105,106,107,108,110,111,112,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,131,132,134,135,136,137,138,139,140,141,143,144,145,146],"609":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/app/components/MainSidebar.vue":{"32":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"79":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"82":[0,1,2,3,4,5,6,7,8,9,10,11,12,18,19,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"87":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"89":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"212":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"213":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"216":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"228":[16,36,41,72,93,138],"229":[16,36,41,72,93,138],"234":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"238":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"243":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"254":[69,93,96,98,112,133,138,139,144,145,146],"263":[109],"270":[144],"273":[144],"285":[16,93,109],"328":[93],"336":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"369":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/app/components/MainSidebarHeader.vue":{"37":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,74,75,76,77,79,80,81,82,83,84,85,88,89,93,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"41":[16,36,41,72,93,138],"45":[144],"69":[16,19,29,30,31,32,34,35,36,41,72,93,138],"114":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"123":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"132":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"144":[18,19,38,73,94,138],"168":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,29,30,31,32,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/app/components/MainSidebarSourceControl.vue":{"41":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"84":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/app/components/Modal.vue":{"59":[1,3,7,8,23,30,31,32,33,34,37,38,39,40,41,51,58,66,68,70,72,78,80,87,88,89,90,91,93,94,96,97,98,99,100,109,127,130,135,137,139,140,143,144,145],"81":[1,3,7,8,23,30,31,32,33,34,37,38,39,40,41,51,58,66,70,72,78,80,87,88,89,90,91,93,94,96,97,98,99,100,109,127,130,135,137,139,140,143,144,145],"90":[1,3,7,8,23,30,31,32,33,34,37,38,39,40,41,51,66,70,72,80,87,88,89,91,93,94,97,98,99,100,109,127,130,135,137,139,140,143,144,145],"97":[23,37,40,51,89,97,98],"102":[1,3,7,8,23,30,31,32,33,34,37,38,39,40,41,51,66,70,72,78,80,87,88,89,90,91,93,94,97,98,99,100,109,127,130,135,137,139,140,143,144,145],"109":[23,37,40,51,89,97,98,109],"113":[3,7,8,23,30,31,33,34,37,38,39,51,66,68,70,80,87,88,89,91,93,94,97,98,99,100,109,127,130,135,137,139,140,143,144,145],"125":[7,8,23,30,31,33,34,37,38,51,80,88,89,91,97,98,127,130,139,143,145],"129":[1,3,7,8,23,30,31,32,33,34,37,38,39,40,41,51,58,66,68,70,72,78,80,87,88,89,90,91,93,94,96,97,98,99,100,109,127,130,135,137,139,140,143,144,145],"162":[1,3,7,8,23,30,31,32,33,34,37,38,39,40,41,51,58,66,68,70,72,78,80,87,88,89,90,91,93,94,96,97,98,99,100,109,127,130,135,137,139,140,143,144,145],"164":[1,3,7,8,23,30,31,32,33,34,37,38,39,40,41,51,58,66,72,78,80,89,90,91,97,98,100,127,130,139,140,144,145],"178":[72,109]},"packages/frontend/editor-ui/src/app/components/ModalDrawer.vue":{"7":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"40":[1,2,4,21,23,27,37,40,47,51,64,69,70,71,74,77,83,84,85,88,89,97,98,102,103,104,105,107,108,109,117,121,123,124,125,126,127,129,133,135,138,139,143,144,145,146],"61":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"75":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"89":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"91":[15]},"packages/frontend/editor-ui/src/app/components/ModalRoot.vue":{"20":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"21":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,38,39,40,41,42,43,44,45,46,47,48,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,104,105,106,107,108,110,111,112,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,131,132,134,135,136,137,138,139,140,141,143,144,145,146]},"packages/frontend/editor-ui/src/app/components/Modals.vue":{"144":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"146":[3,7,8,23,30,33,37,38,39,51,58,80,89,97,98,127,130,145],"166":[109],"174":[3,23,37,38,39,89,97,98],"178":[68],"184":[109,143],"192":[137],"200":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"204":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"210":[100],"228":[94],"234":[66,100,139,140,144],"238":[93],"242":[93],"246":[96,99,144],"252":[87],"260":[87],"271":[90,91],"325":[89],"331":[89],"357":[144],"386":[78,145],"395":[72],"404":[1],"416":[70],"422":[70,72],"446":[135],"470":[88],"488":[66,100,139,140,144]},"packages/frontend/editor-ui/src/app/components/NodeExecuteButton.vue":{"15":[1,2,3,4,7,8,9,11,12,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"59":[1,2,3,4,7,8,9,11,12,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"74":[1,2,8,9,27,61,65,67,75,81,110,118,120,122,124,125,128,129,131],"81":[1,2,3,4,7,8,9,11,12,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"93":[1,2,3,4,7,8,9,11,12,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"99":[1,2,3,4,7,8,9,11,12,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"105":[1,2,3,4,7,8,9,11,12,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"116":[1,2,3,4,7,8,9,11,12,21,22,23,24,27,28,37,38,52,53,55,57,58,60,61,62,65,67,75,76,80,81,82,83,84,96,98,100,103,104,105,106,109,110,111,113,114,117,118,119,120,121,122,124,125,126,127,128,129,130,131,132,133,136,138,140],"120":[1,2,8,9,12,27,60,61,65,67,75,81,110,118,120,122,124,125,127,128,129,131],"132":[1,2,8,9,27,61,65,67,75,81,110,118,120,122,124,125,128,129,131],"136":[1,2,3,4,7,8,9,11,12,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"148":[1,2,3,4,7,8,9,11,12,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144]},"packages/frontend/editor-ui/src/app/components/NodeIcon.vue":{"43":[1,2,3,4,5,6,7,8,9,11,12,14,21,22,23,24,27,28,34,37,38,49,51,52,53,54,55,56,57,58,60,61,62,65,66,67,74,75,76,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,142,144,145,146],"44":[1,2,3,4,5,6,7,8,9,11,12,14,21,22,23,24,27,28,34,37,38,49,51,52,53,54,55,56,57,58,60,61,62,65,66,67,74,75,76,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,142,144,145,146],"48":[0,1,2,3,4,5,6,7,8,9,11,12,13,14,21,22,23,24,26,27,28,34,37,38,42,45,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"50":[0,1,2,3,4,5,6,7,8,9,11,12,13,14,21,22,23,24,26,27,28,34,37,38,42,45,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"51":[0,1,2,3,4,5,6,7,8,9,11,12,13,14,21,22,23,24,26,27,28,34,37,38,42,45,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"56":[0,1,2,3,4,5,6,7,8,9,11,12,13,14,21,22,23,24,26,27,28,34,37,38,42,45,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"61":[0,1,2,3,4,5,6,7,8,9,11,12,13,14,21,22,23,24,26,27,28,34,37,38,42,45,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"66":[0,1,2,3,4,5,6,7,8,9,11,12,13,14,21,22,23,24,26,27,28,34,37,38,42,45,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"71":[0,1,2,3,4,5,6,7,8,9,11,12,13,14,21,22,23,24,26,27,28,34,37,38,42,45,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/app/components/NpsSurvey.vue":{"14":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"40":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"117":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"127":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"144":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"146":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,38,39,40,41,42,43,44,45,46,47,48,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,104,105,106,107,108,110,111,112,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,131,132,134,135,136,137,138,139,140,141,143,144,145,146]},"packages/frontend/editor-ui/src/app/components/SaveButton.vue":{"12":[3,7,8,23,30,33,37,38,39,51,58,80,89,90,91,97,98,127,130,145],"36":[3,7,8,23,30,33,37,38,39,51,58,80,89,90,91,97,98,127,130,145],"45":[3,7,8,23,30,33,37,38,39,51,58,80,89,90,91,97,98,127,130,145],"73":[7,8,23,30,33,37,38,51,80,89,90,91,97,98,127,145]},"packages/frontend/editor-ui/src/app/components/TidyUpIcon.vue":{"2":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/app/components/UpdatesPanel.vue":{"11":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"15":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,38,39,40,41,42,43,44,45,46,47,48,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,104,105,106,107,108,110,111,112,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,131,132,134,135,136,137,138,139,140,141,143,144,145,146],"24":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"29":[15],"61":[15],"70":[15]},"packages/frontend/editor-ui/src/app/components/WorkflowProductionChecklist.vue":{"32":[0,1,2,3,4,5,6,7,8,9,10,11,12,22,26,27,28,37,38,42,45,48,49,50,52,59,60,61,62,63,64,65,66,67,68,69,74,75,76,79,81,82,85,96,98,99,100,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,131,133,134,135,136,137,138,139,140,141,142,144,145,146],"49":[26,66,68,100,139,140,144],"50":[26,66,68,100,139,140,144],"51":[26,66,68,100,139,140,144],"57":[68,100],"61":[26,66,68,100,139,140,144],"66":[26,66,68,100,139,140,144],"67":[26,66,68,100,139,140,144],"72":[26,66,68,100,139,140,144],"73":[26,66,68,100,139,140,144],"76":[26,66,68,100,139,140,144],"81":[68,100,139],"85":[66,68,100,139,140,144],"87":[0,1,2,3,4,5,6,7,8,9,10,11,12,22,26,27,28,37,42,45,49,50,52,59,60,61,62,63,64,65,66,67,68,69,74,75,76,79,81,82,85,96,98,99,100,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,131,133,134,135,136,137,138,139,140,141,142,144,145,146],"91":[0,1,2,3,4,5,6,7,8,9,10,11,12,22,26,27,28,37,38,42,45,49,50,52,59,60,61,62,63,64,65,66,67,68,69,74,75,76,79,81,82,85,96,98,99,100,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,121,122,123,124,125,126,128,129,131,133,134,135,136,137,138,139,140,141,142,144,145,146],"92":[38,68,138],"94":[0,1,2,3,4,5,6,7,8,9,10,11,12,22,26,27,28,37,38,42,45,49,50,52,59,60,61,62,63,64,65,66,67,68,69,74,75,76,79,81,82,85,96,98,99,100,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,131,133,134,135,136,137,138,139,140,141,142,144,145,146],"98":[0,1,2,3,4,5,6,7,8,9,10,11,12,22,26,27,28,37,38,42,45,49,50,52,59,60,61,62,63,64,65,66,67,68,69,74,75,76,79,81,82,85,96,98,99,100,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,131,133,134,135,136,137,138,139,140,141,142,144,145,146],"102":[0,1,2,3,4,5,6,7,8,9,10,11,12,22,26,27,28,37,38,42,45,49,50,52,59,60,61,62,63,64,65,66,67,68,69,74,75,76,79,81,82,85,96,98,99,100,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,121,122,123,124,125,126,128,129,131,133,134,135,136,137,138,139,140,141,142,144,145,146],"104":[0,1,2,3,4,5,6,7,8,9,10,11,12,22,26,27,28,37,38,42,45,48,49,50,52,59,60,61,62,63,64,65,66,67,68,69,74,75,76,79,81,82,85,96,98,99,100,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,131,133,134,135,136,137,138,139,140,141,142,144,145,146],"169":[0,1,2,3,4,5,6,7,8,9,10,11,12,22,26,27,28,37,38,42,45,50,52,59,60,61,62,63,64,65,66,67,68,69,74,75,76,79,81,82,85,96,98,99,100,104,105,106,107,110,111,112,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,131,134,135,136,137,138,139,140,141,144,145,146],"215":[0,1,2,3,4,5,6,7,8,9,10,11,12,22,26,27,28,37,38,42,45,48,49,50,52,59,60,61,62,63,64,65,66,67,68,69,74,75,76,79,81,82,85,96,98,99,100,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,131,133,134,135,136,137,138,139,140,141,142,144,145,146],"224":[68,100],"249":[68,100],"259":[68,100],"275":[68,100],"286":[68,100],"294":[68,100,139],"298":[68,100],"302":[68,100,139],"312":[0,1,2,3,4,5,6,7,8,9,10,11,12,22,26,27,28,37,38,42,45,48,49,50,52,59,60,61,62,63,64,65,66,67,68,69,74,75,76,79,81,82,85,96,98,99,100,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,131,133,134,135,136,137,138,139,140,141,142,144,145,146],"314":[66,68,100,139,140,144],"321":[68,100,139],"328":[68],"340":[0,1,2,3,4,5,6,7,8,9,10,11,12,22,26,27,28,37,38,42,45,48,49,50,52,59,60,61,62,63,64,65,66,67,68,69,74,75,76,79,81,82,85,96,98,99,100,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,131,133,134,135,136,137,138,139,140,141,142,144,145,146],"343":[0,1,2,3,4,5,6,7,8,9,10,11,12,22,26,27,28,37,38,42,45,48,49,50,52,59,60,61,62,63,64,65,66,67,68,69,74,75,76,79,81,82,85,96,98,99,100,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,131,133,134,135,136,137,138,139,140,141,142,144,145,146]},"packages/frontend/editor-ui/src/app/components/app/AppBanners.vue":{"7":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"9":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"10":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/app/components/app/AppChatPanel.vue":{"8":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"16":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"18":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"26":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"41":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/app/components/app/AppCommandBar.vue":{"11":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"24":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"26":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"28":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"34":[144],"37":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/app/components/app/AppHeader.vue":{"6":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/app/components/app/AppLayout.vue":{"5":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"6":[3,15,16,18,19,20,22,23,26,35,37,38,39,40,41,68,69,70,71,72,73,88,89,93,94,96,97,98,112,133,138,139,144,145,146],"9":[25,33,36,87,89,90,91,92,93,94,95],"12":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"14":[18,20,93],"15":[13,14,101,102,112,115,117,141,142],"16":[29,30,31,32,34,35],"18":[42,43,44,45,46,47,48,49,50,51],"30":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"35":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"37":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/app/components/app/AppModals.vue":{"7":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/app/components/layouts/ResourcesListLayout.vue":{"150":[3,15,16,18,19,20,22,23,26,37,38,39,40,41,68,69,70,71,72,73,88,89,93,94,96,97,98,133,138,139,144,146],"151":[144],"154":[3,15,16,18,19,20,22,23,26,37,38,39,40,41,68,69,70,71,72,73,88,89,93,94,96,97,98,133,138,139,144,146],"165":[3,15,16,18,19,20,22,23,26,37,38,39,40,41,68,69,70,71,72,73,88,89,93,94,96,97,98,133,138,139,144,146],"169":[3,15,16,18,20,23,37,38,39,40,41,68,69,70,71,72,88,89,97,98,133,138,139,144,146],"173":[23,37,38,39,72,88,89,97,98],"198":[37,39,72,88,97,98],"242":[3,15,16,18,19,20,22,23,26,37,38,39,40,41,68,69,70,71,72,73,88,89,93,94,96,97,98,133,138,139,144,146],"243":[144],"252":[3,15,16,18,19,20,22,23,26,37,38,39,40,41,68,69,70,71,72,73,88,89,93,94,96,97,98,133,138,139,144,146],"259":[3,15,16,18,19,20,22,23,26,37,38,39,40,41,68,69,70,71,72,73,88,89,93,94,96,97,98,133,138,139,144,146],"260":[40,68,69,70,72,138,144],"266":[3,15,16,18,19,20,22,23,26,37,38,39,40,41,68,69,70,71,72,73,88,89,93,94,96,97,98,133,138,139,144,146],"273":[3,15,16,18,19,20,22,23,26,37,38,39,40,41,68,69,70,71,72,73,88,89,93,94,96,97,98,133,138,139,144,146],"274":[69,88,144],"278":[3,15,16,18,19,20,22,23,26,37,38,39,40,41,68,69,70,71,72,73,88,89,93,94,96,97,98,133,138,139,144,146],"279":[3,23,38,97,98],"285":[3,15,16,18,19,20,22,23,26,37,38,39,40,41,68,69,70,71,72,73,88,89,93,94,96,97,98,133,138,139,144,146],"292":[3,15,16,18,19,20,22,23,26,37,38,39,40,41,68,69,70,71,72,73,88,89,93,94,96,97,98,133,138,139,144,146],"299":[3,15,16,18,19,20,22,23,26,37,38,39,40,41,68,69,70,71,72,73,88,89,93,94,96,97,98,133,138,139,144,146],"311":[15,18,19,20,40,41,69,71,72,73,93,94,96,98,133,138,139,144],"316":[23,37,69,70,88,89,97,98,144],"330":[3,15,16,18,19,20,22,23,26,37,38,39,40,41,68,69,70,71,72,73,88,89,93,94,96,97,98,133,138,139,144,146],"344":[15,16,18,19,20,22,23,26,37,38,39,40,41,68,69,70,71,72,73,88,89,93,94,96,97,98,133,138,139,144,146],"349":[144],"354":[3,15,16,18,19,20,23,37,38,39,40,41,68,69,70,71,72,73,88,89,93,94,96,97,98,133,138,139,144,146],"358":[41],"366":[37],"377":[3,23,38,40,41,68,69,70,72,97,98,138],"387":[3,23,38,40,41,68,69,70,72,97,98,138,144],"395":[38,40,72,97,98,138],"402":[3,23,38,40,41,68,69,70,72,97,98,138,144],"417":[88],"421":[144],"425":[3,23,38,40,41,68,69,70,72,97,98,138],"426":[3,23,38,40,41,68,69,70,72,97,98,138],"439":[23,37,38,39,72,89,97,98],"446":[88],"453":[37],"459":[144],"463":[69,88,144],"477":[37,41],"526":[3,15,16,18,19,20,22,23,26,37,38,39,40,41,68,69,70,71,72,73,88,89,93,94,96,97,98,133,138,139,144,146],"576":[15,16,18,19,20,22,26,40,41,68,69,70,71,72,73,93,94,96,98,133,138,139,144,146],"592":[3,15,16,18,19,20,22,23,26,37,38,39,40,41,68,69,70,71,72,73,88,89,93,94,96,97,98,133,138,139,144,146],"624":[15,16,18,19,20,22,23,26,37,38,39,40,41,68,69,70,71,72,73,88,89,93,94,96,97,98,133,138,139,144,146],"639":[15,16,18,19,20,22,23,26,37,38,39,40,41,68,69,70,71,72,73,88,89,93,94,96,97,98,133,138,139,144,146],"649":[37],"650":[15,16,18,19,20,22,23,26,37,38,39,40,41,68,69,70,71,72,73,88,89,93,94,96,97,98,133,138,139,144,146],"652":[15,16,18,19,20,22,23,26,37,38,39,40,41,68,69,70,71,72,73,88,89,93,94,96,97,98,133,138,139,144,146],"670":[144],"688":[15,16,18,19,20,22,23,26,37,38,39,40,41,68,69,70,71,72,73,88,89,93,94,96,97,98,133,138,139,144,146],"694":[15,16,18,19,20,22,23,26,37,38,39,40,41,68,69,70,71,72,73,88,89,93,94,96,97,98,133,138,139,144,146],"721":[23,37,38,39,72,89,97,98],"732":[15,16,18,20,40,41,68,69,70,71,72,133,138,139,144,146],"764":[88],"768":[88],"779":[88,144]},"packages/frontend/editor-ui/src/app/components/transitions/SlideTransition.vue":{"3":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/app/composables/useActivityDetection.ts":{"6":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"9":[2,3,4,5,7,11,22,38,60,67,68,75,81,82,98,100,103,107,109,113,116,118,120,121,126,127,128,129,131,133,135,138,139,140,141,142,144,145],"15":[2,3,4,5,7,11,22,38,52,60,66,67,68,75,81,82,98,100,103,104,105,107,109,110,111,113,116,117,118,120,121,126,127,128,129,131,133,135,138,139,140,141,142,144,145],"16":[2,3,4,5,7,11,22,38,52,60,66,67,68,75,81,82,98,100,103,104,105,107,109,110,111,113,116,117,118,120,121,126,127,128,129,131,133,135,138,139,140,141,142,144,145],"21":[7,22,42,50,68,69,96,98,100,105,107,112,113,114,115,117,133,138,139,141,142,144,145,146],"22":[7,22,42,50,68,69,96,98,100,105,107,112,113,114,115,117,133,138,139,141,142,144,145,146],"28":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"29":[2,3,4,5,7,11,22,38,52,60,66,67,68,75,81,82,98,100,103,104,105,107,109,110,111,113,116,117,118,120,121,126,127,128,129,131,133,135,138,139,140,141,142,144,145],"39":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"46":[7,42,50,68,69,96,98,100,105,112,113,114,115,117,133,138,139,141,142,144,145,146]},"packages/frontend/editor-ui/src/app/composables/useAiGateway.ts":{"13":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"17":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,25,26,27,28,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"30":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,34,36,37,38,42,45,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/app/composables/useBackendStatus.ts":{"10":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"19":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"49":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"67":[0,7,9,34,35,41,46,49,60,67,68,98,104,105,111,112,113,115,117,136,142],"72":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/app/composables/useBeforeUnload.ts":{"15":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"22":[22,69,104,105,107,116,133,135,138,144],"27":[22,69,104,105,107,116,133,135,138,144],"32":[22,69,104,105,107,116,133,135,138,144],"43":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"47":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"51":[7,42,50,69,96,98,100,105,112,113,114,115,117,133,138,139,141,142,144,145,146]},"packages/frontend/editor-ui/src/app/composables/useBrowserNotifications.ts":{"57":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"66":[5,10],"80":[5,10]},"packages/frontend/editor-ui/src/app/composables/useBugReporting.ts":{"30":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/app/composables/useCalloutHelpers.ts":{"33":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"111":[7,8,37,52,80,103,114,126,127]},"packages/frontend/editor-ui/src/app/composables/useCanvasOperations.ts":{"221":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,80,82,96,98,99,100,103,104,105,109,110,111,113,114,119,120,121,122,124,126,127,129,130,131,132,133,136,138,140,142,144],"225":[1,2,3,4,5,7,8,11,12,21,23,24,27,28,37,38,52,53,54,55,56,57,58,60,61,62,64,65,67,74,77,78,80,82,83,84,85,96,98,99,100,103,104,105,108,109,110,111,113,114,116,117,119,120,121,122,124,125,126,127,129,130,131,132,133,135,136,138,140,142,143,144,145,146],"235":[5],"248":[5],"265":[5,81,103,104,107,109,138],"273":[5,81,103,104,107,109,138],"282":[5,81,82,83,103,104,107,109,138],"304":[109],"313":[83,135],"341":[135],"353":[105,127,136],"409":[77,103,104,107,109,117,135],"482":[77,103,104,107,109,117,135],"521":[103,104,107,109,135],"526":[103,104,107,109,135],"533":[109,135],"538":[77,103,104,107,109,117,135],"557":[135],"637":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"647":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"670":[0,1,2,3,4,6,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,54,55,56,57,58,60,61,62,64,65,66,67,74,75,76,77,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145],"686":[7,100,103,105,109,117,140,141,142],"699":[109],"742":[0,1,2,3,4,5,6,7,8,9,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"762":[1,2,3,4,5,7,8,11,12,21,23,24,27,28,37,38,52,53,54,55,56,57,58,60,61,62,64,65,67,74,77,78,80,82,83,84,85,96,98,99,100,103,104,105,108,109,110,111,113,114,116,117,119,120,121,122,124,125,126,127,129,130,131,132,133,135,136,138,140,142,143,144,145,146],"770":[1,2,3,4,5,7,8,11,12,21,23,24,27,28,37,38,52,53,54,55,56,57,58,60,61,62,64,65,67,74,77,78,80,82,83,84,85,96,98,99,100,103,104,105,108,109,110,111,113,114,116,117,119,120,121,122,124,125,126,127,129,130,131,132,133,135,136,138,140,142,143,144,145,146],"850":[1,2,3,4,5,7,8,11,12,21,23,24,27,28,37,38,52,53,54,55,56,57,58,60,61,62,64,65,67,74,77,78,80,82,83,84,85,96,98,99,100,103,104,105,108,109,110,111,113,114,116,117,119,120,121,122,124,125,126,127,129,130,131,132,133,135,136,138,140,142,143,144,145,146],"869":[1,2,3,4,5,7,8,11,12,21,23,24,27,28,37,38,52,53,54,55,56,57,58,60,61,62,64,65,67,74,77,78,80,82,83,84,85,96,98,99,100,103,104,105,108,109,110,111,113,114,116,117,119,120,121,122,124,125,126,127,129,130,131,132,133,135,136,138,140,142,143,144,145,146],"883":[1,2,3,4,5,7,8,11,12,21,23,24,27,28,37,38,52,53,54,55,56,57,58,60,61,62,64,65,67,74,77,78,80,82,83,84,85,96,98,99,100,103,104,105,108,109,110,111,113,114,116,117,119,120,121,122,124,125,126,127,129,130,131,132,133,135,136,138,140,142,143,144,145,146],"906":[1,2,3,4,5,7,8,11,12,21,23,24,27,28,37,38,52,53,54,55,56,57,58,60,61,62,64,65,67,74,77,78,80,82,83,84,85,96,98,99,100,103,104,105,108,109,110,111,113,114,116,117,119,120,121,122,124,125,126,127,129,130,131,132,133,135,136,138,140,142,143,144,145,146],"955":[109,135],"964":[1,2,3,4,5,7,8,11,12,21,23,24,27,28,37,38,52,53,54,55,56,57,58,60,61,62,64,65,67,74,77,78,80,82,83,84,85,96,98,99,100,103,104,105,108,109,110,111,113,114,116,117,119,120,121,122,124,125,126,127,129,130,131,132,133,135,136,138,140,142,143,144,145,146],"1090":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,80,82,83,96,98,99,100,103,104,105,108,109,110,111,113,114,116,119,120,121,122,124,126,127,129,130,131,132,133,136,138,140,142,144],"1100":[108],"1106":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,126,127,129,130,131,132,133,136,138,140,142,144],"1136":[1,2,3,4,5,7,8,11,12,21,23,24,27,28,37,38,52,53,54,55,56,57,58,60,61,62,64,65,67,74,77,78,80,82,83,84,85,96,98,99,100,103,104,105,108,109,110,111,113,114,116,117,119,120,121,122,124,125,126,127,129,130,131,132,133,135,136,138,140,142,143,144,145,146],"1179":[1,2,3,4,5,7,8,11,12,21,23,24,27,28,37,38,52,53,54,55,56,57,58,60,61,62,64,65,67,74,77,78,80,82,83,84,85,96,98,99,100,103,104,105,108,109,110,111,113,114,116,117,119,120,121,122,124,125,126,127,129,130,131,132,133,135,136,138,140,142,143,144,145,146],"1185":[1,2,3,4,5,7,8,11,12,21,23,24,27,28,37,38,52,53,54,55,56,57,58,60,61,62,64,65,67,74,77,78,80,82,83,84,85,96,98,99,100,103,104,105,108,109,110,111,113,114,116,117,119,120,121,122,124,125,126,127,129,130,131,132,133,135,136,138,140,142,143,144,145,146],"1190":[1,2,3,4,5,7,8,11,12,21,23,24,27,28,37,38,52,53,54,55,56,57,58,60,61,62,64,65,67,74,77,78,80,82,83,84,85,96,98,99,100,103,104,105,108,109,110,111,113,114,116,117,119,120,121,122,124,125,126,127,129,130,131,132,133,135,136,138,140,142,143,144,145,146],"1210":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,80,82,83,96,98,99,100,103,104,105,108,109,110,111,113,114,116,119,120,121,122,124,126,127,129,130,131,132,133,136,138,140,142,144],"1222":[0,1,2,3,4,5,6,7,8,9,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"1234":[1,2,3,4,5,7,8,11,12,21,23,24,27,28,37,38,52,53,54,55,56,57,58,60,61,62,64,65,67,74,77,78,80,82,83,84,85,96,98,99,100,103,104,105,108,109,110,111,113,114,116,117,119,120,121,122,124,125,126,127,129,130,131,132,133,135,136,138,140,142,143,144,145,146],"1360":[7,8,37,52,67,80,83,103,104,105,109,110,111,116,119,121,126,129,131,132,133],"1373":[3,7,8,11,12,21,23,28,37,38,52,55,58,60,61,67,80,82,83,96,98,100,103,104,105,109,110,111,113,116,119,120,121,122,124,126,127,129,130,131,132,133,136,140],"1394":[82,83,103],"1450":[3,7,8,11,12,21,23,28,37,38,52,55,58,60,61,67,80,82,83,96,98,100,103,104,105,109,110,111,113,116,119,120,121,122,124,126,127,129,130,131,132,133,136,140],"1455":[7,8,37,52,80,126],"1478":[7,67,83,103,104,105,109,110,111,116,119,121,129,131,132,133],"1518":[1,2,3,4,5,7,8,11,12,21,23,24,27,28,37,38,52,53,54,55,56,57,58,60,61,62,64,65,67,74,77,78,80,82,83,84,85,96,98,99,100,103,104,105,108,109,110,111,113,114,116,117,119,120,121,122,124,125,126,127,129,130,131,132,133,135,136,138,140,142,143,144,145,146],"1524":[0,1,2,3,4,5,6,7,8,9,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"1539":[82,83,103],"1561":[82,83,103],"1598":[82,83,103],"1613":[83],"1618":[82,83,103],"1620":[82,83,103],"1626":[83],"1640":[83],"1652":[83],"1666":[83],"1673":[83],"1680":[82,83,103],"1687":[82,83,103],"1695":[83,103],"1704":[83,103],"1708":[82,83,103],"1720":[82,83,103],"1723":[82,83,103],"1726":[82,83,103],"1827":[83],"1874":[82,83,103],"1893":[82,83,103],"1937":[1,2,3,4,5,7,8,11,12,21,23,24,27,28,37,38,52,53,55,57,58,60,61,62,64,67,74,77,80,82,83,84,85,96,98,100,103,104,105,107,108,109,110,111,113,116,117,119,120,121,122,124,125,126,127,129,130,131,132,133,135,136,138,140,143],"1970":[1,2,3,4,5,7,8,11,12,21,23,24,27,28,37,38,52,53,55,57,58,60,61,62,64,67,74,77,80,82,83,84,85,96,98,100,103,104,105,107,109,110,111,113,116,117,119,120,121,122,124,125,126,127,129,130,131,132,133,135,136,138,140,143],"1980":[109,135],"1993":[77,103,104,107,109,117,135],"2059":[5,77,82,83,103,104,107,109,117,135],"2083":[5,77,82,83,103,104,107,109,117,135],"2097":[109,135],"2103":[7,24,67,104,135],"2120":[7,104,135],"2147":[7,135],"2151":[24,67,104,135],"2155":[1,2,3,4,5,7,8,11,12,21,23,24,27,28,37,38,52,53,55,57,58,60,61,62,64,67,74,77,80,82,83,84,85,96,98,100,103,104,105,107,108,109,110,111,113,116,117,119,120,121,122,124,125,126,127,129,130,131,132,133,135,136,138,140,143],"2163":[1,2,3,4,5,7,8,11,12,21,23,24,27,28,37,38,52,53,55,57,58,60,61,62,64,67,74,77,80,82,83,84,85,96,98,100,103,104,105,107,108,109,110,111,113,116,117,119,120,121,122,124,125,126,127,129,130,131,132,133,135,136,138,140,143],"2169":[1,2,3,4,5,7,8,11,12,21,23,24,27,28,37,38,52,53,55,57,58,60,61,62,64,67,74,77,80,82,83,84,85,96,98,100,103,104,105,107,109,110,111,113,116,117,119,120,121,122,124,125,126,127,129,130,131,132,133,135,136,138,140,143],"2176":[1,2,3,4,5,7,8,11,12,21,23,24,27,28,37,38,52,53,55,57,58,60,61,62,64,67,74,77,80,82,83,84,85,96,98,100,103,104,105,107,109,110,111,113,116,117,119,120,121,122,124,125,126,127,129,130,131,132,133,135,136,138,140,143],"2180":[1,2,3,4,5,7,8,11,12,21,23,24,27,28,37,38,52,53,55,57,58,60,61,62,64,67,74,77,80,82,83,84,85,96,98,100,103,104,105,107,109,110,111,113,116,117,119,120,121,122,124,125,126,127,129,130,131,132,133,135,136,138,140,143],"2185":[1,2,3,4,5,7,8,11,12,21,23,24,27,28,37,38,52,53,55,57,58,60,61,62,64,67,74,77,80,82,83,84,85,96,98,100,103,104,105,107,109,110,111,113,116,117,119,120,121,122,124,125,126,127,129,130,131,132,133,135,136,138,140,143],"2264":[1,2,3,4,5,7,8,11,12,21,23,24,27,28,37,38,52,53,55,57,58,60,61,62,64,67,74,77,80,82,83,84,85,96,98,100,103,104,105,107,109,110,111,113,116,117,119,120,121,122,124,125,126,127,129,130,131,132,133,135,136,138,140,143],"2295":[1,2,3,4,5,7,8,11,12,21,23,24,27,28,37,38,52,53,54,55,56,57,58,60,61,62,64,65,67,74,77,80,82,83,84,85,96,98,99,100,103,104,105,108,109,110,111,113,114,116,117,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,143,144],"2322":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"2358":[0,1,2,6,7,8,9,13,14,22,26,27,28,42,45,48,49,50,59,60,62,63,64,66,67,74,75,76,79,81,82,96,98,99,102,104,105,106,107,110,112,114,115,116,117,118,119,120,123,124,125,126,127,128,129,133,134,135,138,139,141,142,144,145,146],"2364":[0,1,2,6,7,8,9,13,14,22,26,27,28,42,45,48,49,50,59,60,62,63,64,66,67,74,75,76,79,81,82,98,99,102,104,105,106,107,110,112,114,115,116,117,118,119,120,123,124,125,126,127,128,129,133,134,135,138,139,141,142,144,145,146],"2365":[0,1,2,6,7,8,9,13,14,22,26,27,28,42,45,48,49,50,59,60,62,63,64,66,67,74,75,76,79,81,82,98,99,102,104,105,106,107,110,112,114,115,116,117,118,119,120,123,124,125,126,127,128,129,133,134,135,138,139,141,142,144,145,146],"2366":[0,1,2,6,7,8,9,13,14,22,26,27,28,42,45,48,49,50,59,60,62,63,64,66,67,74,75,76,79,81,82,98,99,102,104,105,106,107,110,112,114,115,116,117,118,119,120,123,124,125,126,127,128,129,133,134,135,138,139,141,142,144,145,146],"2368":[0,1,2,6,7,8,9,13,14,22,26,27,28,42,45,48,49,50,59,60,62,63,64,66,67,74,75,76,79,81,82,98,99,102,104,105,106,107,110,112,114,115,116,117,118,119,120,123,124,125,126,127,128,129,133,134,135,138,139,141,142,144,145,146],"2410":[1,2,4,27,64,74,77,83,84,85,105,109,117,124,125,127,129,133,138,143],"2426":[1,2,4,27,64,74,77,83,84,85,105,109,117,124,125,127,129,133,138,143],"2444":[1,2,4,27,64,74,77,83,84,85,105,109,117,124,125,127,129,133,138,143],"2460":[1,2,4,27,64,74,77,83,84,85,105,109,117,124,125,127,129,133,138,143],"2463":[1,2,4,27,64,74,77,83,84,85,105,109,117,124,125,127,129,133,138,143],"2496":[1,2,4,27,64,74,77,83,84,85,105,109,117,124,125,127,129,133,138,143],"2626":[1,2,4,27,64,74,77,83,84,85,105,109,117,124,125,127,129,133,138,143],"2656":[1,2,4,27,64,74,77,83,84,85,105,109,117,124,125,127,129,133,138,143],"2671":[1,2,4,27,64,74,77,83,84,85,105,109,117,124,125,127,129,133,138,143],"2678":[1,2,4,27,64,74,77,83,84,85,105,109,117,124,125,127,129,133,138,143],"2685":[1,2,4,27,64,74,77,83,84,85,105,109,117,124,125,127,129,133,138,143],"2686":[1,2,4,27,64,74,77,83,84,85,105,109,117,124,125,127,129,133,138,143],"2806":[1,2,4,27,64,74,77,83,84,85,105,109,117,124,125,127,129,133,138,143],"2829":[64,83,84,125,127,129,133,143],"2831":[125,143],"2834":[84,133,143],"2838":[84,133,143],"2848":[84,133,143],"2849":[84,133,143],"2860":[143],"2883":[103,105,109,129,138,145],"2897":[1,2,4,27,64,74,77,83,84,85,105,109,117,124,125,127,129,133,138,143],"2921":[103,105,109,129,138,145],"2933":[103,105,109,129,138,145],"2975":[145],"2980":[145],"2989":[103,105,109,129,138,145],"3010":[103,105,138,145],"3017":[103,105,138,145],"3018":[103,105,138,145],"3029":[105,109,129],"3036":[105,109,129],"3039":[103,138,145],"3051":[103,138,145],"3061":[117,141,142],"3111":[7,8,9,81,102],"3126":[7,8,9,81,102],"3131":[78,145,146],"3208":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,80,82,83,96,98,99,100,103,104,105,108,109,110,111,113,114,116,119,120,121,122,124,126,127,129,130,131,132,133,136,138,140,142,144],"3234":[7,8,24,37,52,53,55,57,58,62,80,82,124,126,127,130,131,138],"3284":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"3285":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"3288":[78,145,146],"3296":[78,145,146],"3303":[78,145,146]},"packages/frontend/editor-ui/src/app/composables/useClipboard.ts":{"24":[93,114],"44":[105,109,111,138,139],"55":[105,109,111,138],"73":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,29,30,31,32,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,88,93,94,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"86":[1,2,3,4,7,8,9,11,12,21,22,28,30,32,37,38,41,42,47,50,52,53,55,57,60,62,65,67,69,76,79,80,81,82,83,84,88,93,96,98,100,103,104,105,106,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,135,138,139,140,141,142,144,145,146]},"packages/frontend/editor-ui/src/app/composables/useCollectionOverhaul.ts":{"5":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,30,33,34,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,90,91,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145],"8":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,30,33,34,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,90,91,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145]},"packages/frontend/editor-ui/src/app/composables/useDataSchema.ts":{"31":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"34":[1,2,5,9,147,11,27,49,61,62,66,74,75,79,82,85,104,106,110,111,113,114,116,117,118,119,120,121,122,123,124,125,127,128,129,131,132,134,135],"57":[147],"64":[147,62,74,106,117,120,122,123,127,128],"74":[1,2,9,147,11,27,49,61,62,66,74,75,79,82,85,104,106,110,111,113,114,116,117,118,119,120,121,122,123,124,125,127,128,129,131,132,134,135],"99":[1,2,5,9,147,11,27,49,61,62,66,74,75,79,82,85,104,106,110,111,113,114,116,117,118,119,120,121,122,123,124,125,127,128,129,131,132,134,135],"109":[147,118,132],"129":[147,118,132],"150":[147,118,132],"162":[1,2,9,147,11,12,27,49,60,61,62,65,66,67,75,79,82,85,104,110,113,114,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135],"178":[1,2,3,4,5,7,8,9,147,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,107,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"206":[1,2,3,4,5,7,8,9,147,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,107,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"215":[147,14,106,111,113,119,120,121,122,123,125,127,128,129,135],"220":[147,14,106,111,113,119,120,121,122,123,125,127,128,129,135],"227":[147,125],"235":[1,2,9,147,11,27,49,61,62,66,74,75,79,82,85,104,106,110,111,113,114,116,117,118,119,120,121,122,123,124,125,127,128,129,131,132,134,135],"240":[147,125],"364":[1,2,9,147,11,27,49,61,62,66,74,75,79,82,85,104,106,110,111,113,114,116,117,118,119,120,121,122,123,124,125,127,128,129,131,132,134,135],"366":[1,2,147,11,27,49,61,62,66,74,75,79,82,85,104,110,113,114,116,117,118,121,124,125,128,129,131,132,134],"377":[147,118,132],"384":[1,2,9,147,11,27,49,61,62,66,74,75,79,82,85,104,106,110,111,113,114,116,117,118,119,120,121,122,123,124,125,127,128,129,131,132,134,135],"393":[1,2,9,147,11,27,49,61,62,66,74,75,79,82,85,104,106,110,111,113,114,116,117,118,119,120,121,122,123,124,125,127,128,129,131,132,134,135],"395":[1,2,9,147,11,27,49,61,62,66,74,75,79,82,85,104,106,110,111,113,114,116,117,118,119,120,121,122,123,124,125,127,128,129,131,132,134,135],"398":[147,120,125],"406":[1,2,9,147,11,27,49,61,62,66,74,75,79,82,85,104,106,110,111,113,114,116,117,118,119,120,121,122,123,124,125,127,128,129,131,132,134,135],"467":[1,2,9,147,11,27,49,61,62,66,74,75,79,82,85,104,106,110,111,113,114,116,117,118,119,120,121,122,123,124,125,127,128,129,131,132,134,135],"508":[1,2,147,11,27,49,61,62,66,74,75,79,82,85,104,106,110,111,113,114,116,117,118,119,120,121,122,123,124,125,127,128,129,131,132,134,135],"513":[1,2,147,11,27,49,61,62,66,74,75,79,82,85,104,106,110,111,113,114,116,117,118,119,120,121,122,123,124,125,127,128,129,131,132,134,135]},"packages/frontend/editor-ui/src/app/composables/useDebounce.ts":{"19":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"30":[1,2,3,4,5,7,8,9,147,11,12,14,21,22,23,24,27,28,30,37,38,39,40,41,49,51,52,53,55,57,58,60,61,62,64,65,66,67,68,69,74,75,76,79,80,81,82,83,84,85,89,90,91,96,97,98,99,100,103,104,105,109,110,111,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,141,142,144,145,146],"43":[1,3,7,8,147,11,12,21,23,24,28,37,38,41,52,53,54,55,56,57,58,60,61,62,65,67,69,80,82,83,88,96,98,99,100,103,104,105,109,110,111,113,114,115,116,118,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144,146]},"packages/frontend/editor-ui/src/app/composables/useDebugInfo.ts":{"72":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"78":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"115":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"126":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"136":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"147":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"154":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"158":[109],"166":[109],"169":[109],"174":[109],"184":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"201":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"219":[109],"233":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"237":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/app/composables/useDependencies.ts":{"14":[3,15,16,18,19,20,22,23,26,37,38,39,40,41,68,69,70,71,72,73,89,93,94,96,97,98,133,138,139,144,146],"18":[3,15,16,18,20,23,37,38,39,40,41,68,69,70,71,72,89,97,98,133,138,139,144,146],"59":[38,97,98,139],"67":[15,16,18,20,23,37,38,39,40,41,68,69,70,71,72,89,97,98,133,138,139,144,146],"70":[38,97,98,139],"73":[15,16,18,20,23,37,38,39,40,41,68,69,70,71,72,89,97,98,133,138,139,144,146]},"packages/frontend/editor-ui/src/app/composables/useDocumentVisibility.ts":{"12":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"17":[15,22,25,29,30,35,41,44,68,69,70,71,72,89,91,93,98,104,105,107,116,133,135,138,139,144,146],"28":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"36":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"40":[1,2,3,4,131,135]},"packages/frontend/editor-ui/src/app/composables/useErrorHandler.ts":{"26":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/app/composables/useExecutingNode.ts":{"15":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"19":[0,1,2,4,6,7,8,9,11,12,26,27,28,38,45,49,50,59,60,61,62,63,64,65,66,67,74,75,79,81,82,85,102,103,104,105,110,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135,141,142],"24":[0,1,2,4,6,7,8,9,11,12,26,27,28,38,45,49,50,59,60,61,62,63,64,65,66,67,74,75,79,81,82,85,102,103,104,105,110,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135,141,142],"33":[0,1,2,4,6,7,8,9,11,26,27,28,38,45,49,50,59,60,61,62,63,64,65,66,67,74,75,79,81,82,85,102,103,104,105,110,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135,141,142],"38":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/app/composables/useExposeCssVar.ts":{"7":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"11":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"12":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/app/composables/useExternalHooks.ts":{"10":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/app/composables/useFloatingUiOffsets.ts":{"9":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"15":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,90,91,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"16":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"19":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"20":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"29":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/app/composables/useFreeAiCredits.ts":{"24":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,29,30,31,32,33,34,35,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145],"26":[29,30,31,32,34,35],"38":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,29,30,31,32,33,34,35,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145]},"packages/frontend/editor-ui/src/app/composables/useGlobalEntityCreation.ts":{"22":[5,15,21,23,26,35,37,39,40,41,53,54,56,57,58,60,61,62,64,67,68,69,70,71,72,74,75,76,77,79,80,81,82,83,85,88,89,96,98,99,103,104,106,109,111,112,113,118,119,120,121,122,127,129,130,131,136,138,144],"25":[5,15,21,23,26,35,37,39,40,41,53,54,56,57,58,60,61,62,64,67,68,69,70,71,72,74,75,76,77,79,80,81,82,83,85,88,89,96,98,99,103,104,106,109,111,112,113,118,119,120,121,122,127,129,130,131,136,138,144],"65":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"68":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"72":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"76":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"83":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"85":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"92":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"102":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"226":[5,15,21,23,26,35,37,39,40,41,53,54,56,57,58,60,61,62,64,67,68,69,70,71,72,74,75,76,77,79,80,81,82,83,85,88,89,96,98,99,103,104,106,109,111,112,113,118,119,120,121,122,127,129,130,131,136,138,144],"260":[5,15,21,23,26,35,37,39,40,41,53,54,56,57,58,60,61,62,64,67,68,69,70,71,72,74,75,76,77,79,80,81,82,83,85,88,89,96,98,99,103,104,106,109,111,112,113,118,119,120,121,122,127,129,130,131,136,138,144],"320":[15,41,71,98,138,144],"343":[15,41,71,98,133,138,144],"354":[18,19,38,73,94,138],"379":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"380":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"381":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/app/composables/useGlobalLinkActions.ts":{"14":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"15":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"18":[7,42,50,69,96,98,100,105,112,113,114,115,117,133,138,139,141,142,144,145,146],"22":[127],"34":[0,1,2,3,4,5,6,7,8,9,10,11,12,14,21,22,23,24,26,27,28,36,37,38,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145],"55":[127],"60":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"69":[7,42,50,69,96,98,100,105,112,113,114,115,117,133,138,139,141,142,144,145,146]},"packages/frontend/editor-ui/src/app/composables/useHistoryHelper.ts":{"17":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"26":[109,135],"54":[109],"82":[109,135],"88":[109,135],"93":[109],"104":[1,2,4,5,7,21,27,37,40,47,51,53,57,64,69,70,71,74,77,80,82,83,84,85,88,102,103,104,105,107,108,109,116,117,121,123,124,125,126,127,129,133,135,138,139,140,141,142,143,144,145,146],"111":[1,2,4,5,7,21,23,27,37,40,47,51,53,57,64,69,70,71,74,77,80,82,83,84,85,88,89,97,98,102,103,104,105,107,108,109,116,117,121,123,124,125,126,127,129,133,135,138,139,140,141,142,143,144,145,146],"141":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/app/composables/useKeybindings.ts":{"60":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,26,27,28,29,30,31,32,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"81":[5,7,21,40,53,57,80,82,83,103,104,105,107,108,109,116,126,133,135,138,139,140,141,142,144,145,146],"83":[1,2,4,5,7,21,23,27,37,40,47,51,53,57,64,69,70,71,74,77,80,82,83,84,85,88,89,97,98,102,103,104,105,107,108,109,116,117,121,123,124,125,126,127,129,133,135,138,139,140,141,142,143,144,145,146],"87":[5,7,21,40,53,57,80,82,83,103,104,105,107,108,109,116,126,133,135,138,139,140,141,142,144,145,146],"89":[5,7,21,40,53,57,80,82,83,103,104,105,107,108,109,116,126,133,135,138,139,140,141,142,144,145,146],"91":[5,7,21,40,53,57,80,82,83,103,104,105,107,108,109,116,126,133,135,138,139,140,141,142,144,145,146],"96":[5,7,21,40,53,57,80,82,83,103,104,105,107,108,109,116,126,133,135,138,139,140,141,142,144,145,146],"98":[5,7,21,40,53,57,80,82,83,103,104,105,107,108,109,116,126,133,135,138,139,140,141,142,144,145,146],"99":[5,7,21,40,53,57,80,82,83,103,104,105,107,108,109,116,126,133,135,138,139,140,141,142,144,145,146],"103":[5,7,21,40,53,57,80,82,83,103,104,105,107,108,109,116,126,133,135,138,139,140,141,142,144,145,146],"109":[5,7,21,40,53,57,80,82,83,103,104,105,107,108,109,116,126,133,135,138,139,140,141,142,144,145,146],"127":[5,7,21,40,53,57,80,82,83,103,104,105,107,108,109,116,126,133,135,138,139,140,141,142,144,145,146],"145":[5,7,21,40,53,57,80,82,83,103,104,105,107,108,109,116,126,133,135,138,139,140,141,142,144,145,146],"199":[1,2,4,5,7,21,23,27,37,40,47,51,53,57,64,69,70,71,74,77,80,82,83,84,85,88,89,97,98,102,103,104,105,107,108,109,116,117,121,123,124,125,126,127,129,133,135,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/app/composables/useLayoutProps.ts":{"4":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"7":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/app/composables/useLoadingService.ts":{"10":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"14":[147,22,69,78,104,105,107,116,117,133,135,138,141,142,143,144,145,146],"26":[147,78,145,146],"32":[147,78,117,141,142,143,145,146],"39":[1,2,3,4,5,7,8,147,10,11,12,22,27,28,37,38,52,60,61,64,65,67,69,74,75,81,82,85,99,100,103,104,105,107,109,110,111,113,114,117,118,119,120,121,122,124,125,126,127,128,129,131,133,135,136,137,138,140,141,142,144,145,146]},"packages/frontend/editor-ui/src/app/composables/useN8nLocalStorage.ts":{"26":[3,15,16,18,19,20,22,23,26,37,38,39,40,41,68,69,70,71,72,73,88,89,93,94,96,97,98,133,138,139,144,146],"29":[15,16,18,19,20,22,26,40,41,68,69,70,71,72,73,93,94,96,98,133,138,139,144,146],"33":[41],"58":[15,16,18,19,20,22,26,40,41,68,69,70,71,72,73,93,94,96,98,133,138,139,144,146]},"packages/frontend/editor-ui/src/app/composables/useNodeConnections.ts":{"12":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"25":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"26":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,55,57,58,59,60,61,62,63,64,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,141,142,143,145,146],"29":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"30":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,55,57,58,59,60,61,62,63,64,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,141,142,143,145,146],"33":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"34":[0,7,8,9,147,37,52,79,80,100,103,117,126,127],"37":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,55,57,58,59,60,61,62,63,64,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,141,142,143,145,146],"45":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"46":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"49":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"50":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"53":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"61":[147,104,135]},"packages/frontend/editor-ui/src/app/composables/useNodeDirtiness.ts":{"24":[82,104,105,117,135,141,142],"32":[82,104,105,117,135,141,142],"55":[117,135],"63":[82,104,105,117,135,141,142],"64":[82,104,105,117,135,141,142],"74":[141,142],"86":[2,67,75,82,110,113,117,118,127,129,131,135],"121":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"127":[0,1,2,4,6,7,8,9,11,12,26,27,28,38,45,49,50,59,60,61,62,63,64,65,66,67,74,75,79,81,82,85,102,103,104,105,110,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135,141,142],"131":[82,141,142],"135":[0,1,2,4,6,7,8,9,11,12,26,27,28,38,45,49,50,59,60,61,62,63,64,65,66,67,74,75,79,81,82,85,102,103,104,105,110,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135,141,142],"137":[0,1,2,4,6,7,8,9,11,12,26,27,28,38,45,49,50,59,60,61,62,63,64,66,67,74,75,79,81,82,85,102,104,105,110,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135,141,142],"138":[0,7,8,9,117],"141":[0,1,2,4,6,7,8,9,11,12,26,27,28,38,45,49,50,59,60,61,62,63,64,65,66,67,74,75,79,81,82,85,102,103,104,105,110,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135,141,142],"158":[0,1,2,4,6,7,8,9,11,12,26,27,28,38,45,49,50,59,60,61,62,63,64,65,66,67,74,75,79,81,82,85,102,103,104,105,110,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135,141,142],"194":[82],"197":[82],"237":[0,1,2,3,4,5,6,7,8,9,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"241":[2,67,75,82,110,113,117,118,127,129,131,135],"250":[82],"287":[0,1,2,4,6,7,8,9,11,12,26,27,28,38,45,49,50,59,60,61,62,63,64,66,67,74,75,79,81,82,85,102,104,105,110,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135,141,142],"288":[0,1,2,4,6,7,8,9,11,12,26,27,28,38,45,49,50,59,60,61,62,63,64,66,67,74,75,79,81,82,85,102,104,105,110,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135,141,142]},"packages/frontend/editor-ui/src/app/composables/useNodeDocsUrl.ts":{"5":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"8":[58],"10":[37,58,125,126],"18":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144]},"packages/frontend/editor-ui/src/app/composables/useNodeExecution.ts":{"81":[1,2,3,4,5,7,8,9,11,12,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"105":[1,2,3,4,5,7,8,9,11,12,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"114":[1,2,3,4,5,7,8,9,11,12,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"118":[1,2,3,4,5,7,8,9,11,12,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"124":[1,2,3,4,5,7,8,9,11,12,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"128":[12,60,67],"130":[1,2,3,4,5,7,8,9,11,12,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"132":[1,2,8,9,27,61,65,67,75,81,110,118,120,122,124,125,128,129,131],"138":[1,2,3,4,5,7,8,9,11,12,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140],"140":[1,2,3,4,5,7,8,9,11,12,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140],"142":[1,12,60,65,67,129],"144":[1,2,3,4,5,7,8,9,11,12,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"146":[1,2,3,4,5,7,8,9,11,12,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"156":[1,2,3,4,5,7,8,9,11,12,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"169":[1,2,3,4,5,7,8,9,11,12,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"177":[1,2,3,4,5,7,8,9,11,12,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"183":[1,3,5,7,8,12,21,24,37,53,60,65,67,76,100,104,109,111,114,118,119,120,121,122,123,124,126,129,130,132,133,140,144],"190":[1,2,3,4,7,8,9,11,12,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"214":[1,2,3,4,5,7,8,9,11,12,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"242":[1,2,3,4,5,7,8,9,11,12,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"248":[1,2,3,4,5,7,8,9,11,12,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"347":[8,9,81],"356":[1,2,8,9,27,61,65,67,75,81,110,118,120,122,124,125,128,129,131]},"packages/frontend/editor-ui/src/app/composables/useNodeHelpers.ts":{"64":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"80":[1,2,3,4,5,7,8,9,147,11,12,14,21,22,23,24,27,28,34,37,38,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,90,91,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"110":[1,2,3,4,5,7,8,9,147,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"143":[1,2,3,4,7,8,9,147,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"156":[7,8,147,22,23,37,38,60,67,80,96,98,117,127,130],"157":[7,8,147,22,23,37,38,60,67,80,96,98,117,127,130],"158":[7,8,147,22,23,37,38,60,67,80,96,98,117,127,130],"162":[1,2,3,4,5,6,7,8,9,147,11,12,14,21,22,23,24,26,27,28,30,33,34,37,38,39,49,50,51,52,53,55,57,58,59,60,61,62,63,65,66,67,74,75,76,78,79,80,81,82,83,84,85,89,90,91,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,143,144,145,146],"182":[8,147,34,126],"243":[0,1,2,4,6,7,8,9,147,11,12,26,27,28,34,38,45,49,50,59,60,61,62,63,64,65,66,67,74,75,79,81,82,85,102,103,104,105,110,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,131,134,135,141,142,146],"259":[147,22,37,38,61],"273":[0,1,2,3,4,5,6,7,8,9,147,11,12,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"293":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"301":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,21,22,23,24,26,27,28,36,37,38,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"313":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"321":[2,4,7,8,147,11,12,21,23,24,27,28,37,38,58,60,61,62,67,75,84,96,98,103,104,105,109,110,111,113,118,119,120,121,122,124,126,127,129,130,131,135,136,145],"329":[1,2,3,4,5,7,8,147,11,12,21,22,23,24,27,28,37,38,52,53,54,55,56,57,58,60,61,62,64,65,67,74,75,77,78,80,82,83,84,85,96,98,99,100,103,104,105,108,109,110,111,113,114,116,117,118,119,120,121,122,124,125,126,127,129,130,131,132,133,135,136,138,140,141,142,143,144,145,146],"344":[2,4,5,7,8,147,11,12,21,23,24,27,28,37,38,58,60,61,62,67,75,84,96,98,103,104,105,109,110,111,113,118,119,120,121,122,124,126,127,129,130,131,135,136],"352":[0,1,2,3,4,5,6,7,8,9,147,11,12,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"379":[0,1,2,3,4,5,6,7,8,9,147,11,12,21,22,23,24,26,27,28,34,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"392":[0,1,2,3,4,5,6,7,8,9,147,11,12,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,55,57,58,59,60,61,62,63,64,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,100,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,141,142,143,145,146],"417":[147],"419":[147],"424":[3,4,5,6,7,8,9,147,11,12,21,22,23,24,26,27,34,37,38,50,52,53,55,57,58,59,60,61,63,66,67,74,75,76,78,79,80,81,83,96,98,100,103,105,109,111,113,114,116,117,118,124,126,127,128,129,130,132,134,140,143,144,145,146],"453":[0,1,2,3,4,5,6,7,8,9,147,11,12,21,22,23,24,26,27,28,34,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"561":[5,7,8,147,23,34,37,59,60,63,66,67,80,96,98,117,127,130,145],"569":[147],"616":[147,22,37,38,61],"624":[147,22,37],"635":[147,22,37],"638":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,33,36,37,38,39,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,97,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"653":[1,2,3,4,6,7,8,9,147,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,102,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"657":[1,2,3,4,6,7,8,9,147,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,102,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"663":[1,2,3,4,7,8,9,147,11,12,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140],"665":[1,2,147,11,27,49,61,62,66,74,75,79,82,85,104,110,113,114,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135],"671":[1,2,147,11,27,49,61,62,66,74,75,79,82,85,104,106,110,111,113,114,116,117,118,119,120,121,122,123,124,125,127,128,129,131,132,134,135],"679":[1,2,147,11,27,49,61,62,66,74,75,79,82,85,104,110,113,114,116,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135],"685":[1,2,3,4,6,7,8,9,147,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,102,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"711":[1,2,6,7,8,9,147,11,12,27,49,60,61,62,65,66,67,74,75,79,81,82,85,102,104,110,113,114,116,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135],"719":[1,2,3,4,6,7,8,9,147,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,102,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"750":[7,147,100,103,105,109,117,140,141,142],"757":[7,147,100,103,105,109,117,140,141,142],"799":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"833":[147,12,53,59,60,64,67,124],"844":[147,12,53,59,60,64,67,124],"856":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"860":[5,7,8,147,22,59,60,63,66,117,145],"876":[5,7,8,147,22,59,60,63,66,117,145],"898":[147],"911":[1,2,4,147,27,64,74,77,83,84,85,105,109,117,124,125,127,129,133,138,143],"915":[1,2,4,147,27,64,74,77,83,84,85,105,109,117,124,125,127,129,133,138,143],"918":[1,2,4,147,27,64,74,77,83,84,85,105,109,117,124,125,127,129,133,138,143],"936":[1,2,3,4,7,8,147,11,12,21,23,24,27,28,37,38,52,53,54,55,56,57,58,60,61,62,64,65,67,74,77,78,80,82,83,84,85,96,98,99,100,103,104,105,108,109,110,111,113,114,116,117,119,120,121,122,124,125,126,127,129,130,131,132,133,135,136,138,140,142,143,144,145],"942":[147,109],"976":[9,147,62,114,117,120,124,125,128,129],"992":[1,2,3,4,6,7,8,9,147,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,102,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"1067":[0,1,2,3,4,5,7,8,147,11,12,21,22,23,24,37,38,52,53,55,57,58,60,61,67,74,76,78,79,80,83,96,98,100,103,105,111,113,114,117,120,124,126,127,128,129,130,132,136,140,141,142,143,145,146],"1099":[1,3,7,8,147,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,80,82,83,96,98,99,100,103,104,105,108,109,110,111,113,114,116,119,120,121,122,124,126,127,129,130,131,132,133,136,138,140,142,144]},"packages/frontend/editor-ui/src/app/composables/useNodeIconSource.ts":{"6":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,34,36,37,38,42,45,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"12":[1,2,3,4,5,6,7,8,9,11,12,14,21,22,23,24,27,28,34,37,38,49,51,52,53,54,55,56,57,58,60,61,62,65,66,67,74,75,76,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,142,144,145,146]},"packages/frontend/editor-ui/src/app/composables/useNodeType.ts":{"8":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"16":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,54,55,56,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,142,144],"29":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,54,55,56,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,142,144],"31":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144]},"packages/frontend/editor-ui/src/app/composables/usePinnedData.ts":{"72":[1,2,3,4,6,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,102,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,143,144],"80":[1,2,3,4,6,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,102,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"85":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"95":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,107,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"106":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"111":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"173":[74,109,111,113,119,120,121,122,124,125,127,128,129,143],"177":[74,109,111,113,119,120,121,122,124,125,127,128,129,143],"227":[74,109,111,113,119,120,121,122,124,125,127,128,129,143],"246":[129],"268":[74,109,111,113,119,120,121,122,124,125,127,128,129,143]},"packages/frontend/editor-ui/src/app/composables/usePostMessageHandler.ts":{"57":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"70":[68],"76":[13,14,68,102,112],"116":[68,117,141,142],"145":[68,117,141,142],"168":[68],"212":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"274":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"279":[68,112,133,139]},"packages/frontend/editor-ui/src/app/composables/usePushConnection/usePushConnection.ts":{"47":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,87,95,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"48":[0,1,2,3,4,5,6,7,8,9,10,11,12,22,26,27,28,37,38,42,45,49,50,52,59,60,61,62,63,64,65,66,67,68,69,74,75,76,79,81,82,85,96,98,99,100,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,131,133,134,135,136,137,138,139,140,141,142,144,145,146],"53":[42,50,68,112,133,139],"62":[0,1,2,3,4,5,6,7,8,9,10,11,12,22,26,27,28,37,38,42,45,49,50,52,59,60,61,62,63,64,65,66,67,68,69,74,75,76,79,81,82,85,96,98,99,100,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,131,133,134,135,136,137,138,139,140,141,142,144,145,146]},"packages/frontend/editor-ui/src/app/composables/useResizablePanel.ts":{"51":[68],"61":[68],"62":[68],"63":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,29,30,31,32,34,35,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"92":[68],"96":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,29,30,31,32,34,35,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"100":[68],"104":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,29,30,31,32,34,35,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"108":[68],"125":[68],"138":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,29,30,31,32,34,35,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"139":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,29,30,31,32,34,35,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"145":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,29,30,31,32,34,35,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"153":[6,7,9,32,42,50,81,100,105,112,113,114,115,117,133,139,141,142],"159":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,29,30,31,32,34,35,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"160":[6,7,8,9,68,81,102,117],"161":[6,7,8,9,68,81,102,117]},"packages/frontend/editor-ui/src/app/composables/useResolvedExpression.ts":{"25":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,30,33,34,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,90,91,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145],"46":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,30,33,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,90,91,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145],"52":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,30,33,34,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,90,91,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145],"53":[1,66,74,85,114,117,119,120,121,124,127,128,129],"54":[1,7,8,37,52,66,74,76,80,81,85,89,103,114,117,119,120,121,122,124,126,127,128,129,130,131],"59":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,30,33,34,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,90,91,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145],"61":[1,7,8,37,52,66,74,76,80,81,85,89,103,114,117,119,120,121,122,124,126,127,128,129,130,131],"100":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,30,33,34,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,90,91,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145],"126":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,30,33,34,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,90,91,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145],"127":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,30,33,34,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,90,91,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145],"128":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,30,33,34,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,90,91,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145]},"packages/frontend/editor-ui/src/app/composables/useResourcesListI18n.ts":{"8":[3,15,16,18,19,20,22,23,26,37,38,39,40,41,68,69,70,71,72,73,88,89,93,94,96,97,98,133,138,139,144,146],"15":[15,16,18,19,20,22,23,26,37,38,39,40,41,68,69,70,71,72,73,88,89,93,94,96,97,98,133,138,139,144,146]},"packages/frontend/editor-ui/src/app/composables/useSelectionValidation.ts":{"20":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"32":[147,107],"49":[147,107,135],"56":[147,107],"67":[147,107,135],"73":[147,107,135],"75":[147,107,135],"82":[147,107,135],"84":[147,107,135]},"packages/frontend/editor-ui/src/app/composables/useSettingsItems.ts":{"23":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"192":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"195":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/app/composables/useSidebarLayout.ts":{"9":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,29,30,31,32,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"12":[16,36,41,72,93,138]},"packages/frontend/editor-ui/src/app/composables/useStorage.ts":{"4":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/app/composables/useStyles.ts":{"26":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"27":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"34":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/app/composables/useTelemetry.ts":{"4":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/app/composables/useTelemetryInitializer.ts":{"13":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"27":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"32":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"36":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"40":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"59":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"69":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/app/composables/useToast.ts":{"23":[0,1,2,4,6,7,8,9,11,15,23,26,27,28,30,32,33,34,35,37,38,39,41,45,49,50,51,59,60,61,62,63,64,65,66,67,68,69,70,71,72,74,75,79,80,81,82,85,87,88,89,92,93,94,97,98,99,102,103,104,105,110,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,130,131,133,134,135,137,138,139,141,142,144,145,146],"93":[15,68,69,70,72,92,93,94,113,133,139,144],"107":[15],"149":[34,35,37,41,92,129,145,146],"186":[0,1,2,7,8,34,35,37,38,41,92,110,113,114,117,124,129,141,142,145,146],"192":[0,1,2,4,6,7,8,9,11,12,20,26,27,28,38,42,49,50,59,60,61,62,63,64,65,66,67,69,74,75,79,81,82,85,93,96,98,100,102,103,104,105,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,131,133,134,135,138,139,141,142,144,145,146],"193":[1,2,113,141,142,145],"203":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"205":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/app/composables/useUniqueNodeName.ts":{"4":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"11":[7,104,105,108,109,110,111,129,131,132,138],"12":[7,104,105,108,109,110,111,129,131,132,138],"27":[1,2,3,4,5,7,8,11,12,21,23,24,27,28,37,38,52,53,54,55,56,57,58,60,61,62,64,65,67,74,77,78,80,82,83,84,85,96,98,99,100,103,104,105,108,109,110,111,113,114,116,117,119,120,121,122,124,125,126,127,129,130,131,132,133,135,136,138,140,142,143,144,145,146],"34":[7,104,105,108,109,110,111,129,131,132,138]},"packages/frontend/editor-ui/src/app/composables/useUserHelpers.ts":{"5":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"6":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"12":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/app/composables/useWorkflowDiffRouting.ts":{"18":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"27":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"50":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"73":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"111":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"133":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/app/composables/useWorkflowExtraction.ts":{"38":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"86":[135],"101":[135],"104":[135],"127":[135],"138":[135],"146":[135],"147":[135],"153":[135],"154":[135],"208":[135],"233":[135],"260":[135],"265":[135],"266":[135],"273":[135],"307":[135],"338":[135],"343":[135],"359":[135],"412":[135],"419":[135],"422":[135],"431":[135],"432":[135],"438":[135],"439":[135],"455":[135],"483":[135],"484":[135],"492":[135],"499":[135],"511":[135],"527":[135]},"packages/frontend/editor-ui/src/app/composables/useWorkflowHelpers.ts":{"71":[1,7,8,147,12,14,21,24,34,37,52,53,60,62,66,67,74,76,79,80,81,85,89,103,104,111,114,117,118,119,120,121,122,124,126,127,128,129,130,131,135,136,144],"172":[1,147,66,74,79,85,114,117,119,120,121,124,127,128,129,131,135],"275":[147,21,124,127,130,131,135,136],"285":[147,21,124,127,130,131,135,136],"310":[0,1,2,4,7,8,147,11,12,26,27,28,38,49,50,59,60,62,63,64,66,67,74,77,82,83,84,85,104,105,109,113,114,115,116,117,118,123,124,125,127,128,129,133,134,135,138,141,142,143,146],"316":[1,7,8,147,12,14,21,24,37,52,53,60,62,66,67,74,76,79,80,81,85,103,104,111,114,117,118,119,120,121,122,124,126,127,128,129,130,131,135,136,144],"347":[1,147,66,79,85,111,114,117,119,120,121,122,127,128,129,131,135],"363":[1,147,65,67,103,114,129],"389":[1,7,8,147,12,14,21,24,37,52,53,60,62,65,66,67,74,76,79,80,81,85,103,104,111,114,117,118,119,120,121,122,124,126,127,128,129,130,131,135,136,144],"478":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"491":[1,2,4,147,27,64,74,77,83,84,85,105,109,117,124,125,127,129,133,138,143],"517":[1,2,3,4,7,8,147,11,21,23,24,27,28,37,38,52,53,54,55,56,57,58,61,62,64,74,77,80,82,83,84,85,96,98,99,103,104,105,109,110,111,113,114,117,120,124,125,126,127,129,130,131,133,136,138,140,142],"531":[8,147,12,14,21,24,37,53,60,67,114,118,124,129,130,144],"552":[147,12,14,21,24,37,53,60,67,114,118,124,129,130,144],"593":[1,2,147],"596":[1,2,147],"627":[1,7,8,147,12,14,21,24,34,37,52,53,60,66,67,74,76,79,80,81,85,89,103,111,114,117,118,119,120,121,122,124,126,127,128,129,130,131,144],"657":[147],"704":[1,2,4,147,27,64,74,77,83,84,85,105,109,117,124,125,127,129,133,138,143],"735":[147,68,103,105,109,129,138,145],"739":[147,103,105,109,129,138,145],"744":[147,145],"746":[147,145],"760":[147,68],"768":[147],"778":[0,1,2,6,7,8,9,147,13,14,22,26,27,28,42,45,48,49,50,59,60,62,63,64,66,67,68,74,75,76,79,81,82,96,98,99,102,104,105,106,107,110,112,114,115,116,117,118,119,120,123,124,125,126,127,128,129,133,134,135,138,139,141,142,144,145,146],"816":[0,1,2,6,7,8,9,147,13,14,22,26,27,28,42,45,48,49,50,59,60,62,63,64,66,67,68,74,75,76,79,81,82,96,98,99,102,104,105,106,107,110,112,114,115,116,117,118,119,120,123,124,125,126,127,128,129,133,134,135,138,139,141,142,144,145,146],"847":[147],"857":[147],"870":[147],"881":[147]},"packages/frontend/editor-ui/src/app/composables/useWorkflowId.ts":{"6":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"12":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/app/composables/useWorkflowImport.ts":{"11":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"17":[13,14,68,102,112],"19":[13,14,68,102,112]},"packages/frontend/editor-ui/src/app/composables/useWorkflowInitialization.ts":{"81":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"92":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"93":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"94":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"95":[68],"96":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"98":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"123":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"188":[0,6,7,9,22,26,42,45,48,49,50,59,60,62,63,66,68,75,76,79,81,96,98,104,105,106,107,112,113,114,115,116,117,118,120,123,124,125,126,127,128,133,134,135,138,139,141,142,144,145,146],"205":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"207":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"243":[0,6,7,9,22,26,42,45,48,49,50,59,60,62,63,66,68,75,76,79,81,96,98,104,105,106,107,112,114,115,116,117,118,120,123,124,125,126,127,128,133,134,135,138,139,141,142,144,145,146],"295":[1,2,3,4,5,7,8,10,11,12,13,14,21,23,24,26,27,28,36,37,38,52,53,54,55,56,57,58,60,61,62,64,65,67,68,69,74,77,80,82,83,84,85,96,98,99,100,101,102,103,104,105,108,109,110,111,112,113,114,117,119,120,121,122,124,125,126,127,129,130,131,132,133,136,137,138,139,140,141,142,143,144],"307":[1,2,3,4,5,7,8,10,11,12,13,14,21,23,24,26,27,28,36,37,38,52,53,54,55,56,57,58,60,61,62,64,65,67,68,69,74,77,80,82,83,84,85,96,98,99,100,101,102,103,104,105,108,109,110,111,112,113,114,117,119,120,121,122,124,125,126,127,129,130,131,132,133,136,137,138,139,140,141,142,143,144],"337":[0,6,7,9,22,26,42,45,48,49,50,59,60,62,63,66,68,75,76,79,81,96,98,104,105,106,107,112,114,115,116,117,118,120,123,124,125,126,127,128,133,134,135,138,139,141,142,144,145,146],"392":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"462":[42,50,68,112,133,139]},"packages/frontend/editor-ui/src/app/composables/useWorkflowSaving.ts":{"44":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"71":[112,133,139],"75":[133],"147":[1,2,3,4,5,7,8,10,11,12,22,27,28,37,38,52,60,61,64,65,67,69,74,75,81,82,85,99,100,103,104,105,107,109,110,111,113,114,117,118,119,120,121,122,124,125,126,127,128,129,131,133,135,136,137,138,140,141,142,144,145,146],"154":[1,2,3,4,5,7,8,10,11,12,22,27,28,37,38,52,60,61,64,65,67,69,74,75,81,82,85,99,100,103,104,105,107,109,110,111,113,114,117,118,119,120,121,122,124,125,126,127,128,129,131,133,135,136,137,138,140,141,142,144,145,146],"184":[1,2,3,4,5,7,8,10,11,12,22,27,28,37,38,52,60,61,64,65,67,69,74,75,81,82,85,99,100,103,104,105,107,109,110,111,113,114,117,118,119,120,121,122,124,125,126,127,128,129,131,133,135,136,137,138,140,141,142,144,145,146],"359":[1,2,3,4,5,7,8,10,11,12,27,28,37,38,52,60,61,64,65,67,68,69,74,82,85,99,100,103,104,105,109,110,111,113,114,117,119,121,122,124,125,126,127,129,131,133,136,137,138,140,142,144,145,146],"555":[1,2,3,4,5,7,8,11,22,27,28,37,38,52,60,64,67,69,74,82,85,99,100,103,104,105,107,109,110,111,113,114,117,118,119,120,121,124,125,126,127,128,129,133,136,137,138,140,141,142,144,145],"569":[1,2,3,4,5,7,8,11,22,27,28,37,38,52,60,64,67,69,74,82,85,99,100,103,104,105,107,109,110,111,113,114,117,118,119,120,121,124,125,126,127,128,129,133,136,137,138,140,141,142,144,145],"588":[1,2,3,4,5,7,8,11,12,21,22,23,24,27,28,37,38,52,53,54,55,56,57,58,60,61,62,64,65,67,69,74,75,77,78,80,81,82,83,84,85,96,98,99,100,103,104,105,107,108,109,110,111,113,114,116,117,118,119,120,121,122,124,125,126,127,128,129,130,131,132,133,135,136,137,138,140,141,142,143,144,145,146],"614":[144],"622":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/app/composables/useWorkflowState.ts":{"29":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"38":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"64":[0,1,2,4,6,7,8,9,11,12,13,14,26,27,28,38,45,49,50,59,60,61,62,63,64,65,66,67,74,75,79,81,82,85,101,102,103,104,105,110,112,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135,141,142,146],"70":[1,2,3,4,5,7,8,10,11,12,13,14,21,23,24,26,27,28,36,37,38,52,53,54,55,56,57,58,60,61,62,64,65,67,69,74,77,78,80,82,83,84,85,96,98,99,100,101,102,103,104,105,108,109,110,111,112,113,114,117,119,120,121,122,124,125,126,127,129,130,131,132,133,136,137,138,139,140,141,142,143,144,145,146],"104":[117],"148":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"188":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/app/composables/useWorkflowUpdate.ts":{"44":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"64":[5],"66":[5],"69":[5],"76":[5],"99":[5],"112":[5],"189":[5],"198":[5],"202":[5],"217":[5],"242":[5],"254":[5],"255":[5],"259":[5],"261":[5],"285":[5],"319":[5],"334":[5],"349":[5],"370":[5]},"packages/frontend/editor-ui/src/app/composables/useWorkflowsCache.ts":{"27":[0,1,2,3,4,5,6,7,8,9,10,11,12,22,26,27,28,37,38,42,45,48,49,50,52,59,60,61,62,63,64,65,66,67,68,69,74,75,76,79,81,82,85,96,98,99,100,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,131,133,134,135,136,137,138,139,140,141,142,144,145,146],"30":[0,1,2,3,4,5,6,7,8,9,10,11,12,22,26,27,28,37,38,42,45,49,50,52,59,60,61,62,63,64,65,66,67,68,69,74,75,76,79,81,82,85,96,98,99,100,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,131,133,134,135,136,137,138,139,140,141,142,144,145,146],"35":[0,1,2,3,4,5,6,7,8,9,10,11,12,22,26,27,28,37,38,42,45,48,49,50,52,59,60,61,62,63,64,65,66,67,68,69,74,75,76,79,81,82,85,96,98,99,100,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,131,133,134,135,136,137,138,139,140,141,142,144,145,146],"39":[0,1,2,3,4,5,6,7,8,9,10,11,12,22,26,27,28,37,38,42,45,48,49,50,52,59,60,61,62,63,64,65,66,67,68,69,74,75,76,79,81,82,85,96,98,99,100,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,131,133,134,135,136,137,138,139,140,141,142,144,145,146],"46":[0,1,2,3,4,5,6,7,8,9,10,11,12,22,26,27,28,37,38,42,45,48,49,50,52,59,60,61,62,63,64,65,66,67,68,69,74,75,76,79,81,82,85,96,98,99,100,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,131,133,134,135,136,137,138,139,140,141,142,144,145,146],"62":[66,68,100,139,140,144],"85":[66,68,100,139,140,144],"96":[68,100],"104":[68],"113":[68],"120":[68,100],"123":[68,100]},"packages/frontend/editor-ui/src/app/constants/actions.ts":{"1":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/app/constants/durations.ts":{"33":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/app/constants/experiments.ts":{"6":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/app/constants/navigation.ts":{"1":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"79":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/app/constants/nodeTypes.ts":{"136":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/app/constants/workflows.ts":{"9":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/app/init.ts":{"45":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"99":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"163":[36],"185":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"230":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"243":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"279":[93]},"packages/frontend/editor-ui/src/app/layouts/BaseLayout.vue":{"10":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/app/layouts/DefaultLayout.vue":{"8":[3,15,16,18,19,20,22,23,26,35,37,38,39,40,41,68,69,70,71,72,73,88,89,93,94,96,97,98,112,133,138,139,144,145,146],"10":[3,15,16,18,19,20,22,23,26,35,37,38,39,40,41,68,69,70,71,72,73,88,89,93,94,96,97,98,112,133,138,139,144,145,146]},"packages/frontend/editor-ui/src/app/layouts/WorkflowLayout.vue":{"46":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"55":[68,78,133,139,145,146],"68":[68,113],"76":[68,112,133,139],"85":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"87":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"89":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"94":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"97":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/app/models/history.ts":{"8":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"35":[1,2,3,4,5,7,8,147,11,12,21,23,24,27,28,37,38,52,53,54,55,56,57,58,60,61,62,64,65,67,74,77,80,81,82,83,84,85,96,98,99,100,103,104,105,107,108,109,110,111,113,114,116,117,119,120,121,122,124,125,126,127,129,130,131,132,133,135,136,138,140,141,142,143,144],"44":[147,135],"52":[1,2,3,4,5,7,8,147,10,11,12,21,23,24,27,28,37,38,52,53,54,55,56,57,58,60,61,62,64,65,67,74,77,80,81,82,83,84,85,96,98,99,100,103,104,105,107,108,109,110,111,113,114,116,117,119,120,121,122,124,125,126,127,129,130,131,132,133,135,136,138,140,141,142,143,144],"57":[1,2,4,7,8,147,11,12,27,28,38,60,61,64,65,67,74,81,82,85,103,104,105,110,113,114,117,119,121,122,124,125,127,129,131,135,141,142],"58":[1,2,4,7,8,147,11,12,27,28,38,60,61,64,65,67,74,81,82,85,103,104,105,110,113,114,117,119,121,122,124,125,127,129,131,135,141,142],"69":[5,147,81,82,83,103,104,107,109,138],"81":[147,109],"85":[5,147,82,83,103],"96":[147,109],"97":[147,109],"110":[1,2,3,4,5,7,8,147,11,12,21,23,24,27,28,37,38,52,53,54,55,56,57,58,60,61,62,64,65,67,74,77,80,82,83,84,85,96,98,99,100,103,104,105,108,109,110,111,113,114,116,117,119,120,121,122,124,125,126,127,129,130,131,132,133,135,136,138,140,142,143,144],"115":[147,109,135],"119":[1,2,3,4,5,7,8,147,11,12,21,23,24,27,28,37,38,52,53,55,57,58,60,61,62,64,67,74,77,80,82,83,84,85,96,98,100,103,104,105,108,109,110,111,113,116,117,119,120,121,122,124,125,126,127,129,130,131,132,133,135,136,138,140,143],"123":[147,109,135],"124":[147,109,135],"134":[147,77,103,104,107,109,117,135],"139":[147,109,135],"143":[147,104,109,135],"147":[147,109,135],"148":[147,109,135],"158":[1,2,3,4,5,7,8,147,11,12,21,23,24,27,28,37,38,52,53,55,57,58,60,61,62,64,67,74,77,80,82,83,84,85,96,98,100,103,104,105,107,108,109,110,111,113,116,117,119,120,121,122,124,125,126,127,129,130,131,132,133,135,136,138,140,143],"163":[147,109,135],"167":[1,2,5,8,147,55,64,74,77,82,83,85,103,104,107,109,117,124,125,127,129,135,143],"177":[147,109,135],"178":[147,109,135],"188":[5,147,77,82,83,103,104,107,109,117,135],"193":[147,109,135],"197":[5,147,77,82,83,103,104,107,109,117,135],"207":[147,109,135],"208":[147,109,135],"209":[147,109,135],"224":[7,147,100,103,105,109,117,140,141,142],"231":[147,109],"235":[147,105,109],"241":[147,109],"242":[147,109],"257":[147,105],"263":[147],"267":[147],"275":[147],"276":[147],"287":[147,83,135],"296":[147,135],"305":[147,83],"314":[147,135],"315":[147,135]},"packages/frontend/editor-ui/src/app/moduleInitializer/modalRegistry.ts":{"6":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"10":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"11":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"14":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"42":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/app/moduleInitializer/moduleInitializer.ts":{"31":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"32":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"33":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"42":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"44":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"62":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"64":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"75":[40,41,42,43,44,45,46,47,48,49,50,51],"101":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"102":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"103":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"114":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"115":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"116":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/app/moduleInitializer/resourceRegistry.ts":{"25":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/app/plugins/cache.ts":{"3":[0,1,2,3,4,5,6,7,8,9,10,11,12,22,26,27,28,37,38,42,45,48,49,50,52,59,60,61,62,63,64,65,66,67,68,69,74,75,76,79,81,82,85,96,98,99,100,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,131,133,134,135,136,137,138,139,140,141,142,144,145,146],"8":[0,1,2,3,4,5,6,7,8,9,10,11,12,22,26,27,28,37,38,42,45,48,49,50,52,59,60,61,62,63,64,65,66,67,68,69,74,75,76,79,81,82,85,96,98,99,100,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,131,133,134,135,136,137,138,139,140,141,142,144,145,146],"9":[0,1,2,3,4,5,6,7,8,9,10,11,12,22,26,27,28,37,38,42,45,49,50,52,59,60,61,62,63,64,65,66,67,68,69,74,75,76,79,81,82,85,96,98,99,100,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,131,133,134,135,136,137,138,139,140,141,142,144,145,146],"10":[0,1,2,3,4,5,6,7,8,9,10,11,12,22,26,27,28,37,38,42,45,49,50,52,59,60,61,62,63,64,65,66,67,68,69,74,75,76,79,81,82,85,96,98,99,100,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,131,133,134,135,136,137,138,139,140,141,142,144,145,146],"13":[0,1,2,3,4,5,6,7,8,9,10,11,12,22,26,27,28,37,38,42,45,49,50,52,59,60,61,62,63,64,65,66,67,68,69,74,75,76,79,81,82,85,96,98,99,100,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,131,133,134,135,136,137,138,139,140,141,142,144,145,146],"25":[68],"33":[0,1,2,3,4,5,6,7,8,9,10,11,12,22,26,27,28,37,38,42,45,48,49,50,52,59,60,61,62,63,64,65,66,67,68,69,74,75,76,79,81,82,85,96,98,99,100,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,131,133,134,135,136,137,138,139,140,141,142,144,145,146],"34":[0,1,2,3,4,5,6,7,8,9,10,11,12,22,26,27,28,37,38,42,45,48,49,50,52,59,60,61,62,63,64,65,66,67,68,69,74,75,76,79,81,82,85,96,98,99,100,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,131,133,134,135,136,137,138,139,140,141,142,144,145,146],"36":[0,1,2,3,4,5,6,7,8,9,10,11,12,22,26,27,28,37,38,42,45,48,49,50,52,59,60,61,62,63,64,65,66,67,68,69,74,75,76,79,81,82,85,96,98,99,100,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,131,133,134,135,136,137,138,139,140,141,142,144,145,146],"39":[0,1,2,3,4,5,6,7,8,9,10,11,12,22,26,27,28,37,38,42,45,49,50,52,59,60,61,62,63,64,65,66,67,68,69,74,75,76,79,81,82,85,96,98,99,100,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,131,133,134,135,136,137,138,139,140,141,142,144,145,146],"40":[68],"44":[66,68,100,139,140,144],"49":[0,1,2,3,4,5,6,7,8,9,10,11,12,22,26,27,28,37,38,42,45,49,50,52,59,60,61,62,63,64,65,66,67,68,69,74,75,76,79,81,82,85,96,98,99,100,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,131,133,134,135,136,137,138,139,140,141,142,144,145,146],"53":[68],"58":[68],"63":[68],"67":[68],"68":[68],"71":[68],"82":[68],"89":[0,1,2,3,4,5,6,7,8,9,10,11,12,22,26,27,28,37,38,42,45,48,49,50,52,59,60,61,62,63,64,65,66,67,68,69,74,75,76,79,81,82,85,96,98,99,100,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,131,133,134,135,136,137,138,139,140,141,142,144,145,146],"99":[0,1,2,3,4,5,6,7,8,9,10,11,12,22,26,27,28,37,38,42,45,49,50,52,59,60,61,62,63,64,65,66,67,68,69,74,75,76,79,81,82,85,96,98,99,100,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,131,133,134,135,136,137,138,139,140,141,142,144,145,146],"100":[0,1,2,3,4,5,6,7,8,9,10,11,12,22,26,27,28,37,38,42,45,49,50,52,59,60,61,62,63,64,65,66,67,68,69,74,75,76,79,81,82,85,96,98,99,100,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,131,133,134,135,136,137,138,139,140,141,142,144,145,146],"104":[68],"111":[66,68,100,139,140,144],"112":[66,68,100,139,140,144],"117":[68],"118":[68],"123":[68],"124":[68]},"packages/frontend/editor-ui/src/app/plugins/chartjs.ts":{"15":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/app/plugins/components.ts":{"10":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/app/plugins/directives.ts":{"5":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/app/plugins/sentry.ts":{"26":[86],"29":[86],"53":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/app/plugins/telemetry/index.ts":{"33":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"37":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"72":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"104":[0,1,2,3,4,5,6,7,8,9,10,11,12,16,20,21,22,23,24,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,95,96,97,98,99,100,102,103,104,105,106,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"127":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"157":[93],"169":[110],"199":[2,4,7,8,11,12,21,23,24,27,28,37,38,58,60,61,62,67,75,84,96,98,103,104,105,109,110,111,113,118,119,120,121,122,124,126,127,129,130,131,135,136],"274":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/app/push-connection/useEventSourceClient.ts":{"13":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/app/push-connection/useHeartbeat.ts":{"12":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"17":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"21":[32,112]},"packages/frontend/editor-ui/src/app/push-connection/useReconnectTimer.ts":{"14":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"33":[32,112],"40":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,29,30,31,32,34,35,36,37,38,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,69,74,75,76,77,78,79,80,81,82,83,84,85,87,95,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/app/push-connection/useWebSocketClient.ts":{"24":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"35":[0,34,46,49],"40":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,29,30,31,32,34,35,36,37,38,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,69,74,75,76,77,78,79,80,81,82,83,84,85,87,95,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"53":[0,1,2,3,4,5,6,7,8,9,10,11,12,22,26,27,28,29,30,31,32,34,35,37,38,42,45,49,50,52,59,60,61,62,63,64,65,66,67,69,74,75,76,79,81,82,85,96,98,99,100,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,131,133,134,135,136,137,138,139,140,141,142,144,145,146],"61":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,29,30,31,32,34,35,36,37,38,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,87,95,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"75":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,29,30,31,32,34,35,36,37,38,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,69,74,75,76,77,78,79,80,81,82,83,84,85,87,95,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"94":[0,1,2,3,4,5,6,7,8,9,10,11,12,22,26,27,28,37,38,42,45,48,49,50,52,59,60,61,62,63,64,65,66,67,68,69,74,75,76,79,81,82,85,96,98,99,100,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,131,133,134,135,136,137,138,139,140,141,142,144,145,146]},"packages/frontend/editor-ui/src/app/router.ts":{"40":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"41":[7,105,113,114,115,117,141,142],"42":[7,105,114,115,117,141],"43":[7,105,113,114,115,117,141,142],"44":[7,105,114,115,117,141],"47":[105,113,114,115,117,141,142],"48":[105,114,115,117,141],"51":[25,92,93],"52":[25,92,93],"53":[94],"54":[94],"56":[87],"57":[87],"58":[36],"59":[36],"60":[90,91],"61":[90,91],"63":[18,20,93],"65":[145],"66":[145],"67":[146],"68":[146],"69":[145],"70":[145],"71":[146],"72":[146],"78":[93],"82":[89],"87":[89],"96":[95],"97":[95],"98":[112],"99":[112],"100":[146],"101":[100],"102":[100],"105":[100],"106":[100],"174":[15,16,18,19,22,26,31,40,41,71,72,73,133,144],"253":[78,145],"282":[146],"287":[146],"446":[1,2,3,4,5,7,8,10,11,12,21,23,24,26,27,28,36,37,38,52,53,54,55,56,57,58,60,61,62,64,65,67,69,74,77,78,80,82,83,84,85,96,98,99,100,103,104,105,108,109,110,111,113,114,117,119,120,121,122,124,125,126,127,129,130,131,132,133,136,137,138,139,140,142,143,144,145,146],"466":[13,14,102,112,115,117,141,142],"477":[101],"483":[101],"591":[17],"610":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"732":[1,2,3,4,5,10],"786":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,20,21,22,23,24,25,26,27,28,29,30,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"1009":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,20,21,22,23,24,25,26,27,28,29,30,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"1085":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"1100":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"1110":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"1142":[18,20,94],"1174":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/app/stores/aiGateway.store.ts":{"13":[147],"17":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"27":[147],"37":[147],"48":[147],"59":[147],"70":[147],"74":[147],"78":[147]},"packages/frontend/editor-ui/src/app/stores/backendConnection.store.ts":{"7":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"10":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/app/stores/canvas.store.ts":{"6":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"13":[0,6,9,147,21,42,50,67,81,103,104,105,106,107,108,117,124,125,135],"20":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/app/stores/cloudPlan.store.ts":{"25":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"34":[93],"40":[18,19,36,73,93,94,138],"42":[36],"45":[36],"48":[36],"58":[36],"65":[36],"71":[36],"73":[36],"83":[36],"85":[36],"87":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"89":[36],"91":[15,16,18,19,20,22,26,40,41,68,69,70,71,72,73,93,94,96,98,133,138,139,144,146],"111":[36],"122":[25,36,92,93],"127":[36],"142":[36],"158":[36],"183":[36],"204":[36],"217":[36],"228":[36],"236":[36]},"packages/frontend/editor-ui/src/app/stores/favorites.store.ts":{"9":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"16":[147],"17":[147],"20":[147],"21":[147],"24":[147],"25":[147],"28":[147],"29":[147],"32":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"42":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,15,16,18,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,74,75,76,77,78,79,80,81,82,83,84,85,89,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"43":[147],"48":[147,15,40,41,70,71,98,138,144],"49":[147],"57":[147],"64":[147],"82":[147,139,144],"83":[147],"88":[147,93]},"packages/frontend/editor-ui/src/app/stores/focusPanel.store.ts":{"47":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"54":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"64":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"72":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"73":[84,106],"74":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"77":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"99":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"105":[68,84,106],"140":[1,2,3,4,5,7,8,10,11,12,27,28,37,38,52,60,61,64,65,67,68,69,74,82,85,99,100,103,104,105,109,110,111,113,114,117,119,121,122,124,125,126,127,129,131,133,136,137,138,140,142,144,145,146],"176":[84,106],"194":[84,106],"205":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"206":[84,106],"218":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/app/stores/history.store.ts":{"10":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"17":[147,109,135],"24":[1,2,3,4,5,7,8,147,11,12,21,23,24,27,28,37,38,52,53,54,55,56,57,58,60,61,62,64,65,67,74,77,80,81,82,83,84,85,96,98,99,100,103,104,105,107,108,109,110,111,113,114,116,117,119,120,121,122,124,125,126,127,129,130,131,132,133,135,136,138,140,141,142,143,144],"28":[1,2,3,4,5,7,8,147,11,12,21,23,24,27,28,37,38,52,53,55,57,58,60,61,62,64,67,74,77,80,82,83,84,85,96,98,100,103,104,105,107,108,109,110,111,113,116,117,119,120,121,122,124,125,126,127,129,130,131,132,133,135,136,138,140,143],"41":[147,109],"48":[1,2,3,4,5,7,8,147,11,12,21,23,24,27,28,37,38,52,53,54,55,56,57,58,60,61,62,64,65,67,74,77,80,81,82,83,84,85,96,98,99,100,103,104,105,107,108,109,110,111,113,114,116,117,119,120,121,122,124,125,126,127,129,130,131,132,133,135,136,138,140,141,142,143,144],"53":[147,109,135],"58":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"61":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"64":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"68":[147,109],"74":[147,109,135],"78":[1,2,3,4,5,7,8,147,10,11,12,21,23,24,27,28,37,38,52,53,54,55,56,57,58,60,61,62,64,65,67,74,77,80,81,82,83,84,85,96,98,99,100,103,104,105,107,108,109,110,111,113,114,116,117,119,120,121,122,124,125,126,127,129,130,131,132,133,135,136,138,140,141,142,143,144],"81":[1,2,3,4,5,7,8,147,10,11,12,21,23,24,27,28,37,38,52,53,54,55,56,57,58,60,61,62,64,65,67,74,77,80,81,82,83,84,85,96,98,99,100,103,104,105,107,108,109,110,111,113,114,116,117,119,120,121,122,124,125,126,127,129,130,131,132,133,135,136,138,140,141,142,143,144]},"packages/frontend/editor-ui/src/app/stores/logs.store.ts":{"19":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"22":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"50":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"54":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"58":[6,7,9,102],"62":[6,7,9,102],"66":[6,7,8,9,81,102,117],"74":[6,7,8,9,81,102,117],"78":[117],"124":[6,7,8,9,81,102,117],"130":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"131":[6,7,8,9,81,102,117],"134":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"135":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"136":[6,7,8,9,37,52,80,81,102,117,126],"137":[6,7,8,9,81,102,117]},"packages/frontend/editor-ui/src/app/stores/nodeTypes.store.ts":{"42":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"57":[1,2,3,4,5,7,8,147,10,11,12,21,23,24,26,27,28,36,37,38,52,53,54,55,56,57,58,60,61,62,64,65,67,68,69,74,77,78,80,82,83,84,85,96,98,99,100,103,104,105,108,109,110,111,113,114,116,117,119,120,121,122,124,125,126,127,129,130,131,132,133,136,137,138,139,140,142,143,144,145,146],"58":[1,2,3,4,5,7,8,147,10,11,12,21,23,24,26,27,28,36,38,52,53,54,55,56,57,58,60,61,62,64,65,67,68,69,74,77,78,80,82,83,84,85,96,98,99,100,104,105,108,110,111,114,116,117,119,120,121,122,124,125,126,127,131,132,136,137,138,139,140,143,144,145,146],"76":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,21,22,23,24,26,27,28,34,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,87,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"78":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,21,22,23,24,26,27,28,36,37,38,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,87,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"79":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,21,22,23,24,26,27,28,36,37,38,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,87,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"82":[1,3,7,8,147,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"84":[1,3,7,8,147,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"85":[1,3,7,8,147,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"88":[1,3,7,8,147,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"92":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"93":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,76,77,78,80,82,83,84,85,96,98,99,100,103,104,105,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"94":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,76,77,78,80,82,83,84,85,96,98,99,100,103,104,105,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"98":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,21,22,23,24,26,27,28,34,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,87,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"100":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,21,22,23,24,26,27,28,34,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,87,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"108":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,21,22,23,24,26,27,28,34,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,87,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"109":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,21,22,23,24,26,27,28,34,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,87,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"125":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,30,33,34,36,37,38,42,45,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,89,90,91,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"126":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,30,33,34,36,38,42,45,48,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,89,90,91,96,97,98,99,100,101,102,104,105,106,107,108,110,111,112,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,131,132,134,135,136,137,138,139,140,141,143,144,145,146],"141":[1,2,3,4,7,8,9,147,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"142":[1,2,3,4,7,8,9,147,11,12,14,21,22,23,24,27,28,38,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,104,105,106,110,111,114,116,117,118,119,120,121,122,123,124,125,126,127,128,131,132,134,135,136,138,140,144],"147":[147,61],"148":[147,61],"159":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"160":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,38,42,45,48,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,104,105,106,107,110,111,112,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,131,132,134,135,136,138,139,140,141,143,144,145,146],"172":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"177":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"178":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,38,42,45,48,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,104,105,106,107,108,110,111,112,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,131,132,134,135,136,138,139,140,141,143,144,145,146],"184":[0,1,2,3,4,5,7,8,9,147,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"185":[0,1,2,3,4,5,7,8,9,147,11,12,14,21,22,23,24,27,28,38,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,104,105,106,110,111,114,116,117,118,119,120,121,122,123,124,125,126,127,128,131,132,134,135,136,138,140,144],"188":[0,1,2,3,4,5,7,8,9,147,11,12,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140],"200":[1,2,3,4,7,8,9,147,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"201":[1,2,3,4,7,8,9,147,11,12,14,21,22,23,24,27,28,38,52,53,55,57,58,60,61,62,65,66,67,74,75,76,80,81,82,83,84,85,96,98,100,104,105,106,110,111,114,116,117,118,119,120,121,122,123,124,125,126,127,128,131,132,134,135,136,138,140,144],"204":[1,2,3,4,7,8,9,147,11,12,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140],"216":[147],"217":[147],"222":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,21,22,23,24,26,27,28,34,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,87,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"226":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,21,22,23,24,26,27,28,34,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,87,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"229":[147],"230":[147],"236":[7,8,147,34,52,126,127],"237":[7,8,147,34,52,126,127],"241":[7,8,147,34,52,126,127],"262":[7,8,147,34,52,126,127],"278":[147],"279":[147],"283":[147],"302":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"303":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,38,42,45,48,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,104,105,106,107,110,111,112,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,131,132,134,135,136,138,139,140,141,143,144,145,146],"317":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,55,57,58,59,60,61,62,63,64,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,141,142,143,145,146],"328":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"336":[147],"337":[147],"343":[147],"352":[147],"364":[147],"375":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"382":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"388":[147],"396":[147,21,124,127],"400":[147,130],"404":[147,130,131],"412":[147,135,136],"420":[147],"424":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,87,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"434":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,87,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"441":[147,58,87],"456":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"457":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,38,42,45,48,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,104,105,106,107,108,110,111,112,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,131,132,134,135,136,138,139,140,141,143,144,145,146],"466":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"469":[147],"470":[0,1,2,4,5,6,7,8,9,147,11,12,14,21,24,26,27,28,37,38,45,49,50,52,53,59,60,61,62,63,64,65,66,67,74,75,76,77,79,80,81,82,83,84,85,101,102,103,104,105,109,110,111,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,133,134,135,136,138,141,142,143,144,146]},"packages/frontend/editor-ui/src/app/stores/npsSurvey.store.ts":{"18":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"27":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"35":[7,8,12,15,23,40,53,57,64,65,71,80,84,85,87,88,90,91,92,94,95,96,97,98,100,104,105,106,109,117,118,119,120,121,122,125,126,127,130,131,134,135,137,139,140,141,142,146],"75":[93],"79":[1,2,3,4,5,7,8,11,22,27,28,37,38,52,60,64,67,69,74,82,85,99,100,103,104,105,107,109,110,111,113,117,118,119,120,121,124,125,126,127,128,129,133,136,137,138,140,142,144,145]},"packages/frontend/editor-ui/src/app/stores/posthog.store.ts":{"19":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"34":[93],"49":[93],"57":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"61":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"68":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"160":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/app/stores/pushConnection.store.ts":{"17":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"35":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,29,30,31,32,34,35,36,37,38,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,69,74,75,76,77,78,79,80,81,82,83,84,85,87,95,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"38":[32,42,50,112,139],"46":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"48":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"66":[0,1,2,3,4,5,6,7,8,9,10,11,12,22,26,27,28,29,30,31,32,34,35,37,38,42,45,49,50,52,59,60,61,62,63,64,65,66,67,68,69,74,75,76,79,81,82,85,96,98,99,100,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,131,133,134,135,136,137,138,139,140,141,142,144,145,146],"80":[0,1,2,3,4,5,6,7,8,9,10,11,12,22,26,27,28,29,30,31,32,34,35,37,38,42,45,49,50,52,59,60,61,62,63,64,65,66,67,68,69,74,75,76,79,81,82,85,96,98,99,100,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,131,133,134,135,136,137,138,139,140,141,142,144,145,146],"85":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"87":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"93":[0,1,2,3,4,5,6,7,8,9,10,11,12,22,26,27,28,37,38,42,45,48,49,50,52,59,60,61,62,63,64,65,66,67,68,69,74,75,76,79,81,82,85,96,98,99,100,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,131,133,134,135,136,137,138,139,140,141,142,144,145,146],"105":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,29,30,31,32,34,35,36,37,38,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,69,74,75,76,77,78,79,80,81,82,83,84,85,87,95,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"125":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,29,30,31,32,34,35,36,37,38,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,87,95,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"132":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,29,30,31,32,34,35,36,37,38,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,87,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"148":[32,112,133,139],"160":[32,112],"173":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"174":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,29,30,31,32,34,35,36,37,38,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,87,95,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"195":[42,50,112,133,139],"199":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,29,30,31,32,34,35,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,69,74,75,76,77,78,79,80,81,82,83,84,85,95,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/app/stores/rbac.store.ts":{"8":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"77":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"113":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/app/stores/roles.store.ts":{"19":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"36":[15,35,41,71,89,98,138,144],"37":[15,35,41,71,89,98,138,144],"40":[15,35,41,71,89,98,138,144],"42":[15,35,41,71,89,98,138,144],"43":[15,35,41,71,89,98,138,144],"46":[15,35,41,71,89,98,138,144],"53":[33,38,97,98],"54":[33,38,97,98],"57":[96,99,144],"58":[96,99,144],"61":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/app/stores/settings.store.ts":{"22":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"51":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"53":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"55":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"59":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"61":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"63":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"68":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"70":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"72":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"74":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"76":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"78":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"80":[36],"82":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"84":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"86":[36],"88":[36],"90":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"94":[1,2,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,80,82,83,84,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,144],"96":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"100":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"104":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"106":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"108":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"110":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"112":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"131":[1,2,3,4,7,8,9,11,12,14,15,16,18,19,20,21,22,23,24,26,27,28,29,30,31,32,33,34,35,37,38,39,40,41,49,51,52,53,55,57,58,60,61,62,65,66,67,68,69,70,71,72,73,74,75,76,79,80,81,82,83,84,85,88,89,93,94,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,144,145,146],"135":[29,30,31,32,34,35],"141":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"147":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,26,27,28,36,37,38,40,41,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,93,94,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"151":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"155":[7,8,12,15,23,40,53,57,64,65,71,80,84,85,87,88,90,91,92,94,95,96,97,98,100,104,105,106,109,117,118,119,120,121,122,125,126,127,130,131,134,135,137,139,140,141,142,146],"163":[25,92,93],"165":[3,15,16,18,19,20,22,23,26,37,38,39,40,41,68,69,70,71,72,73,88,89,93,94,96,97,98,133,138,139,144,146],"167":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"169":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"173":[1,2,3,4,7,8,9,11,12,14,15,21,22,23,24,27,28,34,35,37,38,41,49,52,53,55,57,58,60,61,62,65,66,67,71,74,75,76,79,80,81,82,83,84,85,89,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"187":[8],"191":[35,71],"195":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,20,21,22,23,24,26,27,28,36,37,38,40,41,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"199":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"205":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"207":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"209":[146],"211":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"213":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"215":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,20,21,22,23,24,25,26,27,28,29,30,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"217":[87],"223":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"224":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,69,74,75,76,77,78,79,80,81,82,83,84,85,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"226":[95,100,105,125],"228":[100],"232":[36],"234":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"238":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"240":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"272":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"276":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"280":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"284":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"288":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"292":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"342":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"366":[146],"367":[146],"372":[100],"381":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/app/stores/ui.store.ts":{"118":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"177":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"284":[15,19,22,41,44,68,69,70,71,72,89,93,98,104,105,107,112,113,114,115,116,117,133,135,138,139,141,142,144,146],"285":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"346":[0,1,2,3,4,5,6,7,8,9,11,12,13,14,21,22,23,24,26,27,28,29,30,31,32,33,34,35,37,38,39,42,45,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,72,74,75,76,77,78,79,80,81,82,83,84,85,89,96,97,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"350":[0,1,2,3,4,5,6,7,8,9,11,12,13,14,21,22,23,24,26,27,28,29,30,31,32,33,34,35,37,38,39,42,45,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,72,74,75,76,77,78,79,80,81,82,83,84,85,89,96,97,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"354":[88,99,144],"412":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"413":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"419":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"421":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"423":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"425":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"431":[0,6,7,9,22,26,42,45,48,49,50,59,60,62,63,66,68,75,76,79,81,84,96,98,102,104,105,106,107,108,109,112,114,115,116,117,118,120,123,124,125,126,127,128,129,133,134,135,138,139,141,142,144,145,146],"439":[0,1,2,3,4,5,6,7,8,9,10,11,12,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"440":[1,2,3,4,5,7,8,10,11,12,22,27,28,37,38,52,60,61,64,65,67,68,69,74,75,81,82,85,99,100,103,104,105,107,109,110,111,113,114,117,118,119,120,121,122,124,125,126,127,128,129,131,133,135,136,137,138,140,141,142,144,145,146],"446":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"451":[1,2,4,5,7,21,23,27,37,40,47,51,53,57,64,66,69,70,71,74,77,80,82,83,84,85,88,89,97,98,100,102,103,104,105,107,108,109,116,117,121,123,124,125,126,127,129,133,135,138,139,140,141,142,143,144,145,146],"468":[3,7,8,23,30,33,37,38,39,51,58,80,87,89,97,98,127,130,145],"475":[3,7,8,23,30,33,37,38,39,51,58,70,80,87,89,97,98,127,130,145],"482":[3,7,8,23,30,37,38,39,51,58,80,89,97,98,127,130,145],"489":[1,31,32,33,34,66,68,70,72,88,89,90,91,94,96,99,100,135,139,140,144],"496":[1,3,7,8,15,23,30,31,32,33,34,37,38,39,40,41,51,58,66,68,70,72,78,80,87,88,89,90,91,93,94,96,97,98,99,100,109,127,130,135,137,139,140,143,144,145],"504":[1,31,32,33,34,66,68,70,72,88,89,90,91,94,96,99,100,135,139,140,144],"509":[1,3,5,7,8,10,23,30,31,32,33,34,37,38,39,40,41,42,50,51,66,68,69,70,72,80,87,88,89,91,93,94,96,97,98,99,100,105,109,112,113,114,115,117,127,130,133,135,137,138,139,140,141,142,143,144,145,146],"514":[1,3,7,8,23,30,31,32,33,34,37,38,39,40,41,51,66,68,70,72,80,87,88,89,91,93,94,97,98,99,100,109,127,130,135,137,139,140,143,144,145],"522":[33,37,38],"534":[3,7,8,23,30,37,38,39,51,58,80,89,97,98,127,130,145],"559":[87],"565":[87],"575":[70],"584":[70,72],"601":[1,2,3,4,5,7,8,10,11,12,22,27,28,37,38,52,60,61,64,65,67,68,69,74,75,81,82,85,99,100,103,104,105,107,109,110,111,113,114,117,118,119,120,121,122,124,125,126,127,128,129,131,133,135,136,137,138,140,141,142,144,145,146],"607":[1,2,3,4,5,7,8,10,11,12,22,27,28,37,38,52,60,61,64,65,67,68,69,74,75,81,82,85,99,100,103,104,105,107,109,110,111,113,114,117,118,119,120,121,122,124,125,126,127,128,129,131,133,135,136,137,138,140,141,142,144,145,146],"614":[16,36,41,72,93,138],"625":[13,14,102,112],"630":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"637":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"648":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"656":[0,1,2,4,6,7,8,9,11,26,27,28,38,45,49,50,59,60,61,62,63,64,65,66,67,74,75,79,81,82,85,102,103,104,105,110,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135,141,142],"660":[1,2,3,4,5,7,8,11,12,21,22,23,24,27,28,37,38,52,53,54,55,56,57,58,60,61,62,64,65,67,69,74,75,77,78,80,81,82,83,84,85,90,91,96,98,99,100,103,104,105,107,108,109,110,111,113,114,116,117,118,119,120,121,122,124,125,126,127,128,129,130,131,132,133,135,136,137,138,140,141,142,143,144,145,146],"668":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,90,91,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"676":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"698":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"699":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"705":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"707":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"731":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"732":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"733":[26,66,100,139,140,144],"746":[25,92,93],"789":[3,23,31,33,37,38,39,72,78,89,97,98,145],"797":[3,23,31,33,37,38,39,72,89,97,98,145],"799":[3,23,31,33,37,38,39,72,89,97,98,145]},"packages/frontend/editor-ui/src/app/stores/ui.utils.ts":{"4":[14,101],"12":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"17":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"23":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/app/stores/versions.store.ts":{"32":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"64":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"95":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"99":[15],"103":[0,1,2,3,4,5,6,7,8,9,10,11,12,16,18,19,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"109":[0,1,2,3,4,5,6,7,8,9,10,11,12,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"115":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"125":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"140":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"141":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"142":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"145":[0,1,2,3,4,5,6,7,8,9,10,11,12,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"158":[0,1,2,3,4,5,6,7,8,9,10,11,12,16,18,19,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"173":[0,1,2,3,4,5,6,7,8,9,10,11,12,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"178":[0,1,2,3,4,5,6,7,8,9,10,11,12,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"185":[0,1,2,3,4,5,6,7,8,9,10,11,12,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"192":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"233":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"237":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"260":[15]},"packages/frontend/editor-ui/src/app/stores/workflowDocument/useWorkflowDocumentActive.ts":{"14":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"17":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,21,22,24,26,27,28,37,38,45,49,50,52,59,60,61,62,63,64,65,66,67,69,74,75,79,81,82,85,99,100,102,103,104,105,106,107,109,110,111,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"21":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,22,26,27,28,37,38,42,45,48,49,50,52,59,60,61,62,63,64,65,66,67,68,69,74,75,76,79,81,82,85,96,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,131,133,134,135,136,137,138,139,140,141,142,144,145,146],"30":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,22,26,27,28,37,38,42,45,48,49,50,52,59,60,61,62,63,64,65,66,67,68,69,74,75,76,79,81,82,85,96,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,131,133,134,135,136,137,138,139,140,141,142,144,145,146],"34":[0,1,2,6,7,8,9,147,22,26,27,28,42,45,48,49,50,59,60,62,63,64,66,67,68,74,75,76,79,81,82,96,98,99,102,104,105,106,107,110,112,114,115,116,117,118,119,120,123,124,125,126,127,128,129,133,134,135,138,139,141,142,144,145,146]},"packages/frontend/editor-ui/src/app/stores/workflowDocument/useWorkflowDocumentChecksum.ts":{"12":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"17":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,22,26,27,28,37,38,42,45,48,49,50,52,59,60,61,62,63,64,65,66,67,68,69,74,75,76,79,81,82,85,96,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,131,133,134,135,136,137,138,139,140,141,142,144,145,146],"22":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,22,26,27,28,37,38,42,45,48,49,50,52,59,60,61,62,63,64,65,66,67,68,69,74,75,76,79,81,82,85,96,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,131,133,134,135,136,137,138,139,140,141,142,144,145,146]},"packages/frontend/editor-ui/src/app/stores/workflowDocument/useWorkflowDocumentConnections.ts":{"33":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"44":[0,1,2,5,6,7,8,9,147,13,14,22,26,27,28,42,45,48,49,50,59,60,62,63,64,66,67,68,74,75,76,78,79,81,82,96,98,99,101,102,104,105,106,107,110,112,114,115,116,117,118,119,120,123,124,125,126,127,128,129,133,134,135,136,138,139,141,142,144,145,146],"49":[1,2,3,4,5,7,8,147,11,12,21,23,24,27,28,37,38,52,53,55,57,58,60,61,62,64,67,74,77,80,82,83,84,85,96,98,100,103,104,105,107,109,110,111,113,116,117,119,120,121,122,124,125,126,127,129,130,131,132,133,135,136,138,140,143],"110":[5,147,77,82,83,103,104,107,109,117,135],"140":[147,77,103,104,107,109,117,135],"182":[147,91],"191":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,34,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,89,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"193":[0,1,2,3,4,5,6,7,8,9,147,11,12,21,22,24,26,27,28,37,38,42,45,48,49,50,52,53,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,85,98,99,100,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"197":[0,1,2,3,4,5,6,7,8,9,147,11,12,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,55,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"204":[0,1,2,3,4,5,6,7,8,9,147,11,12,21,22,24,26,27,28,37,38,42,45,48,49,50,52,53,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,85,98,99,100,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"215":[0,1,2,5,6,7,8,9,147,13,14,22,26,27,28,42,45,48,49,50,59,60,62,63,64,66,67,68,74,75,76,78,79,81,82,96,98,99,101,102,104,105,106,107,110,112,114,115,116,117,118,119,120,123,124,125,126,127,128,129,133,134,135,136,138,139,141,142,144,145,146],"219":[1,2,3,4,5,7,8,147,11,12,21,23,24,27,28,37,38,52,53,55,57,58,60,61,62,64,67,74,77,80,82,83,84,85,96,98,100,103,104,105,107,109,110,111,113,116,117,119,120,121,122,124,125,126,127,129,130,131,132,133,135,136,138,140,143],"223":[5,147,77,82,83,103,104,107,109,117,135],"227":[147,77,103,104,107,109,117,135],"234":[147],"240":[147,91]},"packages/frontend/editor-ui/src/app/stores/workflowDocument/useWorkflowDocumentDescription.ts":{"12":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"17":[0,1,2,6,7,8,9,147,13,14,22,26,27,28,42,45,48,49,50,59,60,62,63,64,66,67,68,74,75,76,79,81,82,96,98,99,101,102,104,105,106,107,110,112,114,115,116,117,118,119,120,123,124,125,126,127,128,129,133,134,135,138,139,141,142,144,145,146],"25":[0,1,2,6,7,8,9,147,13,14,22,26,27,28,42,45,48,49,50,59,60,62,63,64,66,67,68,74,75,76,79,81,82,96,98,99,101,102,104,105,106,107,110,112,114,115,116,117,118,119,120,123,124,125,126,127,128,129,133,134,135,138,139,141,142,144,145,146]},"packages/frontend/editor-ui/src/app/stores/workflowDocument/useWorkflowDocumentExpression.ts":{"6":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"11":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,34,37,38,42,45,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,89,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/app/stores/workflowDocument/useWorkflowDocumentGraph.ts":{"15":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"20":[0,1,2,3,4,5,7,8,9,147,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,107,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"28":[0,1,2,3,4,7,8,9,147,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"36":[1,2,3,4,5,7,8,9,147,11,12,14,21,22,23,24,27,28,37,38,49,52,53,54,55,56,57,58,60,61,62,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,108,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,142,143,144,145,146],"40":[147,135],"47":[147,82,83,103],"73":[147],"77":[8,9,147,81],"81":[1,7,8,147,12,14,21,24,37,52,53,60,62,66,67,74,76,79,80,81,85,103,104,111,114,117,118,119,120,121,122,124,126,127,128,129,130,131,135,136,144],"85":[1,7,8,147,12,14,21,24,37,52,53,60,62,66,67,74,76,79,80,81,85,103,104,111,114,117,118,119,120,121,122,124,126,127,128,129,130,131,135,136,144],"93":[1,2,3,4,7,8,9,147,11,12,21,22,23,24,27,28,37,38,52,53,55,57,58,60,61,62,67,74,75,76,79,80,81,82,83,84,96,98,100,103,104,105,106,109,110,111,113,116,117,118,119,120,121,122,124,125,126,127,128,129,130,131,132,133,134,136,138,140],"108":[0,1,2,8,9,147,27,49,61,65,67,75,79,81,103,110,114,117,118,119,120,121,122,124,125,128,129,131],"111":[0,1,2,8,9,147,27,49,61,75,79,81,110,114,117,118,119,120,121,122,124,125,128,129,131],"117":[0,1,2,9,147,27,49,61,65,67,75,79,103,110,114,117,118,119,120,121,122,124,125,128,129,131],"119":[147]},"packages/frontend/editor-ui/src/app/stores/workflowDocument/useWorkflowDocumentHomeProject.ts":{"9":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"14":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"22":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/app/stores/workflowDocument/useWorkflowDocumentIsArchived.ts":{"12":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"17":[0,1,2,6,7,8,9,147,13,14,22,26,27,28,42,45,48,49,50,59,60,62,63,64,66,67,68,74,75,76,79,81,82,96,98,99,101,102,104,105,106,107,110,112,114,115,116,117,118,119,120,123,124,125,126,127,128,129,133,134,135,138,139,141,142,144,145,146],"22":[0,1,2,6,7,8,9,147,13,14,22,26,27,28,42,45,48,49,50,59,60,62,63,64,66,67,68,74,75,76,79,81,82,96,98,99,101,102,104,105,106,107,110,112,114,115,116,117,118,119,120,123,124,125,126,127,128,129,133,134,135,138,139,141,142,144,145,146]},"packages/frontend/editor-ui/src/app/stores/workflowDocument/useWorkflowDocumentMeta.ts":{"13":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"18":[0,1,2,6,7,8,9,147,13,14,22,23,26,27,28,37,42,45,48,49,50,59,60,62,63,64,66,67,68,74,75,76,78,79,80,81,82,96,98,99,101,102,104,105,106,107,110,112,114,115,116,117,118,119,120,123,124,125,126,127,128,129,130,133,134,135,138,139,141,142,144,145,146],"26":[0,1,2,6,7,8,9,147,13,14,22,26,27,28,42,45,48,49,50,59,60,62,63,64,66,67,68,74,75,76,79,81,82,96,98,99,101,102,104,105,106,107,110,112,114,115,116,117,118,119,120,123,124,125,126,127,128,129,133,134,135,138,139,141,142,144,145,146],"30":[7,8,147,23,37,67,78,80,96,98,117,127,130,145,146]},"packages/frontend/editor-ui/src/app/stores/workflowDocument/useWorkflowDocumentName.ts":{"16":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"21":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"27":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/app/stores/workflowDocument/useWorkflowDocumentNodeGroups.ts":{"29":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"36":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,22,26,27,28,37,38,45,49,50,52,59,60,61,62,63,64,65,66,67,69,74,75,79,81,82,85,99,100,102,103,104,105,107,109,110,111,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,131,133,134,135,136,137,138,140,141,142,143,144,145,146],"38":[147],"48":[0,1,2,6,7,8,9,147,13,14,22,26,27,28,42,45,48,49,50,59,60,62,63,64,66,67,68,74,75,76,79,81,82,96,98,99,101,102,104,105,106,107,110,112,114,115,116,117,118,119,120,123,124,125,126,127,128,129,133,134,135,138,139,141,142,144,145,146],"49":[147,107],"56":[147,107],"68":[147,107],"77":[0,1,2,6,7,8,9,147,13,14,22,26,27,28,42,45,48,49,50,59,60,62,63,64,66,67,68,74,75,76,79,81,82,96,98,99,101,102,104,105,106,107,110,112,114,115,116,117,118,119,120,123,124,125,126,127,128,129,133,134,135,138,139,141,142,144,145,146],"81":[147,107],"95":[147,107],"96":[147],"114":[147,107],"118":[147,107],"124":[147,107],"129":[147],"134":[147],"140":[147],"149":[147],"156":[147],"160":[147],"165":[147,77,90,91,103,104,107,109,117,135],"168":[147,107],"177":[147,13,14,42,45,50,91,102,112,117,133,139,141,142]},"packages/frontend/editor-ui/src/app/stores/workflowDocument/useWorkflowDocumentNodeMetadata.ts":{"20":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"29":[0,1,2,5,6,7,8,9,147,13,14,22,26,27,28,34,42,45,48,49,50,51,59,60,62,63,64,66,67,68,74,75,76,79,81,82,91,96,98,99,101,102,104,105,106,107,110,112,114,115,116,117,118,119,120,123,124,125,126,127,128,129,133,134,135,136,138,139,141,142,144,145,146],"34":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,34,37,38,42,45,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,90,91,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"42":[1,2,3,4,5,7,8,9,147,11,12,14,21,22,23,24,27,28,37,38,49,52,53,54,55,56,57,58,60,61,62,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,108,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,142,143,144,145,146],"52":[147,113],"65":[147,77,90,91,103,104,107,109,117,135],"75":[147,105,127,136],"89":[0,1,2,5,6,7,8,9,147,13,14,22,26,27,28,34,42,45,48,49,50,51,59,60,62,63,64,66,67,68,74,75,76,79,81,82,91,96,98,99,101,102,104,105,106,107,110,112,114,115,116,117,118,119,120,123,124,125,126,127,128,129,133,134,135,136,138,139,141,142,144,145,146],"94":[1,2,3,4,5,7,8,147,11,12,21,23,24,27,28,37,38,52,53,54,55,56,57,58,60,61,62,64,65,67,74,77,78,80,82,83,84,85,90,91,96,98,99,100,103,104,105,108,109,110,111,113,114,116,117,119,120,121,122,124,125,126,127,129,130,131,132,133,135,136,138,140,142,143,144,145,146],"100":[0,1,2,5,6,7,8,9,147,13,14,22,26,27,28,34,42,45,48,49,50,51,59,60,62,63,64,66,67,74,75,76,79,81,82,98,99,101,102,104,105,106,107,110,112,114,115,116,117,118,119,120,123,124,125,126,127,128,129,133,134,135,136,138,139,141,142,144,145,146],"105":[147,77,90,91,103,104,107,109,117,135],"109":[147,105,127,136],"113":[1,2,3,4,5,7,8,9,147,11,12,14,21,22,23,24,27,28,37,38,49,52,53,54,55,56,57,58,60,61,62,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,108,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,142,143,144,145,146],"117":[2,4,5,7,8,147,11,12,21,24,27,28,37,38,53,55,58,60,61,62,67,75,83,84,103,104,105,109,110,111,113,118,119,120,121,122,124,127,129,130,131,135,136],"124":[147],"131":[147],"138":[147,113],"142":[0,1,2,4,6,7,8,9,147,11,12,26,27,28,38,45,49,50,59,60,61,62,63,64,65,66,67,74,75,79,81,82,85,102,103,104,105,110,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135,141,142],"146":[0,1,2,4,6,7,8,9,147,11,12,26,27,28,38,45,49,50,59,60,61,62,63,64,66,67,74,75,79,81,82,85,102,104,105,110,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135,141,142],"150":[0,1,2,4,6,7,8,9,147,11,12,26,27,28,38,45,49,50,59,60,61,62,63,64,65,66,67,74,75,79,81,82,85,102,103,104,105,110,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135,141,142],"154":[1,2,3,4,7,8,9,147,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144]},"packages/frontend/editor-ui/src/app/stores/workflowDocument/useWorkflowDocumentNodes.ts":{"76":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"92":[0,1,2,3,4,5,7,8,147,11,12,21,22,23,24,27,28,37,38,52,53,55,57,58,60,61,62,67,74,75,76,78,79,80,81,82,83,84,90,91,96,98,100,103,104,105,107,109,110,111,113,114,117,118,119,120,121,122,124,126,127,128,129,130,131,132,135,136,138,140,141,142,143,145,146],"116":[0,1,2,5,6,7,8,9,147,13,14,22,26,27,28,34,42,45,48,49,50,51,59,60,62,63,64,66,67,68,74,75,76,79,81,82,96,98,99,101,102,104,105,106,107,110,112,114,115,116,117,118,119,120,123,124,125,126,127,128,129,133,134,135,136,138,139,141,142,144,145,146],"140":[0,1,2,5,6,7,8,9,147,13,14,22,26,27,28,34,42,45,48,49,50,51,59,60,62,63,64,66,67,74,75,76,79,81,82,98,99,101,102,104,105,106,107,110,112,114,115,116,117,118,119,120,123,124,125,126,127,128,129,133,134,135,136,138,139,141,142,144,145,146],"144":[1,2,3,4,5,7,8,147,11,12,21,23,24,27,28,37,38,52,53,54,55,56,57,58,60,61,62,64,65,67,74,77,78,80,82,83,84,85,90,91,96,98,99,100,103,104,105,108,109,110,111,113,114,116,117,119,120,121,122,124,125,126,127,129,130,131,132,133,135,136,138,140,142,143,144,145,146],"164":[147,90,91],"165":[147,90,91],"180":[147,77,103,104,107,109,117,135],"181":[147,77,103,104,107,109,117,135],"182":[147,77,103,104,107,109,117,135],"202":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"226":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"241":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"255":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"269":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,34,37,38,42,45,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,90,91,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"272":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,34,37,38,42,45,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,90,91,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"275":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"279":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"282":[147,13,77,90,91,103,104,107,109,117,135],"285":[147,13,77,90,91,103,104,107,109,117,135],"292":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"300":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"301":[0,1,2,5,6,7,8,9,147,13,14,22,26,27,28,34,42,45,48,49,50,51,59,60,62,63,64,66,67,74,75,76,79,81,82,98,99,101,102,104,105,106,107,110,112,114,115,116,117,118,119,120,123,124,125,126,127,128,129,133,134,135,136,138,139,141,142,144,145,146],"302":[0,1,2,5,6,7,8,9,147,13,14,22,26,27,28,34,42,45,48,49,50,51,59,60,62,63,64,66,67,74,75,76,79,81,82,98,99,101,102,104,105,106,107,110,112,114,115,116,117,118,119,120,123,124,125,126,127,128,129,133,134,135,136,138,139,141,142,144,145,146],"308":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,34,37,38,42,45,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,74,75,76,77,78,79,80,81,82,83,84,85,90,91,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"342":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,34,37,38,42,45,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,74,75,76,77,78,79,80,81,82,83,84,85,90,91,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"368":[147],"370":[1,2,3,4,5,7,8,147,11,12,21,23,24,27,28,37,38,52,53,54,55,56,57,58,60,61,62,64,65,67,74,77,78,80,82,83,84,85,96,98,99,100,103,104,105,108,109,110,111,113,114,116,117,119,120,121,122,124,125,126,127,129,130,131,132,133,135,136,138,140,142,143,144,145,146],"372":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"373":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"379":[1,3,7,8,147,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,80,82,83,96,98,99,100,103,104,105,108,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"380":[1,3,7,8,147,11,12,21,23,28,37,38,52,54,55,56,58,60,61,67,80,82,83,96,98,100,103,104,105,109,110,111,113,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,140],"387":[0,1,2,3,4,5,6,7,8,9,147,11,12,14,21,22,23,24,26,27,28,37,38,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"391":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"395":[1,2,3,4,7,8,9,147,11,12,21,22,23,24,27,28,37,38,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"396":[1,2,3,4,7,8,9,147,11,12,21,22,23,24,27,28,37,38,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"399":[7,147,100,103,105,109,117,129,138,140,141,142,145],"407":[0,1,2,5,6,7,8,9,147,13,14,22,26,27,28,34,42,45,48,49,50,51,59,60,62,63,64,66,67,68,74,75,76,79,81,82,96,98,99,101,102,104,105,106,107,110,112,114,115,116,117,118,119,120,123,124,125,126,127,128,129,133,134,135,136,138,139,141,142,144,145,146],"411":[1,2,3,4,5,7,8,147,11,12,21,23,24,27,28,37,38,52,53,54,55,56,57,58,60,61,62,64,65,67,74,77,78,80,82,83,84,85,90,91,96,98,99,100,103,104,105,108,109,110,111,113,114,116,117,119,120,121,122,124,125,126,127,129,130,131,132,133,135,136,138,140,142,143,144,145,146],"415":[147,90,91],"419":[147,77,103,104,107,109,117,135],"423":[2,3,4,7,8,147,11,12,21,23,24,27,28,37,38,53,55,57,58,60,61,62,67,75,83,84,96,98,100,103,104,105,109,110,111,113,118,119,120,121,122,124,126,127,129,130,131,132,135,136,140],"424":[2,3,4,7,8,147,11,12,21,23,24,27,28,37,38,53,55,57,58,60,61,62,67,75,83,84,96,98,100,103,104,105,109,110,111,113,118,119,120,121,122,124,126,127,129,130,131,132,135,136,140],"449":[3,8,147,12,21,23,28,37,53,55,57,60,67,96,98,100,103,104,105,109,110,111,119,121,124,127,129,130,131,132,136,140],"450":[3,8,147,12,21,23,28,37,53,55,57,60,67,96,98,100,103,104,105,109,110,111,119,121,124,127,129,130,131,132,136,140],"468":[5,147,81,82,83,103,104,107,109,138],"469":[5,147,81,82,83,103,104,107,109,138],"492":[5,147,81,82,83,103,104,107,109,138],"493":[5,147,81,82,83,103,104,107,109,138],"499":[147],"500":[147],"505":[7,8,147,22,23,37,38,67,80,90,91,96,98,100,103,105,109,117,127,130,140,141,142,145],"506":[7,8,147,22,23,37,38,67,80,90,91,96,98,100,103,105,109,117,127,130,140,141,142,145],"522":[0,1,2,3,4,5,6,7,8,9,147,11,12,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"523":[0,1,2,3,4,5,6,7,8,9,147,11,12,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"550":[147,91],"560":[147,113],"561":[147,113],"568":[147],"573":[147],"603":[7,8,147,22,23,34,37,38,80,127,130],"610":[7,8,147,22,23,34,37,38,80,127,130],"629":[7,8,147,37,80]},"packages/frontend/editor-ui/src/app/stores/workflowDocument/useWorkflowDocumentNodesIssues.ts":{"11":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"12":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,22,26,27,28,37,38,42,45,48,49,50,52,53,59,60,61,62,63,64,65,66,67,68,69,74,75,76,79,80,81,82,85,96,98,99,100,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"13":[0,1,2,3,4,5,6,7,8,9,147,11,12,22,26,27,28,37,38,42,45,48,49,50,52,53,59,60,61,62,63,64,65,66,67,74,75,76,79,80,81,82,85,98,99,100,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"23":[147],"25":[147],"29":[1,3,5,6,7,8,9,147,12,21,24,26,37,52,53,60,65,66,67,76,78,80,81,100,104,106,109,114,117,118,119,120,121,122,124,126,127,129,130,132,133,139,140,143,144,145,146],"30":[1,3,5,6,7,8,9,147,12,21,24,26,37,52,53,60,65,66,67,76,78,80,81,100,104,106,109,114,117,118,119,120,121,122,124,126,127,129,130,132,133,139,140,143,144,145,146],"42":[5,147,10],"45":[147],"48":[5,147],"57":[5,147],"61":[5,147],"83":[147]},"packages/frontend/editor-ui/src/app/stores/workflowDocument/useWorkflowDocumentParentFolder.ts":{"9":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"14":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"22":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/app/stores/workflowDocument/useWorkflowDocumentPinData.ts":{"23":[147,74,109,111,113,119,120,121,122,124,125,127,128,129,143],"28":[147,74,109,111,113,119,120,121,122,124,125,127,128,129,143],"41":[0,1,2,6,7,8,9,147,13,14,22,26,27,28,42,45,48,49,50,59,60,62,63,64,66,67,68,74,75,76,79,81,82,91,96,98,99,101,102,104,105,106,107,110,112,114,115,116,117,118,119,120,123,124,125,126,127,128,129,133,134,135,138,139,141,142,144,145,146],"42":[147,14,74,106,114,118,119,120,123,124,125,127,128,129,135,146],"43":[147,14,74,106,114,118,119,120,123,124,125,127,128,129,135,146],"53":[1,2,3,4,6,7,8,9,147,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,102,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,143,144,145],"57":[147,14,74,106,109,111,113,118,119,120,121,122,123,124,125,127,128,129,135,143],"61":[147,74,109,111,113,119,120,121,122,124,125,127,128,129,143],"64":[147,74,109,111,113,119,120,121,122,124,125,127,128,129,143],"69":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"74":[0,1,2,6,7,8,9,147,13,14,22,26,27,28,42,45,48,49,50,59,60,62,63,64,66,67,68,74,75,76,79,81,82,91,96,98,99,101,102,104,105,106,107,110,112,114,115,116,117,118,119,120,123,124,125,126,127,128,129,133,134,135,138,139,141,142,144,145,146],"79":[147,74,109,111,113,119,120,121,122,124,125,127,128,129,143],"87":[147,77,90,91,103,104,107,109,113,117,135],"96":[147,105,127,136],"102":[147],"103":[147],"109":[147],"120":[0,1,2,6,7,8,9,147,13,14,22,26,27,28,42,45,48,49,50,59,60,62,63,64,66,67,68,74,75,76,79,81,82,91,96,98,99,101,102,104,105,106,107,110,112,114,115,116,117,118,119,120,123,124,125,126,127,128,129,133,134,135,138,139,141,142,144,145,146],"124":[147,74,109,111,113,119,120,121,122,124,125,127,128,129,143],"128":[147,77,90,91,103,104,107,109,113,117,135],"132":[147,105,127,136],"136":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,34,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,69,74,75,76,77,78,79,80,81,82,83,84,85,89,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"140":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/app/stores/workflowDocument/useWorkflowDocumentScopes.ts":{"13":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"18":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"23":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/app/stores/workflowDocument/useWorkflowDocumentSettings.ts":{"23":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"28":[0,1,2,6,7,8,9,147,13,14,22,26,27,28,42,45,48,49,50,59,60,62,63,64,66,67,68,74,75,76,79,81,82,96,98,99,101,102,104,105,106,107,110,112,114,115,116,117,118,119,120,123,124,125,126,127,128,129,133,134,135,138,139,141,142,144,145,146],"37":[0,1,2,6,7,8,9,147,13,14,22,26,27,28,42,45,48,49,50,59,60,62,63,64,66,67,68,74,75,76,79,81,82,96,98,99,101,102,104,105,106,107,110,112,114,115,116,117,118,119,120,123,124,125,126,127,128,129,133,134,135,138,139,141,142,144,145,146],"41":[147],"45":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,22,26,27,28,37,38,45,49,50,52,59,60,61,62,63,64,65,66,67,69,74,75,79,81,82,85,99,100,102,103,104,105,106,107,109,110,111,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,131,132,133,134,135,136,137,138,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/app/stores/workflowDocument/useWorkflowDocumentSharedWithProjects.ts":{"13":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"18":[0,1,2,6,7,8,9,147,13,14,22,26,27,28,42,45,48,49,50,59,60,62,63,64,66,67,68,74,75,76,79,81,82,96,98,99,101,102,104,105,106,107,110,112,114,115,116,117,118,119,120,123,124,125,126,127,128,129,133,134,135,138,139,141,142,144,145,146],"29":[0,1,2,6,7,8,9,147,13,14,22,26,27,28,42,45,48,49,50,59,60,62,63,64,66,67,68,74,75,76,79,81,82,96,98,99,101,102,104,105,106,107,110,112,114,115,116,117,118,119,120,123,124,125,126,127,128,129,133,134,135,138,139,141,142,144,145,146]},"packages/frontend/editor-ui/src/app/stores/workflowDocument/useWorkflowDocumentTags.ts":{"15":[0,1,2,6,7,8,9,147,13,14,22,26,27,28,42,45,48,49,50,59,60,62,63,64,66,67,68,74,75,76,79,81,82,83,84,96,98,99,101,102,104,105,106,107,110,112,114,115,116,117,118,119,120,123,124,125,126,127,128,129,133,134,135,137,138,139,141,142,143,144,145,146],"16":[147,84,133,137,143],"19":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"24":[0,1,2,6,7,8,9,147,13,14,22,26,27,28,42,45,48,49,50,59,60,62,63,64,66,67,68,74,75,76,79,81,82,83,84,96,98,99,101,102,104,105,106,107,110,112,114,115,116,117,118,119,120,123,124,125,126,127,128,129,133,134,135,137,138,139,141,142,143,144,145,146],"29":[147,137],"30":[147],"37":[0,1,2,6,7,8,9,147,13,14,22,26,27,28,42,45,48,49,50,59,60,62,63,64,66,67,68,74,75,76,79,81,82,96,98,99,101,102,104,105,106,107,110,112,114,115,116,117,118,119,120,123,124,125,126,127,128,129,133,134,135,137,138,139,141,142,144,145,146],"41":[147,64,83,84,125,127,129,133,143],"46":[147,137]},"packages/frontend/editor-ui/src/app/stores/workflowDocument/useWorkflowDocumentTimestamps.ts":{"19":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"26":[0,1,2,6,7,8,9,147,13,14,22,26,27,28,42,45,48,49,50,59,60,62,63,64,66,67,68,74,75,76,79,81,82,96,98,99,101,102,104,105,106,107,110,112,114,115,116,117,118,119,120,123,124,125,126,127,128,129,133,134,135,138,139,141,142,144,145,146],"31":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,22,26,27,28,37,38,42,45,48,49,50,52,59,60,61,62,63,64,65,66,67,68,69,74,75,76,79,81,82,85,96,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,131,133,134,135,136,137,138,139,140,141,142,144,145,146],"36":[0,1,2,6,7,8,9,147,13,14,22,26,27,28,42,45,48,49,50,59,60,62,63,64,66,67,68,74,75,76,79,81,82,96,98,99,101,102,104,105,106,107,110,112,114,115,116,117,118,119,120,123,124,125,126,127,128,129,133,134,135,138,139,141,142,144,145,146],"40":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,22,26,27,28,37,38,42,45,48,49,50,52,59,60,61,62,63,64,65,66,67,68,69,74,75,76,79,81,82,85,96,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,131,133,134,135,136,137,138,139,140,141,142,144,145,146]},"packages/frontend/editor-ui/src/app/stores/workflowDocument/useWorkflowDocumentUsedCredentials.ts":{"13":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"18":[0,1,2,6,7,8,9,147,13,14,22,26,27,28,42,45,48,49,50,59,60,62,63,64,66,67,68,74,75,76,79,81,82,96,98,99,101,102,104,105,106,107,110,112,114,115,116,117,118,119,120,123,124,125,126,127,128,129,133,134,135,138,139,141,142,144,145,146],"26":[0,1,2,6,7,8,9,147,13,14,22,26,27,28,42,45,48,49,50,59,60,62,63,64,66,67,68,74,75,76,79,81,82,96,98,99,101,102,104,105,106,107,110,112,114,115,116,117,118,119,120,123,124,125,126,127,128,129,133,134,135,138,139,141,142,144,145,146],"27":[7,8,147,22,59,60,63,66,117,145]},"packages/frontend/editor-ui/src/app/stores/workflowDocument/useWorkflowDocumentVersionData.ts":{"14":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"20":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,22,26,27,28,37,38,42,45,48,49,50,52,59,60,61,62,63,64,65,66,67,68,69,74,75,76,79,81,82,85,96,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,131,133,134,135,136,137,138,139,140,141,142,144,145,146],"32":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,22,26,27,28,37,38,42,45,48,49,50,52,59,60,61,62,63,64,65,66,67,68,69,74,75,76,79,81,82,85,96,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,131,133,134,135,136,137,138,139,140,141,142,144,145,146]},"packages/frontend/editor-ui/src/app/stores/workflowDocument/useWorkflowDocumentViewport.ts":{"13":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"18":[7,147,13,14,42,45,50,69,96,98,100,102,105,112,113,114,115,117,133,138,139,141,142,144,145,146],"26":[7,147,13,14,42,45,50,69,96,98,100,102,105,112,113,114,115,117,133,138,139,141,142,144,145,146]},"packages/frontend/editor-ui/src/app/stores/workflowDocument/useWorkflowDocumentWorkflowObject.ts":{"12":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"26":[147,13,14,42,45,50,101,102,112,117,133,139,141,142],"46":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,34,37,38,42,45,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,74,75,76,77,78,79,80,81,82,83,84,85,90,91,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"50":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,55,57,58,59,60,61,62,63,64,66,67,68,74,75,76,77,78,79,80,81,82,83,84,85,91,96,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"54":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"58":[0,1,2,6,7,8,9,147,13,14,22,26,27,28,42,45,48,49,50,59,60,62,63,64,66,67,68,74,75,76,79,81,82,96,98,99,101,102,104,105,106,107,110,112,114,115,116,117,118,119,120,123,124,125,126,127,128,129,133,134,135,138,139,141,142,144,145,146],"62":[1,2,4,5,147,27,64,74,77,83,84,85,101,105,109,117,124,125,127,129,133,136,138,143],"81":[5,147,105,127,136],"87":[5,147,105,127,136]},"packages/frontend/editor-ui/src/app/stores/workflowDocument.store.ts":{"117":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"127":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"141":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"142":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"152":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"166":[0,1,2,6,7,8,9,147,13,14,22,26,27,28,42,45,48,49,50,59,60,62,63,64,66,67,68,74,75,76,79,81,82,96,98,99,101,102,104,105,106,107,110,112,114,115,116,117,118,119,120,123,124,125,126,127,128,129,133,134,135,138,139,141,142,144,145,146],"175":[3,8,147,12,21,23,28,37,53,55,57,60,67,96,98,100,103,104,105,109,110,111,119,121,124,127,129,130,131,132,136,140],"177":[147],"178":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,34,37,38,42,45,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,74,75,76,77,78,79,80,81,82,83,84,85,90,91,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"179":[147,77,90,91,103,104,107,109,117,135],"184":[147],"185":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,55,57,58,59,60,61,62,63,64,66,67,68,74,75,76,77,78,79,80,81,82,83,84,85,91,96,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"208":[1,2,3,4,5,7,8,147,11,12,21,22,23,24,27,28,37,38,52,53,54,55,56,57,58,60,61,62,64,65,67,74,75,77,78,80,81,82,83,84,85,90,91,96,98,99,100,103,104,105,107,108,109,110,111,113,114,116,117,118,119,120,121,122,124,125,126,127,129,130,131,132,133,135,136,138,140,141,142,143,144,145,146],"209":[1,2,3,4,5,7,8,147,11,12,21,23,24,27,28,37,38,52,53,55,57,58,60,61,62,64,67,74,77,80,82,83,84,85,96,98,100,103,104,105,107,109,110,111,113,116,117,119,120,121,122,124,125,126,127,129,130,131,132,133,135,136,138,140,143],"210":[147,107],"212":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,34,37,38,42,45,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,74,75,76,77,78,79,80,81,82,83,84,85,90,91,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"218":[147,91],"225":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,22,26,27,28,37,38,49,50,52,59,60,61,62,63,64,65,66,67,69,74,75,79,81,82,85,99,100,102,103,104,105,107,109,110,111,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,131,133,134,135,136,137,138,140,141,142,144,145,146],"226":[0,1,2,3,4,5,6,7,8,9,147,11,12,22,26,27,28,37,38,49,50,52,59,60,61,62,63,64,65,66,67,74,75,79,81,82,85,99,100,102,103,104,105,107,109,110,111,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,131,133,134,135,136,138,140,141,142,144,145,146],"246":[147,107],"259":[147,101],"311":[147,13,14,42,45,50,102,112,117,133,139,141,142],"351":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,34,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,89,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"366":[0,1,2,4,5,6,7,8,9,147,10,11,26,27,28,38,45,49,50,59,60,61,62,63,64,65,66,67,74,75,79,81,82,85,102,103,104,105,109,110,111,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135,141,142,143],"445":[147,42,50,112,133,139],"461":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"463":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"472":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/app/stores/workflowExecutionState.store.ts":{"46":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"62":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"63":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"102":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"115":[0,1,2,4,6,7,8,9,147,11,12,13,14,26,27,28,38,45,49,50,59,60,61,62,63,64,65,66,67,74,75,79,81,82,85,101,102,103,104,105,110,112,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135,141,142,146],"135":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,30,33,34,36,37,38,39,42,45,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,89,90,91,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"156":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"163":[147],"173":[147],"179":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"185":[147,120,123,125,128],"191":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"198":[147],"213":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"225":[1,2,3,4,6,7,8,9,147,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,102,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"231":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"248":[147],"251":[147],"256":[147],"257":[147],"262":[147],"266":[0,1,2,4,6,7,8,9,147,11,12,13,14,26,27,28,38,45,49,50,59,60,61,62,63,64,65,66,67,74,75,79,81,82,85,101,102,103,104,105,110,112,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135,141,142,146],"288":[147,113,117,141,142],"297":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,21,22,23,24,26,27,28,36,37,38,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"303":[147],"314":[147],"333":[0,1,2,4,6,7,8,9,147,11,12,26,27,28,38,45,49,50,59,60,61,62,63,64,65,66,67,74,75,79,81,82,85,102,103,104,105,110,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135,141,142],"345":[7,147,77,100,103,104,105,107,109,117,135,140,141,142],"352":[6,7,8,9,147,12,26,60,67,81,102,114,117,129],"357":[147,113],"362":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,21,22,23,24,26,27,28,36,37,38,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"375":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"397":[147],"406":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,21,22,23,24,26,27,28,36,37,38,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"411":[147],"416":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"421":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"425":[147],"427":[147],"433":[147],"435":[147],"436":[147],"445":[147],"450":[147],"455":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"468":[147,105,127,136],"493":[147],"518":[147],"524":[147],"530":[147],"543":[147,105,127,136],"568":[147,13,14,42,45,50,102,112,117,133,139,141,142],"661":[147,13,14,42,45,50,102,112,117,133,139,141,142]},"packages/frontend/editor-ui/src/app/stores/workflowSave.store.ts":{"15":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"26":[1,2,3,4,5,7,8,11,12,21,22,23,24,27,28,37,38,52,53,54,55,56,57,58,60,61,62,64,65,67,69,74,75,77,78,80,81,82,83,84,85,96,98,99,100,103,104,105,107,108,109,110,111,113,114,116,117,118,119,120,121,122,124,125,126,127,128,129,130,131,132,133,135,136,137,138,140,141,142,143,144,145,146],"30":[1,2,3,4,5,7,8,10,11,12,22,27,28,37,38,52,60,61,64,65,67,69,74,75,81,82,85,99,100,103,104,105,107,109,110,111,113,114,117,118,119,120,121,122,124,125,126,127,128,129,131,133,135,136,137,138,140,141,142,144,145,146],"55":[1,2,4,5,7,8,11,22,27,28,38,42,50,60,64,67,74,75,81,82,85,99,104,105,107,110,111,113,114,117,118,119,120,121,124,125,126,128,129,131,133,135,140,141,142,144],"63":[42,50]},"packages/frontend/editor-ui/src/app/stores/workflowState.store.ts":{"8":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/app/stores/workflows.store.ts":{"53":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"82":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"87":[7,147,105,113,114,115,117,141,142],"88":[147],"91":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,30,33,34,36,37,38,39,42,45,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,89,90,91,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"98":[1,2,3,4,6,7,8,9,147,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,102,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"101":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"107":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"110":[147,120,123,125,128],"122":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"132":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"133":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,22,26,27,28,37,38,42,45,48,49,50,52,59,60,61,62,63,64,65,66,67,68,69,74,75,76,79,81,82,85,96,98,99,100,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,131,133,134,135,136,137,138,139,140,141,142,144,145,146],"142":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,30,33,34,36,37,38,39,42,45,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,89,90,91,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"150":[1,2,3,4,5,7,8,9,147,11,12,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"152":[147],"153":[147],"158":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,30,33,34,36,37,38,39,42,45,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,89,90,91,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"160":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"164":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"175":[1,2,3,4,7,8,9,147,11,12,21,22,23,24,27,28,37,38,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"179":[1,2,3,4,7,8,9,147,11,12,21,22,23,24,27,28,37,38,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"189":[147],"190":[147],"193":[147,78,145,146],"194":[147],"214":[147,143],"221":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"249":[147],"257":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"261":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"270":[0,1,2,6,7,8,9,147,22,26,27,28,42,45,48,49,50,59,60,62,63,64,66,67,68,74,75,76,79,81,82,96,98,99,102,104,105,106,107,110,112,114,115,116,117,118,119,120,123,124,125,126,127,128,129,133,134,135,138,139,141,142,144,145,146],"277":[147,139,144],"293":[147,139,144],"308":[147,66,100,139,140,144],"320":[147,139,144],"324":[147,68],"342":[147],"346":[147],"350":[147],"354":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"358":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"362":[147],"366":[147,105,127,136],"370":[147],"374":[7,147,77,100,103,104,105,107,109,117,135,140,141,142],"379":[147],"397":[147,113,117,141,142],"411":[1,2,3,4,5,7,8,147,10,11,12,22,27,28,37,38,52,60,61,64,65,67,68,69,70,74,75,81,82,85,99,100,103,104,105,107,109,110,111,113,114,117,118,119,120,121,122,124,125,126,127,128,129,131,133,135,136,137,138,140,141,142,144,145,146],"412":[1,2,3,4,5,7,8,147,11,12,22,27,28,37,38,52,60,61,64,65,67,74,75,81,82,85,99,100,103,104,105,107,109,110,111,113,114,117,118,119,120,121,122,124,125,126,127,128,129,131,133,135,136,138,140,141,142,144,145,146],"420":[1,2,3,4,5,7,8,147,10,11,12,27,28,37,38,52,60,61,64,65,67,68,69,74,82,85,99,100,103,104,105,109,110,111,113,114,117,119,121,122,124,125,126,127,129,131,133,135,136,137,138,140,142,144,145,146],"454":[1,2,4,5,7,8,147,11,22,27,28,38,60,64,67,68,70,74,75,81,82,85,99,104,105,107,110,111,113,114,117,118,119,120,121,124,125,126,128,129,131,133,135,140,141,142,144],"497":[147,66,100,135,139,140,144],"511":[147,144],"538":[147],"590":[0,1,2,4,6,7,8,9,147,11,12,26,27,28,38,49,50,59,60,61,62,63,64,65,66,67,74,75,79,81,82,85,102,103,104,105,110,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135,141,142,146],"609":[147],"617":[0,1,2,4,6,7,8,9,147,11,26,27,28,38,45,49,50,59,60,61,62,63,64,65,66,67,74,75,79,81,82,85,102,103,104,105,110,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135,141,142],"629":[147],"633":[147],"637":[147]},"packages/frontend/editor-ui/src/app/stores/workflowsList.store.ts":{"13":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"22":[147,135,136],"23":[147,135,136],"27":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"32":[147],"33":[147],"41":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,15,16,18,20,22,26,27,28,37,38,40,41,42,45,48,49,50,52,59,60,61,62,63,64,65,66,67,68,69,70,71,72,74,75,76,79,81,82,85,96,98,99,100,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,131,133,134,135,136,137,138,139,140,141,142,144,145,146],"51":[147,139,144],"56":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"66":[147,66,100,139,140,144],"79":[147,139,144],"93":[147,15,16,18,19,20,22,26,40,41,68,69,70,71,72,73,93,94,96,98,133,135,136,138,139,144,146],"129":[147,15,16,18,20,40,41,68,69,70,71,72,133,135,136,138,139,144,146],"130":[147,15,16,18,20,40,41,68,69,70,71,72,133,135,136,138,139,144,146],"141":[147,100,144],"168":[147,100,144],"181":[147],"187":[0,1,2,6,7,8,9,147,22,26,27,28,42,45,48,49,50,59,60,62,63,64,66,67,68,69,70,72,74,75,76,79,81,82,85,96,98,99,100,104,105,106,107,110,112,114,115,116,117,118,119,120,123,124,125,126,127,128,129,133,134,135,138,139,141,142,144,145,146],"193":[147,87],"197":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,36,37,38,40,41,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,93,94,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"203":[1,2,3,4,5,7,8,147,10,11,12,21,23,24,26,27,28,36,37,38,52,53,54,55,56,57,58,60,61,62,64,65,67,69,74,77,80,82,83,84,85,96,98,99,100,103,104,105,108,109,110,111,113,114,117,119,120,121,122,124,125,126,127,129,130,131,132,133,136,137,138,139,140,142,143,144],"209":[147,139,144],"215":[147,139,144],"236":[147,139,144]},"packages/frontend/editor-ui/src/app/utils/aiUtils.ts":{"57":[7,117],"82":[117],"87":[117],"236":[7,117],"248":[7,117],"263":[7,117],"264":[7,117],"274":[6,7,8,9,81,102,117],"286":[117],"300":[0,1,2,3,4,5,6,7,8,9,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/app/utils/credentialOnlyNodes.ts":{"5":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,30,33,34,36,37,38,42,45,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,89,90,91,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"9":[147,61],"13":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"17":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"52":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/app/utils/htmlUtils.ts":{"8":[0,1,2,3,4,6,7,8,9,147,11,15,23,26,27,28,30,32,33,34,35,37,38,39,40,41,45,49,50,51,53,59,60,61,62,63,64,65,66,67,68,69,70,71,72,74,75,76,79,80,81,82,85,87,88,89,91,92,93,94,97,98,99,100,102,103,104,105,109,110,111,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,133,134,135,137,138,139,140,141,142,144,145,146],"10":[147,15,68,69,70,72,76,120,124,135,139,144],"31":[147,15,34,35,37,41,68,69,70,72,76,92,94,120,122,124,129,135,139,144,145,146],"44":[147,32,37,40,41,69,70,88,91,100,105,113,114,130,133,139,144,145],"51":[147],"55":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"56":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"57":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"63":[147,103,138,145],"80":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"101":[1,2,7,8,147,21,28,37,52,76,80,81,84,89,103,104,105,106,109,110,111,114,117,119,120,121,122,124,126,127,128,130,131]},"packages/frontend/editor-ui/src/app/utils/injectStrict.ts":{"4":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/app/utils/modules/tabUtils.ts":{"22":[3,15,16,18,19,20,22,23,26,35,37,38,39,40,41,68,69,70,71,72,73,88,89,93,94,96,97,98,133,138,139,144,146],"45":[3,15,16,18,19,20,22,23,26,35,37,38,39,40,41,68,69,70,71,72,73,88,89,93,94,96,97,98,133,138,139,144,146],"49":[3,15,16,18,19,20,22,23,26,35,37,38,39,40,41,68,69,70,71,72,73,88,89,93,94,96,97,98,133,138,139,144,146]},"packages/frontend/editor-ui/src/app/utils/nodeIcon.ts":{"79":[0,1,2,3,4,5,6,7,8,9,11,12,13,14,21,22,23,24,26,27,28,34,37,38,42,45,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,79,80,81,82,83,84,85,89,96,97,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"93":[0,1,2,3,4,5,6,7,8,9,11,12,13,14,21,22,23,24,26,27,28,34,37,38,42,45,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,89,96,97,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"103":[0,1,2,3,4,5,6,7,8,9,11,12,13,14,21,22,23,24,26,27,28,34,37,38,42,45,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,79,80,81,82,83,84,85,89,96,97,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"111":[1,3,5,7,8,11,21,23,28,34,37,51,52,53,54,55,56,57,61,62,63,65,66,74,75,76,78,79,80,83,96,98,100,103,104,105,109,110,111,114,116,117,118,119,120,121,122,124,125,126,127,128,129,130,132,133,134,140,143,145,146],"116":[0,1,2,3,4,5,6,7,8,9,11,12,13,14,21,22,23,24,26,27,28,34,37,38,42,45,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,89,96,97,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"123":[1,3,5,7,8,11,21,23,28,34,37,51,52,53,54,55,56,57,61,62,63,65,66,74,75,76,78,79,80,83,96,98,100,103,104,105,109,110,111,114,116,117,118,119,120,121,122,124,125,126,127,128,129,130,132,133,134,140,143,145,146],"129":[0,1,2,3,4,5,6,7,8,9,11,12,13,14,21,22,23,24,26,27,28,34,37,38,42,45,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,79,80,81,82,83,84,85,89,96,97,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"150":[0,1,2,3,4,5,6,7,8,9,11,12,13,14,21,22,23,24,26,27,28,34,37,38,42,45,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,89,96,97,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/app/utils/nodeTypes/nodeTypeTransforms.ts":{"8":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"29":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"32":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/app/utils/nodeTypesUtils.ts":{"39":[3,7,8,147,23,30,33,37,38,39,51,52,58,80,89,97,98,127,130,145],"42":[3,7,8,147,23,30,33,37,38,39,51,52,58,80,89,97,98,127,130,145],"50":[3,4,5,6,7,8,9,147,11,12,21,22,23,24,26,27,34,37,38,50,51,52,53,55,57,58,59,60,61,63,66,67,74,75,76,78,79,80,81,83,96,98,100,103,105,109,111,113,114,116,117,118,124,126,127,128,129,130,132,134,140,143,144,145,146],"54":[147,78,127,130,145],"57":[147,78,127,130,145],"61":[147,21,24,67,118,124,129,144,146],"65":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"66":[0,1,2,3,4,5,6,7,8,9,147,11,12,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"71":[147,145,146],"72":[147,145,146],"73":[147,145,146],"77":[147,145,146],"80":[147,89,119,120,121,122,127,129,130,131,136],"81":[147,89,119,120,121,122,127,129,130,131],"84":[1,2,3,4,5,7,8,9,147,11,12,14,21,22,23,24,27,28,30,33,34,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,90,91,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145],"104":[1,2,3,4,5,6,7,8,9,147,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,102,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"105":[1,2,6,7,9,147,11,12,14,27,49,60,61,62,65,66,67,74,75,79,81,82,85,102,104,106,110,111,113,114,116,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135],"113":[3,7,8,147,23,37,53,55,80,96,98,100,117,124,126,127,130,135,136,140],"125":[3,5,7,8,147,21,22,23,24,34,37,38,51,52,53,55,57,58,60,61,67,74,76,80,96,98,100,105,111,117,124,126,127,128,129,130,132,140],"145":[1,2,3,4,5,7,8,9,147,11,12,21,23,24,28,34,37,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,90,91,96,98,100,103,104,105,106,109,110,111,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140],"152":[3,5,147,21,23,24,37,51,53,55,60,67,76,96,98,124,127,128,129,130,132,140],"155":[3,5,147,21,23,24,37,51,55,60,67,76,96,98,124,127,128,129,130,132,140],"172":[1,2,3,5,7,8,9,147,12,21,24,28,34,37,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,84,85,90,91,100,103,104,105,106,109,110,111,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140],"177":[3,5,7,8,147,21,24,34,37,51,52,53,57,58,60,61,67,74,80,100,105,111,117,126,127],"181":[147,21,24,53,60,67],"186":[147,21,24,53,60,67],"188":[147,21,24,53,60,67],"205":[1,2,3,5,7,8,147,23,30,33,37,38,39,51,58,80,89,96,97,98,127,130,145],"219":[3,5,147,23,37,51,96,98,127,130],"223":[3,5,147,23,37,51,96,98,127,130],"226":[3,5,147,23,37,51,96,98,127,130],"253":[3,5,147,23,37,51,96,98,127,130],"262":[5,147,51],"268":[5,147,51],"277":[3,5,147,23,37,51,96,98,127,130],"284":[3,5,147,23,37,51,96,98,127,130],"290":[3,5,7,8,147,23,37,51,58,80,96,98,127,130],"299":[3,5,147,23,37,51,96,98,127,130],"307":[3,5,147,21,23,37,51,53,55,76,96,98,124,127,128,129,130,132,140],"312":[3,5,147,21,23,37,51,53,55,76,96,98,124,127,128,129,130,132,140],"324":[1,2,3,5,7,8,9,147,12,21,23,24,28,34,37,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,84,85,90,91,96,98,100,103,104,105,106,109,110,111,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140],"330":[3,5,7,8,147,21,23,24,34,37,51,52,53,55,57,58,60,61,67,74,76,80,96,98,100,105,111,117,124,126,127,128,129,130,132,140],"332":[3,5,147,21,23,24,37,51,53,55,60,67,76,96,98,124,127,128,129,130,132,140],"333":[3,5,147,21,23,24,37,51,53,55,60,67,76,96,98,124,127,128,129,130,132,140],"335":[3,5,147,21,23,24,37,51,53,55,60,67,76,96,98,124,127,128,129,130,132,140],"351":[3,5,147,21,23,24,37,51,53,55,60,67,76,96,98,124,127,128,129,130,132,140],"374":[147,23,37,96,98,127,130],"400":[3,5,147,21,23,37,51,53,55,76,96,98,124,127,128,129,130,132,140],"409":[147],"410":[147],"422":[1,2,3,4,5,7,8,9,147,11,12,14,21,22,23,24,27,28,30,33,34,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,90,91,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145],"429":[147,131],"442":[147,131],"451":[147,131],"478":[147,131],"490":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,29,30,31,32,33,34,35,37,38,39,42,45,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,72,74,75,76,77,78,79,80,81,82,83,84,85,89,96,97,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/app/utils/nodeViewUtils.ts":{"60":[147,13,14,78,102,112,145,146],"61":[147,13,14,78,102,112,145,146],"70":[1,2,4,147,27,64,74,77,83,84,85,105,109,117,124,125,127,129,133,138,143],"71":[1,2,4,147,27,64,74,77,83,84,85,105,109,117,124,125,127,129,133,138,143],"80":[1,2,4,147,27,64,74,77,83,84,85,105,109,117,124,125,127,129,133,138,143],"81":[1,2,4,147,27,64,74,77,83,84,85,105,109,117,124,125,127,129,133,138,143],"90":[1,2,4,147,27,64,74,77,83,84,85,105,109,117,124,125,127,129,133,138,143],"91":[1,2,4,147,27,64,74,77,83,84,85,105,109,117,124,125,127,129,133,138,143],"100":[1,2,4,147,27,64,74,77,83,84,85,105,109,117,124,125,127,129,133,138,143],"101":[1,2,4,147,27,64,74,77,83,84,85,105,109,117,124,125,127,129,133,138,143],"110":[1,2,4,147,27,64,74,77,83,84,85,105,109,117,124,125,127,129,133,138,143],"127":[3,7,8,147,11,12,21,23,28,37,38,52,55,58,60,61,67,80,82,83,96,98,100,103,104,105,109,110,111,113,116,119,120,121,122,124,126,127,129,130,131,132,133,136,138,140],"144":[147,82,83,103],"159":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,34,37,38,42,45,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"178":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,34,37,38,42,45,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"188":[1,2,3,4,5,7,8,147,11,12,21,23,24,27,28,37,38,52,53,54,55,56,57,58,60,61,62,64,65,67,74,77,78,80,82,83,84,85,96,98,99,100,103,104,105,108,109,110,111,113,114,116,117,119,120,121,122,124,125,126,127,129,130,131,132,133,135,136,138,140,142,143,144,145,146],"253":[0,1,2,4,6,7,8,9,147,11,12,14,21,22,27,49,52,54,55,56,60,62,66,67,74,75,76,79,81,84,85,103,104,105,106,107,108,109,110,111,113,114,116,117,118,119,120,121,123,124,125,126,127,128,129,131,134,135,138,139,140,141,142,145],"263":[147,108],"275":[147,108],"294":[147,108],"303":[147,13,14,78,102,112,145,146],"314":[147,13,14,78,102,112,145,146],"384":[1,2,3,4,6,7,8,9,147,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,102,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"526":[147,104],"552":[1,2,4,5,7,147,21,23,27,37,40,47,51,53,57,64,69,70,71,74,77,80,82,83,84,85,88,89,97,98,100,102,103,104,105,107,108,109,112,113,114,115,116,117,121,123,124,125,126,127,129,133,135,138,139,140,141,142,143,144,145,146],"569":[1,2,3,4,6,7,8,147,11,12,21,23,24,27,28,37,38,52,53,54,55,56,57,58,60,61,62,64,65,67,74,77,80,82,83,84,85,96,98,99,100,103,104,105,108,109,110,111,113,114,116,117,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,143,144],"581":[6,147,117],"590":[6,147,117],"596":[6,147,117],"632":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/app/utils/nodes/nodeTransforms.ts":{"23":[0,1,2,3,4,5,7,8,147,11,12,21,22,23,24,26,27,28,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,76,77,78,79,80,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"48":[3,4,5,7,8,147,11,12,21,22,23,24,26,27,37,38,50,52,53,55,57,58,59,60,61,63,66,67,74,76,78,79,80,83,96,98,100,103,105,109,111,113,114,117,124,126,127,128,129,130,132,140,143,144,145,146],"58":[147,145,146],"72":[3,5,7,8,147,21,23,24,37,52,53,55,57,58,59,60,61,63,66,67,74,76,78,79,80,83,96,98,100,105,111,117,124,126,127,128,129,130,132,140,143,145,146],"86":[0,1,2,3,4,5,7,8,147,11,12,21,22,23,24,26,27,28,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,76,77,78,79,80,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"92":[3,5,7,8,147,21,23,24,37,52,53,55,57,58,59,60,61,63,66,67,74,76,78,79,80,83,96,98,100,105,111,117,124,126,127,128,129,130,132,140,143,145,146],"103":[0,1,2,9,147,27,49,61,65,67,75,79,81,103,110,114,118,119,120,121,122,124,125,128,129,131],"117":[1,2,3,4,5,7,8,9,147,11,12,14,21,22,23,24,27,28,30,33,34,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,90,91,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145],"137":[1,2,3,4,7,8,9,147,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,90,91,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"156":[0,1,2,3,4,5,6,7,8,9,147,11,12,22,26,27,28,37,38,49,50,52,59,60,61,62,63,64,65,66,67,74,75,79,81,82,85,99,100,102,103,104,105,107,109,110,111,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,131,133,134,135,136,138,140,141,142,144,145,146],"215":[7,8,147,59,60,63,66,67,117,145],"216":[7,8,147,59,60,63,66,67,117,145]},"packages/frontend/editor-ui/src/app/utils/objectUtils.ts":{"3":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,34,37,38,42,45,48,49,50,51,52,53,55,57,58,59,60,61,62,63,64,65,66,67,68,74,75,76,77,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"7":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,34,37,38,42,45,48,49,50,51,52,53,55,57,58,59,60,61,62,63,64,65,66,67,68,74,75,76,77,79,80,81,82,83,84,85,90,91,96,98,99,100,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"11":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,34,37,38,42,45,48,49,50,51,52,53,55,57,58,59,60,61,62,63,64,65,66,67,68,74,75,76,77,79,80,81,82,83,84,85,90,91,96,98,99,100,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"15":[147,123,125],"16":[147,123,125],"28":[1,2,3,4,147],"54":[147],"58":[147]},"packages/frontend/editor-ui/src/app/utils/rbac/checks/hasRole.ts":{"5":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/app/utils/rbac/checks/hasScope.ts":{"4":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/app/utils/rbac/checks/isAuthenticated.ts":{"5":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"14":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/app/utils/rbac/checks/isValid.ts":{"3":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/app/utils/rbac/middleware/authenticated.ts":{"6":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/app/utils/rbac/middleware/custom.ts":{"4":[3,15,16,18,19,20,22,23,26,31,35,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,68,69,70,71,72,73,87,88,89,93,94,96,97,98,133,138,139,144,146]},"packages/frontend/editor-ui/src/app/utils/rbac/permissions.ts":{"28":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/app/utils/typeGuards.ts":{"31":[147],"35":[147,120,128],"39":[147,39,130,145],"43":[1,2,5,9,147,11,27,49,61,62,66,74,75,79,82,85,104,106,110,111,113,114,116,117,118,119,120,121,122,123,124,125,127,128,129,131,132,134,135],"46":[147],"49":[3,5,147,12,21,23,34,37,51,53,55,57,58,60,67,74,76,79,96,98,100,105,111,114,117,119,120,121,124,125,127,128,129,130,131,132,134,135,136,140],"57":[3,7,8,147,23,30,33,37,38,39,51,58,80,89,97,98,127,130,145],"61":[147,131],"65":[147,89],"71":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"77":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,141,142,143,144,145,146],"81":[7,8,147,21,52,54,55,56,82,83,103,104,116,126,127,131],"90":[147,12,21,24,60,67,114,118,124,129,144],"96":[147,113,131],"102":[147],"109":[147,89,105,113,114,115,117,141,142],"113":[147,37,39,72,88,97,98],"117":[147,37,39,72,88,97,98],"121":[147,88],"125":[147,23,37,38,39,72,88,89,97,98],"129":[147],"135":[147,37,39,72,88,97,98],"142":[147,15,16,18,19,20,22,23,26,37,38,39,40,41,68,69,70,71,72,73,88,89,93,94,96,97,98,133,138,139,144,146],"155":[147,15,35,41,71,89,98,138,144],"164":[147],"167":[147,144]},"packages/frontend/editor-ui/src/app/utils/typesUtils.ts":{"12":[147],"14":[1,2,6,7,9,147,11,12,14,27,49,60,61,62,65,66,67,74,75,79,81,82,85,102,104,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135,143,146],"23":[1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,30,33,34,36,37,38,39,49,51,52,53,54,55,56,57,58,60,61,62,64,65,66,67,69,70,72,74,75,76,77,78,79,80,81,82,83,84,85,89,90,91,96,97,98,99,100,101,102,103,104,105,106,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"40":[147,145,146],"52":[147],"56":[147,15,16,18,20,23,33,37,38,39,40,41,68,69,70,71,72,89,97,98,133,138,139,144,145,146],"60":[147,74,109,111,113,119,120,121,122,124,125,127,128,129,143],"66":[147,129],"71":[1,2,6,7,9,147,11,12,14,27,49,60,61,62,65,66,67,74,75,79,81,82,85,102,104,106,110,111,113,114,116,117,118,119,120,121,122,123,124,125,127,128,129,131,132,134,135],"82":[147],"88":[147],"89":[147],"99":[147],"119":[147,111,119,120,121,122,128,129],"124":[147,111,119,120,121,122,128,129],"166":[147,78,145,146],"170":[1,2,3,4,5,6,7,8,9,147,11,12,14,21,22,23,24,27,28,30,33,34,37,38,39,49,51,52,53,54,55,56,57,58,60,61,62,64,65,66,67,68,69,70,72,74,75,76,77,79,80,81,82,83,84,85,89,90,91,96,97,98,99,100,101,103,104,105,106,107,108,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,141,142,143,144,145],"174":[4,7,8,147,11,12,23,24,27,30,37,38,39,40,51,60,61,62,67,75,80,89,90,91,97,98,106,113,119,120,121,122,124,127,128,129,130,131,145],"183":[147],"192":[147],"201":[4,7,8,147,11,12,23,24,27,30,34,37,38,39,51,55,58,60,61,62,67,75,80,89,90,91,97,98,106,110,113,119,120,121,122,124,127,128,129,130,131,145]},"packages/frontend/editor-ui/src/app/views/NodeView.vue":{"151":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"155":[68],"158":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"162":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"163":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,104,105,106,107,108,110,111,112,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,131,132,134,135,136,137,138,139,140,141,143,144,145,146],"177":[1,2,3,4,5,7,8,11,22,27,28,37,38,52,60,64,67,68,69,74,82,85,99,100,103,104,105,107,109,110,111,113,114,117,118,119,120,121,124,125,126,127,128,129,133,136,137,138,140,141,142,144,145],"188":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"265":[68],"274":[0,1,2,3,4,5,6,7,8,9,10,11,12,14,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"280":[68],"285":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"289":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"290":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,68,80,82,83,96,98,99,100,103,104,105,108,109,110,111,113,114,116,117,119,120,121,122,124,126,127,129,130,131,132,133,136,138,140,141,142,144],"291":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"294":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"301":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"313":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"323":[68],"327":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"329":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"333":[6,7,8,9,37,52,68,80,81,102,117,126],"339":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"366":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"371":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"381":[68],"413":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"415":[0,1,2,3,4,5,6,7,8,9,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"421":[0,1,2,3,4,5,7,9,11,12,21,22,23,24,26,27,28,37,38,42,45,48,49,50,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,74,75,76,77,78,79,82,83,84,85,96,98,99,100,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"423":[0,1,2,3,4,5,7,9,11,12,21,22,23,24,26,27,28,37,38,42,45,48,49,50,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,74,75,76,77,78,79,82,83,84,85,96,98,99,100,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"424":[0,1,2,3,4,5,7,9,11,12,21,22,23,24,26,27,28,37,38,42,45,48,49,50,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,74,75,76,77,78,79,82,83,84,85,96,98,99,100,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"428":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"429":[0,1,2,3,4,5,6,7,8,9,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"431":[0,1,2,4,6,7,8,9,11,12,26,27,28,38,45,49,50,59,60,61,62,63,64,65,66,67,68,74,75,79,81,82,85,102,103,104,105,110,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135,141,142,146],"438":[5,68],"449":[68,135],"453":[68,81,103,104,107,109,138],"457":[68],"461":[68,109],"465":[68,77,103,117],"466":[68],"474":[68,103,104,107,109],"478":[68,109,135],"482":[68,100,103,117],"490":[68,109],"494":[7,68,105,109,140,141,142],"502":[1,2,4,8,9,11,12,14,22,27,49,60,62,66,67,68,74,75,76,79,81,84,85,103,104,105,106,107,109,110,111,113,114,116,117,118,119,120,121,123,124,125,126,127,128,129,134,135,138,139,140,141,142,145],"507":[1,2,4,8,9,11,12,14,22,27,49,60,62,66,68,74,75,76,79,81,84,85,105,110,111,113,114,116,117,118,119,120,121,123,124,125,126,127,128,129,134,135],"519":[68],"523":[68],"527":[0,1,2,3,4,6,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,54,55,56,57,58,60,61,62,64,65,66,67,68,74,75,76,77,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145],"532":[68,103,138,145],"538":[68,105,109,138,139],"586":[68,105,109,138],"591":[68],"599":[68,105,109,129],"611":[68],"619":[68],"623":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"627":[7,42,50,68,69,96,98,100,105,112,113,114,115,117,133,138,139,141,142,144,145,146],"632":[68],"636":[68],"640":[68],"646":[68,105],"668":[68,105],"687":[68,105],"704":[68],"714":[68,135],"726":[68],"730":[7,68],"734":[24,67,68,104],"738":[7,8,21,52,54,55,56,68,103,104,116,131],"753":[68],"778":[68,104,135],"782":[68,109,135],"786":[7,8,21,52,54,55,56,68,103,104,116,131],"800":[68],"814":[68,103,109],"818":[68,109,135],"826":[1,2,4,27,64,68,74,77,83,84,85,117,124,125,127,129,133,143],"841":[1,2,4,27,64,68,74,77,83,84,85,117,124,125,127,129,133,143],"844":[68],"857":[68,143],"867":[68,143],"870":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"876":[7,42,50,68,69,96,98,100,105,112,113,114,115,117,133,138,139,141,142,144,145,146],"887":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,68,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"891":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,68,80,82,83,96,98,99,100,103,104,105,108,109,110,111,113,114,116,119,120,121,122,124,126,127,129,130,131,132,133,136,138,140,142,144],"903":[68],"923":[68,109,135],"927":[68,110,111,126,131],"935":[68,126],"948":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,68,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"957":[68],"961":[68,142],"965":[68],"974":[0,1,2,3,4,6,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,54,55,56,57,58,60,61,62,64,65,66,67,68,74,75,76,77,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145],"980":[68,108],"984":[68,82,83,103],"1004":[68],"1019":[68],"1022":[68],"1049":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"1055":[1,2,3,4,5,7,8,10,11,12,21,23,24,26,27,28,36,37,38,52,53,54,55,56,57,58,60,61,62,64,65,67,68,69,74,77,78,80,82,83,84,85,96,98,99,100,103,104,105,108,109,110,111,113,114,117,119,120,121,122,124,125,126,127,129,130,131,132,133,136,137,138,139,140,142,143,144,145,146],"1057":[5,23,26,37,68,69,96,98,133,136,138,144],"1068":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"1069":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"1073":[0,1,2,3,4,5,7,9,11,12,21,22,23,24,26,27,28,37,38,42,45,48,49,50,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,74,75,76,77,78,79,82,83,84,85,96,98,99,100,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"1085":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"1088":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"1091":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"1095":[0,9,49,68,79,81,103,114,118,119,121],"1117":[68],"1138":[68],"1153":[68],"1165":[0,9,49,68,79,81,103,114,118,119,121],"1177":[68,117,141,142],"1210":[68,117,141,142],"1221":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"1226":[7,42,50,68,69,96,98,100,105,112,113,114,115,117,133,138,139,141,142,144,145,146],"1231":[68,117],"1237":[68],"1241":[4,7,11,12,26,27,28,38,49,50,59,60,62,63,64,66,67,68,74,82,85,104,105,113,114,115,116,117,118,123,124,125,127,128,129,134,135,141,142],"1245":[4,7,11,12,26,27,28,38,49,50,59,60,62,63,64,66,67,68,74,82,85,104,105,113,114,115,116,117,118,123,124,125,127,128,129,134,135,141,142],"1253":[1,2,3,4,5,6,7,8,9,10,11,12,21,23,24,26,27,28,36,37,38,52,53,54,55,56,57,58,60,61,62,64,65,67,68,69,74,77,78,80,81,82,83,84,85,96,98,99,100,102,103,104,105,108,109,110,111,113,114,117,119,120,121,122,124,125,126,127,129,130,131,132,133,136,137,138,139,140,142,143,144,145,146],"1254":[6,7,8,9,37,52,68,80,81,83,102,103,105,108,109,117,124,126],"1259":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"1262":[0,1,2,3,4,5,6,7,8,9,11,12,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"1270":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"1271":[0,1,2,3,4,5,6,7,8,9,11,12,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"1274":[1,2,3,4,5,6,7,8,9,10,11,12,21,23,24,26,27,28,36,37,38,52,53,54,55,56,57,58,60,61,62,64,65,67,68,69,74,77,78,80,81,82,83,84,85,96,98,99,100,102,103,104,105,108,109,110,111,113,114,117,119,120,121,122,124,125,126,127,129,130,131,132,133,136,137,138,139,140,142,143,144,145,146],"1280":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"1287":[68],"1290":[68],"1296":[7,68,102],"1304":[7,68],"1323":[68],"1324":[68],"1333":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"1344":[7,42,50,68,69,96,98,100,105,112,113,114,115,117,133,138,139,141,142,144,145,146],"1359":[68],"1379":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"1383":[7,42,50,68,69,96,98,100,105,112,113,114,115,117,133,138,139,141,142,144,145,146],"1390":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"1394":[7,42,50,68,69,96,98,100,105,112,113,114,115,117,133,138,139,141,142,144,145,146],"1402":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,68,80,82,83,96,98,99,100,103,104,105,108,109,110,111,113,114,116,117,119,120,121,122,124,126,127,129,130,131,132,133,136,138,140,141,142,144],"1441":[68],"1445":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"1463":[68,113],"1479":[1,2,3,4,7,8,11,12,21,23,24,27,28,37,38,52,53,54,55,56,57,58,60,61,62,64,65,67,68,74,77,80,82,83,84,85,96,98,99,100,103,104,105,108,109,110,111,113,114,116,117,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,143,144],"1483":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"1489":[1,2,3,4,7,8,11,12,21,23,24,27,28,37,38,52,53,54,55,56,57,58,60,61,62,64,65,67,68,74,77,80,82,83,84,85,96,98,99,100,103,104,105,108,109,110,111,113,114,116,117,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,143,144],"1490":[1,2,3,4,7,8,11,12,21,23,24,27,28,37,38,52,53,54,55,56,57,58,60,61,62,64,65,67,68,74,77,80,82,83,84,85,96,98,99,100,103,104,105,108,109,110,111,113,114,116,117,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,143,144],"1497":[0,6,9,21,67,68,81,103,104,105,106,107,108,117,124,125,135],"1502":[0,6,9,21,67,68,81,103,104,105,106,107,108,117,124,125,135],"1510":[68,103],"1532":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"1535":[68],"1542":[68,127],"1562":[68],"1565":[68],"1572":[7,42,50,68,69,96,98,100,105,112,113,114,115,117,133,138,139,141,142,144,145,146],"1578":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"1585":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"1601":[1,2,3,4,7,8,9,11,12,21,22,23,24,27,28,37,38,52,53,55,57,58,60,61,62,65,66,67,68,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"1619":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"1624":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"1630":[1,2,3,4,5,7,8,10,11,12,21,23,24,26,27,28,36,37,38,52,53,54,55,56,57,58,60,61,62,64,65,67,68,69,74,77,78,80,82,83,84,85,96,98,99,100,103,104,105,108,109,110,111,113,114,117,119,120,121,122,124,125,126,127,129,130,131,132,133,136,137,138,139,140,142,143,144,145,146],"1662":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"1664":[1,2,3,4,7,8,9,11,12,21,22,23,24,27,28,37,38,52,53,55,57,58,60,61,62,65,66,67,68,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"1673":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"1675":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,68,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"1693":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"1694":[1,2,3,4,5,7,8,11,12,21,22,23,24,27,28,37,38,52,53,54,55,56,57,58,60,61,62,64,65,67,68,69,74,75,77,78,80,81,82,83,84,85,96,98,99,100,103,104,105,107,108,109,110,111,113,114,116,117,118,119,120,121,122,124,125,126,127,128,129,130,131,132,133,135,136,137,138,140,141,142,143,144,145,146],"1712":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"1713":[5,10,68],"1725":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"1735":[0,1,2,9,27,45,49,50,61,65,66,67,75,79,103,110,114,117,118,119,120,121,122,124,125,128,129,131],"1736":[0,1,2,9,27,45,49,50,61,65,66,67,75,79,103,110,114,117,118,119,120,121,122,124,125,128,129,131],"1741":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"1750":[0,1,2,3,4,5,7,9,11,12,21,23,26,27,28,37,38,45,49,50,55,58,59,60,61,62,63,64,65,66,67,74,75,77,79,82,83,85,96,98,99,100,103,104,105,107,109,110,111,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,146],"1760":[0,1,2,3,4,5,7,9,11,12,21,23,26,27,28,37,38,45,49,50,55,58,59,60,61,62,63,64,65,66,67,74,75,77,79,82,83,85,96,98,99,100,103,104,105,107,109,110,111,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,146],"1761":[0,1,2,3,4,5,7,9,11,12,21,23,26,27,28,37,38,45,49,50,55,58,59,60,61,62,63,64,65,66,67,74,75,77,79,82,83,85,96,98,99,100,103,104,105,107,109,110,111,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,146],"1772":[7,68,100,105,112,113,114,115,117,133,139,141,142],"1801":[68],"1821":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"1823":[1,2,7,8,27,28,60,64,67,74,82,99,104,105,110,114,117,119,124,125,129,139],"1844":[0,1,2,3,4,5,6,7,8,9,10,11,12,14,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"1868":[7,42,50,68,69,96,98,100,105,112,113,114,115,117,133,138,139,141,142,144,145,146],"1936":[146],"1946":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"1962":[4,7,11,12,26,27,28,38,49,50,59,60,62,63,64,66,67,74,82,85,104,105,113,114,115,116,117,118,123,124,125,127,128,129,134,135,141,142],"1977":[6,7,8,9,37,52,80,81,102,117,126]},"packages/frontend/editor-ui/src/experiments/aiTemplatesStarterCollection/stores/aiTemplatesStarterCollection.store.ts":{"20":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,26,27,28,36,37,38,40,41,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,93,94,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"33":[15,16,18,19,20,40,41,68,69,70,71,72,73,93,94,96,98,133,138,139,144,146]},"packages/frontend/editor-ui/src/experiments/emptyStateBuilderPrompt/stores/emptyStateBuilderPrompt.store.ts":{"23":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,26,27,28,36,37,38,40,41,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,93,94,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"58":[18,19,73,93,94,138],"86":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/experiments/readyToRunWorkflows/stores/readyToRunWorkflows.store.ts":{"21":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,26,27,28,36,37,38,40,41,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,93,94,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"30":[15,16,18,19,20,22,26,40,41,68,69,70,71,72,73,93,94,96,98,133,138,139,144,146],"42":[15,16,18,19,20,22,26,40,41,68,69,70,71,72,73,93,94,96,98,133,138,139,144,146]},"packages/frontend/editor-ui/src/experiments/readyToRunWorkflowsV2/stores/readyToRunWorkflowsV2.store.ts":{"12":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/experiments/resourceCenter/stores/resourceCenter.store.ts":{"19":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"32":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"114":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/experiments/sidebarExpanded/useSidebarExpandedExperiment.ts":{"6":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"10":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/experiments/utils.ts":{"11":[1,2,3,4,5,7,8,10,11,12,21,23,24,26,27,28,36,37,38,52,53,54,55,56,57,58,60,61,62,64,65,67,68,69,74,77,78,80,82,83,84,85,96,98,99,100,103,104,105,108,109,110,111,113,114,117,119,120,121,122,124,125,126,127,129,130,131,132,133,136,137,138,139,140,142,143,144,145,146],"18":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"25":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/features/agents/composables/useAgentPermissions.ts":{"34":[3,15,16,18,19,20,22,23,26,35,37,38,39,40,41,68,69,70,71,72,73,88,89,93,94,96,97,98,133,138,139,144,146]},"packages/frontend/editor-ui/src/features/ai/assistant/assistant.api.ts":{"15":[5,147,10],"42":[1,2,3,4,147],"71":[2,147],"83":[147,110],"95":[147],"105":[147],"125":[5,147,10],"132":[147],"136":[147],"143":[147],"151":[147],"160":[147]},"packages/frontend/editor-ui/src/features/ai/assistant/assistant.store.ts":{"37":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"45":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"55":[2],"56":[2],"76":[1,2,3,4,5,10],"77":[1,2,4],"79":[1,2,3,4],"81":[1,2,3,4,5,10],"91":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"93":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"97":[1,2,3],"99":[1,3],"104":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"112":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"116":[1,2,3,4],"120":[1,2,3,4],"133":[1,2,3,4],"135":[1,2,3,4],"139":[1,2,3,4],"196":[1,2],"207":[3],"213":[1,2,3,4],"217":[1,2,3,4],"240":[1,2,3,4],"244":[1,3,4],"270":[1,2,3,4],"290":[1,2,3,4],"294":[1,2,3,4],"298":[1,2,3,4],"309":[3],"328":[1,4],"410":[1,3,4],"470":[1,3,4],"471":[1,3,4],"483":[1,2],"544":[1,2],"545":[1,2],"552":[2],"580":[2],"581":[2],"588":[0,1,2,4,6,7,8,9,11,12,26,27,28,38,45,49,50,59,60,61,62,63,64,65,66,67,74,75,79,81,82,85,102,103,104,105,110,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135,141,142],"619":[1,4],"669":[1,4],"670":[1,4],"682":[1,4],"696":[1,2,3,4,5,10],"736":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"737":[1,2,3,4,5,7,8,11,12,21,22,23,24,27,28,37,38,52,53,54,55,56,57,58,60,61,62,64,65,67,69,74,75,77,78,80,81,82,83,84,85,90,91,96,98,99,100,103,104,105,107,108,109,110,111,113,114,116,117,118,119,120,121,122,124,125,126,127,128,129,130,131,132,133,135,136,137,138,140,141,142,143,144,145,146],"743":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"744":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/features/ai/assistant/builder.store.ts":{"165":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"187":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"229":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,20,21,22,23,24,26,27,28,29,30,31,32,34,35,36,37,38,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,74,75,76,77,78,79,80,81,82,83,84,85,93,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"256":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"259":[5,10],"298":[5,10],"301":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"317":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"321":[5,10],"323":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"329":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"349":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"361":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"365":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"368":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"370":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"377":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"387":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"409":[5,10],"419":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"431":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,20,21,22,23,24,26,27,28,29,30,31,32,34,35,36,37,38,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,74,75,76,77,78,79,80,81,82,83,84,85,93,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"462":[0,1,2,4,6,7,8,9,11,26,27,28,38,45,49,50,59,60,61,62,63,64,65,66,67,74,75,79,81,82,85,102,103,104,105,110,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135,141,142],"469":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"477":[5,10],"481":[5,10],"503":[5,10],"530":[5,10],"531":[5,10],"580":[5,10],"652":[10],"663":[10],"672":[10],"703":[5,10],"734":[5,10],"747":[5,10],"824":[5,10],"840":[5,10],"872":[5],"896":[5,10],"1033":[5],"1036":[5],"1058":[5],"1065":[10],"1136":[5,10],"1405":[5],"1410":[5],"1437":[5,10],"1448":[1,2,4,5,7,8,11,22,27,28,38,60,64,67,74,75,81,82,85,99,104,105,107,110,111,113,114,117,118,119,120,121,124,125,126,128,129,131,133,135,140,141,142,144],"1456":[1,2,4,5,7,8,11,22,27,28,38,60,64,67,74,75,81,82,85,99,104,105,107,110,111,113,114,117,118,119,120,121,124,125,126,128,129,131,133,135,140,141,142,144],"1464":[5],"1468":[5,10],"1473":[5,10],"1487":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"1488":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"1521":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"1534":[5],"1555":[5],"1687":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/features/ai/assistant/chatPanel.store.ts":{"32":[1,2,3,4,5,10],"39":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"50":[1,2,3,4],"58":[1,2,3,4,5,10],"64":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"66":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"73":[1,2,3,4,5,10],"107":[1,3],"114":[1,2,3,4,5,10],"123":[1],"131":[1],"146":[1,4,5,10],"154":[1,2,3,4,5,10],"186":[3],"204":[1,2],"220":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"221":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"258":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"259":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/features/ai/assistant/chatPanelState.store.ts":{"14":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/features/ai/assistant/components/Agent/AskAssistantBuild.vue":{"76":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"90":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"120":[5],"127":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"128":[5],"134":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"138":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"143":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"153":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"158":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"169":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"170":[5,10],"172":[5,10],"180":[5,10],"181":[5,10],"184":[5,10],"200":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"201":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"202":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"205":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"211":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"218":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"225":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"229":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"247":[5],"252":[5],"260":[5],"269":[5],"281":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"313":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"345":[0,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,37,38,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,90,91,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"347":[5,10],"394":[5,10],"410":[5],"419":[7,15,20,23,29,30,31,32,34,35,38,40,41,42,43,44,45,46,47,48,49,50,51,68,69,70,71,72,78,93,96,97,98,100,105,112,113,114,115,117,133,138,139,141,142,144,145,146],"543":[5],"557":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"559":[0,1,5,6,7,8,9,10,11,12,13,14,15,20,21,22,23,24,26,27,28,29,30,31,32,34,35,36,37,38,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,74,75,76,77,78,79,80,81,82,83,84,85,93,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"594":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"595":[5,10],"607":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"609":[5,10],"684":[7,15,20,23,29,30,31,32,34,35,38,40,41,42,43,44,45,46,47,48,49,50,51,68,69,70,71,72,78,93,96,97,98,100,105,112,113,114,115,117,133,138,139,141,142,144,145,146],"691":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"703":[5,10],"709":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"712":[5,10],"743":[5,10],"749":[5],"756":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"773":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"778":[5,10],"785":[0,6,7,8,9,11,12,13,14,21,22,23,24,26,27,28,37,38,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,90,91,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"788":[5],"840":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"870":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"880":[0,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,37,38,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,90,91,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/features/ai/assistant/components/AssistantsHub.vue":{"19":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"39":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"40":[1,2,3,4,5,10],"51":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"85":[1],"89":[1,2,3,4,5,10],"98":[0,1,2,3,4,5,6,7,8,9,10,11,12,26,27,28,38,45,49,50,59,60,61,62,63,64,65,66,67,74,75,79,81,82,85,102,103,104,105,110,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135,141,142],"106":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"112":[1,2,3,4,5,7,8,9,10,11,12,15,20,21,22,23,24,27,28,29,30,31,32,34,35,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,55,57,58,60,61,62,64,65,66,67,68,69,70,71,72,74,75,76,78,79,80,81,82,83,84,85,88,89,93,96,97,98,99,100,103,104,105,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,144,145,146],"124":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"141":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"150":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,38,39,40,41,42,43,44,45,46,47,48,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,104,105,106,107,108,110,111,112,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,131,132,134,135,136,137,138,139,140,141,143,144,145,146],"164":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"169":[5,10]},"packages/frontend/editor-ui/src/features/ai/assistant/components/Chat/AskAssistantChat.vue":{"13":[1,2,3,4],"27":[1,2,3,4],"32":[1,2,3,4],"34":[1,2,3,4],"39":[1,4],"50":[1,4],"65":[2],"72":[2],"80":[1,2,3,4],"84":[1,2,3,4],"87":[1,4],"96":[1],"108":[1,2,3,4]},"packages/frontend/editor-ui/src/features/ai/assistant/components/Chat/AskAssistantFloatingButton.vue":{"13":[1,2,3,68],"21":[1,2,3,68],"35":[68],"39":[68],"59":[1,2,3,68],"71":[68],"76":[1,2,3,68]},"packages/frontend/editor-ui/src/features/ai/assistant/components/Chat/AskModeEmptyState.vue":{"5":[1,2,3,4],"6":[1,2,3,4]},"packages/frontend/editor-ui/src/features/ai/assistant/components/FocusedNodes/ChatInputWithMention.vue":{"24":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"45":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"66":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"67":[5,10],"73":[5,10],"103":[5],"114":[5,10],"121":[5,10],"127":[10],"159":[5,10],"174":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/features/ai/assistant/composables/useAIAssistantHelpers.ts":{"43":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"59":[1,2,3,147],"71":[147],"78":[1,2,3,147],"97":[147],"98":[147],"110":[147],"119":[147],"128":[147],"134":[147],"160":[147],"177":[147],"204":[1,2,147],"211":[1,2,147],"224":[1,2,3,4,147],"248":[3,147],"273":[1,2,147],"295":[1,2,3,147],"298":[1,2,3,147],"306":[1,2,3,5,147],"332":[1,4,147],"354":[4,147],"376":[4,147],"417":[1,4,5,147,10],"425":[147],"444":[147],"462":[147],"506":[147],"579":[147],"593":[147],"629":[147]},"packages/frontend/editor-ui/src/features/ai/assistant/composables/useAskModeCoachmark.ts":{"14":[5,10],"17":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"25":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"27":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"35":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/features/ai/assistant/composables/useBuilderMessages.ts":{"82":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"88":[5,10],"89":[5,10],"208":[5],"326":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"327":[5,10],"330":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"342":[5],"395":[5],"419":[5],"436":[5],"460":[5],"462":[5],"471":[5,10],"517":[10],"556":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,20,21,22,23,24,26,27,28,29,30,31,32,34,35,36,37,38,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,74,75,76,77,78,79,80,81,82,83,84,85,93,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/features/ai/assistant/composables/useBuilderTodos.ts":{"37":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"47":[5],"89":[5],"129":[5,10],"138":[5],"151":[5,10],"206":[5,10],"212":[5],"246":[5,10],"247":[5],"254":[5]},"packages/frontend/editor-ui/src/features/ai/assistant/composables/useFocusedNodesChipUI.ts":{"14":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/features/ai/assistant/composables/useNodeMention.ts":{"32":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"61":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"62":[5,7,8,11,12,21,23,28,37,38,42,45,48,49,50,52,55,58,60,61,67,77,80,82,83,96,98,100,102,103,104,105,107,108,109,110,111,112,113,116,117,119,120,121,122,124,126,127,129,130,131,132,133,135,136,138,139,140,141,142],"155":[5,10]},"packages/frontend/editor-ui/src/features/ai/assistant/composables/useReviewChanges.ts":{"34":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"71":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"100":[5],"107":[5],"116":[5],"128":[5],"139":[5],"145":[5],"252":[1,2,3,4],"278":[5,10],"288":[5],"299":[5,10],"309":[1,2,3,4],"311":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/features/ai/assistant/focusedNodes.store.ts":{"25":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"27":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"33":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"35":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"45":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"240":[5,10],"266":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"267":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"282":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"283":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,90,91,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"285":[0,1,2,3,4,5,6,7,8,9,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,90,91,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"311":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"312":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,90,91,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"324":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"325":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,90,91,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"334":[5,10]},"packages/frontend/editor-ui/src/features/ai/chatHub/chat.store.ts":{"107":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"136":[29,30,31,32,34,35],"139":[29,30,31,32,34,35],"146":[29,30,31,32,34,35],"162":[29,30,31,32,34,35],"172":[29,30,31,32,34,35],"176":[29,30,31,32,34,35],"213":[29,30,31,32,34,35],"236":[30],"278":[29,30,31,32,34,35],"304":[29,30,31,32],"314":[29,30,31,32,34,35],"333":[29,30,31,32,34,35],"340":[34],"367":[29,30,31,32,34,35],"370":[29,30,31,32,34,35],"376":[29,30,31,32,34,35],"381":[29,30,31,32,34,35],"410":[29,30,31,32,34,35],"440":[29,30],"446":[29,30],"457":[29,30,31,32,34,35],"466":[29,30,31,32,34,35],"483":[34,35],"592":[29,30,31,32,34,35],"607":[29],"654":[34],"691":[30],"794":[30],"946":[30],"958":[32],"982":[32],"993":[32],"1028":[32],"1053":[32],"1073":[32],"1078":[32],"1088":[29,30,31,32,34,35],"1092":[29,30,31,32,34,35],"1103":[33],"1114":[33],"1124":[33],"1141":[29,30,31,32,34,35],"1187":[29,30,31,32],"1205":[29,30,31,32,34,35],"1221":[34,35],"1243":[29,30,31,32,34,35],"1285":[29,30,31,32,34,35],"1326":[29,30,31,32,34,35],"1353":[29,30,31,32,34,35],"1383":[29],"1404":[30],"1522":[29,30,31,32,34,35],"1523":[29,30,31,32,34,35],"1548":[29,30,31,32,34,35],"1549":[29,30,31,32,34,35]},"packages/frontend/editor-ui/src/features/ai/chatHub/chatHubPanel.store.ts":{"19":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"29":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"66":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"67":[3,7,15,20,23,29,30,31,32,34,35,38,40,41,42,43,44,45,46,47,48,49,50,51,68,69,70,71,72,78,93,96,97,98,100,105,112,113,114,115,117,133,138,139,141,142,144,145,146]},"packages/frontend/editor-ui/src/features/ai/chatHub/module.descriptor.ts":{"18":[29,30,31,32,34,35],"19":[35],"20":[35],"21":[32],"22":[32],"23":[33],"24":[33],"46":[34],"57":[32],"69":[31],"93":[33],"203":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/features/ai/evaluation.ee/evaluation.store.ts":{"10":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"24":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"26":[147],"28":[147],"29":[147],"43":[147],"50":[147],"63":[147,100],"67":[147],"79":[147],"85":[147],"97":[147],"106":[147],"125":[147],"136":[147],"137":[147],"143":[147],"148":[147],"159":[147],"160":[147]},"packages/frontend/editor-ui/src/features/ai/instanceAi/instanceAi.store.ts":{"20":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"38":[44,46,47],"39":[44,46,47],"43":[42,43,44,45,46,47,48,49,50,51],"48":[42,43,44,45,46,47,48,49,50,51],"61":[47],"82":[42,43,44,45,46,47,48,49,50,51],"93":[42,43,44,45,46,47,48,49,50,51],"105":[42,43,44,45,46,47,48,49,50,51],"113":[42,43,44,45,46,47,48,49,50,51],"116":[42,45,49,50],"130":[42,43,44,45,46,47,48,49,50,51],"142":[42,43,44,45,46,47,48,49,50,51],"150":[42,43,44,45,46,47,48,49,50,51],"151":[42,43,44,45,46,47,48,49,50,51],"152":[42,43,44,45,46,47,48,49,50,51],"167":[42,43,44,45,46,47,48,49,50,51],"173":[47],"189":[47],"202":[47],"208":[47],"209":[47],"273":[42,43,44,45,46,47,48,49,50,51]},"packages/frontend/editor-ui/src/features/ai/instanceAi/instanceAiSettings.store.ts":{"30":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"83":[42,43,44,45,46,47,48,49,50,51],"87":[42,43,44,45,46,47,48,49,50,51],"227":[42,43,44,45,46,47,48,49,50,51],"490":[42,43,44,45,46,47,48,49,50,51],"494":[42,43,44,45,46,47,48,49,50,51]},"packages/frontend/editor-ui/src/features/ai/mcpAccess/module.descriptor.ts":{"41":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/features/collaboration/collaboration/collaboration.store.ts":{"32":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"70":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"78":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"79":[0,1,2,3,4,5,6,7,8,9,10,11,12,22,26,27,28,37,38,42,45,49,50,52,59,60,61,62,63,64,65,66,67,68,69,74,75,76,79,81,82,85,96,98,99,100,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,131,133,134,135,136,137,138,139,140,141,142,144,145,146],"82":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"86":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"90":[0,1,2,3,4,5,6,7,8,9,10,11,12,22,26,27,28,37,38,42,45,48,49,50,52,59,60,61,62,63,64,65,66,67,68,69,74,75,76,79,81,82,85,96,98,99,100,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,131,133,134,135,136,137,138,139,140,141,142,144,145,146],"108":[0,1,2,3,4,5,6,7,8,9,10,11,12,22,26,27,28,37,38,42,45,48,49,50,52,59,60,61,62,63,64,65,66,67,68,69,74,75,76,79,81,82,85,96,98,99,100,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,131,133,134,135,136,137,138,139,140,141,142,144,145,146],"113":[22,42,50,69,104,105,107,112,116,133,135,138,139,144],"117":[22,42,50,104,105,107,112,116,133,135,139,144],"122":[0,1,2,3,4,5,6,7,8,9,10,11,12,22,26,27,28,37,38,42,45,48,49,50,52,59,60,61,62,63,64,65,66,67,68,69,74,75,76,79,81,82,85,96,98,99,100,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,131,133,134,135,136,137,138,139,140,141,142,144,145,146],"129":[0,1,2,3,4,5,6,7,8,9,10,11,12,22,26,27,28,37,38,42,45,48,49,50,52,59,60,61,62,63,64,65,66,67,69,74,75,76,79,81,82,85,96,98,99,100,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,131,133,134,135,136,137,138,139,140,141,142,144,145,146],"134":[2,3,4,5,7,11,22,38,42,50,52,60,66,67,75,81,82,98,100,103,104,105,107,109,110,111,112,113,116,117,118,120,121,126,127,128,129,131,133,135,138,139,140,141,142,144,145],"153":[2,3,4,5,7,11,22,38,52,60,66,67,75,81,82,98,100,103,104,105,107,109,110,111,113,116,117,118,120,121,126,127,128,129,131,133,135,138,139,140,141,142,144,145],"161":[2,3,4,5,7,11,22,38,42,50,52,60,66,67,75,81,82,98,100,103,104,105,107,109,110,111,112,113,116,117,118,120,121,126,127,128,129,131,133,135,138,139,140,141,142,144,145],"195":[22,69,104,105,107,116,133,135,138,144],"204":[2,3,4,5,7,11,22,38,52,60,66,67,75,81,82,98,100,103,104,105,107,109,110,111,113,116,117,118,120,121,126,127,128,129,131,133,135,138,139,140,141,142,144,145],"208":[1,2,3,4,5,7,8,10,11,12,21,22,23,24,27,28,37,38,52,53,54,55,56,57,58,60,61,62,64,65,66,67,69,74,75,77,78,80,81,82,83,84,85,96,98,99,100,103,104,105,107,108,109,110,111,113,114,116,117,118,119,120,121,122,124,125,126,127,128,129,130,131,132,133,135,136,137,138,139,140,141,142,143,144,145,146],"247":[133,139],"266":[0,7,9,38,49,67,68,105,113,114,115,117,123,125,128,135,141,142],"281":[0,1,2,3,4,5,6,7,8,9,10,11,12,22,26,27,28,37,38,42,45,48,49,50,52,59,60,61,62,63,64,65,66,67,68,69,74,75,76,79,81,82,85,96,98,99,100,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,131,133,134,135,136,137,138,139,140,141,142,144,145,146],"288":[0,1,2,3,4,5,6,7,8,9,10,11,12,22,26,27,28,37,38,42,45,48,49,50,52,59,60,61,62,63,64,65,66,67,69,74,75,76,79,81,82,85,96,98,99,100,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,131,133,134,135,136,137,138,139,140,141,142,144,145,146],"293":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"297":[1,2,3,4,5,7,8,11,12,22,27,28,38,42,50,52,60,61,64,65,67,69,74,75,81,82,85,90,91,99,100,103,104,105,107,109,110,111,112,113,114,117,118,119,120,121,122,124,125,126,127,128,129,131,133,135,136,137,138,139,140,141,142,144,145,146],"302":[7],"312":[7],"318":[1,2,4,5,7,8,11,22,27,28,38,60,64,66,67,74,75,81,82,85,99,100,104,105,107,110,111,113,114,117,118,119,120,121,124,125,126,128,129,131,133,135,139,140,141,142,144],"345":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"346":[1,2,3,4,5,7,8,11,12,21,22,23,24,27,28,37,38,52,53,54,55,56,57,58,60,61,62,64,65,67,69,74,75,77,78,80,81,82,83,84,85,90,91,96,98,99,100,103,104,105,107,108,109,110,111,113,114,116,117,118,119,120,121,122,124,125,126,127,128,129,130,131,132,133,135,136,137,138,140,141,142,143,144,145,146],"355":[0,1,2,3,4,5,6,7,8,9,10,11,12,22,26,27,28,37,38,42,45,49,50,52,59,60,61,62,63,64,65,66,67,68,69,74,75,76,79,81,82,85,96,98,99,100,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,131,133,134,135,136,137,138,139,140,141,142,144,145,146],"367":[0,1,2,3,4,5,6,7,8,9,10,11,12,22,26,27,28,37,38,42,45,48,49,50,52,59,60,61,62,63,64,65,66,67,68,69,74,75,76,79,81,82,85,96,98,99,100,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,131,133,134,135,136,137,138,139,140,141,142,144,145,146],"389":[0,1,2,3,4,5,6,7,8,9,10,11,12,22,26,27,28,37,38,42,45,49,50,52,59,60,61,62,63,64,65,66,67,68,69,74,75,76,79,81,82,85,96,98,99,100,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,131,133,134,135,136,137,138,139,140,141,142,144,145,146],"445":[42,50,112,133,139]},"packages/frontend/editor-ui/src/features/collaboration/collaboration/components/CollaborationPane.vue":{"11":[0,1,2,3,4,5,6,7,8,9,10,11,12,22,26,27,28,37,38,42,45,48,49,50,52,59,60,61,62,63,64,65,66,67,68,69,74,75,76,79,81,82,85,96,98,99,100,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,131,133,134,135,136,137,138,139,140,141,142,144,145,146],"15":[22,68,69,104,105,107,116,133,135,138,144],"24":[0,1,2,3,4,5,6,7,8,9,10,11,12,22,26,27,28,37,38,42,45,48,49,50,52,59,60,61,62,63,64,65,66,67,68,69,74,75,76,79,81,82,85,96,98,99,100,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,131,133,134,135,136,137,138,139,140,141,142,144,145,146],"26":[68,138],"27":[68,138],"29":[68,138],"35":[68,138],"37":[0,1,2,3,4,5,6,7,8,9,10,11,12,22,26,27,28,37,38,42,45,48,49,50,52,59,60,61,62,63,64,65,66,67,68,69,74,75,76,79,81,82,85,96,98,99,100,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,131,133,134,135,136,137,138,139,140,141,142,144,145,146],"41":[42,50,68,112,133,139],"44":[0,1,2,3,4,5,6,7,8,9,10,11,12,22,26,27,28,37,38,42,45,48,49,50,52,59,60,61,62,63,64,65,66,67,68,69,74,75,76,79,81,82,85,96,98,99,100,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,131,133,134,135,136,137,138,139,140,141,142,144,145,146]},"packages/frontend/editor-ui/src/features/collaboration/projects/components/ProjectCardBadge.vue":{"23":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"37":[15,16,18,20,23,37,38,39,40,41,69,71,72,89,97,98,133,138,139,144,146],"46":[15,16,18,20,23,37,38,39,40,41,69,71,72,89,97,98,133,138,139,144,146],"50":[15,16,18,20,23,37,38,39,40,41,69,71,72,89,97,98,133,138,139,144,146],"73":[15,16,18,20,23,37,38,39,40,41,69,71,72,89,97,98,133,138,139,144,146],"77":[15,16,18,20,23,37,38,39,40,41,69,71,72,89,97,98,133,138,139,144,146],"89":[15,16,18,20,23,37,38,39,40,41,69,71,72,89,97,98,133,138,139,144,146],"105":[15,16,18,20,23,37,38,39,40,41,69,71,72,89,97,98,133,138,139,144,146],"148":[15,16,18,20,23,37,38,39,40,41,69,71,72,89,97,98,133,138,139,144,146],"175":[15,16,18,20,23,37,38,39,40,41,69,71,72,89,97,98,133,138,139,144,146],"178":[15,16,18,20,40,41,69,71,72,133,138,139,144,146]},"packages/frontend/editor-ui/src/features/collaboration/projects/components/ProjectCreateResource.vue":{"14":[3,15,16,18,19,20,22,23,26,37,38,39,40,41,68,69,70,71,72,73,88,89,93,94,96,97,98,133,138,139,144,146],"23":[3,15,16,18,19,20,22,23,26,37,38,39,40,41,68,69,70,71,72,73,88,89,93,94,96,97,98,133,138,139,144,146],"34":[41,69,70],"35":[3,15,16,18,19,20,22,23,26,37,38,39,40,41,68,69,70,71,72,73,88,89,93,94,96,97,98,133,138,139,144,146]},"packages/frontend/editor-ui/src/features/collaboration/projects/components/ProjectHeader.vue":{"46":[15,23,35,37,39,41,68,69,70,71,72,89,96,98,138,144],"48":[3,15,16,18,19,20,22,23,26,35,37,38,39,40,41,68,69,70,71,72,73,88,89,93,94,96,97,98,133,138,139,144,146],"50":[15,23,35,37,39,41,68,69,70,71,72,89,96,98,138,144],"70":[15,23,35,37,39,41,68,69,70,71,72,89,96,98,138,144],"82":[3,15,16,18,19,20,22,23,26,35,37,38,39,40,41,68,69,70,71,72,73,88,89,93,94,96,97,98,133,138,139,144,146],"86":[3,15,23,35,37,38,39,40,41,68,69,70,71,72,89,96,97,98,138,144],"90":[3,15,16,18,19,20,22,23,26,35,37,38,39,40,41,68,69,70,71,72,73,88,89,93,94,96,97,98,133,138,139,144,146],"107":[3,15,23,35,37,38,39,40,41,68,69,70,71,72,89,96,97,98,138,144],"110":[88],"113":[88],"117":[3,15,23,38,40,41,71,72,97,98,138,144],"121":[3,15,16,18,19,20,22,23,26,35,37,38,39,40,41,68,69,70,71,72,73,88,89,93,94,96,97,98,133,138,139,144,146],"128":[3,15,16,18,19,20,22,23,26,37,38,39,40,41,68,69,70,71,72,73,88,89,93,94,96,97,98,133,138,139,144,146],"135":[3,15,16,18,19,20,22,23,26,35,37,38,39,40,41,68,69,70,71,72,73,88,89,93,94,96,97,98,133,138,139,144,146],"149":[3,15,16,18,19,20,22,23,26,35,37,38,39,40,41,68,69,70,71,72,73,88,89,93,94,96,97,98,133,138,139,144,146],"162":[15,16,18,19,20,22,26,40,41,68,69,70,71,72,73,93,94,96,98,133,138,139,144,146],"172":[3,23,37,38,39,72,89,97,98],"182":[40,41],"192":[88],"209":[3,15,16,18,19,20,22,23,26,37,38,39,40,41,68,69,70,71,72,73,88,89,93,94,96,97,98,133,138,139,144,146],"216":[3,15,16,18,19,20,22,23,26,37,38,39,40,41,68,69,70,71,72,73,88,89,93,94,96,97,98,133,138,139,144,146],"232":[3,15,16,18,19,20,22,23,26,37,38,39,40,41,68,69,70,71,72,73,88,89,93,94,96,97,98,133,138,139,144,146],"308":[3,15,16,18,19,20,22,23,26,35,37,38,39,40,41,68,69,70,71,72,73,88,89,93,94,96,97,98,133,138,139,144,146],"314":[3,23,37,38,69,96,97,98,138,144],"324":[69,96,98,138,144],"335":[3,23,37,38,69,96,97,98,138,144],"348":[69,96,98,138,144],"358":[3,23,37,38,97,98],"370":[69,70],"373":[40,41],"379":[88],"389":[3,15,16,18,19,20,22,23,26,35,37,38,39,40,41,68,69,70,71,72,73,88,89,93,94,96,97,98,133,138,139,144,146],"399":[3,15,16,18,19,20,22,23,26,35,37,38,39,40,41,68,69,70,71,72,73,88,89,93,94,96,97,98,133,138,139,144,146],"419":[15,23,35,37,39,41,68,69,70,71,72,89,96,98,138,144],"427":[15,23,35,37,39,41,68,69,70,71,72,89,96,98,138,144],"437":[3,15,16,18,19,20,22,23,26,35,37,38,39,40,41,68,69,70,71,72,73,88,89,93,94,96,97,98,133,138,139,144,146],"451":[71],"462":[3,23,37,38,40,41,69,70,88,96,97,98,138,144],"479":[3,15,16,18,19,20,22,23,26,35,37,38,39,40,41,68,69,70,71,72,73,88,89,93,94,96,97,98,133,138,139,144,146],"482":[3,15,16,18,19,20,22,23,26,38,40,41,71,72,73,88,89,93,94,97,98,133,138,139,144,146],"487":[71],"514":[3,15,16,18,19,20,22,23,26,37,38,39,40,41,68,69,70,71,72,73,88,89,93,94,96,97,98,133,138,139,144,146],"521":[41,69,70],"522":[3,15,16,18,19,20,22,23,26,37,38,39,40,41,68,69,70,71,72,73,88,89,93,94,96,97,98,133,138,139,144,146],"527":[3,23,37,38,40,41,69,88,96,97,98,138,144]},"packages/frontend/editor-ui/src/features/collaboration/projects/components/ProjectNavigation.vue":{"22":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"46":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"48":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"53":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"58":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"59":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"62":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"74":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"83":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"92":[5,15,21,23,26,35,37,39,40,41,53,54,56,57,58,60,61,62,64,67,68,69,70,71,72,74,75,76,77,79,80,81,82,83,85,88,89,96,98,99,103,104,106,109,111,112,113,118,119,120,121,122,127,129,130,131,136,138,144],"104":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"116":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"118":[42,43,44,45,46,47,48,49,50,51],"126":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"140":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"145":[69,93,96,98,112,133,138,139,144,145,146],"148":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"246":[41,72,138],"263":[5,15,21,23,26,35,37,39,40,41,53,54,56,57,58,60,61,62,64,67,68,69,70,71,72,74,75,76,77,79,80,81,82,83,85,88,89,96,98,99,103,104,106,109,111,112,113,118,119,120,121,122,127,129,130,131,136,138,144]},"packages/frontend/editor-ui/src/features/collaboration/projects/components/ProjectTabs.vue":{"22":[3,15,16,18,19,20,22,23,26,35,37,38,39,40,41,68,69,70,71,72,73,88,89,93,94,96,97,98,133,138,139,144,146],"36":[3,15,16,18,19,20,22,23,26,35,37,38,39,40,41,68,69,70,71,72,73,88,89,93,94,96,97,98,133,138,139,144,146],"38":[3,15,16,18,19,20,22,23,26,35,37,38,39,40,41,68,69,70,71,72,73,88,89,93,94,96,97,98,133,138,139,144,146],"44":[3,15,23,35,37,38,39,40,41,68,69,70,71,72,89,96,97,98,138,144],"46":[3,15,16,18,19,20,22,23,26,35,37,38,39,40,41,68,69,70,71,72,73,88,89,93,94,96,97,98,133,138,139,144,146],"89":[3,15,16,18,19,20,22,23,26,35,37,38,39,40,41,68,69,70,71,72,73,88,89,93,94,96,97,98,133,138,139,144,146],"102":[3,15,16,18,19,20,22,23,26,35,37,38,39,40,41,68,69,70,71,72,73,88,89,93,94,96,97,98,133,138,139,144,146],"141":[3,15,16,18,19,20,22,23,26,35,37,38,39,40,41,68,69,70,71,72,73,88,89,93,94,96,97,98,133,138,139,144,146],"142":[3,15,16,18,19,20,22,23,26,35,37,38,39,40,41,68,69,70,71,72,73,88,89,93,94,96,97,98,133,138,139,144,146],"158":[3,15,16,18,19,20,22,23,26,35,37,38,39,40,41,68,69,70,71,72,73,88,89,93,94,96,97,98,133,138,139,144,146]},"packages/frontend/editor-ui/src/features/collaboration/projects/composables/useFavoriteNavItems.ts":{"22":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"128":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/features/collaboration/projects/composables/useProjectPages.ts":{"7":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"11":[3,15,23,35,37,38,39,41,68,69,70,71,72,89,96,97,98,138,144],"14":[3,15,16,18,19,20,22,23,26,35,37,38,39,40,41,68,69,70,71,72,73,88,89,93,94,96,97,98,133,138,139,144,146],"17":[3,15,16,18,19,20,22,23,26,35,37,38,39,40,41,68,69,70,71,72,73,88,89,93,94,96,97,98,133,138,139,144,146]},"packages/frontend/editor-ui/src/features/collaboration/projects/projects.api.ts":{"7":[147,15,35,41,71,89,98,138,144],"11":[147,70,72,144],"27":[147,33,38,94,96,97,98,99,144],"45":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"49":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"53":[3,5,147,15,23,26,35,37,38,39,40,41,68,69,70,71,72,89,96,97,98,112,133,136,138,141,142,144],"57":[147,15,41,71,98,138,144],"64":[147,15,41,71,98,138,144],"72":[147],"85":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"89":[147,35,71],"97":[147,35],"106":[147]},"packages/frontend/editor-ui/src/features/collaboration/projects/projects.routes.ts":{"10":[15,16,18,19,20,22,26,40,41,68,69,70,71,72,73,93,94,96,98,133,138,139,144,146],"11":[3,23,37,38,39,72,89,97,98],"12":[3,23,38,39,72,89,97,98],"13":[15,35,41,71,89,98,138,144],"16":[88],"18":[3,15,16,18,19,20,22,23,26,31,37,38,39,40,41,68,69,70,71,72,73,88,89,93,94,96,97,98,133,138,139,144,146],"22":[3,15,23,37,38,39,40,41,68,69,70,72,89,96,97,98,138,144],"33":[15,16,18,19,20,22,26,31,40,41,68,69,70,71,72,73,93,94,96,98,133,138,139,144,146],"44":[3,23,37,38,39,72,89,97,98],"64":[68,69,70],"74":[88],"134":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"146":[15,35,41,71,89,98,138,144],"147":[15,35,41,71,89,98,138,144],"169":[3,15,16,18,19,20,22,23,26,31,38,40,41,71,72,73,88,89,93,94,97,98,133,138,139,144,146],"184":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/features/collaboration/projects/projects.store.ts":{"32":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"51":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"54":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"58":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"64":[147,144],"65":[147],"66":[147],"68":[147,33,38,89,97,98],"69":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"70":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"71":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"72":[147],"75":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"81":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"84":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"89":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"90":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"95":[3,5,147,15,16,18,19,20,22,23,26,29,30,31,32,34,35,37,38,40,41,42,43,44,45,46,47,48,49,50,51,71,72,73,88,89,93,94,97,98,112,133,136,138,139,141,142,144,146],"99":[147,15,35,41,71,89,98,138,144],"103":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"107":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"111":[147],"119":[147,70,72,144],"129":[147,33,38,94,96,97,98,99,144],"139":[3,5,147,15,23,26,35,37,38,39,40,41,68,69,70,71,72,89,96,97,98,112,133,136,138,141,142,144],"142":[3,147,15,23,35,37,38,39,40,41,68,69,70,71,72,89,96,97,98,138,144],"146":[5,147,23,26,37,112,133,136,141,142,144],"153":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"159":[147,15,41,71,98,138,144],"166":[147,15,41,71,98,138,144],"174":[147,15,41,71,98,138,144],"192":[147,35,71],"200":[147,35],"209":[147],"214":[147],"217":[147],"220":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"224":[0,6,7,9,147,22,26,42,45,48,49,50,59,60,62,63,66,68,75,76,79,81,96,98,104,105,106,107,112,114,115,116,117,118,120,123,124,125,126,127,128,133,134,135,138,139,141,142,144,145,146],"232":[147,98],"262":[147,72],"285":[147],"299":[147,15,35,41,71,89,98,138,144],"310":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/features/collaboration/projects/projects.utils.ts":{"16":[147,33,38,94,96,97,98,99,144],"18":[147,33,38,94,96,97,98,99,144],"31":[147,15,16,18,19,20,22,23,26,37,38,39,40,41,68,69,70,71,72,73,88,89,93,94,96,97,98,133,138,139,144,146],"33":[147,70,72,144],"42":[147],"50":[3,7,8,147,18,23,30,33,37,38,39,41,51,58,69,70,72,80,89,94,96,97,98,99,100,127,130,138,144,145],"64":[147,72],"69":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/features/core/dataTable/components/NodeStorageLimitCallout.vue":{"9":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"13":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"28":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144]},"packages/frontend/editor-ui/src/features/core/dataTable/dataTable.api.ts":{"13":[147,40,41,144],"40":[147,40,41],"61":[147,41],"77":[147,40],"93":[147,40],"109":[147,40],"122":[147,40],"139":[147],"156":[147,40,41],"176":[147,40],"193":[147,40],"214":[147,40],"220":[147,40],"238":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"246":[147],"269":[147],"283":[147]},"packages/frontend/editor-ui/src/features/core/dataTable/dataTable.store.ts":{"37":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"50":[40,41],"56":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"64":[40,41],"72":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"76":[40,41,144],"101":[40,41],"176":[41],"179":[41],"185":[40],"197":[40],"199":[40],"207":[40],"215":[40],"236":[40,41],"237":[40,41],"244":[40],"256":[40],"264":[40],"278":[40],"279":[40],"313":[40,41],"331":[40],"341":[40],"356":[40],"360":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/features/core/folders/components/FolderBreadcrumbs.vue":{"59":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,21,22,23,24,26,27,28,36,37,38,40,41,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,72,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"65":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,21,22,23,24,26,27,28,36,37,38,40,41,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,72,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"67":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,21,22,23,24,26,27,28,36,37,38,40,41,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,72,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"76":[69],"88":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,21,22,23,24,26,27,28,36,37,38,40,41,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,72,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"92":[69,70],"96":[15,40,41,68,69,70,72,96,98,138,144],"107":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,21,22,23,24,26,27,28,36,37,38,40,41,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,72,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"111":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,21,22,23,24,26,27,28,36,37,38,40,41,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,72,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"147":[69],"162":[69],"174":[69,70],"178":[68],"185":[68,69,70],"196":[69],"208":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,21,22,23,24,26,27,28,36,37,38,40,41,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,72,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"209":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,21,22,23,24,26,27,28,36,37,38,40,41,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,72,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"212":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,21,22,23,24,26,27,28,36,37,38,40,41,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,72,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"219":[15,40,41,42,50,68,69,70,72,96,98,112,133,138,139,144],"242":[68,69,70],"249":[68,69,70],"275":[15,40,41,68,69,70,72,96,98,138,144],"305":[69,70]},"packages/frontend/editor-ui/src/features/core/folders/components/ProjectBreadcrumb.vue":{"30":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,21,22,23,24,26,27,28,36,37,38,40,41,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,72,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"52":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,21,22,23,24,26,27,28,36,37,38,40,41,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,72,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"63":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,21,22,23,24,26,27,28,36,37,38,40,41,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,72,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"75":[68,69,70],"79":[68],"91":[68,69,70],"100":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,21,22,23,24,26,27,28,36,37,38,40,41,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,72,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/features/core/folders/composables/useParentFolder.ts":{"5":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"11":[1,2,3,4,5,7,8,10,11,12,13,14,21,23,24,26,27,28,36,37,38,52,53,54,55,56,57,58,60,61,62,64,65,67,68,69,74,77,80,82,83,84,85,96,98,99,100,101,102,103,104,105,108,109,110,111,112,113,114,117,119,120,121,122,124,125,126,127,129,130,131,132,133,136,137,138,139,140,141,142,143,144]},"packages/frontend/editor-ui/src/features/core/folders/folders.constants.ts":{"16":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/features/core/folders/folders.store.ts":{"23":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"40":[15,16,18,19,20,40,41,68,69,70,71,72,73,93,94,96,98,133,138,139,144,146],"41":[68,69,70],"52":[69,70],"56":[69,70],"64":[68,69,70],"75":[68,69,70],"81":[68,69,70],"99":[15,16,18,19,20,22,26,40,41,68,69,70,71,72,73,93,94,96,98,133,138,139,144,146],"115":[70],"116":[70],"121":[70],"125":[70],"134":[70,72],"174":[70],"183":[70],"190":[70],"206":[70],"219":[68,70],"249":[70],"262":[69],"273":[69],"342":[69]},"packages/frontend/editor-ui/src/features/credentials/components/CredentialEdit/CredentialConfig.vue":{"80":[3,7,8,23,30,33,37,38,39,51,58,80,89,97,98,127,130,145],"111":[3,7,8,23,30,33,37,38,39,51,58,80,89,97,98,127,130,145],"132":[3,7,8,23,30,33,37,38,39,51,58,80,89,97,98,127,130,145],"135":[3,37,39,130,145],"140":[3,7,8,23,30,33,37,38,39,51,58,80,89,97,98,127,130,145],"141":[3,7,8,23,30,33,37,38,39,51,58,80,89,97,98,127,130,145],"144":[3,7,8,23,30,33,37,38,39,51,58,80,89,97,98,127,130,145],"174":[3,7,8,23,30,33,37,38,39,51,58,80,89,97,98,127,130,145],"179":[3,37,39,130,145],"187":[3,7,8,23,30,33,37,38,39,51,58,80,89,97,98,127,130,145],"196":[3,7,8,23,30,33,37,38,39,51,58,80,89,97,98,127,130,145],"206":[3,7,8,23,30,33,37,38,39,51,58,80,89,97,98,127,130,145],"210":[3,7,8,23,30,33,37,38,39,51,58,80,89,97,98,127,130,145],"212":[3,7,8,23,30,33,37,38,39,51,58,80,89,97,98,127,130,145],"214":[3,7,8,23,30,33,37,38,39,51,58,80,89,97,98,127,130,145],"225":[3],"229":[3,7,8,23,30,33,37,38,39,51,58,80,89,97,98,127,130,145],"231":[7,8,23,30,33,37,38,39,51,80,89,97,98,127,130,145],"235":[3,7,8,23,30,33,37,38,39,51,58,80,89,97,98,127,130,145],"239":[3,7,8,23,30,33,37,38,39,51,58,80,89,97,98,127,130,145],"241":[3,7,8,23,30,33,37,38,39,51,58,80,89,97,98,127,130,145],"246":[3,7,8,23,30,33,37,38,39,51,58,80,89,97,98,127,130,145],"250":[3,7,8,23,30,33,37,38,39,51,80,89,97,98,127,130,145],"254":[7,8,23,30,37,38,39,51,80,89,97,98,127,130,145],"267":[3,37],"271":[3],"289":[39],"294":[3,7,8,23,30,33,37,38,39,51,58,80,89,97,98,127,130,145],"340":[3,7,8,23,30,33,37,38,39,51,80,89,97,98,127,130,145],"342":[3,7,8,23,30,33,38,39,51,80,89,97,98,127,145],"389":[3,37,39,130],"392":[3,7,8,23,30,33,37,38,51,58,80,89,97,98,127,145],"412":[3,7,8,23,30,33,37,38,39,51,58,80,89,97,98,127,130,145],"541":[39,130,145],"549":[3,7,8,23,30,33,37,38,39,51,58,80,97,98,127,130,145],"551":[3,7,8,23,30,33,38,39,51,58,80,97,98,127,145],"553":[3,7,8,23,30,33,38,39,51,58,80,97,98,127,145]},"packages/frontend/editor-ui/src/features/credentials/components/CredentialEdit/CredentialEdit.vue":{"102":[3,7,8,23,30,33,37,38,39,51,58,80,89,97,98,127,130,145],"104":[37,130,145],"109":[37,130,145],"159":[3,7,8,23,30,33,37,38,39,51,58,80,89,97,98,127,130,145],"169":[3,7,8,23,30,33,37,38,39,51,58,80,89,97,98,127,130,145],"174":[3,7,8,23,30,33,37,38,39,51,58,80,89,97,98,127,130,145],"183":[3,7,8,23,30,37,38,39,51,58,80,89,97,98,127,130,145],"199":[3,7,8,37,58,80],"212":[3,7,8,23,30,33,37,38,39,51,58,80,89,97,98,127,130,145],"229":[3,7,8,23,30,33,37,38,39,51,58,80,89,97,98,127,130,145],"244":[3,7,8,23,30,33,37,38,39,51,58,80,89,97,98,127,130,145],"249":[7,8,23,30,33,37,38,39,51,80,89,97,98,127,130,145],"254":[7,8,23,30,33,37,38,51,80,89,97,98,127,145],"262":[7,8,23,30,33,37,38,51,80,97,98,127,145],"265":[7,8,23,30,33,37,38,51,80,97,98,127,145],"277":[7,8,23,30,33,37,38,51,80,97,98,127,145],"285":[3,7,8,23,30,33,37,38,39,51,58,80,89,97,98,127,130,145],"293":[3,7,8,23,30,33,37,38,39,51,58,80,89,97,98,127,130,145],"304":[3,7,8,23,30,33,37,38,39,51,58,80,89,97,98,127,130,145],"306":[3,7,8,23,37,51,58,80,127,130],"311":[3,39],"315":[3,7,8,23,30,33,37,38,39,51,58,80,89,97,98,127,130,145],"320":[3,7,8,23,30,33,37,38,39,51,58,80,89,97,98,127,130,145],"326":[3,7,8,23,30,33,37,38,39,51,58,80,89,97,98,127,130,145],"338":[3,7,8,23,30,33,37,38,39,51,58,80,89,97,98,127,130,145],"345":[3,7,8,23,30,33,37,38,39,51,58,80,89,97,98,127,130,145],"382":[3,7,8,23,30,33,37,38,39,51,58,80,89,97,98,127,130,145],"388":[3,7,8,23,30,33,37,38,39,51,58,80,89,97,98,127,130,145],"410":[3,7,8,23,30,33,37,38,39,51,58,80,89,97,98,127,130,145],"420":[3,7,8,23,30,33,37,38,39,51,58,80,89,97,98,127,130,145],"428":[3,7,8,23,30,33,37,38,39,51,58,80,89,97,98,127,130,145],"435":[33,37,38,97,98],"437":[3,7,8,23,30,33,37,38,39,51,58,80,89,97,98,127,130,145],"448":[3,7,8,23,30,33,37,38,39,51,58,80,89,97,98,127,130,145],"450":[3,7,8,23,30,33,37,38,39,51,58,80,89,97,98,127,130,145],"469":[3,7,8,23,30,33,37,38,39,51,58,80,89,97,98,127,130,145],"478":[3,7,8,23,30,33,37,38,39,51,58,80,89,97,98,127,130,145],"549":[3,7,8,23,30,33,37,38,39,51,58,80,89,97,98,127,130,145],"564":[7,8,23,30,33,37,38,51,80,89,97,98,127,130,145],"596":[3,7,8,23,30,33,37,38,39,51,58,80,89,97,98,127,130,145],"620":[3,7,8,23,30,33,37,38,39,51,58,80,89,97,98,127,130,145],"648":[33,37,38],"650":[33,37,38],"656":[33,37,38],"715":[33,38,97,98],"730":[97,98],"739":[33,38],"744":[3,37],"752":[3,37],"759":[3,37],"799":[7,8,23,30,37,38,39,51,80,89,97,98,127,130,145],"815":[37],"819":[3,7,8,23,30,33,37,38,39,51,58,80,89,97,98,127,130,145],"835":[23,37,38,51,89,97,98,145],"841":[7,8,23,30,33,37,39,51,80,97,98,127,145],"842":[7,8,23,30,33,37,39,51,80,97,98,127,145],"857":[33,37,38],"882":[7,8,23,30,33,37,51,80,97,98,127,145],"895":[7,8,23,30,33,37,38,39,51,80,89,97,98,127,130,145],"896":[7,8,23,30,33,37,38,39,51,80,89,97,98,127,130,145],"901":[3,7,8,23,37,51,58,80,127,130],"910":[7,8,23,30,33,37,38,39,51,80,89,97,98,127,130,145],"985":[7,8,23,30,33,37,38,39,51,80,89,97,98,127,130,145],"1043":[7,8,23,30,33,37,38,39,51,80,89,97,98,127,145],"1076":[7,8,23,30,37,38,39,51,80,89,97,98,127,130,145],"1099":[7,8,23,30,37,38,39,51,80,89,97,98,127,130,145],"1149":[33,37,38,97,98],"1197":[37],"1237":[39,130,145],"1313":[39],"1345":[39],"1349":[39],"1398":[3,37],"1455":[3,37],"1480":[3,7,8,23,30,33,37,38,39,51,58,80,89,97,98,127,130,145],"1492":[3,7,8,23,30,33,37,38,39,51,58,80,89,97,98,127,130,145],"1531":[3,7,8,23,30,33,37,38,39,51,58,80,89,97,98,127,130,145],"1563":[3,7,8,23,30,33,37,38,39,51,58,80,89,97,98,127,130,145],"1567":[3,7,8,23,30,33,37,38,39,51,58,80,89,97,98,127,130,145],"1571":[33,38,97,98]},"packages/frontend/editor-ui/src/features/credentials/components/CredentialEdit/CredentialInputs.vue":{"21":[3,7,8,23,30,33,37,38,39,51,58,80,89,97,98,127,130,145],"25":[3,7,8,23,30,33,37,38,39,51,58,80,89,97,98,127,130,145],"29":[3,7,8,23,30,33,37,38,39,51,58,80,89,97,98,127,130,145],"30":[3,7,8,23,30,33,37,38,39,51,58,80,89,97,98,127,130,145],"39":[7,8,23,30,37,38,39,51,80,89,97,98,127,130,145],"41":[3,7,8,23,30,33,37,38,39,51,58,80,89,97,98,127,130,145],"47":[3,7,8,23,30,33,37,38,39,51,58,80,89,97,98,127,130,145]},"packages/frontend/editor-ui/src/features/credentials/components/CredentialEdit/CredentialModeSelector.vue":{"23":[3,7,8,23,30,33,37,38,39,51,58,80,89,97,98,127,130,145],"41":[3,7,8,23,30,33,37,38,39,51,58,80,89,97,98,127,130,145],"42":[3,7,8,23,30,33,37,38,39,51,58,80,89,97,98,127,130,145],"47":[3,7,8,23,37,51,58,80,127,130],"48":[3,7,8,23,37,51,58,80,127,130],"55":[3,7,8,23,30,33,37,38,39,51,58,80,89,97,98,145],"56":[3,7,8,23,30,33,37,38,39,51,58,80,89,97,98,145],"61":[3],"72":[3,7,8,23,30,33,37,38,39,51,58,80,89,97,98,127,130,145],"83":[3,7,8,23,30,33,37,38,39,51,58,80,89,97,98,127,130,145],"95":[3,23,37,51,127,130],"107":[3,7,8,23,30,33,37,38,39,51,58,80,89,97,98,127,130,145],"129":[3,23,37,51,127,130],"151":[3,7,8,23,30,33,37,38,39,51,58,80,89,97,98,127,130,145],"152":[3,23,37,51,127,130],"153":[3,23,37,51,127,130],"156":[3,23,37,51,127,130],"163":[3,23,37,51,127,130],"164":[3,23,37,51,127,130],"171":[3,37],"174":[3,7,8,23,30,33,37,38,39,51,58,80,89,97,98,127,130,145],"181":[3,23,37,51,127,130],"191":[3,23,37,51,127,130],"193":[3,23,51,127]},"packages/frontend/editor-ui/src/features/credentials/components/CredentialEdit/GoogleAuthButton.vue":{"2":[3,37,39,130]},"packages/frontend/editor-ui/src/features/credentials/components/CredentialIcon.vue":{"24":[3,5,7,8,23,29,30,31,32,33,34,35,37,38,39,51,52,58,72,80,89,97,98,127,130,145],"26":[3,5,7,8,23,29,30,31,32,33,34,35,37,38,39,51,52,58,72,80,89,97,98,127,130,145],"30":[3,5,7,8,23,29,30,31,32,33,34,35,37,38,39,51,52,58,72,80,89,97,98,127,130,145],"38":[3,5,7,8,23,29,30,31,32,33,34,35,37,38,39,51,52,58,72,80,89,97,98,127,130,145],"49":[3,5,7,8,23,29,30,31,32,33,34,35,37,38,39,51,52,58,72,80,89,97,98,127,130,145],"55":[3,5,7,8,23,29,30,31,32,33,34,35,37,38,39,51,52,58,72,80,89,97,98,127,130,145],"65":[3,5,7,8,23,29,30,31,32,33,34,35,37,38,39,51,52,58,72,80,89,97,98,127,130,145],"75":[3,5,7,8,23,29,30,31,32,33,34,35,37,38,39,51,52,58,72,80,89,97,98,127,130,145]},"packages/frontend/editor-ui/src/features/credentials/components/CredentialsSelectModal.vue":{"14":[3,23,37,38,39,89,97,98],"27":[3,23,37,38,39,89,97,98],"34":[3,23,37,38,39,89,97,98],"42":[3,23,37,38,39,89,97,98],"43":[3,23,37,38,39,89,97,98],"46":[3,23,37,38,39,89,97,98],"50":[3,23,37,38,39,89,97,98],"63":[3,23,37,38,39,89,97,98],"76":[3,23,37,38,39,89,97,98],"81":[3,23,37,38,39,89,97,98],"96":[3,23,37,38,39,89,97,98],"98":[3,23,37,38,39,89,97,98],"100":[3,23,38,39,89,97,98],"110":[3,23,37,38,39,89,97,98]},"packages/frontend/editor-ui/src/features/credentials/components/NodeCredentials.vue":{"114":[3,5,7,8,21,22,23,24,34,37,38,51,53,55,57,58,60,61,67,74,76,80,96,98,100,105,111,117,124,126,127,128,129,130,132,140],"129":[3,4,5,7,8,11,12,21,22,23,24,27,34,37,38,51,52,53,55,57,58,60,61,67,74,76,80,83,96,98,100,103,105,111,113,114,117,118,124,126,127,128,129,130,132,140,144],"131":[1,2,3,4,5,7,8,9,11,12,21,22,23,24,27,28,34,37,38,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"144":[1,2,3,4,5,7,8,9,11,12,21,22,23,24,27,28,34,37,38,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"148":[3,7,8,21,23,24,34,37,52,53,55,57,58,60,61,67,74,76,80,96,98,100,105,111,117,124,126,127,128,129,130,132,140],"159":[3,5,7,8,21,22,23,24,34,37,38,51,52,53,55,57,58,60,61,67,74,76,80,96,98,100,105,111,117,124,126,127,128,129,130,132,140],"163":[5,7,8,22,23,34,37,38,51,60,67,80,96,98,117,127,130],"171":[3,5,7,8,21,22,23,24,34,37,38,51,52,53,55,57,58,60,61,67,74,76,80,96,98,100,105,111,117,124,126,127,128,129,130,132,140],"188":[1,2,3,4,5,7,8,9,11,12,21,22,23,24,27,28,34,37,38,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"189":[1,2,3,4,5,7,8,9,11,12,21,22,23,24,27,28,34,37,38,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"214":[1,2,3,4,5,7,8,9,11,12,21,22,23,24,27,28,34,37,38,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"219":[3,5,7,8,21,23,24,34,37,38,51,52,53,55,57,58,61,67,74,76,80,96,98,100,105,111,117,124,126,127,128,129,130,132,140],"233":[7,8,23,34,37,38,51,67,80,96,98,117,127,130],"249":[1,2,3,4,5,7,8,9,11,12,21,22,23,24,27,28,34,37,38,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"250":[1,2,3,4,5,7,8,9,11,12,21,22,23,24,27,28,34,37,38,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"257":[3,7,8,23,37,51,58,80,127,130],"340":[1,2,3,4,5,7,8,9,11,12,21,22,23,24,27,28,34,37,38,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"345":[5,7,8,22,23,34,37,38,51,60,67,80,96,98,117,127,130],"352":[22],"356":[5,7,8,22,23,34,37,38,51,60,67,80,96,98,117,127,130],"364":[37],"383":[3,7,8,23,37,51,58,80,127,130],"414":[130],"424":[7,8,22,23,34,37,38,51,67,80,96,98,117,127,130],"502":[23,37,96,98,127,130],"537":[3,5,7,8,22,23,34,37,38,51,52,60,67,80,96,98,117,127,130],"541":[3,5,7,8,21,22,23,24,34,37,38,51,52,53,55,57,58,60,61,67,74,76,80,96,98,100,105,111,117,124,126,127,128,129,130,132,140],"586":[5,7,8,22,23,34,37,38,51,60,67,80,96,98,117,127,130],"599":[37],"614":[3,5,7,8,21,22,23,24,34,37,38,51,52,53,55,57,58,60,61,67,74,76,80,96,98,100,105,111,117,124,126,127,128,129,130,132,140],"633":[7,8,22,34,38,51,127],"637":[5,7,8,22,23,34,37,38,51,60,67,80,96,98,117,127,130],"641":[7,8,127],"642":[7,8,127],"647":[3,52],"652":[3,5,7,21,22,23,24,34,37,51,52,53,55,57,58,61,74,76,80,100,105,111,124,126,127,128,129,130,132,140],"653":[3,5,7,21,22,23,24,34,37,51,52,53,55,57,58,61,74,76,80,100,105,111,124,126,127,128,129,130,132,140],"659":[3,5,7,21,23,24,34,37,51,52,53,55,57,58,61,74,76,80,100,105,111,124,126,127,128,129,130,132,140],"663":[3,5,7,8,21,22,23,24,34,37,38,51,53,55,57,58,60,61,67,74,76,80,96,98,100,105,111,117,124,126,127,128,129,130,132,140],"667":[3,52],"713":[3,5,7,8,21,22,23,24,34,37,38,51,52,53,55,57,58,60,61,67,74,76,80,96,98,100,105,111,117,124,126,127,128,129,130,132,140],"715":[5,51],"751":[3],"759":[3],"760":[3],"782":[3,7,23,37,51,58,80,127,130],"783":[3,5,7,21,23,24,34,37,51,53,55,57,58,61,74,76,80,100,105,111,124,126,127,128,129,130,132,140],"802":[22,34,38,51],"809":[5,7,8,22,23,34,37,38,51,60,67,80,96,98,117,127,130],"814":[5,7,8,22,23,34,37,38,51,60,67,80,96,98,117,127,130],"840":[5,7,8,22,23,34,37,38,51,60,67,80,96,98,117,127,130],"841":[5,7,8,22,23,34,37,38,51,60,67,80,96,98,117,127,130],"847":[7,8,127],"877":[22],"892":[37]},"packages/frontend/editor-ui/src/features/credentials/composables/useCredentialOAuth.ts":{"38":[3,5,7,8,21,22,23,24,30,33,34,37,38,39,51,52,53,55,57,58,61,74,76,80,89,97,98,100,105,111,124,126,127,128,129,130,132,140,145],"56":[3,5,7,8,21,22,23,24,30,33,34,37,38,39,51,52,53,55,57,58,61,74,76,80,89,97,98,100,105,111,124,126,127,128,129,130,132,140,145],"69":[3,7,8,23,30,33,37,38,39,51,52,58,80,89,97,98,127,130,145],"79":[3,5,7,21,22,23,24,34,37,51,52,53,55,57,58,61,74,76,80,100,105,111,124,126,127,128,129,130,132,140],"96":[3,21,23,37,55,76,124,127,128,129,130,132,140],"106":[3],"111":[3,21,23,37,52,55,76,124,127,128,129,130,132,140],"112":[3,21,23,37,52,55,76,124,127,128,129,130,132,140],"117":[3,52],"319":[1,2,3,4,5,7,8,9,11,12,21,22,23,24,27,28,34,37,38,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144]},"packages/frontend/editor-ui/src/features/credentials/composables/useNodeCredentialOptions.ts":{"30":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,34,37,38,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"38":[3,5,7,8,21,23,34,37,51,52,53,55,57,58,61,67,74,76,80,96,98,100,105,111,117,124,126,127,128,129,130,132,140],"40":[1,2,3,4,5,7,8,9,11,12,21,22,23,24,27,28,34,37,38,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"44":[1,2,3,4,5,7,8,9,11,12,21,22,23,24,27,28,34,37,38,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"45":[3,5,7,8,21,22,23,24,34,37,38,51,52,53,55,57,58,60,61,67,74,76,80,96,98,100,105,111,117,124,126,127,128,129,130,132,140],"55":[3,5,7,8,21,22,23,24,34,37,38,51,52,53,55,57,58,60,61,67,74,76,80,96,98,100,105,111,117,124,126,127,128,129,130,132,140],"57":[3,5,7,8,21,22,23,24,34,37,38,51,52,53,55,57,58,60,61,67,74,76,80,96,98,100,105,111,117,124,126,127,128,129,130,132,140],"59":[5,7,8,22,23,34,37,38,51,60,67,80,96,98,117,127,130],"69":[22,37,38,51],"75":[3,4,5,7,8,11,12,21,22,23,24,27,34,37,38,51,52,53,55,57,58,60,61,67,74,76,80,83,96,98,100,103,105,111,113,114,117,118,124,126,127,128,129,130,132,140,144],"92":[3,5,7,8,21,22,23,24,34,37,38,51,52,53,55,57,58,60,61,67,74,76,80,96,98,100,105,111,117,124,126,127,128,129,130,132,140],"102":[3,5,7,8,21,22,23,24,34,37,38,51,52,53,55,57,58,60,61,67,74,76,80,96,98,100,105,111,117,124,126,127,128,129,130,132,140],"107":[3,21,23,37,53,55,76,96,98,124,127,128,129,130,132,140],"114":[5,51],"120":[3,5,7,8,21,22,23,24,34,37,38,51,52,53,55,57,58,60,61,67,74,76,80,96,98,100,105,111,117,124,126,127,128,129,130,132,140],"126":[5,7,8,22,23,34,37,38,51,60,67,80,96,98,117,127,130]},"packages/frontend/editor-ui/src/features/credentials/credentials.api.ts":{"15":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"33":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"37":[3,7,8,147,23,30,37,38,39,51,58,80,89,97,98,127,130,145],"60":[1,2,3,4,5,7,8,9,147,11,12,21,22,23,24,27,28,33,34,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,70,72,74,75,76,79,80,81,82,83,84,85,89,90,91,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145],"76":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,21,22,23,24,26,27,28,29,30,31,32,34,35,36,37,38,42,45,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"85":[7,8,147,23,30,37,38,39,51,80,89,97,98,127,130,145],"92":[147,37],"96":[147],"100":[147,33,37,38,97,98],"113":[5,147,31,33,37,38,51,145],"123":[147,145],"136":[147,39,130],"148":[5,7,8,147,23,30,33,37,51,80,97,98,127,145]},"packages/frontend/editor-ui/src/features/credentials/credentials.store.ts":{"41":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"49":[5,147,51],"53":[5,147,51],"63":[147],"67":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"68":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,21,22,23,24,26,27,28,29,30,31,32,33,34,35,36,37,38,39,42,45,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,72,74,75,76,77,78,79,80,81,82,83,84,85,87,89,91,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"73":[3,5,7,8,147,21,22,23,24,29,30,31,32,33,34,35,37,38,39,51,52,53,55,57,58,59,60,61,63,66,67,68,72,74,76,78,80,89,96,97,98,100,103,105,109,111,117,124,126,127,128,129,130,132,138,140,144,145],"74":[7,8,147,22,30,34,35,37,39,51,53,57,58,60,61,67,72,74,76,80,97,98,100,103,105,109,111,127,129,130,145],"77":[5,7,8,147,22,23,29,30,31,32,33,34,35,37,59,60,63,66,67,78,80,96,98,117,127,130,145],"80":[5,7,8,147,22,23,29,30,31,32,33,34,35,37,59,60,63,66,67,78,80,96,98,117,127,130,145],"82":[5,7,8,147,22,23,29,30,31,32,33,34,35,37,59,60,63,66,67,80,96,98,117,127,130,145],"91":[3,5,7,8,147,21,22,23,24,34,37,38,51,52,53,55,57,58,60,61,67,74,76,80,96,98,100,105,111,117,124,126,127,128,129,130,132,140],"95":[3,5,7,8,147,21,22,23,24,34,37,38,51,52,53,55,57,58,60,61,67,74,76,80,96,98,100,105,111,117,124,126,127,128,129,130,132,140],"97":[5,7,8,147,21,22,23,34,37,38,51,53,57,58,60,61,67,74,76,80,96,98,100,105,111,117,127,129,130],"107":[7,8,147,23,37,80,127,130],"108":[7,8,147,23,80,127],"112":[7,8,147,23,37,80,127,130],"116":[7,8,147,127],"124":[1,2,3,4,5,7,8,9,147,11,12,14,21,22,23,24,27,28,29,30,31,32,33,34,35,37,38,39,49,51,52,53,55,57,58,59,60,61,62,63,65,66,67,72,74,75,76,78,79,80,81,82,83,84,85,89,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,143,144,145,146],"125":[1,2,3,4,5,7,8,9,147,11,12,14,21,22,23,24,27,28,29,30,31,32,33,34,35,37,38,39,49,51,52,53,55,57,58,59,60,61,62,63,65,66,67,72,74,75,76,78,79,80,81,82,83,84,85,89,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,143,144,145,146],"128":[3,5,7,8,147,22,23,29,30,31,32,33,34,35,37,38,39,51,58,67,80,89,96,97,98,105,117,127,130,143,145],"129":[3,5,7,8,147,22,23,29,30,31,32,33,34,35,37,38,39,51,58,67,80,89,96,97,98,105,117,127,130,143,145],"132":[7,8,147,23,34,37,38,80,127,130],"133":[7,8,147,23,34,38,80,127],"139":[5,7,8,147,22,23,29,30,31,32,33,34,35,37,59,60,63,66,67,78,80,96,98,117,127,130,145],"140":[5,7,8,147,22,23,29,30,31,32,33,34,35,59,60,63,66,67,78,80,96,98,117,127,145],"145":[147],"146":[147],"151":[7,8,147,23,30,33,37,38,51,80,97,98,127,145],"152":[7,8,147,23,30,33,38,51,80,97,98,127,145],"160":[7,8,147,23,30,33,37,38,51,80,97,98,127,145],"165":[147,22,37],"166":[147,22],"172":[147,22,37],"196":[3,7,8,147,23,30,33,37,38,39,51,58,80,89,97,98,127,130,145],"197":[3,7,8,147,23,30,33,38,39,51,58,80,89,97,98,127,145],"214":[3,7,8,147,23,30,33,37,38,39,51,58,80,89,97,98,127,130,145],"215":[3,7,8,147,23,30,33,38,39,51,58,80,89,97,98,127,145],"222":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"223":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"234":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"235":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"245":[147],"246":[147],"253":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,21,22,23,24,26,27,28,29,30,31,32,33,34,35,36,37,38,39,42,45,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,72,74,75,76,77,78,79,80,81,82,83,84,85,89,90,91,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"254":[5,7,8,147,21,22,23,29,30,31,32,33,34,35,37,38,39,51,53,57,58,59,60,61,63,65,66,67,70,72,74,75,76,77,79,80,81,82,83,84,85,89,91,96,97,98,100,103,104,105,106,109,111,112,113,117,118,119,120,121,122,125,127,129,130,131,145],"265":[7,8,147,23,30,33,37,38,39,51,80,89,97,98,127,130,145],"277":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"285":[1,2,3,4,5,7,8,9,147,11,12,21,22,23,24,27,28,33,34,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,70,72,74,75,76,79,80,81,82,83,84,85,89,90,91,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145],"317":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,21,22,23,24,26,27,28,29,30,31,32,34,35,36,37,38,42,45,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"328":[5,147,31,33,37,38,51,145],"336":[1,2,3,4,5,7,8,9,147,11,12,14,21,22,23,24,27,28,34,37,38,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"349":[7,8,147,23,30,37,38,39,51,80,89,97,98,127,130,145],"386":[147,33,37,38,97,98],"399":[147,37],"408":[147],"419":[147,39,130],"423":[147,145],"427":[5,7,8,147,23,30,33,37,51,80,97,98,127,145],"442":[3,7,8,147,23,30,37,38,39,51,58,80,89,97,98,127,130,145],"459":[147,97,98],"469":[147,97,98],"481":[147],"487":[147],"544":[5,147,31,33,78,145],"553":[5,147,31,33,145],"555":[5,147,31,33,145]},"packages/frontend/editor-ui/src/features/credentials/quickConnect/components/QuickConnectButton.vue":{"9":[3,7,8,23,30,33,37,38,39,51,52,58,80,89,97,98,127,130,145],"35":[3,7,8,23,30,33,37,38,51,52,58,80,89,97,98,127,145],"44":[3,7,8,23,30,33,37,38,39,51,52,58,80,89,97,98,127,130,145],"49":[3,7,8,23,30,33,37,38,39,51,52,58,80,89,97,98,127,130,145],"64":[3,7,8,23,30,33,37,38,51,52,58,80,89,97,98,127,145]},"packages/frontend/editor-ui/src/features/credentials/quickConnect/composables/useQuickConnect.ts":{"33":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,34,37,38,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"41":[3,8,12,21,23,28,37,53,56,57,58,60,67,87,96,98,100,103,104,105,109,110,111,119,121,124,125,127,129,130,131,132,136,140],"51":[3,5,7,8,21,22,23,24,34,37,51,52,53,55,57,58,61,74,76,80,100,105,111,124,126,127,128,129,130,132,140],"64":[3,8,12,21,23,28,37,53,56,57,58,60,67,87,96,98,100,103,104,105,109,110,111,119,121,124,125,127,129,130,131,132,136,140],"71":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"117":[1,2,3,4,5,7,8,9,11,12,21,22,23,24,27,28,30,33,34,37,38,49,51,52,53,55,56,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,87,89,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145]},"packages/frontend/editor-ui/src/features/credentials/views/CredentialsView.vue":{"62":[3,23,38,97,98],"79":[23,37,38,39,72,89,97,98],"85":[23,37,38,39,72,89,97,98],"88":[3,23,37,38,39,72,89,97,98],"89":[23,37,38,39,72,89,97,98],"114":[3,23,37,38,39,72,89,97,98],"116":[3,23,37,38,39,72,89,97,98],"132":[23,38,39,89],"136":[23,37,38,39,89,97,98],"144":[23,39,89],"153":[3,23,37,38,39,72,89,97,98],"164":[23,37,38,39,72,89,97,98],"187":[3,23,37,38,39,72,89,97,98],"197":[3,23,37,38,39,72,89,97,98],"220":[3,23,37,38,39,72,89,97,98],"249":[37,38,72,97,98],"253":[3,23,37,38,39,72,89,97,98],"255":[23,37,38,39,89,97,98],"268":[3,23,37,38,39,72,89,97,98],"270":[3,23,37,38,39,72,89,97,98],"271":[3,23,37,38,39,89,97,98],"280":[3,23,37,38,39,72,89,97,98],"290":[3,23,37,38,39,72,89,97,98],"309":[3,23,37,38,39,72,89,97,98],"319":[23,37,38,39,72,89,97,98]},"packages/frontend/editor-ui/src/features/execution/executions/composables/useExecutionData.ts":{"8":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"12":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"23":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144]},"packages/frontend/editor-ui/src/features/execution/executions/composables/useExecutionRedaction.ts":{"10":[1,2,3,4,6,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,102,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"17":[6,7,8,9,81,102,117],"19":[6,7,8,9,81,102,117]},"packages/frontend/editor-ui/src/features/execution/executions/executions.store.ts":{"31":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"42":[7,105,113,114,115,117,141,142],"63":[7,105,113,114,115,117,141,142],"66":[113,115,141,142],"73":[7,105,113,114,115,117,141,142],"74":[105,113,114,115,117,141,142],"103":[7,105,113,114,115,117,141,142],"111":[7,105,113,114,115,117,141,142],"112":[142],"123":[7,105,113,114,115,117,141,142],"133":[142],"140":[114],"145":[141],"149":[7,105,113,114,115,117,141,142],"157":[7,105,113,114,115,117,141,142],"177":[7,105,113,114,115,117,141,142],"194":[105,113,114,115,117,141,142],"208":[7,105,113,114,115,117,141,142],"214":[113,114,115,141,142],"222":[7,105,113,114,115,117,141,142],"227":[7,105,113,114,115,117,141,142],"286":[117],"308":[114],"330":[7,105,113,141,142],"338":[7,105,113,141,142]},"packages/frontend/editor-ui/src/features/execution/executions/executions.utils.ts":{"48":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"62":[7,147,105,113,114,115,117,141,142],"124":[147,11,12,60],"137":[0,1,2,4,6,7,8,9,147,11,12,26,27,28,38,45,49,50,59,60,61,62,63,64,65,66,67,74,75,79,81,82,85,102,103,104,105,110,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135,141,142],"139":[0,1,2,4,6,7,8,9,147,11,12,26,27,28,38,49,50,59,60,61,62,63,64,65,66,67,74,75,79,81,82,85,102,103,104,105,110,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135,141,142],"190":[147,117],"247":[1,2,6,7,8,9,147,11,12,27,49,60,61,62,65,66,67,74,75,79,81,82,85,102,104,110,113,114,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135],"248":[1,2,6,7,8,9,147,11,12,27,49,60,61,62,65,66,67,74,75,79,81,82,85,102,104,110,113,114,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135],"256":[1,2,6,7,8,9,147,11,12,27,49,60,61,62,65,66,67,74,75,79,81,82,85,102,104,110,113,114,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135],"265":[1,2,6,7,8,9,147,11,12,27,49,60,61,62,65,66,67,74,75,79,81,82,85,102,104,110,113,114,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135],"266":[1,2,6,7,8,9,147,11,12,27,49,60,61,62,65,66,67,74,75,79,81,82,85,102,104,110,113,114,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135],"269":[147],"324":[0,1,2,4,6,7,8,9,147,11,26,27,28,38,45,49,50,59,60,61,62,63,64,65,66,67,74,75,79,81,82,85,102,103,104,105,110,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135,141,142],"362":[0,1,2,7,8,147,38,113,114,117,124,141,142],"404":[0,1,2,4,6,7,8,9,147,11,26,27,28,38,45,49,50,59,60,61,62,63,64,65,66,67,74,75,79,81,82,85,102,103,104,105,110,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135,141,142],"421":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"435":[5,147],"442":[5,147,66,114,118,129],"448":[0,1,2,3,4,5,7,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,82,83,84,85,96,98,99,100,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"454":[147],"490":[147],"512":[147]},"packages/frontend/editor-ui/src/features/execution/insights/components/InsightsSummary.vue":{"33":[3,15,16,18,20,22,23,26,38,40,41,71,72,88,89,93,97,98,133,138,139,144,146],"46":[3,15,16,18,20,22,23,26,38,40,41,71,72,88,89,93,97,98,133,138,139,144,146],"54":[3,15,16,18,20,22,23,26,38,40,41,71,72,88,89,93,97,98,133,138,139,144,146],"56":[3,15,16,18,20,22,23,26,38,40,41,71,72,88,89,93,97,98,133,138,139,144,146],"59":[3,15,16,18,20,22,23,26,38,40,41,71,72,88,89,93,97,98,133,138,139,144,146],"60":[3,15,16,18,20,22,23,26,38,40,41,71,72,88,89,93,97,98,133,138,139,144,146],"118":[3,15,16,18,20,22,23,26,38,40,41,71,72,88,89,93,97,98,133,138,139,144,146],"133":[3,15,16,18,20,22,23,26,38,40,41,71,72,88,89,93,97,98,133,138,139,144,146]},"packages/frontend/editor-ui/src/features/execution/insights/insights.api.ts":{"16":[3,15,16,18,20,22,23,26,38,40,41,71,72,88,89,93,97,98,133,138,139,144,146],"34":[3,15,16,18,20,22,23,26,38,40,41,71,72,88,89,93,97,98,133,138,139,144,146]},"packages/frontend/editor-ui/src/features/execution/insights/insights.constants.ts":{"21":[3,15,16,18,20,22,23,26,38,40,41,71,72,88,89,93,97,98,133,138,139,144,146],"22":[3,15,16,18,20,22,23,26,38,40,41,71,72,88,89,93,97,98,133,138,139,144,146],"23":[3,15,16,18,20,22,23,26,38,40,41,71,72,88,89,93,97,98,133,138,139,144,146],"24":[3,15,16,18,20,22,23,26,38,40,41,71,72,88,89,93,97,98,133,138,139,144,146],"25":[3,15,16,18,20,22,23,26,38,40,41,71,72,88,89,93,97,98,133,138,139,144,146]},"packages/frontend/editor-ui/src/features/execution/insights/insights.store.ts":{"12":[3,15,16,18,19,20,22,23,26,37,38,39,40,41,68,69,70,71,72,73,88,89,93,94,96,97,98,133,138,139,144,146],"17":[3,15,16,18,19,20,22,23,26,38,40,41,71,72,73,88,89,93,94,97,98,133,138,139,144,146],"21":[3,15,16,18,20,22,23,26,38,40,41,71,72,88,89,93,97,98,133,138,139,144,146],"25":[3,15,16,18,19,20,22,23,26,38,40,41,71,72,73,88,89,93,94,97,98,133,138,139,144,146],"30":[3,15,16,18,20,22,23,26,38,40,41,71,72,88,89,93,97,98,133,138,139,144,146]},"packages/frontend/editor-ui/src/features/execution/insights/insights.utils.ts":{"17":[3,15,16,18,20,22,23,26,38,40,41,71,72,88,89,93,97,98,133,138,139,144,146],"19":[3,15,16,18,20,22,23,26,38,40,41,71,72,88,89,93,97,98,133,138,139,144,146],"20":[3,15,16,18,20,22,23,26,38,40,41,71,72,88,89,93,97,98,133,138,139,144,146],"23":[3,15,16,18,20,22,23,26,38,40,41,71,72,88,89,93,97,98,133,138,139,144,146],"24":[3,15,16,18,20,22,23,26,38,40,41,71,72,88,89,93,97,98,133,138,139,144,146],"52":[3,15,16,18,20,22,23,26,38,40,41,71,72,88,89,93,97,98,133,138,139,144,146],"54":[3,15,16,18,20,22,23,26,38,40,41,71,72,88,89,93,97,98,133,138,139,144,146],"79":[3,15,16,18,20,22,23,26,38,40,41,71,72,88,89,93,97,98,133,138,139,144,146],"96":[3,15,16,18,20,22,23,26,38,40,41,71,72,88,89,93,97,98,133,138,139,144,146],"117":[3,15,16,18,20,22,23,26,38,40,41,71,72,88,89,93,97,98,133,138,139,144,146]},"packages/frontend/editor-ui/src/features/execution/logs/components/LogsOverviewPanel.vue":{"39":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"51":[6,7,8,9,68,81,102,117],"52":[6,7,8,9,68,81,102,117],"57":[6,7,8,9,68,81,102,117],"59":[6,7,8,9,68,81,102,117],"67":[6,7,8,9,68,81,102,117],"72":[6,7,8,9,68,81,102,117],"75":[6,7,8,9,68,81,102,117],"78":[68],"80":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"94":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"98":[0,1,2,4,6,7,8,9,11,26,27,28,38,45,49,50,59,60,61,62,63,64,65,66,67,74,75,79,81,82,85,103,104,105,110,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135,141,142],"107":[0,1,2,4,6,7,8,9,11,26,27,28,38,45,49,50,59,60,61,62,63,64,65,66,67,74,75,79,81,82,85,103,104,105,110,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135,141,142],"125":[6,7,8,9,81,102,117],"147":[117],"148":[6,117]},"packages/frontend/editor-ui/src/features/execution/logs/components/LogsPanel.vue":{"21":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"31":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"70":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"71":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"74":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"83":[6,7,8,9,68,81,102,117],"88":[6,7,8,9,68,81,102,117],"94":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"112":[68],"120":[68,117],"123":[68,117],"133":[68],"138":[68],"141":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"173":[6,7,8,9,37,52,80,81,102,117,126],"199":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"242":[6,7,8,9,81,102,117]},"packages/frontend/editor-ui/src/features/execution/logs/components/LogsPanelActions.vue":{"19":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"22":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"23":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"26":[6,7,8,9,68,81,102,117],"35":[68],"44":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"51":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"75":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/features/execution/logs/components/LogsPanelHeader.vue":{"8":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"10":[6,7,68,117],"13":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"20":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/features/execution/logs/components/LogsViewKeyboardEventListener.vue":{"8":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"11":[5,7,21,53,57,68,80,82,83,103,104,105,107,108,109,116,126,133,135,138,139,140,141,142,144,145,146],"24":[68],"27":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/features/execution/logs/composables/useChatState.ts":{"42":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"49":[6,7,8,9,68,81,102,117],"63":[6,7,8,9,68,81,102,117],"64":[68,117],"67":[6,7,8,9,68,81,102,117],"69":[68],"70":[6,7,8,9,37,52,68,80,81,102,117,126],"78":[6,7,8,9,37,52,68,80,81,102,117,126],"105":[6,7,8,9,37,52,68,80,81,102,117,126],"124":[6,7,8,9,37,52,68,80,81,102,117,126],"129":[6,7,8,9,37,52,68,80,81,102,117,126],"134":[6,7,8,9,37,52,68,80,81,102,117,126],"139":[6,7,8,9,68,81,102,117],"153":[6,7,8,9,68,81,102,117],"169":[6,7,8,9,68,81,102,117],"181":[68],"182":[68],"183":[68],"187":[68],"188":[68],"234":[6,7,8,9,68,81,102,117],"280":[6,7,8,9,68,81,102,117],"294":[6,7,8,9,68,81,102,117],"325":[68,117],"333":[6,7,9,68,102],"346":[68],"354":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"355":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"366":[6,7,8,9,37,52,68,80,81,102,117,126]},"packages/frontend/editor-ui/src/features/execution/logs/composables/useClearExecutionButtonVisible.ts":{"9":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"14":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"17":[0,1,2,3,4,5,6,7,8,9,11,12,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"18":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"19":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"21":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"22":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"24":[0,1,2,3,4,5,6,7,8,9,11,12,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"25":[0,1,2,3,4,5,6,7,8,9,11,12,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"28":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/features/execution/logs/composables/useLogsExecutionData.ts":{"35":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"47":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"54":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"60":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"61":[0,1,2,4,6,7,8,9,11,12,26,27,28,38,45,49,50,59,60,61,62,63,64,65,66,67,74,75,79,81,82,85,102,103,104,105,110,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135,141,142,146],"76":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"86":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"91":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"110":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"121":[68],"149":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"150":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"151":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"152":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"153":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"155":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"178":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"179":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"188":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"198":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/features/execution/logs/composables/useLogsPanelLayout.ts":{"16":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"30":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"32":[68],"38":[6,7,8,9,37,52,68,80,81,102,117,126],"40":[68],"45":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"51":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"56":[6,7,8,9,68,81,102,117],"57":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"58":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"67":[68],"77":[6,7,68,117],"91":[68],"97":[68],"110":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"133":[7,42,50,68,100,105,112,113,114,115,117,133,139,141,142]},"packages/frontend/editor-ui/src/features/execution/logs/composables/useLogsSelection.ts":{"20":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"29":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"30":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"38":[6,68,117],"46":[6,68,117],"63":[68],"78":[68],"94":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"105":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"120":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"126":[7,8,9,81,117]},"packages/frontend/editor-ui/src/features/execution/logs/composables/useLogsTreeExpand.ts":{"10":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"14":[7,68,117]},"packages/frontend/editor-ui/src/features/execution/logs/composables/usePopOutWindow.ts":{"32":[68],"39":[68],"61":[68],"77":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"88":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"89":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"90":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"93":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"104":[68],"121":[68],"141":[68],"168":[68],"171":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"180":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"185":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"194":[7,42,50,68,100,105,112,113,114,115,117,133,139,141,142],"199":[7,42,50,68,100,105,112,113,114,115,117,133,139,141,142]},"packages/frontend/editor-ui/src/features/execution/logs/logs.utils.ts":{"33":[6,7,8,9,68,81,102,117],"34":[6,7,8,9,68,81,102,117],"48":[6,7,8,9,68,81,102,117],"56":[6,7,8,9,68,81,102,117],"80":[6,7,8,9,68,81,102,117],"110":[7,8,68,117],"118":[7,8,68,117],"119":[7,8,68,117],"123":[7,8,68,117],"144":[6,7,8,9,68,81,102,117],"162":[6,7,8,9,68,81,102,117],"166":[6,7,8,9,68,81,102,117],"172":[6,7,8,9,68,81,102,117],"186":[0,1,2,4,6,7,9,11,26,27,28,38,45,49,50,59,60,61,62,63,64,65,66,67,68,74,75,79,81,82,85,102,103,104,105,110,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135,141,142],"187":[6,7,68,81,102,117],"193":[6,7,68,81,102,117],"207":[6,7,8,9,68,81,102,117],"213":[6,7,8,9,68,81,102,117],"229":[6,7,8,9,68,81,102,117],"237":[68],"242":[7,8,68,117],"260":[6,7,8,9,68,81,102,117],"276":[6,7,8,9,68,81,102,117],"284":[6,7,8,9,68,81,102,117],"303":[68],"304":[68],"307":[0,1,2,3,4,6,7,8,9,11,12,21,22,23,24,26,27,28,37,38,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,74,75,76,77,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145],"326":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"337":[6,7,8,9,81,117],"360":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"376":[68],"381":[68],"386":[6,7,8,9,68,81,102,117],"404":[6,7,8,9,68,81,102,117],"418":[6,7,8,9,68,81,102,117],"423":[6,7,8,9,68,81,102,117],"428":[6,7,8,9,68,81,102,117],"438":[68,117],"440":[6,7,8,9,68,81,102,117],"463":[6,7,8,9,68,81,102,117],"467":[6,7,8,9,68,81,102,117],"495":[6,68,117],"507":[68,117],"518":[68,117],"543":[68,117],"595":[68,117],"602":[68,117],"614":[68,117],"677":[6,7,8,9,68,81,102,117],"681":[6,7,8,9,68,81,102,117],"691":[0,1,2,4,6,7,8,9,11,12,26,27,28,38,45,49,50,59,60,61,62,63,64,65,66,67,68,74,75,79,81,82,85,102,103,104,105,110,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135,141,142,146],"699":[0,1,2,4,6,7,8,9,11,12,26,27,28,38,45,49,50,59,60,61,62,63,64,65,66,67,68,74,75,79,81,82,85,102,103,104,105,110,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135,141,142]},"packages/frontend/editor-ui/src/features/instanceRegistry/stores/instanceRegistry.store.ts":{"7":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"14":[109]},"packages/frontend/editor-ui/src/features/integrations/externalSecrets.ee/externalSecrets.ee.store.ts":{"21":[89],"24":[89],"28":[89],"61":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,30,33,34,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,72,74,75,76,79,80,81,82,83,84,85,89,90,91,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145],"67":[3,7,8,23,30,33,37,38,39,51,58,80,89,97,98,127,130,145],"79":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,30,33,34,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,90,91,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145],"92":[89],"93":[89],"97":[89],"100":[89],"101":[89],"141":[3,7,8,23,30,33,37,38,39,51,58,80,89,97,98,127,130,145],"155":[3,7,8,23,30,33,37,38,39,51,58,80,89,97,98,127,130,145],"176":[3,7,8,23,30,33,37,38,39,51,58,80,89,97,98,127,130,145],"208":[3,7,8,23,30,33,37,38,39,51,58,80,89,97,98,127,130,145]},"packages/frontend/editor-ui/src/features/integrations/sourceControl.ee/sourceControl.api.ts":{"22":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"24":[147],"30":[147],"37":[147],"44":[147],"53":[147],"61":[147],"65":[147],"76":[147],"87":[147],"96":[147]},"packages/frontend/editor-ui/src/features/integrations/sourceControl.ee/sourceControl.store.ts":{"14":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"18":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"24":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"45":[147],"58":[147],"62":[147],"66":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"68":[147],"73":[147],"78":[147],"87":[147],"102":[147],"112":[147],"116":[147],"124":[147]},"packages/frontend/editor-ui/src/features/ndv/panel/components/InputPanel.vue":{"62":[1,2,3,4,7,8,9,11,12,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140],"112":[1,2,3,4,7,8,9,11,12,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140],"121":[1,2,3,4,7,8,9,11,12,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140],"129":[1,2,3,4,7,8,9,11,12,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140],"133":[1,2,3,4,7,8,9,11,12,21,22,23,24,27,28,37,38,52,53,55,57,58,60,61,62,67,74,75,76,79,80,81,82,83,84,96,98,100,103,104,105,106,109,110,111,113,116,117,118,119,120,121,122,124,125,126,127,128,129,130,131,132,133,134,136,138,140],"153":[1,2,3,4,7,8,9,11,12,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140],"154":[1,2,3,4,7,8,9,11,12,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140],"163":[1,2,3,4,7,8,9,11,12,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140],"187":[1,2,3,4,7,8,9,11,12,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,66,67,74,75,76,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140],"188":[7,127],"192":[1,2,3,4,7,8,9,11,12,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140],"200":[1,2,3,4,7,8,9,11,12,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140],"216":[1,2,27,61,62,75,110,118,119,120,121,122,124,125,128,129,131,134],"224":[1,2,3,4,7,8,9,11,12,21,22,23,24,27,28,37,38,52,53,55,57,58,60,61,62,67,74,75,76,79,80,81,82,83,84,96,98,100,103,104,105,106,109,110,111,113,116,117,118,119,120,121,122,124,125,126,127,128,129,130,131,132,133,134,136,138,140],"229":[1,2,3,4,7,8,9,11,12,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140],"244":[1,2,3,4,7,8,9,11,12,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140],"245":[1,2,3,4,7,8,9,11,12,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,66,67,74,75,76,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140],"248":[1,2,3,4,7,8,9,11,12,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140],"255":[1,2,3,4,7,8,9,11,12,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,66,67,74,75,76,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140],"259":[1,2,3,4,7,8,9,11,12,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140],"260":[1,2,3,4,7,8,9,11,12,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,66,67,74,75,76,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140],"266":[1,2,3,4,7,8,9,11,12,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140],"285":[1,2,3,4,7,8,9,11,12,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140],"287":[1,2,3,4,7,8,9,11,12,21,22,23,24,27,28,37,38,52,53,55,57,58,60,61,62,67,75,76,80,81,82,83,84,96,98,100,103,104,105,109,110,111,113,117,118,119,120,121,124,125,126,127,128,129,130,131,132,133,136,138,140],"292":[1,2,3,4,7,8,9,11,12,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140],"305":[12,60,67,106,119,120,121,122,127,128,129,131],"307":[60,67,119,120,121,122,127,129,131],"325":[1,2,3,4,7,8,9,11,12,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,66,67,74,75,76,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140],"345":[110,120],"358":[1,2,3,4,7,8,9,11,12,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140],"362":[9,125],"366":[1,2,3,4,7,8,9,11,12,21,22,23,24,27,28,37,38,52,53,55,57,58,60,61,62,67,74,75,76,79,80,81,82,83,84,96,98,100,103,104,105,106,109,110,111,113,116,117,118,119,120,121,122,124,125,126,127,128,129,130,131,132,133,134,136,138,140],"370":[123],"374":[120,125,128],"383":[117,120,123,124,125,128],"387":[120,128],"388":[120,128],"404":[9,79,103,110,117,120,123,124,125,126,127,128,130],"410":[1,2,3,4,7,8,9,11,12,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140],"446":[79,117,120,123,124,125,128],"449":[1,2,3,4,7,8,9,11,12,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140],"456":[1,2,3,4,7,8,9,11,12,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140],"468":[79,117,120,123,124,125,128],"477":[8,37,79,80,127],"481":[8,37,79,80,127],"490":[1,2,3,4,7,8,9,11,12,21,22,23,24,27,28,37,38,52,53,55,57,58,60,61,62,67,75,76,80,81,82,83,84,96,98,100,103,104,105,109,110,111,113,117,118,119,120,121,124,125,126,127,128,129,130,131,132,133,136,138,140],"524":[1,2,3,4,7,8,9,11,12,21,22,23,24,27,28,37,38,52,53,55,57,58,60,61,62,67,75,76,80,81,82,83,84,96,98,100,103,104,105,109,110,111,113,117,118,119,120,121,124,125,126,127,128,129,130,131,132,133,136,138,140],"526":[1,2,3,4,7,8,9,11,12,21,22,23,24,27,28,38,52,53,55,57,58,60,61,62,67,75,76,80,81,82,83,84,96,98,100,104,105,110,111,117,118,119,120,121,124,125,126,127,128,131,132,136,138,140],"632":[8,21,37,67,80,98,104,124,127,129,133],"677":[9]},"packages/frontend/editor-ui/src/features/ndv/panel/components/NDVFloatingNodes.vue":{"13":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"18":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"30":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"32":[126],"39":[4,7,21,23,37,53,57,75,80,82,83,103,104,105,109,111,116,119,120,121,122,123,124,125,126,127,129,130,131,133,144],"53":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"55":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140],"65":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140],"68":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"97":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"101":[1,3,4,7,8,9,11,12,21,22,28,37,38,52,53,55,57,60,62,65,67,76,79,80,81,82,83,84,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,131,132,133,135,138,140,144],"107":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"125":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140],"131":[110,111,126,131]},"packages/frontend/editor-ui/src/features/ndv/panel/components/NDVHeader.vue":{"27":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,68,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"32":[68],"34":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,68,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"62":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,68,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"64":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,68,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"70":[68],"72":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,68,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144]},"packages/frontend/editor-ui/src/features/ndv/panel/components/NDVSubConnections.vue":{"25":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"57":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"61":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"66":[8,126],"84":[7,8,37,52,80,100,103,126,127],"87":[7,8,37,52,80,100,103,126,127],"99":[8,126],"110":[7,8,37,52,80,100,103,126,127],"127":[7,8,37,52,80,100,103,126,127],"131":[7,8,37,52,80,100,103,126,127],"133":[7,8,37,52,80,100,103,126,127],"137":[7,8,37,52,80,100,103,126,127],"145":[7,8,37,52,80,100,103,126,127],"152":[7,8,37,52,100,126,127],"167":[7,8,37,52,80,100,103,126,127],"169":[8,126],"183":[8,126],"186":[7,8,37,52,80,100,103,126,127],"193":[1,2,3,4,7,8,9,11,12,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,66,67,74,75,76,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140],"201":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"210":[1,2,3,4,7,8,9,11,12,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,66,67,74,75,76,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140],"231":[126],"250":[1,2,27,61,65,75,110,118,120,122,124,125,128,129,131],"253":[1,2,27,61,65,75,110,118,120,122,124,125,128,129,131],"259":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"260":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"262":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"274":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"296":[7,8,37,52,100,126,127],"297":[7,8,37,52,80,100,103,126,127],"305":[126],"317":[126],"335":[7,8,37,52,80,100,103,126,127],"355":[8,126],"376":[8,126]},"packages/frontend/editor-ui/src/features/ndv/panel/components/OutputPanel.vue":{"36":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"86":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"91":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"117":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"121":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"127":[1,2,3,4,7,8,9,11,12,21,22,23,24,27,28,37,38,52,53,55,57,58,60,61,62,65,67,74,75,76,79,80,81,82,83,84,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,124,125,126,127,128,129,130,131,132,133,134,136,138,140,144],"131":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"148":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"157":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"161":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"169":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"171":[1,2,9,11,27,49,60,61,62,65,66,67,75,85,110,113,114,117,118,120,122,123,124,125,127,128,129,131,134,135],"189":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"207":[1,2,9,11,27,49,60,61,62,65,66,67,75,85,110,113,114,117,118,120,122,123,124,125,127,128,129,131,134,135],"215":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"219":[1,2,3,4,7,8,9,11,12,21,22,23,24,27,28,37,38,52,53,55,57,58,60,61,62,65,67,74,75,76,79,80,81,82,83,84,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,124,125,126,127,128,129,130,131,132,133,134,136,138,140,144],"223":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"246":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"267":[125],"271":[125],"290":[9,125,128,134],"295":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"308":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"314":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"345":[9,11,12,14,27,60,61,62,65,66,67,75,85,110,111,113,114,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135],"346":[120,123,125,128],"347":[123,125],"348":[111,114,125,128],"351":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"377":[1,2,3,4,7,8,9,11,12,21,22,23,24,27,28,37,38,52,53,55,57,58,60,61,62,65,67,74,75,76,79,80,81,82,83,84,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,124,125,126,127,128,129,130,131,132,133,134,136,138,140,144],"400":[1,3,7,8,12,21,24,37,53,60,65,67,76,100,104,109,111,114,118,119,120,121,122,124,126,129,130,132,133,140,144],"408":[1,2,3,4,7,8,9,11,12,21,22,23,24,27,28,37,38,52,53,55,57,58,60,61,62,67,74,75,76,79,80,81,82,83,84,96,98,100,103,104,105,109,110,111,113,116,117,118,119,120,121,122,124,125,126,127,128,129,130,131,132,133,134,136,138,140],"410":[1,2,3,4,7,8,9,11,12,21,22,23,24,27,28,37,38,52,53,55,57,58,60,61,62,65,67,74,75,76,79,80,81,82,83,84,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,124,125,126,127,128,129,130,131,132,133,134,136,138,140,144],"421":[7,8,37,52,55,62,79,80,82,117,126,127,128],"459":[1,2,3,4,7,8,9,11,12,21,22,23,24,27,28,37,38,52,53,55,57,58,60,61,62,65,67,74,75,76,80,81,82,83,84,96,98,100,103,104,105,109,110,111,113,114,116,118,119,120,121,122,124,125,126,127,128,129,130,131,132,133,134,136,138,140,144],"493":[117],"495":[117],"499":[9],"538":[9,117,125,128,134]},"packages/frontend/editor-ui/src/features/ndv/panel/components/PanelDragButtonV2.vue":{"11":[1,2,3,4,7,8,9,11,12,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,66,67,68,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"17":[68],"21":[68],"25":[68],"27":[1,2,3,4,7,8,9,11,12,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,66,67,68,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144]},"packages/frontend/editor-ui/src/features/ndv/panel/composables/useNdvLayout.ts":{"21":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"29":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"35":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"37":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,68,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"41":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"45":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"46":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,68,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"51":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"53":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"75":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"102":[68],"106":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"119":[68],"123":[68],"157":[68],"175":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,68,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"182":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/Collection/CollectionParameter.vue":{"9":[1,3,4,7,8,9,11,12,14,21,22,24,27,34,37,38,49,52,53,55,57,60,61,62,66,67,76,79,80,81,82,83,85,90,91,100,103,104,105,106,109,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,132,133,134,135,136,138,144],"25":[1,3,4,7,8,9,11,12,14,21,22,24,27,34,38,52,53,55,57,60,61,62,66,67,76,79,80,81,82,83,85,90,91,100,104,105,106,111,114,116,117,118,119,120,121,122,123,124,125,126,127,128,132,134,135,136,138,144],"34":[60,67]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/Collection/CollectionParameterLegacy.vue":{"24":[1,3,4,7,8,9,11,12,14,21,22,24,27,34,37,38,49,52,53,55,57,60,61,62,66,67,76,79,80,81,82,83,85,90,91,100,103,104,105,106,109,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,132,133,134,135,136,138,144],"44":[1,3,4,7,8,9,11,12,21,22,24,27,34,37,38,49,52,53,55,57,60,61,62,66,67,76,79,80,81,82,83,85,90,91,100,103,104,105,106,109,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,132,133,135,136,138,144],"48":[1,3,4,7,8,9,11,12,21,22,24,27,34,37,38,49,52,53,55,57,60,61,62,66,67,76,79,80,81,82,83,85,90,91,100,103,104,105,106,109,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,132,133,135,136,138,144],"55":[1,3,4,7,8,9,11,12,21,22,24,27,34,37,38,49,52,53,55,57,60,61,62,66,67,76,79,80,81,82,83,85,90,91,100,103,104,105,106,109,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,132,133,138,144],"61":[1,3,4,7,8,9,11,12,21,22,24,27,34,37,38,49,52,53,55,57,60,61,62,66,67,76,79,80,81,82,83,85,90,91,100,103,104,105,106,109,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,132,133,138,144],"73":[1,3,4,7,8,9,11,12,14,21,22,24,27,34,37,38,49,52,53,55,57,60,61,62,66,67,76,79,80,81,82,83,85,90,91,100,103,104,105,106,109,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,132,133,134,135,136,138,144],"89":[4,27,60,67,76,125,134],"93":[4,27,60,67,76,125,134],"110":[1,3,4,7,8,9,11,12,14,21,22,24,27,34,37,38,49,52,53,55,57,60,61,62,66,67,76,79,80,81,82,83,85,90,91,100,103,104,105,106,109,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,132,133,134,135,136,138,144],"112":[1,3,4,7,8,9,11,12,14,21,22,24,27,34,37,38,49,52,53,55,57,60,61,62,66,67,76,79,80,81,82,83,85,90,91,100,103,104,105,106,109,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,132,133,134,135,136,138,144],"113":[4,27,60,67,76,125,134],"116":[4,27,60,67,76,125,134],"118":[4,27,60,67,76,125,134],"129":[1,3,4,7,8,9,11,12,14,21,22,24,27,34,37,38,49,52,53,55,57,60,61,62,66,67,76,79,80,81,82,83,85,90,91,100,103,104,105,106,109,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,132,133,134,135,136,138,144],"131":[1,3,4,7,8,9,11,12,14,21,22,24,27,34,37,38,49,52,53,55,57,60,61,62,66,67,76,79,80,81,82,83,85,90,91,100,103,104,105,106,109,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,132,133,134,135,136,138,144],"143":[1,3,4,7,8,9,11,12,14,21,22,24,27,34,37,38,49,52,53,55,57,60,61,62,66,67,76,79,80,81,82,83,85,90,91,100,103,104,105,106,109,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,132,133,134,135,136,138,144],"144":[1,3,4,7,8,9,11,12,14,21,22,24,27,34,37,38,49,52,53,55,57,60,61,62,66,67,76,79,80,81,82,83,85,90,91,100,103,104,105,106,109,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,132,133,134,135,136,138,144],"147":[60,67],"201":[60,67],"203":[1,3,4,7,8,9,11,12,14,21,22,24,27,34,37,38,49,52,53,55,57,60,61,62,66,67,76,79,80,81,82,83,85,90,91,100,103,104,105,106,109,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,132,133,134,135,136,138,144],"210":[1,3,7,8,9,11,12,14,21,22,24,34,37,38,49,52,53,55,57,60,61,62,66,67,76,79,80,81,82,83,85,90,91,100,103,104,105,106,109,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,132,133,135,136,138,144],"243":[1,3,4,7,8,9,11,12,21,22,24,27,34,37,38,49,52,53,55,57,60,61,62,66,67,76,79,80,81,82,83,85,90,91,100,103,104,105,106,109,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,132,133,138,144],"246":[1,3,4,7,8,9,11,12,21,22,24,27,34,38,52,53,55,57,60,61,62,66,67,76,79,80,81,82,83,85,90,91,100,104,105,106,111,114,116,117,118,119,120,121,122,123,124,125,126,127,128,132,138,144]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/ExpressionEditModal.vue":{"38":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,30,33,34,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,90,91,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145],"78":[121],"80":[121],"85":[121],"99":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,30,33,34,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,90,91,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145],"100":[121],"136":[121],"141":[121],"156":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,30,33,34,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,90,91,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145],"165":[121],"177":[121],"185":[121],"206":[121],"216":[121],"239":[121]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/ExpressionEditorModal/theme.ts":{"4":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,30,33,34,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,90,91,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145],"33":[121],"39":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,30,33,34,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,90,91,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/FilterConditions/constants.ts":{"299":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"305":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"311":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"317":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"323":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"329":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/FixedCollection/FixedCollectionParameterLegacy.vue":{"66":[1,3,4,7,8,11,12,22,23,24,27,37,53,55,60,65,76,96,98,100,104,109,118,119,120,121,122,123,124,125,126,127,128,129,132,133,140],"71":[1,3,4,7,11,12,22,24,27,53,60,65,67,76,100,104,109,118,119,120,121,122,124,125,127,128,129,132,133,140],"73":[1,3,4,7,11,12,22,24,27,53,60,65,67,76,100,104,109,118,119,120,121,122,124,125,127,128,129,132,133,140],"76":[1,3,4,7,11,12,22,24,27,53,60,65,67,76,100,104,109,118,119,120,121,122,124,125,127,128,129,132,133,140],"80":[1,3,4,7,8,11,12,22,23,24,27,37,53,55,60,65,67,76,96,98,100,104,109,118,119,120,121,122,123,124,125,126,127,128,129,132,133,140],"81":[8,11,12,23,37,55,60,96,98,120,123,124,125,126,127,128,140],"82":[1,3,4,7,11,12,22,24,27,53,60,65,76,100,104,109,118,119,120,121,122,124,125,127,128,129,132,133,140],"83":[1,3,4,7,11,12,22,24,27,53,60,65,67,76,100,104,109,118,119,120,121,122,124,125,127,128,129,132,133,140],"85":[1,3,4,7,8,11,12,22,23,24,27,37,53,55,60,65,76,96,98,100,104,109,118,119,120,121,122,123,124,125,126,127,128,129,132,133,140],"92":[1,3,4,7,8,11,12,22,23,24,27,37,53,55,60,65,67,76,96,98,100,104,109,118,119,120,121,122,123,124,125,126,127,128,129,132,133,140],"94":[1,3,4,7,8,11,12,22,23,24,27,37,53,55,60,65,67,76,96,98,100,104,109,118,119,120,121,122,123,124,125,126,127,128,129,132,133,140],"105":[1,3,4,7,8,11,12,22,23,24,27,37,53,55,60,65,67,76,96,98,100,104,109,118,119,120,121,122,123,124,125,126,127,128,129,132,133,140],"108":[55,60,67],"111":[1,3,4,7,8,11,12,22,23,24,27,37,53,55,60,65,67,76,96,98,100,104,109,118,119,120,121,122,123,124,125,126,127,128,129,132,133,140],"115":[12,60],"122":[12,60],"126":[12,60],"140":[1,3,4,7,8,11,12,22,23,24,27,37,53,55,60,65,67,76,96,98,100,104,109,118,119,120,121,122,123,124,125,126,127,128,129,132,133,140],"155":[12,60],"160":[12,60],"191":[12,60],"196":[1,3,4,7,11,12,22,24,27,53,60,65,67,76,100,104,109,118,119,120,121,122,124,125,127,128,129,132,133,140],"207":[12,60],"232":[1,3,4,7,11,12,22,24,27,53,60,65,67,76,100,104,109,118,119,120,121,122,124,125,127,128,129,132,133,140],"242":[12,60],"263":[60],"276":[60],"299":[1,3,4,7,8,11,12,22,23,24,27,37,53,55,60,65,67,76,96,98,100,104,109,118,119,120,121,122,123,124,125,126,127,128,129,132,133,140],"300":[4,11,12,23,27,37,60,67,104,119,120,126,127],"307":[1,3,4,7,8,11,12,22,23,24,27,37,53,55,60,65,67,76,96,98,100,104,109,118,119,120,121,122,123,124,125,126,127,128,129,132,133,140],"339":[11,12,60,104,120,127],"362":[11,12,60,104,120,127],"368":[11,12,60,104,120,127],"382":[11,12,60,104,120,127],"389":[11,12,60,67,104,119,120],"421":[1,3,4,7,11,12,22,24,27,53,60,65,76,100,104,109,118,119,120,121,122,124,125,127,128,129,132,133,140],"423":[1,3,4,7,8,11,12,22,23,24,27,37,53,55,60,65,67,76,96,98,100,104,109,118,119,120,121,122,123,124,125,126,127,128,129,132,133,140],"439":[1,3,4,7,11,12,22,24,27,53,60,65,67,76,100,104,109,118,119,120,121,122,124,125,127,128,129,132,133,140],"461":[1,3,4,7,11,12,22,24,27,53,60,65,76,100,104,109,118,119,120,121,122,124,125,127,128,129,132,133,140],"531":[60],"532":[12,60],"636":[11,12,60,104,120,127],"644":[120,124,125,128]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/ParameterInput.vue":{"145":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,30,33,34,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,90,91,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145],"236":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,30,33,34,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,90,91,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145],"242":[21,124,127],"246":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,30,33,34,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,90,91,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145],"252":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,30,33,34,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,90,91,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145],"256":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,30,33,34,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,90,91,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145],"258":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,30,33,34,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,90,91,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145],"262":[1,2,3,4,5,7,8,9,11,12,21,22,23,24,27,28,30,33,34,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,90,91,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145],"266":[4,7,8,11,12,23,24,27,30,37,38,39,51,60,61,62,67,80,89,90,91,97,98,113,120,124,127,130,131,145],"280":[9,22,57,105,127,134],"296":[9,22,57,105,127,134],"300":[9,22,57,105,127,134],"308":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,30,33,34,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,90,91,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145],"312":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,30,33,34,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,90,91,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145],"319":[2,7,9,21,22,28,57,84,103,104,105,109,110,111,124,127,134],"328":[3,7,8,23,37,53,55,80,96,98,100,117,124,126,127,130,135,136,140],"332":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,30,33,34,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,90,91,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145],"356":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,30,33,34,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,90,91,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145],"370":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,30,33,34,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,90,91,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145],"373":[2,7,21,28,84,103,104,105,109,110,124],"377":[2,21,28,84,103,104,105,109,110,124],"385":[2,21,28,84,103,104,105,109,110,124],"389":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,30,33,34,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,90,91,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145],"463":[1,3,7,8,23,37,52,53,55,66,74,76,80,81,85,89,96,98,100,103,114,117,119,120,121,122,124,126,127,128,129,130,131,135,136,140],"478":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,30,33,34,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,90,91,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145],"511":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,30,33,34,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,90,91,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145],"528":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,30,33,34,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,90,91,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145],"568":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,34,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,90,91,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"599":[135,136],"618":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,30,33,34,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,90,91,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145],"632":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,30,33,34,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,90,91,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145],"639":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,30,33,34,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,90,91,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145],"647":[34,37,51,79,126],"651":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,30,33,34,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,90,91,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145],"678":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,30,33,34,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,90,91,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145],"697":[2,21,28,84,103,104,105,109,110,124],"701":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,30,33,34,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,90,91,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145],"705":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,30,33,34,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,90,91,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145],"709":[2,21,28,84,103,104,105,109,110,124],"713":[111],"715":[4,7,8,11,12,23,24,27,30,34,37,38,39,51,55,58,60,61,62,67,75,80,89,90,91,97,98,106,110,113,119,120,121,122,124,127,128,129,130,131,145],"716":[11,24,34,37,38,55,58,60,67,75,90,110,119,120,121,127,128,131],"718":[75,113,120],"719":[4,7,8,11,12,23,24,27,30,37,38,39,51,60,61,62,67,75,80,89,90,91,97,98,106,113,119,120,121,124,127,130,131,145],"726":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,30,33,34,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,90,91,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145],"738":[7,124],"740":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,30,33,34,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,90,91,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145],"749":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,30,33,34,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,90,91,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145],"753":[22,37,38],"767":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,30,33,34,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,90,91,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145],"781":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,30,33,34,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,90,91,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145],"789":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,30,33,34,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145],"797":[21,124,127,130],"849":[124],"854":[124],"859":[121],"863":[121],"893":[124],"905":[121],"920":[4,7,8,11,12,23,24,27,30,34,37,38,39,51,55,58,60,61,62,67,75,80,89,90,91,97,98,106,110,113,119,120,121,122,124,127,128,129,130,131,136,145],"928":[4,7,8,11,12,23,24,27,30,34,37,38,39,51,55,58,60,61,62,67,75,80,89,90,91,97,98,106,110,113,119,120,121,122,124,127,128,129,130,131,136,145],"989":[4,7,8,11,12,23,24,27,30,37,38,39,51,60,61,62,67,75,80,89,90,91,97,98,113,120,124,127,130,131,145],"1012":[2,4,7,8,11,12,21,23,24,27,28,30,34,37,38,39,51,55,58,60,61,62,67,75,80,84,89,90,91,97,98,103,104,105,109,110,111,113,119,120,121,122,124,127,129,130,131,135,136,145],"1099":[89,119,120,121,122,127,129,130,131],"1106":[4,7,8,11,12,23,24,27,30,34,37,38,39,51,55,60,61,62,67,75,80,89,90,91,97,98,106,110,113,119,120,121,122,124,127,130,131,136,145],"1173":[4,7,8,11,12,23,24,27,30,37,38,39,51,60,61,62,67,75,80,89,90,91,97,98,113,120,124,127,130,131,145],"1180":[89,119,120,121,122,127,129,130,131,136],"1260":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,30,33,34,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,90,91,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145],"1294":[34,37,51,79,126],"1323":[1,3,4,7,8,9,11,12,21,22,23,28,30,33,34,37,38,51,52,53,55,57,60,62,65,67,76,79,80,81,82,83,84,89,91,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,135,138,140,144,145],"1329":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,30,33,34,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,90,91,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145],"1330":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,30,33,34,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,90,91,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145],"1348":[124,127,130],"1354":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,30,33,34,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,90,91,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145],"1355":[2,3,4,7,8,11,12,21,23,24,27,28,30,33,34,37,38,39,51,58,60,61,62,67,75,80,89,90,91,97,98,103,104,105,109,110,111,113,119,120,121,122,124,126,127,129,130,131,135,136,145],"1365":[21,124,127],"1370":[89,119,120,121,122,126,127,129,130,131,136],"1380":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,30,33,34,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,90,91,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145],"1383":[24,37],"1399":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,30,33,34,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,90,91,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145],"1412":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,30,33,34,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,90,91,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145],"1418":[75,90,111,119,120,122,124,127,129,130,131],"1541":[124],"1625":[2,21,28,84,103,104,105,109,110,124],"1630":[124],"1650":[111],"1695":[111],"1718":[7,124],"1741":[9,22,57,105,127,134],"1770":[4,7,8,11,12,23,24,27,30,37,38,39,51,60,61,62,67,80,89,90,91,97,98,113,120,124,127,130,131,145],"1788":[4,90,120,124,127],"1793":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,30,33,34,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,90,91,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145],"1904":[22,37,38],"1925":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,30,33,34,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,90,91,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145],"1927":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,30,33,34,38,39,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,90,91,96,97,98,100,104,105,106,110,111,114,116,117,118,119,120,121,122,123,124,125,126,127,128,131,132,134,135,136,138,140,144,145],"1932":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,30,33,34,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,90,91,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145],"1964":[21,53,130],"1966":[21,53],"1970":[21,53,130]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/ParameterInputExpanded.vue":{"24":[3,7,8,23,30,33,37,38,39,51,58,80,89,97,98,127,130,145],"61":[3,7,8,23,30,33,37,38,39,51,58,80,89,97,98,127,130,145],"92":[3,7,8,23,30,33,37,38,39,51,58,80,89,97,98,127,130,145],"114":[3,7,8,23,30,33,37,38,39,51,58,80,89,97,98,127,130,145],"122":[3,7,8,23,30,33,37,38,39,51,58,80,89,97,98,127,130,145],"129":[7,8,23,30,37,38,39,51,80,89,97,98,127,130,145],"133":[7,8,23,30,37,38,39,51,80,89,97,98,127,130,145],"142":[89],"146":[7,8,23,30,37,38,39,51,80,89,97,98,127,130,145],"169":[89],"171":[3,7,8,23,30,33,37,38,39,51,58,80,89,97,98,127,130,145],"184":[3,7,8,23,30,33,37,38,39,51,58,80,89,97,98,127,130,145],"194":[3,7,8,23,30,33,37,38,39,51,58,80,89,97,98,127,130,145]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/ParameterInputFull.vue":{"62":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,34,37,38,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,90,91,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"96":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,34,37,38,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,90,91,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"107":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,34,37,38,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,90,91,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"114":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,34,37,38,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,90,91,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"118":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,34,37,38,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,90,91,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"122":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,34,37,38,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,90,91,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"125":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,34,37,38,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,90,91,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"132":[1,3,4,5,7,8,9,11,12,21,22,24,27,34,37,38,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,85,90,100,103,104,105,106,109,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"134":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,34,37,38,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,90,91,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"143":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,34,37,38,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,90,91,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"161":[4,11,12,24,27,34,37,38,51,55,58,60,61,62,67,75,90,91,106,110,113,119,120,121,122,124,127,128,129,130,131,136],"169":[4,11,12,24,27,34,37,38,51,55,60,61,62,67,75,90,91,106,110,113,119,120,121,122,124,127,130,131,136],"185":[1,3,5,7,8,11,12,14,21,22,23,24,27,28,34,37,38,51,52,55,58,60,61,62,67,76,80,83,90,103,104,105,109,110,111,113,114,117,118,119,120,121,122,124,125,126,127,128,129,130,131,134,136],"189":[1,3,7,8,11,12,14,21,22,23,24,27,28,34,37,38,51,52,55,58,60,61,62,67,76,80,83,90,103,104,105,109,110,111,113,114,117,118,119,120,121,122,124,125,126,127,128,129,130,131,134,136],"193":[119,121,122,127,129,130,131,136],"200":[2,4,7,8,11,12,21,24,27,28,34,37,38,51,58,60,61,62,67,75,84,90,91,103,104,105,109,110,111,113,119,120,121,122,124,127,129,130,131,135,136],"204":[4,11,12,24,27,38,51,60,61,62,67,75,90,91,113,120,124,127,131],"210":[120],"218":[120],"289":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,34,37,38,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,90,91,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"294":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,34,37,38,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,90,91,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"295":[131],"304":[1,3,5,7,8,11,12,14,21,22,23,24,27,28,34,37,38,51,52,55,58,60,61,62,67,76,80,83,90,103,104,105,109,110,111,113,114,117,118,119,120,121,122,124,125,126,127,128,129,130,131,134,136],"309":[34,37,51,79,126],"313":[34],"350":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,34,37,38,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,90,91,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"435":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,34,37,38,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,90,91,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"439":[34,37,51,79,126],"452":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,34,37,38,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,90,91,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"473":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,34,37,38,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,90,91,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"506":[34,37,51,79,126]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/ParameterInputHint.vue":{"13":[1,3,7,8,53,65,66,67,76,80,85,89,100,104,109,111,114,117,118,119,120,121,122,124,126,127,128,129,130,131,133,140],"21":[1,3,7,8,53,65,66,67,76,80,85,89,100,104,109,111,114,117,118,119,120,121,122,124,126,127,128,129,130,131,133,140],"23":[76],"27":[1,66,76,85,89,114,117,119,120,121,122,124,127,128,129,130,131],"39":[1,3,7,8,53,65,66,67,76,80,85,89,100,104,109,111,114,117,118,119,120,121,122,124,126,127,128,129,130,131,133,140],"43":[1,3,7,8,53,65,66,67,76,80,85,89,100,104,109,111,114,117,118,119,120,121,122,124,126,127,128,129,130,131,133,140]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/ParameterInputList.vue":{"65":[1,3,4,7,8,11,12,22,23,24,27,37,53,55,60,65,67,76,96,98,100,104,109,118,119,120,121,122,123,124,125,126,127,128,129,132,133,140],"68":[1,3,4,7,8,9,11,12,14,21,22,24,27,34,37,38,49,52,53,55,57,60,61,62,66,67,76,79,80,81,82,83,85,90,91,100,103,104,105,106,109,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,132,133,134,135,136,138,144],"123":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,34,37,38,49,52,53,55,57,60,61,62,65,66,67,76,79,80,81,82,83,84,85,90,91,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,132,133,134,135,136,138,140,144],"144":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,34,37,38,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,90,91,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"146":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,34,37,38,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,90,91,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"175":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,34,37,38,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,90,91,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"188":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,34,37,38,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,90,91,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"194":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,34,37,38,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,90,91,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"195":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,34,37,38,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,90,91,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"217":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,34,37,38,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,90,91,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"241":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,34,37,38,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,90,91,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"268":[1,2,9,27,34,51,60,67,81,84,91,110,111,119,124,125,126,127,129,131,136],"269":[1,2,9,27,34,51,60,67,81,84,91,110,111,119,124,125,126,127,129,131,136],"275":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,34,37,38,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,90,91,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"276":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,34,37,38,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,90,91,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"279":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,34,37,38,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,90,91,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"280":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,34,37,38,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,90,91,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"283":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,34,37,38,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,90,91,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"300":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,34,37,38,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,90,91,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"309":[12,60],"312":[12,60],"335":[12,60],"353":[11],"356":[11],"391":[12,60],"394":[12,60],"398":[12,60],"403":[4,11,12,24,27,34,37,38,51,55,60,61,67,75,90,91,110,113,119,120,121,124,127,130,131,136],"407":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,34,37,38,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,90,91,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"414":[3,4,5,8,11,12,14,21,22,23,24,27,37,38,51,53,55,60,61,67,76,83,96,98,103,113,114,117,118,124,126,127,128,129,130,132,140,144],"421":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,34,37,38,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,90,91,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"425":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,34,37,38,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,90,91,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"440":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,34,37,38,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,90,91,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"447":[7,8],"462":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,34,37,38,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,90,91,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"479":[2,4,7,8,11,12,21,24,27,28,34,37,38,51,58,60,61,62,67,75,84,90,91,103,104,105,109,110,111,113,118,119,120,121,122,124,127,129,130,131,135,136],"489":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,34,37,38,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,90,91,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"504":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,34,37,38,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,90,91,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"508":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,34,37,38,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,90,91,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"536":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,34,37,38,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,90,91,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"542":[7,8,37,52,80,103,126,127],"546":[7,8,37,52,80,103,126,127],"556":[3,12,21,23,34,37,53,55,57,60,67,74,76,79,96,98,100,105,111,119,121,124,125,127,128,129,130,131,132,140],"561":[23,34,37,96,98,127,130],"643":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,34,37,38,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,90,91,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"666":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,34,37,38,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,90,91,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"725":[7,8,37,52,80,103,126,127],"740":[127],"746":[7,8,37,52,80,103,126,127],"798":[1,3,4,7,8,9,11,12,14,21,22,23,24,27,34,37,38,49,52,53,55,57,60,61,62,65,66,67,76,79,80,81,82,83,85,90,91,96,98,100,103,104,105,106,109,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,132,133,134,135,136,138,140,144],"821":[1,3,4,7,8,9,11,12,14,21,22,23,24,27,34,37,38,49,52,53,55,57,60,61,62,65,66,67,76,79,80,81,82,83,85,90,91,96,98,100,103,104,105,106,109,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,132,133,134,135,136,138,140,144],"823":[1,3,4,7,8,9,11,12,14,21,22,23,24,27,34,38,52,53,55,57,60,61,62,65,66,67,76,79,80,81,82,83,85,90,91,96,98,100,104,105,106,111,114,116,117,118,119,120,121,122,123,124,125,126,127,128,132,134,135,136,138,140,144],"943":[4,11,12,24,27,34,37,38,51,55,60,61,67,75,90,91,110,113,119,120,121,124,127,130,131,136]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/ParameterInputWrapper.vue":{"50":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,30,33,34,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,90,91,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145],"70":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,30,33,34,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,90,91,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145],"74":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,30,33,34,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,90,91,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145],"85":[3,7,8,23,37,53,55,80,96,98,100,117,124,126,127,130,140],"91":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,30,33,34,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,90,91,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145],"102":[76,89,119,120,121,124,128,130,131],"104":[128],"106":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,30,33,34,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,90,91,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145],"111":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,30,33,34,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,90,91,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145],"128":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,30,33,34,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,90,91,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145],"132":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,30,33,34,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,90,91,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145],"139":[4,7,8,11,12,23,24,27,30,34,37,38,39,51,55,58,60,61,62,67,75,80,89,90,91,97,98,106,110,113,119,120,121,122,124,127,128,129,130,131,136,145],"143":[4,7,8,11,12,23,24,27,30,34,37,38,39,51,55,60,61,62,67,75,80,89,90,91,97,98,106,110,113,119,120,121,122,124,127,130,131,136,145],"151":[2,4,7,8,11,12,21,23,24,27,28,30,34,37,38,39,51,58,60,61,62,67,75,80,84,89,90,91,97,98,103,104,105,109,110,111,113,119,120,121,122,124,127,129,130,131,135,136,145],"155":[4,7,8,11,12,23,24,27,30,37,38,39,51,60,61,62,67,75,80,89,90,91,97,98,113,120,124,127,130,131,145],"160":[34,37,51,79,126],"161":[89],"168":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,30,33,34,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,90,91,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145],"175":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,30,33,34,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,90,91,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145],"206":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,30,33,34,38,39,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,90,91,96,97,98,100,104,105,106,110,111,114,116,117,118,119,120,121,122,123,124,125,126,127,128,131,132,134,135,136,138,140,144,145]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/ParameterOptions.vue":{"40":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,30,33,34,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,90,91,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145],"61":[1,2,3,4,5,7,8,9,11,12,21,22,23,24,27,28,30,33,34,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,90,91,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145],"62":[1,2,3,4,5,7,8,9,11,12,21,22,23,24,27,28,30,33,34,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,90,91,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145],"63":[1,3,4,7,8,9,11,12,21,22,23,24,27,30,33,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,85,89,90,96,97,98,100,103,104,105,106,109,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145],"64":[1,2,3,4,5,7,8,9,11,12,21,22,23,24,27,28,30,33,34,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,90,91,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145],"67":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,30,33,34,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,90,91,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145],"77":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,30,33,34,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,90,91,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145],"96":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,30,33,34,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,90,91,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145],"115":[1,3,4,7,8,9,11,12,21,22,23,24,27,30,33,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,85,89,90,96,97,98,100,103,104,105,106,109,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145],"116":[1,2,3,4,5,7,8,9,11,12,21,22,23,24,27,28,30,33,34,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,90,91,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145],"120":[1,2,3,4,5,7,8,9,11,12,21,22,23,24,27,28,30,33,34,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,90,91,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145],"128":[1,2,3,4,5,7,8,9,11,12,21,22,23,24,27,28,30,33,34,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,90,91,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145],"173":[131],"174":[89,119,121,122,127,129,130,131,136],"181":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,30,33,34,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,90,91,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145],"189":[131],"215":[131]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/ResourceLocator/ResourceLocator.vue":{"76":[3,7,8,23,37,53,55,80,96,98,100,117,124,126,127,130,140],"166":[127,130],"175":[3,7,8,23,37,53,55,80,96,98,100,117,124,126,127,130,140],"188":[3,7,8,23,37,53,55,80,96,98,100,117,124,126,127,130,140],"195":[124,130],"198":[124,130],"207":[124,130],"220":[3,7,8,23,37,53,55,80,96,98,100,117,124,126,127,130,140],"233":[3,7,8,23,37,53,55,80,96,98,100,117,124,126,127,130,140],"237":[3,7,8,23,37,53,55,80,96,98,100,117,124,126,127,130,140],"241":[3,7,8,23,37,53,55,80,96,98,100,117,124,126,127,130,140],"242":[3,7,8,23,37,53,55,80,96,98,100,117,124,126,127,130,140],"254":[3,7,8,23,37,53,55,80,96,98,100,117,124,126,127,130,140],"290":[3,7,8,23,37,53,55,80,96,98,100,117,124,126,127,130,140],"300":[3,7,8,23,37,53,55,80,96,98,100,117,124,126,127,130,140],"302":[3,7,8,23,37,53,55,80,96,98,100,117,124,126,127,130,140],"315":[3,7,8,23,37,53,55,80,96,98,100,117,124,126,127,130,140],"317":[3,7,8,23,37,53,55,80,96,98,100,117,124,126,127,130,140],"320":[130],"328":[3,7,8,23,37,53,55,80,96,98,100,117,124,126,127,130,140],"330":[3,7,8,23,37,53,55,80,96,98,100,117,124,126,127,130,140],"337":[3,7,8,23,37,53,55,80,96,98,100,117,124,126,127,130,140],"341":[3,7,8,23,37,53,55,80,96,98,100,117,124,126,127,130,140],"342":[3,7,8,23,37,53,55,80,96,98,100,117,124,126,127,130,140],"343":[3,7,8,23,37,53,55,80,96,98,100,117,124,126,127,130,140],"346":[124,130],"350":[3,7,8,23,37,53,55,80,96,98,100,117,124,126,127,130,140],"364":[3,7,8,23,37,53,55,80,96,98,100,117,124,126,127,130,140],"370":[3,7,8,23,37,53,55,80,96,98,100,117,124,126,127,130,140],"376":[3,7,8,23,37,53,55,80,96,98,100,117,124,126,127,130,140],"380":[3,7,8,23,37,53,55,80,96,98,100,117,124,126,127,130,140],"467":[3,7,8,23,37,53,55,80,96,98,100,117,124,126,127,130,140],"473":[124,130],"481":[3,7,8,23,37,53,55,80,96,98,100,117,124,126,127,130,140],"492":[126,127,130],"502":[124,130],"522":[3,7,8,23,37,53,55,80,96,98,100,117,124,126,127,130,140],"523":[124,127,130],"543":[3,7,8,23,37,53,55,80,96,98,100,117,124,126,127,130,140],"544":[7,8,23,37,80,127,130],"565":[3,7,8,23,37,53,55,80,96,98,100,117,124,126,127,130,140],"569":[3,7,8,23,37,53,55,80,96,98,100,117,124,126,127,130,140],"574":[3,7,8,23,37,53,55,80,96,98,100,117,124,126,127,130,140],"579":[7,8,53,55,80,100,117,124,126,127,140],"589":[3,7,8,23,37,53,55,80,96,98,100,117,124,126,127,130,140],"595":[127,130],"622":[3,7,8,23,37,53,55,80,96,98,100,117,124,126,127,130,140],"645":[130],"665":[3,7,8,23,37,53,55,80,96,98,100,117,124,126,127,130,140],"667":[3,7,8,23,37,53,55,80,96,98,100,117,124,126,127,130,140],"672":[3,7,8,23,37,53,55,80,96,98,100,117,124,126,127,130,140],"680":[127,130],"697":[130],"703":[130],"709":[127,130],"728":[127,130],"750":[124,130],"757":[130],"769":[124,130],"780":[124,130],"897":[130],"910":[130],"918":[124,127,130],"943":[3,7,8,23,37,55,80,96,98,100,117,124,126,127,130,140],"951":[124,130],"957":[124,130],"970":[124,127,130],"1013":[3,7,8,23,37,53,55,80,96,98,100,117,124,126,127,130,140],"1043":[124,130],"1050":[124,130],"1055":[130],"1083":[3,7,8,23,37,53,55,80,96,98,100,117,124,126,127,130,140],"1103":[3,7,8,23,37,53,55,80,96,98,100,117,124,126,127,130,140],"1105":[3,7,8,23,53,55,80,96,98,100,117,124,126,127,140],"1112":[3,7,8,23,53,55,80,96,98,100,117,124,126,127,140],"1134":[3,7,8,23,37,53,55,80,96,98,100,117,124,126,127,130,140],"1186":[3,7,8,37,53,55,80,100,117,124,126,127,130],"1210":[127,130]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/ResourceLocator/ResourceLocatorDropdown.vue":{"13":[3,7,8,23,37,53,55,80,96,98,100,117,124,126,127,130,135,136,140],"58":[130],"74":[130,136],"76":[130,136],"116":[3,7,8,23,37,53,55,80,96,98,100,117,124,126,127,130,135,136,140],"117":[124,130,136],"123":[124,130,136],"132":[3,7,8,23,37,53,55,80,96,98,100,117,124,126,127,130,135,136,140],"136":[7,8,53,55,80,100,117,124,126,127,135,140],"196":[136],"200":[136],"213":[136],"216":[136],"227":[136],"242":[127,130],"248":[3,7,8,23,37,53,55,80,96,98,100,117,124,126,127,130,135,136,140],"250":[3,7,8,23,37,53,55,80,96,98,100,117,124,126,127,130,135,136,140],"264":[3,7,8,23,37,53,55,80,96,98,100,117,124,126,127,130,135,136,140],"276":[3,7,8,23,37,53,55,80,96,98,100,117,124,126,127,130,135,136,140],"279":[124,130,136],"301":[130,136],"338":[136],"340":[136],"348":[130,136],"359":[136],"360":[136],"387":[130]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/TextEdit.vue":{"10":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,30,33,34,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,90,91,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145],"31":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,30,33,34,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,90,91,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145],"41":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,30,33,34,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,90,91,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145],"42":[2,3,4,7,8,11,12,21,23,24,27,28,30,33,37,38,39,51,58,60,61,62,67,80,89,90,91,97,98,103,104,105,109,110,111,113,120,124,126,127,130,131,145],"48":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,30,33,34,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,90,91,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145],"66":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,30,33,34,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,90,91,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145]},"packages/frontend/editor-ui/src/features/ndv/parameters/utils/fromAIOverride.utils.ts":{"38":[34],"79":[79],"86":[34,37,51,79,126],"102":[34],"113":[7,8,34,37,51,79,80,117,126,127,130,135,136],"117":[34],"128":[34],"134":[34],"149":[34],"174":[34,37,51,79,126],"196":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,34,37,38,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,90,91,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"205":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,34,37,38,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,90,91,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"209":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,34,37,38,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,90,91,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"227":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,34,37,38,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,90,91,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144]},"packages/frontend/editor-ui/src/features/ndv/runData/components/RunData.vue":{"103":[1,6,7,9,11,12,14,27,49,60,61,62,65,66,67,75,81,85,102,110,111,113,114,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135],"104":[79,114,117,120,125],"106":[1,2,9,11,27,49,61,62,66,74,75,79,82,83,85,104,106,110,111,113,114,116,117,118,119,120,121,122,123,124,125,127,128,129,131,132,134,135],"109":[7,117],"111":[1,2,6,7,9,11,12,14,27,49,60,61,62,65,66,67,74,75,79,81,82,85,102,104,106,110,111,113,114,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135],"262":[1,2,6,11,12,27,49,60,61,62,65,66,67,75,85,110,111,113,114,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135],"263":[1,2,3,4,6,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"264":[1,2,3,4,6,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,102,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"272":[75,79,111,113,114,116,117,119,120,121,122,123,124,125,128,129],"273":[1,2,3,4,6,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,102,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"279":[1,2,3,4,6,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,102,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"280":[1,2,7,9,11,27,49,61,62,66,74,75,79,82,85,104,106,110,111,113,114,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135],"282":[1,2,3,4,6,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,102,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"283":[1,2,9,11,12,14,27,49,60,61,62,65,66,67,74,75,79,82,85,104,110,111,113,114,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135],"284":[1,2,3,4,6,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,102,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"285":[1,2,3,4,6,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,102,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"286":[1,2,3,4,6,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,102,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"289":[1,2,3,4,7,8,9,11,12,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,66,67,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140],"293":[1,2,3,4,6,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,102,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"301":[1,2,7,9,11,27,49,61,62,66,74,75,79,82,83,85,104,106,110,111,113,114,116,117,118,119,120,121,122,123,124,125,127,128,129,131,132,134,135],"302":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"303":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"304":[1,11,12,14,27,49,60,61,62,65,66,67,75,85,110,111,113,114,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135],"312":[1,2,9,11,27,49,61,62,66,74,75,79,82,83,85,104,106,110,111,113,114,116,117,118,119,120,121,122,123,124,125,127,128,129,131,132,134,135],"322":[1,2,3,4,6,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,102,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"328":[1,2,3,4,6,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,102,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"332":[1,2,6,7,8,9,11,12,14,27,49,60,61,62,65,66,67,74,75,79,81,82,83,85,102,104,106,110,111,113,114,116,117,118,119,120,121,122,123,124,125,127,128,129,131,132,134,135],"336":[1,2,6,7,9,11,12,14,27,49,60,61,62,65,66,67,74,75,79,81,82,83,85,102,104,106,110,111,113,114,116,117,118,119,120,121,122,123,124,125,127,128,129,131,132,134,135],"345":[1,2,6,7,9,11,12,14,27,49,60,61,62,65,66,67,74,75,79,81,82,83,85,102,104,106,110,111,113,114,116,117,118,119,120,121,122,123,124,125,127,128,129,131,132,134,135],"349":[1,2,6,7,9,11,12,14,27,49,60,61,62,65,66,67,74,75,79,81,82,83,85,102,104,106,110,111,113,114,116,117,118,119,120,121,122,123,124,125,127,128,129,131,132,134,135],"359":[1,2,3,4,6,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,102,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"361":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"370":[1,2,3,4,6,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,102,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"379":[1,2,6,7,8,9,11,12,14,27,49,60,61,62,65,66,67,74,75,79,81,82,85,102,104,106,110,111,113,114,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135],"383":[1,2,3,4,6,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,102,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"388":[1,2,3,4,6,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,102,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"399":[1,2,3,4,6,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,102,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"405":[1,2,3,4,6,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,102,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"412":[1,2,3,4,6,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,102,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"422":[1,2,3,4,6,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,102,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"425":[1,2,3,4,6,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,102,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"435":[1,2,3,4,6,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,102,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"439":[1,2,3,4,6,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,102,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"443":[1,2,6,12,27,60,61,62,65,67,75,110,117,118,119,120,121,122,124,125,128,129,131,134],"447":[1,2,3,4,6,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,102,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"455":[1,2,3,4,6,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,102,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"458":[1,6,7,11,14,27,49,62,66,74,79,81,82,85,102,104,106,111,113,114,117,118,119,120,121,122,123,124,125,127,128,129,134,135],"459":[1,2,3,4,6,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,102,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"467":[1,6,7,9,11,12,14,27,49,60,61,62,65,66,67,75,81,85,102,110,111,113,114,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135],"468":[1,2,3,4,6,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,102,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"472":[1,2,3,4,6,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,102,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"477":[9,117,125,128,134],"487":[9,117,125,128,134],"493":[1,2,3,4,6,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,102,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"497":[1,2,3,4,6,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,102,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"498":[1,2,3,4,6,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,102,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"499":[1,2,3,4,6,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,102,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"503":[1,2,3,4,6,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,102,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"504":[1,2,3,4,6,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,102,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"514":[1,2,3,4,6,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,102,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"524":[7,9,62,117,123,124,125,128],"525":[7,9,62,117,123,124,125,128],"565":[1,2,3,4,6,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,102,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"569":[1,2,3,4,7,8,9,11,12,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"570":[1,2,3,4,6,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,102,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"576":[1,2,3,4,6,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,102,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"587":[1,2,6,7,9,11,12,14,27,49,60,61,62,65,66,67,74,75,79,81,82,83,85,102,104,106,110,111,113,114,116,117,118,119,120,121,122,123,124,125,127,128,129,131,132,134,135],"591":[1,2,3,4,6,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,102,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"603":[1,2,3,4,6,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,102,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"620":[1,2,3,4,6,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,102,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"625":[1,2,3,4,6,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,102,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"634":[1,11,12,14,27,49,60,61,62,65,66,67,75,85,110,111,113,114,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135],"638":[1,2,3,4,6,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,102,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"656":[9],"662":[1,2,3,4,6,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,102,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"665":[1,2,3,4,7,8,9,11,12,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140],"668":[1,2,3,4,6,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,102,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"670":[1,2,3,4,6,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,102,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"673":[66,76,83,111,116,118,125,129,132,134],"674":[66,76,83,111,116,118,125,129,132,134],"691":[1,2,3,4,6,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,102,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"698":[1,2,3,4,6,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,102,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"702":[1,2,3,4,6,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,102,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"703":[7,117],"706":[1,2,3,4,6,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,102,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"710":[117],"716":[1,2,6,27,60,67,110,111,117,119,120,124,125,126,127,128,129,131,136],"721":[1,2,6,7,8,9,12,27,60,61,62,65,67,75,81,110,111,117,118,119,120,121,122,124,125,128,129,131,134],"731":[1,2,3,4,6,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,102,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"736":[1,2,6,7,9,11,12,14,27,49,60,61,62,65,66,67,75,79,81,82,85,102,104,106,110,111,113,114,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135],"743":[1,2,6,7,8,9,12,27,37,52,60,61,62,65,67,75,79,80,81,110,111,113,117,118,119,120,121,122,123,124,125,126,127,128,129,131,134,136],"752":[1,2,6,7,8,9,12,27,60,61,62,65,67,75,81,110,111,117,118,119,120,121,122,123,124,125,126,127,128,129,131,134,136],"760":[1,2,117,124,128],"767":[123,125],"773":[1,2,3,4,6,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,102,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"782":[1,2,3,4,6,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,102,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"803":[113,117],"814":[1,3,4,6,7,8,9,11,12,21,22,28,37,38,52,53,55,57,60,62,65,67,76,79,80,81,82,83,84,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,131,132,133,135,138,140,144],"819":[1,2,3,4,6,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,102,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"835":[55,74,76,82,114,125,132,136],"862":[1,2,3,4,6,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,102,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"901":[120,123,125,128],"923":[1,2,3,4,6,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,102,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"939":[1,2,6,60,61,67,75,110,111,118,119,120,121,122,123,124,129,131],"947":[1,3,4,6,7,8,9,11,12,21,22,28,37,38,52,53,55,57,60,62,65,67,76,79,80,81,82,83,84,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,131,132,133,135,138,140,144],"955":[1,2,6,12,27,60,61,65,67,75,110,111,113,117,118,119,120,121,122,123,124,129,131],"960":[111,116,119,120,121,122,128,129],"996":[111,116,119,120,121,122,128,129],"1020":[111,119,120,121,122,128,129],"1047":[111,119,120,121,122,128,129],"1057":[113,129],"1111":[128],"1135":[9,125],"1143":[9,125],"1147":[9,125],"1151":[75],"1164":[1,2,6,7,9,12,27,60,61,62,65,67,75,81,110,111,117,119,120,121,122,123,124,125,128,129,131,134],"1187":[79,114,117,120,123,124,125,128],"1218":[9,117,125,128,134],"1246":[1,2,3,4,6,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,102,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"1271":[1,2,3,4,6,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,102,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"1274":[14,106,111,113,119,120,121,122,123,125,127,128,129,135],"1286":[1,2,3,4,6,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,102,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"1292":[123,125],"1295":[1,2,3,4,6,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,102,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"1313":[1,2,3,4,6,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,102,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"1323":[1,2,3,4,6,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,102,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"1350":[1,2,3,4,6,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,102,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"1377":[7,9,62,117,123,124,125,128],"1395":[1,2,3,4,6,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,102,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"1398":[1,2,6,7,9,11,12,14,27,49,60,61,62,65,66,67,75,79,81,82,85,102,104,106,110,111,113,114,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135],"1404":[1,2,3,4,6,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,102,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"1411":[9,125,128,134],"1428":[1,2,3,4,6,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,102,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"1434":[1,2,3,4,6,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,102,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"1440":[1,2,3,4,6,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,102,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"1493":[111,113,119,120,121,122,123,125,128,129],"1497":[14,111,113,119,120,121,122,123,125,128,129],"1505":[14,111,119,120,121,122,123,125,128],"1520":[111,113,116,119,120,121,122,128,129],"1571":[111,116,119,120,121,122,128,129],"1584":[113,129],"1630":[9,125,128,134],"1632":[9,117,125,128,134],"1633":[9,117,125,128,134],"1634":[9,117,125,128,134],"1645":[9,125,128],"1679":[55,76,82,132,136],"1684":[55,76,82,132,136],"1756":[1,2,6,7,8,9,12,27,60,61,62,65,67,75,81,110,117,118,119,120,121,122,124,125,128,129,131,134],"1794":[116],"1800":[111,119,120,121,122,128,129],"1805":[111,116,119,120,121,122,128,129],"1807":[111,116,119,120,121,122,128],"2066":[1,6,7,11,14,27,49,62,66,74,79,81,82,85,102,104,106,111,113,114,117,118,119,120,121,122,123,124,125,127,128,129,134,135],"2109":[123],"2111":[123],"2134":[6,7,9,11,12,14,27,60,61,62,65,66,67,75,81,85,102,110,111,113,114,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135]},"packages/frontend/editor-ui/src/features/ndv/runData/components/RunDataDisplayModeSelect.vue":{"18":[1,2,3,4,6,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,102,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"21":[1,2,3,4,6,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,102,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"45":[1,2,3,4,6,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,102,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"47":[1,2,3,4,6,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,102,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"53":[1,2,3,4,6,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,102,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"62":[79,114,117,120,123,124,125,128],"64":[6,7,8,9,81,102,117]},"packages/frontend/editor-ui/src/features/ndv/runData/schemaPreview.store.ts":{"11":[0,1,2,3,4,6,7,8,9,11,12,14,21,22,23,24,26,27,28,37,38,45,49,50,52,53,55,57,58,59,60,61,62,63,64,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,102,103,104,105,106,109,110,111,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,141,142,144],"21":[0,1,2,4,6,7,8,9,11,12,26,27,28,38,45,49,50,59,60,61,62,63,64,65,66,67,74,75,76,79,81,82,83,85,102,103,104,105,110,111,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,131,132,134,135,141,142],"30":[66,74,76,82,83,111,116,118,121,125,129,132,134],"49":[0,1,2,4,6,7,8,9,11,12,26,27,28,38,45,49,50,59,60,61,62,63,64,65,66,67,74,75,79,81,82,85,102,103,104,105,110,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135,141,142]},"packages/frontend/editor-ui/src/features/ndv/settings/components/NodeSettings.vue":{"158":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"161":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"165":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"169":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"172":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"174":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"180":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"183":[111,116,119,120,121,122,128,129],"185":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"187":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"189":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"193":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"198":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"200":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"204":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"218":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"232":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"240":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"244":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"248":[3,4,7,8,11,12,14,21,22,23,24,27,37,38,52,53,55,57,58,60,61,67,74,76,80,83,96,98,100,103,105,111,113,114,117,118,124,126,127,128,129,130,132,140,144],"252":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"255":[3,4,7,8,11,12,14,21,22,23,24,27,37,38,52,53,55,57,58,60,61,67,74,76,80,83,96,98,100,103,105,111,113,114,117,118,124,126,127,128,129,130,132,140,144],"256":[3,7,8,21,23,24,37,52,53,55,57,58,60,61,67,74,76,80,96,98,100,105,111,117,124,126,127,128,129,130,132,140],"260":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"264":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"273":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"276":[1,2,3,4,7,8,9,11,12,14,21,22,24,27,28,37,38,49,52,53,55,58,60,61,62,65,66,67,75,76,79,80,81,82,83,84,85,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"279":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"281":[124],"302":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"309":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"318":[2,4,7,8,11,12,21,23,24,27,28,37,38,58,60,61,62,67,75,84,96,98,103,104,105,109,110,111,113,118,119,120,121,122,124,126,127,129,130,131,135,136],"485":[126],"493":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"496":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,55,57,58,60,61,62,65,67,80,82,83,84,96,98,100,103,104,105,106,109,110,111,113,116,117,119,120,121,122,124,126,127,129,130,131,132,133,136,138,140,144],"502":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"512":[4,7,8,11,12,24,27,37,38,55,60,61,67,75,110,113,119,121,124,127,130,131,136],"513":[7,8,11,12,24,37,38,55,60,61,67,110,113,119,121,124,127,130,131,136],"521":[1,2,27,61,65,75,110,118,120,122,124,125,128,129,131],"527":[7,8,23,37,67,80,96,98,117,127,130],"551":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"576":[124],"593":[1,2,9,27,60,67,81,110,111,119,124,125,126,127,129,131,136],"597":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"608":[1,3,4,7,8,9,11,12,21,22,28,37,38,52,53,55,57,60,62,65,67,76,79,80,81,82,83,84,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,131,132,133,135,138,140,144],"614":[3,4,7,8,11,12,14,21,22,23,24,27,37,38,52,53,55,57,58,60,61,67,74,76,80,83,96,98,100,103,105,111,113,114,117,118,124,126,127,128,129,130,132,140,144],"779":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144]},"packages/frontend/editor-ui/src/features/ndv/settings/components/NodeSettingsHeader.vue":{"22":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"40":[124]},"packages/frontend/editor-ui/src/features/ndv/settings/components/NodeSettingsHint.vue":{"13":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"16":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"68":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"72":[124],"77":[124]},"packages/frontend/editor-ui/src/features/ndv/settings/components/NodeSettingsTabs.vue":{"29":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"45":[84,106],"49":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"53":[58],"55":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"63":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"130":[124],"161":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144]},"packages/frontend/editor-ui/src/features/ndv/settings/components/NodeWebhooks.vue":{"21":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"38":[12,14,21,24,37,53,60,67,114,118,124,129,130,144],"45":[12,14,21,24,60,67,114,118,124,129,144],"53":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"58":[3,8,11,12,14,21,24,37,53,55,60,67,76,114,117,118,124,127,128,129,130,144],"70":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"124":[12,14,21,24,37,53,60,67,114,118,124,129,130,144],"192":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"193":[1,2,27,60,67,110,111,119,124,125,126,127,129,131,136],"200":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"218":[12,14,21,24,60,67,114,118,124,129,144],"224":[12,14,21,24,60,67,114,118,124,129,144]},"packages/frontend/editor-ui/src/features/ndv/settings/composables/useNodeSettingsParameters.ts":{"56":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,30,33,34,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,90,91,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145],"66":[2,4,7,8,11,12,21,23,24,27,28,37,38,58,60,61,62,67,75,84,96,98,103,104,105,109,110,111,113,118,119,120,121,122,124,126,127,129,130,131,135,136],"130":[127],"186":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,34,37,38,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,90,91,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144]},"packages/frontend/editor-ui/src/features/ndv/shared/composables/useBinaryDataAccessTooltip.ts":{"9":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,30,33,34,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,90,91,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145]},"packages/frontend/editor-ui/src/features/ndv/shared/ndv.store.ts":{"41":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"45":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"46":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"109":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"113":[1,2,3,4,7,8,9,147,11,12,14,21,22,23,24,27,28,30,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145],"135":[1,2,3,4,5,7,8,9,147,11,12,14,21,22,23,24,27,28,30,33,34,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,90,91,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145],"139":[1,2,3,4,7,8,9,147,11,12,14,21,22,23,24,27,28,30,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145],"146":[4,7,8,147,11,12,23,24,27,30,37,38,39,51,60,61,62,67,75,80,89,97,98,106,111,113,119,120,121,122,124,127,128,129,130,131,145],"150":[1,2,3,4,5,7,8,9,147,11,12,21,22,23,24,27,28,34,37,38,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,90,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"152":[147,120],"154":[147,120],"156":[1,2,6,7,9,147,11,12,14,27,49,60,61,62,65,66,67,74,75,79,81,82,85,102,104,106,110,111,113,114,116,117,118,119,120,121,122,123,124,125,127,128,129,131,132,134,135],"158":[1,2,3,4,5,6,7,8,9,147,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,102,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,144],"160":[1,2,6,7,9,147,11,12,14,27,49,60,61,62,65,66,67,74,75,79,81,82,85,102,104,106,110,111,113,114,116,117,118,119,120,121,122,123,124,125,127,128,129,131,132,134,135],"162":[1,2,147,11,27,49,61,62,66,74,75,79,82,85,104,106,110,111,113,114,116,117,118,119,120,121,122,123,124,125,127,128,129,131,132,134,135],"182":[1,2,7,147,52,66,74,76,85,110,111,114,117,119,120,121,122,124,126,127,128,129,130,131],"184":[1,7,147,52,66,74,76,85,111,114,117,119,120,121,122,124,126,127,128,129,130,131],"186":[147,75,89,111,113,119,120,121,122,127,128,129,130,131],"188":[147],"190":[1,2,3,4,5,7,8,9,147,11,12,14,21,22,23,24,27,28,30,33,34,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,90,91,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145],"203":[1,2,3,4,5,7,8,9,147,11,12,14,21,22,23,24,27,28,30,33,34,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,90,91,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145],"211":[1,2,3,4,5,7,8,9,147,11,12,14,21,22,23,24,27,28,30,33,34,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,90,91,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145],"228":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"230":[1,3,4,5,7,8,9,147,10,11,12,21,22,28,37,38,52,53,54,55,57,58,60,62,65,67,76,79,80,81,82,83,84,91,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,131,132,133,135,138,139,140,142,144],"235":[1,2,3,4,7,8,9,147,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,90,91,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"244":[1,2,3,4,7,8,9,147,11,12,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140],"248":[9,147,125,128],"252":[1,2,3,4,7,8,9,147,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"256":[147],"266":[1,2,3,4,7,8,9,147,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"270":[1,3,4,5,7,8,147,11,12,21,22,28,37,38,52,53,55,57,60,62,65,67,76,79,80,82,83,84,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,128,129,131,132,133,135,138,139,140,144],"274":[147,79,111,114,117,120,123,124,125,128],"285":[147,111,116,119,120,121,122,128,129],"289":[147,111,116,119,120,121,122,128,129],"293":[4,147,11,12,24,27,37,38,51,60,61,62,67,75,106,113,119,120,121,122,124,127,128,129,130,131,136],"297":[147,120],"315":[147,120],"325":[147,120],"329":[147,120],"333":[147,120],"337":[147,120,123,125,128],"342":[1,2,3,4,6,7,8,9,147,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,102,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"350":[1,2,3,4,6,7,8,9,147,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,102,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"358":[147,120],"363":[147,120,123,125,128],"368":[147],"373":[4,147,11,12,24,27,38,60,61,62,67,89,111,113,119,120,121,122,127,128,129,130,131],"377":[147],"390":[4,147,11,12,24,27,34,37,38,51,55,58,60,61,62,67,75,90,91,106,110,113,119,120,121,122,124,127,128,129,130,131,136],"467":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"471":[147,42,50,112,133,139],"489":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"491":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"494":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/features/ndv/shared/ndv.utils.ts":{"41":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"57":[2,4,7,8,11,12,21,23,24,27,28,37,38,58,60,61,62,67,75,84,96,98,103,104,105,109,110,111,113,118,119,120,121,122,124,126,127,129,130,131,135,136],"139":[2,4,7,8,11,12,21,23,24,27,28,37,38,58,60,61,62,67,75,84,96,98,103,104,105,109,110,111,113,118,119,120,121,122,124,126,127,129,130,131,135,136],"268":[2,4,7,8,11,12,21,23,24,27,28,37,38,58,60,61,62,67,75,84,96,98,103,104,105,109,110,111,113,118,119,120,121,122,124,127,129,130,131,135,136],"274":[2,4,7,8,11,12,21,23,24,27,28,37,38,58,60,61,62,67,75,84,96,98,103,104,105,109,110,111,113,118,119,120,121,122,124,127,129,130,131,135,136],"296":[127,130],"297":[127,130],"300":[127],"314":[2,4,7,8,11,12,21,23,24,27,28,37,38,58,60,61,62,67,75,84,96,98,103,104,105,109,110,111,113,118,119,120,121,122,124,126,127,129,130,131,135,136],"335":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,30,33,34,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,90,91,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145],"342":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,30,33,34,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,90,91,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145],"346":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,30,33,34,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,90,91,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145],"368":[2,4,7,8,11,12,21,23,24,27,28,37,38,58,60,61,62,67,75,84,96,98,103,104,105,109,110,111,113,118,119,120,121,122,124,126,127,129,130,131,135,136],"374":[89,119,120,121,122,127,129,130,131,136],"447":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,34,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,90,91,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"458":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,34,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"622":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"734":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,34,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144]},"packages/frontend/editor-ui/src/features/ndv/shared/views/NodeDetailsViewV2.vue":{"70":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"86":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"103":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,68,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,144],"105":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,68,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"109":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"118":[1,2,68,110,120,124,125,129,131],"120":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,68,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"134":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"139":[1,2,3,4,7,8,9,11,12,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,66,67,74,75,76,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140],"146":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"159":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"165":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"186":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"193":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,68,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"195":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"199":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,68,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"213":[12,60,67,68,114],"219":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"223":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,68,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"225":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"243":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"249":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"270":[1,2,3,4,7,8,9,11,12,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140],"285":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"296":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,68,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"300":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,68,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"302":[1,3,4,5,7,8,11,12,21,22,28,37,38,52,53,55,57,60,62,65,67,68,76,79,80,82,83,84,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,128,129,131,132,133,135,138,139,140,144],"304":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,68,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"306":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,68,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"312":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,68,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"314":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,68,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"318":[1,2,3,4,7,8,9,11,12,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,68,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"320":[1,2,3,4,7,8,9,11,12,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,66,67,68,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140],"322":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,68,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"324":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"326":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,68,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"330":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,68,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"342":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"353":[1,2,6,60,61,67,68,75,110,111,118,119,120,121,122,123,124,129,131],"357":[68,117],"361":[4,7,21,23,37,53,57,68,75,80,82,83,103,104,105,109,111,116,119,120,121,122,123,124,125,126,127,129,130,131,133,144],"367":[68,120,125,128],"382":[68,117,120,123,124,125,128],"386":[68],"391":[68,120,123,125,128],"406":[68],"421":[68],"425":[68,125],"430":[1,2,3,4,7,8,9,11,12,21,22,23,24,27,28,37,38,52,53,55,57,58,60,61,62,67,68,74,75,76,79,80,81,82,83,84,96,98,100,103,104,105,109,110,111,113,116,117,118,119,120,121,122,124,125,126,127,128,129,130,131,132,133,134,136,138,140],"436":[1,2,27,61,65,68,75,110,118,120,122,124,125,128,129,131],"437":[1,2,68,110,120,124,125,129,131],"445":[68],"449":[1,2,3,4,7,8,9,11,12,21,22,23,24,27,28,37,38,52,53,55,57,58,60,61,62,67,68,74,75,76,79,80,81,82,83,84,96,98,100,103,104,105,109,110,111,113,116,117,118,119,120,121,122,124,125,126,127,128,129,130,131,132,133,134,136,138,140],"458":[9,68,125],"464":[68,110,111,126,131],"468":[68,126],"472":[1,3,4,5,7,8,11,12,21,22,28,37,38,52,53,55,57,60,62,65,67,68,76,79,80,82,83,84,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,128,129,131,132,133,135,138,139,140,144],"512":[1,2,3,4,7,8,9,11,12,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,66,67,68,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140],"521":[9,68,125,128,134],"526":[1,2,3,4,7,8,9,11,12,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,66,67,68,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140],"534":[9,11,12,14,27,60,61,62,65,66,67,68,75,85,110,111,113,114,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135],"538":[68,120,128],"552":[68],"556":[9,68,79,103,110,117,120,123,124,125,126,127,128,130],"561":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,68,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"566":[68,123,125],"570":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,68,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"574":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"578":[68],"582":[68,79,111,114,117,120,123,124,125,128],"588":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"606":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"616":[1,2,3,7,8,9,11,12,22,24,28,37,38,49,52,60,67,82,100,103,104,105,109,110,111,113,114,117,118,119,120,121,122,123,124,125,126,127,128,129,131,132,136,140],"654":[9,68,117,125,128,134],"658":[9,68,125,128],"662":[1,2,3,4,7,8,9,11,12,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,66,67,68,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140],"663":[1,2,3,4,7,8,9,11,12,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,66,67,68,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140],"668":[9,68,125,128],"669":[9,68,125,128],"674":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,68,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"679":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,68,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"682":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,68,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"703":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"709":[7,42,50,68,100,105,112,113,114,115,117,133,139,141,142],"783":[1,2,3,4,7,8,9,11,12,21,22,23,24,27,28,37,38,52,53,55,57,58,60,61,62,67,74,75,76,79,80,81,82,83,84,96,98,100,103,104,105,109,110,111,113,116,117,118,119,120,121,122,124,125,126,127,128,129,130,131,132,133,134,136,138,140],"791":[79,117,120,123,124,125,128],"809":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"850":[125],"857":[111,114,125,128]},"packages/frontend/editor-ui/src/features/resolvers/composables/useDynamicCredentials.ts":{"5":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"9":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,15,16,18,20,21,22,23,24,25,26,27,28,29,30,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/features/settings/communityNodes/communityNodes.store.ts":{"12":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,87,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"22":[58,87],"30":[87],"36":[58,87],"37":[87],"46":[58,87],"55":[58,87],"60":[87],"74":[87],"79":[87],"84":[87],"88":[87],"103":[58]},"packages/frontend/editor-ui/src/features/settings/communityNodes/composables/useInstalledCommunityPackage.ts":{"10":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"16":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"17":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"25":[58],"32":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"34":[9,58,81,126],"41":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144],"51":[1,2,3,4,7,8,9,11,12,14,21,22,23,24,27,28,37,38,49,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,96,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144]},"packages/frontend/editor-ui/src/features/settings/environments.ee/environments.store.ts":{"13":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,30,33,34,36,37,38,39,42,45,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,88,89,90,91,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"18":[147],"21":[147,88],"22":[147,88],"29":[1,2,3,4,5,7,8,9,147,11,12,14,21,22,23,24,27,28,30,33,34,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,90,91,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145],"30":[147,120,127,130],"35":[147,88,120,127,130],"43":[147,88],"46":[147],"56":[147,88],"59":[147],"64":[147,88],"69":[147,88],"74":[147,88],"79":[1,2,3,4,5,7,8,9,147,11,12,14,21,22,23,24,27,28,30,33,34,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,90,91,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145],"80":[147,120,127,130],"89":[147]},"packages/frontend/editor-ui/src/features/settings/sso/sso.store.ts":{"19":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"26":[18,20,93],"39":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"91":[18,20,25,92,93,94],"154":[18,20,93,94],"175":[18,20,93]},"packages/frontend/editor-ui/src/features/settings/users/users.store.ts":{"36":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"37":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"38":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"40":[38,138],"45":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"62":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"64":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"68":[3,12,21,23,28,37,53,56,57,60,67,96,98,100,103,104,105,109,110,111,119,121,124,125,127,129,130,131,132,136,140],"72":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"74":[38,138],"76":[1,3,7,8,11,12,21,23,24,28,35,37,38,41,52,53,54,55,56,57,58,60,61,62,65,67,71,80,82,83,87,89,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"78":[25,92,93],"80":[25,92,93],"84":[7,8,52,81,100,117,126,127],"88":[16],"92":[7,52,81,100,117,126,127],"98":[7,8,37,52,80,103,114,126,127],"124":[94],"130":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"131":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"153":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"166":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"175":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"186":[93],"190":[94],"209":[20,93],"218":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"222":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"226":[93],"283":[92,93],"319":[94],"324":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"374":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,26,27,28,36,37,38,40,41,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,93,94,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"381":[93],"385":[93],"393":[93],"400":[93],"417":[94],"435":[94],"444":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/features/setupPanel/setupPanel.store.ts":{"10":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"14":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"20":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"22":[5],"29":[5],"34":[5]},"packages/frontend/editor-ui/src/features/shared/banners/banners.store.ts":{"14":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"32":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"93":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"97":[36],"102":[93],"110":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/features/shared/banners/components/BannerStack.vue":{"38":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"46":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"51":[36],"55":[36],"56":[36],"59":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"65":[36],"86":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"89":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/features/shared/commandBar/composables/useChatHubCommands.ts":{"28":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"40":[29,30,31,32,34,35],"47":[29,30,31,32,34,35],"81":[29,30,31,32,34,35],"87":[29,30,31,32,34,35],"98":[29,30,31,32,34,35],"101":[29,30,31,32,34,35],"128":[29,30,31,32,34,35],"150":[29,30,31,32,34,35],"151":[29,30,31,32,34,35],"154":[29,30,31,32,34,35],"175":[29,30,31,32,34,35],"176":[29,30,31,32,34,35],"179":[29,30,31,32,34,35],"199":[29,30,31,32,34,35],"200":[29,30,31,32,34,35],"203":[29,30,31,32,34,35]},"packages/frontend/editor-ui/src/features/shared/commandBar/composables/useCommandBar.ts":{"31":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"45":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"52":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"188":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"222":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"244":[144],"253":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"259":[144],"266":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,29,30,31,32,34,35,36,37,38,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"284":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"285":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"289":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"290":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"293":[144],"311":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"314":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/features/shared/commandBar/composables/useCredentialNavigationCommands.ts":{"22":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"40":[144],"41":[144],"44":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"46":[144],"56":[144],"119":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"123":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"130":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"192":[144],"215":[3,15,16,18,19,20,22,23,25,26,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,68,69,70,71,72,73,78,87,88,89,90,91,92,93,94,95,96,97,98,112,115,117,133,138,141,142,144,145,146]},"packages/frontend/editor-ui/src/features/shared/commandBar/composables/useDataTableNavigationCommands.ts":{"20":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"44":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"50":[144],"58":[144],"124":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"128":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"135":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"186":[144]},"packages/frontend/editor-ui/src/features/shared/commandBar/composables/useExecutionCommands.ts":{"27":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"38":[105,113,114,115,117,141,142],"40":[105,113,114,115,117,141,142],"46":[105,113,114,115,117,141,142],"51":[105,113,114,115,117,141,142],"73":[105,113,114,115,117,141,142],"79":[105,113,114,115,117,141,142],"209":[105,113,114,115,117,141,142]},"packages/frontend/editor-ui/src/features/shared/commandBar/composables/useExecutionNavigationCommands.ts":{"10":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"28":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/features/shared/commandBar/composables/useGenericCommands.ts":{"31":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"40":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/features/shared/commandBar/composables/useInstanceAiCommands.ts":{"20":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"27":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"33":[42,43,44,45,46,47,48,49,50,51],"42":[42,43,44,45,46,47,48,49,50,51],"43":[42,43,44,45,46,47,48,49,50,51],"54":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"101":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/features/shared/commandBar/composables/useNodeCommands.ts":{"26":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"43":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"46":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"48":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"52":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"56":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"62":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"91":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"96":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"99":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"107":[0,1,2,3,4,5,6,7,8,9,11,12,21,22,23,24,26,27,28,37,38,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"136":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"137":[0,1,2,3,4,5,6,7,8,9,11,12,21,22,23,24,26,27,28,37,38,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"140":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"148":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/features/shared/commandBar/composables/useProjectNavigationCommands.ts":{"16":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"27":[144],"72":[15,18,19,30,35,38,41,71,73,89,94,98,138,144],"78":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"84":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"125":[144]},"packages/frontend/editor-ui/src/features/shared/commandBar/composables/useRecentResources.ts":{"32":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"43":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"58":[0,1,2,3,4,5,6,7,8,9,10,11,12,22,26,27,28,37,38,52,59,60,61,62,63,64,65,66,67,68,69,74,75,76,79,81,82,85,96,98,99,100,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,131,133,134,135,136,137,138,139,140,141,142,144,145,146],"59":[1,3,4,7,9,11,12,22,27,37,38,52,60,62,65,66,74,75,76,79,81,82,85,98,103,104,105,107,109,111,112,113,114,116,117,118,119,120,121,123,124,125,126,127,128,129,133,134,135,138,139,142,144,145],"70":[1,2,3,4,7,9,11,12,22,27,37,38,52,60,61,62,65,66,67,74,75,76,79,81,82,85,98,103,104,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,131,133,134,135,136,144],"73":[1,7,11,22,37,62,76,79,113,114,116,117,118,120,123,124,125,126,128,129,133],"89":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"177":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"181":[0,6,7,9,22,26,59,60,62,63,66,68,69,75,76,79,81,96,98,104,105,106,107,112,114,115,116,117,118,120,123,124,125,126,127,128,133,134,135,138,139,141,142,144]},"packages/frontend/editor-ui/src/features/shared/commandBar/composables/useWorkflowCommands.ts":{"51":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"68":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"71":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"73":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"77":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"81":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"84":[0,1,2,3,4,5,6,7,8,9,11,12,21,22,23,24,26,27,28,37,38,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"85":[5,7,8,22,23,37,38,59,60,63,66,67,80,96,98,117,127,130,145],"97":[5,7,8,22,23,37,38,59,60,63,66,67,80,96,98,117,127,130,145],"117":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"300":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"302":[0,1,2,3,4,5,6,7,8,9,11,12,21,22,23,24,26,27,28,37,38,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"303":[134,135,136],"304":[134,135,136],"310":[135,136],"320":[135,136],"342":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"383":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"420":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"474":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"484":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/features/shared/commandBar/composables/useWorkflowNavigationCommands.ts":{"29":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"55":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"57":[144],"65":[144],"74":[144],"161":[144],"162":[144],"167":[144],"168":[144],"206":[144],"220":[144],"242":[144],"302":[144],"312":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"313":[144],"316":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"320":[144],"323":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"377":[144],"402":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/features/shared/contextMenu/components/ContextMenu.vue":{"17":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"24":[7,147,81,104,105,107,108,109,129,135],"28":[7,147,81,104,105,107,108,109,129,135],"44":[7,147,81,104,105,107,108,109,129,135],"48":[7,147,81,104,105,107,108,109,129,135],"51":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"59":[7,147,81,104,105,107,108,109,129,135],"74":[7,147,81,104,105,107,108,109,129,135],"81":[7,147,81,104,105,107,108,109,129,135],"82":[7,147,81,104,105,107,108,109,129,135]},"packages/frontend/editor-ui/src/features/shared/contextMenu/composables/useContextMenu.ts":{"16":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"18":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"20":[7,147,81,104,105,107,108,109,129,135],"27":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"32":[7,147,81,104,105,107,108,109,129,135],"53":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"59":[7,147,81,104,105,107,108,109,129,135]},"packages/frontend/editor-ui/src/features/shared/contextMenu/composables/useContextMenuItems.ts":{"46":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"56":[7,147,81,84,104,105,107,108,109,129,135],"60":[7,147,81,84,104,105,107,108,109,129,135],"69":[147],"79":[7,147,81,84,104,105,107,108,109,129,135],"81":[7,147,81,84,104,105,107,109,129,135],"85":[7,147,81,84,104,105,107,109,129,135],"86":[7,147,81,84,104,105,107,109,129,135],"92":[7,147,81,84,104,105,107,109,129,135],"100":[7,147,81,84,104,105,107,109,129,135],"104":[7,147,81,104,105,107,109,129,135],"119":[7,147,81,104,105,107,109,129,135],"128":[7,147,81,84,104,105,107,108,109,129,135],"130":[7,147,81,84,104,105,107,109,129,135],"214":[7,147,81,84,104,105,107,109,129,135],"222":[7,147,81,84,104,105,107,109,129,135],"226":[7,147,81,84,104,105,107,109,129,135]},"packages/frontend/editor-ui/src/features/shared/editors/components/CodeNodeEditor/completions/js.snippets.ts":{"8":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/features/shared/editors/plugins/codemirror/completions/constants.ts":{"467":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"471":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/features/shared/editors/plugins/codemirror/completions/datatype.completions.ts":{"75":[89,111,119,120,121,122,127,128,129,130,131],"163":[119,120,127,129],"179":[119,120,122,127,129],"181":[119,120,122,127,129],"187":[119,120,122,127],"188":[119,120,122,127],"205":[119,120,122,127,129],"208":[119,120,122,127,129],"210":[119,120,122,127,129],"211":[119,120,122,127,129],"215":[122],"240":[119,120,122,127,129],"261":[119,120,122,127,129],"285":[119,120,122,127],"292":[119,120,122,127],"315":[119,120,122,127],"324":[119,120,122,127],"330":[119,120,122,127],"342":[119,120,127],"348":[119,120,127],"353":[119,120,127],"362":[119,120,127],"368":[119,120,122,127],"380":[119,120,122,127],"381":[119,120,122,127],"382":[119,120,122,127],"392":[119,120,122,127,129],"414":[119,120,122,127],"422":[119,120,127,129],"453":[119,120,127,129],"472":[129],"476":[119,120,127],"477":[119,120,127],"527":[119,120,122,127,129],"545":[119,120,122,127,129],"553":[119,120,122,127,129],"561":[119,120,122,127,129],"562":[119,120,122,127,129],"573":[122],"574":[122],"578":[122],"583":[122],"633":[122],"700":[122],"731":[122],"763":[122],"776":[122],"784":[119,120,127],"985":[129],"1077":[129],"1078":[129],"1560":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/features/shared/editors/plugins/codemirror/completions/infoBoxRenderer.ts":{"6":[122],"18":[122],"31":[122],"64":[129],"76":[122,129],"117":[122],"166":[122],"170":[122],"177":[122],"189":[122],"217":[122],"238":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"239":[122]},"packages/frontend/editor-ui/src/features/shared/editors/plugins/codemirror/completions/utils.ts":{"27":[111,119,120,121,122,127,129],"83":[119,120,122,127,129],"119":[119,120,127,129],"122":[119,120,127,129],"131":[89,111,119,120,121,122,127,129,131],"134":[119,120,127],"143":[119,120,127],"169":[111,119,120,121,122,127,129,131],"183":[129],"207":[89,111,119,120,121,122,127,129,131],"232":[1,7,8,37,52,66,74,76,80,81,85,89,103,111,114,117,119,120,121,122,124,126,127,128,129,130,131],"234":[89,111,119,120,121,122,127,129,131],"252":[111,119,120,121,122,127,129,131],"269":[119,120,127,129],"271":[119,120,127,129],"274":[2,21,28,84,103,104,105,109,110,111,119,120,121,122,124,127,129,131],"298":[2,21,28,84,103,104,105,109,110,111,119,120,121,122,124,127,129,131],"302":[2,21,28,84,103,104,105,109,110,111,119,120,121,122,124,127,129,131],"303":[2,21,28,84,103,104,105,109,110,111,119,120,121,122,124,127,129,131],"310":[89,111,119,120,121,122,127,129,131],"314":[89,111,119,120,121,122,127,129,131],"315":[89,111,119,120,121,122,127,129,131],"319":[89,111,119,120,121,122,127,129,131],"328":[89,111,119,120,121,122,127,129,131],"353":[119,120,122,127,129],"356":[119,120,122,127,129],"357":[119,120,122,127,129],"358":[119,120,122,127,129],"376":[111,119,120,121,122,127,129,131],"432":[119,120,122,127,129],"434":[119,120,122,127,129],"438":[119,120,122,127],"439":[119,120,122,127],"442":[119,120,127,129],"453":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"464":[119,120,127],"481":[119,120,122,127,129]},"packages/frontend/editor-ui/src/features/shared/editors/plugins/codemirror/format.ts":{"10":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/features/shared/editors/plugins/codemirror/keymap.ts":{"83":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"100":[120],"261":[111,119,120,121,122,124,127,129,130,131]},"packages/frontend/editor-ui/src/features/shared/editors/plugins/codemirror/multiCursor.ts":{"4":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/features/shared/editors/plugins/codemirror/resolvableHighlighter.ts":{"61":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"62":[1,7,52,66,74,76,85,89,111,114,117,119,120,121,122,124,126,127,128,129,130,131],"65":[1,7,52,66,74,76,85,89,111,114,117,119,120,121,122,124,126,127,128,129,130,131],"75":[111,120,122],"81":[120,127,128,131],"101":[1,7,52,66,74,76,85,89,111,114,117,119,120,121,122,124,126,127,128,129,130,131],"102":[1,7,52,66,74,76,85,89,111,114,117,119,120,121,122,124,126,127,128,129,130,131],"115":[1,7,52,66,74,76,85,89,111,114,117,119,120,121,122,124,126,127,128,129,130,131],"116":[76,111,114,120,121,122,127]},"packages/frontend/editor-ui/src/features/shared/editors/plugins/codemirror/tooltips/InfoBoxTooltip.ts":{"27":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"28":[1,7,8,52,66,74,76,80,81,85,114,117,119,120,121,122,124,126,127,128,131],"44":[119,121,122,129,131],"55":[122],"74":[119,121,122,129,131],"96":[1,7,8,37,52,66,74,76,80,81,85,89,103,114,117,119,120,121,122,124,126,127,128,129,130,131],"100":[1,7,8,37,52,66,74,76,80,81,85,103,114,117,119,120,121,122,124,126,127,128,129,130,131],"104":[1,7,8,37,52,66,74,76,80,81,85,89,103,114,117,119,120,121,122,124,126,127,128,129,130,131,136],"119":[119,121,122,129,131],"120":[119,121,122,129,131],"143":[119,121,122,129,131],"165":[122],"179":[1,7,8,37,52,66,74,76,80,81,85,89,103,114,117,119,120,121,122,124,126,127,128,129,130,131,136],"227":[119,121,122,129,131],"233":[122],"245":[1,7,8,37,52,66,74,76,80,81,85,89,103,114,117,119,120,121,122,124,126,127,128,129,130,131,136],"253":[1,7,8,37,52,66,74,76,80,81,85,89,103,114,117,119,120,121,122,124,126,127,128,129,130,131,136],"262":[1,7,8,37,52,66,74,76,80,81,85,89,103,114,117,119,120,121,122,124,126,127,128,129,130,131,136],"286":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"290":[1,7,8,37,52,66,74,76,80,81,85,89,103,114,117,119,120,121,122,124,126,127,128,129,130,131,136],"293":[1,7,8,37,52,66,74,76,80,81,85,89,103,114,117,119,120,121,122,124,126,127,128,129,130,131,136],"323":[1,7,8,37,52,66,74,76,80,81,85,89,103,114,117,119,120,121,122,124,126,127,128,129,130,131,136],"331":[122,129],"349":[122],"352":[122],"394":[1,2,7,8,21,28,37,52,80,84,89,103,104,105,109,110,111,119,120,121,122,124,126,127,128,130,131],"406":[1,7,8,37,52,66,74,76,80,81,85,89,103,114,117,119,120,121,122,124,126,127,128,129,130,131,136],"414":[1,7,8,37,52,76,80,81,89,103,114,117,119,121,126,128],"420":[1,7,8,37,52,66,74,76,80,81,85,89,103,114,117,119,120,121,122,124,126,127,128,129,130,131,136]},"packages/frontend/editor-ui/src/features/shared/editors/plugins/codemirror/typescript/client/facet.ts":{"9":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/features/shared/envFeatureFlag/useEnvFeatureFlag.ts":{"5":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"8":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/features/shared/nodeCreator/components/ItemTypes/ActionItem.vue":{"19":[3,8,12,21,23,28,37,53,56,57,60,67,68,96,98,100,103,104,105,109,110,111,119,121,124,125,127,129,130,131,132,136,140],"35":[3,8,12,21,23,28,37,53,56,57,60,67,68,96,98,100,103,104,105,109,110,111,119,121,124,125,127,129,130,131,132,136,140],"40":[68],"42":[3,8,12,21,23,28,37,53,56,57,60,67,68,96,98,100,103,104,105,109,110,111,119,121,124,125,127,129,130,131,132,136,140],"45":[68],"75":[68],"88":[68],"94":[68],"99":[3,8,12,21,23,28,37,53,56,57,60,67,68,96,98,100,103,104,105,109,110,111,119,121,124,125,127,129,130,131,132,136,140],"111":[3,8,12,21,23,28,37,53,56,57,60,67,68,96,98,100,103,104,105,109,110,111,119,121,124,125,127,129,130,131,132,136,140],"117":[3,8,12,21,23,28,37,53,56,57,60,67,68,96,98,100,103,104,105,109,110,111,119,121,124,125,127,129,130,131,132,136,140]},"packages/frontend/editor-ui/src/features/shared/nodeCreator/components/ItemTypes/CategoryItem.vue":{"12":[1,3,7,8,11,12,21,23,24,28,37,52,53,54,55,56,57,60,62,65,67,68,80,96,98,100,103,104,105,109,110,111,119,120,121,122,124,125,126,127,129,130,131,132,133,136,140,144],"16":[1,3,7,8,11,12,21,23,24,28,37,52,53,54,55,56,57,60,62,65,67,68,80,96,98,100,103,104,105,109,110,111,119,120,121,122,124,125,126,127,129,130,131,132,133,136,140,144],"20":[1,3,7,8,11,12,21,23,24,28,37,52,53,54,55,56,57,60,62,65,67,68,80,96,98,100,103,104,105,109,110,111,119,120,121,122,124,125,126,127,129,130,131,132,133,136,140,144]},"packages/frontend/editor-ui/src/features/shared/nodeCreator/components/ItemTypes/LabelItem.vue":{"11":[3,21,23,37,57,68,96,98,100,119,121,124,127,129,130,132,140]},"packages/frontend/editor-ui/src/features/shared/nodeCreator/components/ItemTypes/NodeItem.vue":{"38":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,68,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"58":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,68,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"78":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,68,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"85":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,68,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"90":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,68,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"94":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,68,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"98":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,68,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"102":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,68,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"108":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,68,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"110":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,68,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"115":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,68,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"116":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,68,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"118":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,68,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"127":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,68,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"131":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,68,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"135":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,68,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"139":[68],"143":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,68,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"155":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,68,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"157":[68],"171":[68],"173":[68],"178":[68],"181":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,68,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"201":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,68,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"214":[3,7,8,11,21,23,24,28,37,53,54,57,62,67,68,80,96,98,100,103,104,105,109,110,111,120,124,126,127,129,132,140,144],"215":[68],"217":[3,7,8,11,21,23,24,28,37,53,54,57,62,67,68,80,96,98,100,103,104,105,109,110,111,120,124,126,127,129,132,140,144],"227":[58,68],"229":[68],"232":[58,68],"246":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,68,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"258":[68]},"packages/frontend/editor-ui/src/features/shared/nodeCreator/components/ItemTypes/SubcategoryItem.vue":{"13":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,68,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"15":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,68,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"16":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,68,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144]},"packages/frontend/editor-ui/src/features/shared/nodeCreator/components/ItemTypes/ViewItem.vue":{"13":[1,3,7,8,11,12,21,23,28,37,38,54,55,56,58,60,61,67,68,80,82,83,96,98,100,103,104,105,109,110,111,113,116,119,120,121,122,124,125,127,129,130,131,132,133,136,140]},"packages/frontend/editor-ui/src/features/shared/nodeCreator/components/Modes/ActionsMode.vue":{"41":[3,8,12,21,23,28,37,53,56,57,60,67,68,96,98,100,103,104,105,109,110,111,119,121,124,125,127,129,130,131,132,136,140],"63":[3,8,12,21,23,37,53,57,60,68,96,98,111,124,127,129,130,131,132,136,140],"66":[3,8,12,21,23,28,37,53,56,57,60,67,68,96,98,100,103,104,105,109,110,111,119,121,124,125,127,129,130,131,132,136,140],"69":[3,12,21,23,28,37,56,60,67,68,96,98,100,103,104,105,109,110,111,119,121,124,125,127,129,130,131,132,136,140],"76":[8,21,37,53,57,68,124,127,130,131,132],"86":[3,8,12,21,23,37,53,57,60,68,96,98,111,124,127,129,130,131,132,136,140],"92":[3,8,12,21,23,28,37,53,56,57,60,67,68,96,98,100,103,104,105,109,110,111,119,121,124,125,127,129,130,131,132,136,140],"93":[3,8,12,21,23,28,37,53,56,57,60,67,68,96,98,100,103,104,105,109,110,111,119,121,124,125,127,129,130,131,132,136,140],"98":[3,8,12,21,23,28,37,53,56,57,60,67,68,96,98,100,103,104,105,109,110,111,119,121,124,125,127,129,130,131,132,136,140],"100":[3,8,12,21,23,28,37,53,56,57,60,67,68,96,98,100,103,104,105,109,110,111,119,121,124,125,127,129,130,131,132,136,140],"102":[3,8,12,21,23,28,37,53,56,57,60,67,68,96,98,100,103,104,105,109,110,111,119,121,124,125,127,129,130,131,132,136,140],"104":[3,8,12,21,23,28,37,53,56,57,60,67,68,96,98,100,103,104,105,109,110,111,119,121,124,125,127,129,130,131,132,136,140],"109":[3,8,12,21,23,28,37,53,56,57,60,67,68,96,98,100,103,104,105,109,110,111,119,121,124,125,127,129,130,131,132,136,140],"118":[3,8,12,21,23,37,53,57,60,68,96,98,111,124,127,129,130,131,132,136,140],"127":[3,8,12,21,23,28,37,53,56,57,60,67,68,96,98,100,103,104,105,109,110,111,119,121,124,125,127,129,130,131,132,136,140],"130":[3,8,12,21,23,28,37,53,56,57,60,67,68,96,98,100,103,104,105,109,110,111,119,121,124,125,127,129,130,131,132,136,140],"137":[3,8,12,21,23,28,37,53,56,57,60,67,68,96,98,100,103,104,105,109,110,111,119,121,124,125,127,129,130,131,132,136,140],"139":[3,8,12,21,23,28,37,53,56,57,60,67,68,96,98,100,103,104,105,109,110,111,119,121,124,125,127,129,130,131,132,136,140],"151":[68],"157":[68],"161":[3,8,12,21,23,28,37,53,56,57,60,67,68,96,98,100,103,104,105,109,110,111,119,121,124,125,127,129,130,131,132,136,140],"165":[68],"169":[68],"171":[68],"176":[3,8,12,21,23,28,37,53,57,60,67,68,96,98,100,103,104,105,109,110,111,119,121,124,127,129,130,131,132,136,140],"189":[3,8,12,21,23,28,37,53,57,60,67,68,96,98,100,103,104,105,109,110,111,119,121,124,127,129,130,131,132,136,140],"212":[3,8,12,21,23,28,37,53,56,57,60,67,68,96,98,100,103,104,105,109,110,111,119,121,124,125,127,129,130,131,132,136,140],"215":[3,8,12,21,23,28,37,53,56,57,60,67,68,96,98,100,103,104,105,109,110,111,119,121,124,125,127,129,130,131,132,136,140],"223":[3,8,12,21,23,28,37,53,56,57,60,67,68,96,98,100,103,104,105,109,110,111,119,121,124,125,127,129,130,131,132,136,140],"234":[68],"238":[68],"258":[3,8,12,21,23,28,37,53,56,57,60,67,68,96,98,100,103,104,105,109,110,111,119,121,124,125,127,129,130,131,132,136,140],"262":[3,8,12,21,23,28,37,53,56,57,60,67,68,96,98,100,103,104,105,109,110,111,119,121,124,125,127,129,130,131,132,136,140],"263":[3,8,12,21,23,28,37,53,56,57,60,67,68,96,98,100,103,104,105,109,110,111,119,121,124,125,127,129,130,131,132,136,140],"280":[3,8,12,21,23,37,53,57,60,68,96,98,111,124,127,129,130,131,132,136,140],"293":[53,68,124,127,130,131],"299":[53,68,124,127,130,131],"311":[68],"320":[3,8,12,21,23,28,37,53,56,57,60,67,68,96,98,100,103,104,105,109,110,111,119,121,124,125,127,129,130,131,132,136,140],"335":[68,124,130],"339":[68],"341":[68]},"packages/frontend/editor-ui/src/features/shared/nodeCreator/components/Modes/NodesMode.vue":{"54":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,68,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"68":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,68,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"70":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,68,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"73":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,68,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"75":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,68,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"87":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,68,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"97":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,68,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"111":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,68,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"194":[3,8,12,21,23,28,37,53,56,57,60,67,68,96,98,100,103,104,105,109,110,111,119,121,124,125,127,129,130,131,132,136,140],"253":[7,52,54,55,68],"273":[7,52,54,55,68],"289":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,68,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"295":[68],"299":[21,68,103],"307":[21,68,103],"315":[21,68,103],"321":[68],"324":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,68,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"333":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,68,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"343":[68],"344":[68]},"packages/frontend/editor-ui/src/features/shared/nodeCreator/components/NodeCreator.vue":{"54":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"56":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,68,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"64":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,68,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"72":[68,103],"83":[1,3,5,7,8,10,11,12,21,23,24,28,37,38,42,50,52,53,54,55,56,57,58,60,61,62,65,67,68,80,82,83,96,98,99,100,103,104,105,109,110,111,112,113,114,115,116,117,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,139,140,141,142,144],"87":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,68,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"91":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,68,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"96":[68],"99":[68],"119":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"123":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"124":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,68,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"133":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,68,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"141":[21,54,68,127],"144":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"148":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"159":[5,7,10,42,50,68,100,105,112,113,114,115,117,133,139,141,142],"164":[68,125]},"packages/frontend/editor-ui/src/features/shared/nodeCreator/components/NodeCreatorShortcutCoachmark.vue":{"14":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"28":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"31":[68],"45":[68]},"packages/frontend/editor-ui/src/features/shared/nodeCreator/components/OrderSwitcher.vue":{"11":[3,8,12,21,23,28,37,53,56,57,60,67,68,96,98,100,103,104,105,109,110,111,119,121,124,125,127,129,130,131,132,136,140]},"packages/frontend/editor-ui/src/features/shared/nodeCreator/components/Panel/NodesListPanel.vue":{"41":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,68,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"51":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,68,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"53":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,68,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"55":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,68,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"57":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,68,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"59":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,68,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"75":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,68,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"80":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,68,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"82":[58,68],"86":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,68,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"93":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,68,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"105":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,68,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,144],"125":[3,7,8,12,21,23,28,37,52,53,54,55,56,57,58,60,67,68,96,98,100,103,104,105,109,110,111,119,121,124,125,126,127,129,130,131,132,136,140],"130":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,68,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"134":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,68,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"139":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,68,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"144":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,68,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"145":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,68,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"189":[54,56,68],"191":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,68,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"203":[21,53,54,68,105,109]},"packages/frontend/editor-ui/src/features/shared/nodeCreator/components/Panel/SearchBar.vue":{"16":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,68,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"26":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,68,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"30":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,68,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,144],"35":[68],"39":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,68,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"44":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,68,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"52":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,68,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144]},"packages/frontend/editor-ui/src/features/shared/nodeCreator/components/Renderers/CategorizedItemsRenderer.vue":{"28":[1,3,7,8,11,12,21,23,24,28,37,52,53,54,55,56,57,60,62,65,67,68,80,96,98,100,103,104,105,109,110,111,119,120,121,122,124,125,126,127,129,130,131,132,133,136,140,144],"38":[1,3,7,8,11,12,21,23,24,28,37,52,53,54,55,56,57,60,62,65,67,68,80,96,98,100,103,104,105,109,110,111,119,120,121,122,124,125,126,127,129,130,131,132,133,136,140,144],"39":[1,3,7,8,11,12,21,23,24,28,37,52,53,54,55,56,57,60,62,65,67,68,80,96,98,100,103,104,105,109,110,111,119,120,121,122,124,125,126,127,129,130,131,132,133,136,140,144],"41":[1,3,7,8,11,12,21,23,24,28,37,52,53,54,55,56,57,60,62,65,67,68,80,96,98,100,103,104,105,109,110,111,119,120,121,122,124,125,126,127,129,130,131,132,133,136,140,144],"45":[57,68],"49":[53,57,68],"62":[1,3,7,8,11,12,21,23,24,28,37,52,53,54,55,56,57,60,62,65,67,68,80,96,98,100,103,104,105,109,110,111,119,120,121,122,124,125,126,127,129,130,131,132,133,136,140,144],"68":[68],"74":[68],"83":[1,3,7,8,11,12,21,23,24,28,37,52,53,54,55,56,57,60,62,65,67,68,80,96,98,100,103,104,105,109,110,111,119,120,121,122,124,125,126,127,129,130,131,132,133,136,140,144],"84":[53,68],"92":[68],"97":[21,68,103],"103":[68],"106":[1,3,7,8,11,12,21,23,24,28,37,52,53,54,55,56,57,60,62,65,67,68,80,96,98,100,103,104,105,109,110,111,119,120,121,122,124,125,126,127,129,130,131,132,133,136,140,144],"122":[1,3,7,8,11,12,21,23,24,28,37,52,53,54,55,56,57,60,62,65,67,68,80,96,98,100,103,104,105,109,110,111,119,120,121,122,124,125,126,127,129,130,131,132,133,136,140,144],"126":[68],"150":[1,3,7,8,11,12,21,23,24,28,37,52,53,54,55,56,57,60,62,65,67,68,80,96,98,100,103,104,105,109,110,111,119,120,121,122,124,125,126,127,129,130,131,132,133,136,140,144],"151":[53,68,124,127,130,131]},"packages/frontend/editor-ui/src/features/shared/nodeCreator/components/Renderers/ItemsRenderer.vue":{"28":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,68,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"43":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,68,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"45":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,68,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"47":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,68,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"51":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,68,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"61":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,68,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"78":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,68,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"104":[68],"108":[68],"112":[68],"116":[68],"120":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,68,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"124":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,68,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"131":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,68,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"132":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,68,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,144],"139":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,68,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"152":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,68,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"161":[7,55,68,126],"180":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,68,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144]},"packages/frontend/editor-ui/src/features/shared/nodeCreator/composables/useActions.ts":{"65":[3,8,12,21,23,28,37,53,56,57,60,67,96,98,100,103,104,105,109,110,111,119,121,124,125,127,129,130,131,132,136,140],"72":[3,8,12,21,23,28,37,53,56,57,60,67,96,98,100,103,104,105,109,110,111,119,121,124,125,127,129,130,131,132,136,140],"76":[3,8,12,21,23,28,37,53,56,57,60,67,96,98,100,103,104,105,109,110,111,119,121,124,125,127,129,130,131,132,136,140],"77":[3,8,12,21,23,28,37,53,56,57,60,67,96,98,100,103,104,105,109,110,111,119,121,124,125,127,129,130,131,132,136,140],"97":[3,8,12,21,23,28,37,53,56,57,60,67,96,98,100,103,104,105,109,110,111,119,121,124,125,127,129,130,131,132,136,140],"98":[3,8,12,21,23,28,37,53,56,57,60,67,96,98,100,103,104,105,109,110,111,119,121,124,125,127,129,130,131,132,136,140],"103":[3,8,12,21,23,28,37,53,56,57,60,67,96,98,100,103,104,105,109,110,111,119,121,124,125,127,129,130,131,132,136,140],"154":[3,8,12,21,23,28,37,53,56,57,60,67,96,98,100,103,104,105,109,110,111,119,121,124,125,127,129,130,131,132,136,140],"170":[3,8,12,21,23,28,37,53,57,60,67,96,98,100,103,104,105,109,110,111,119,121,124,127,129,130,131,132,136,140],"173":[3,21,23,28,37,57,96,98,100,103,104,105,109,110,111,119,121,124,127,129,130,132,140],"188":[3,8,12,21,23,28,37,53,57,60,67,96,98,100,103,104,105,109,110,111,119,121,124,127,129,130,131,132,136,140],"217":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"243":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,58,60,61,65,67,80,82,83,96,98,99,100,103,104,105,108,109,110,111,113,114,116,119,120,121,122,124,126,127,129,130,131,132,133,136,140,142,144],"251":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,80,82,83,96,98,99,100,103,104,105,108,109,110,111,113,114,116,119,120,121,122,124,126,127,129,130,131,132,133,136,138,140,142,144],"253":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,80,82,83,96,98,99,100,103,104,105,108,109,110,111,113,114,116,119,120,121,122,124,126,127,129,130,131,132,133,136,138,140,142,144],"256":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,80,82,83,96,98,99,100,103,104,105,108,109,110,111,113,114,116,119,120,121,122,124,126,127,129,130,131,132,133,136,138,140,142,144],"269":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,80,82,83,96,98,99,100,103,104,105,108,109,110,111,113,114,116,119,120,121,122,124,126,127,129,130,131,132,133,136,138,140,142,144],"278":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,80,82,83,96,98,99,100,103,104,105,108,109,110,111,113,114,116,119,120,121,122,124,126,127,129,130,131,132,133,136,138,140,142,144],"282":[7,8,103],"286":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,80,82,83,96,98,99,100,103,104,105,108,109,110,111,113,114,116,119,120,121,122,124,126,127,129,130,131,132,133,136,138,140,142,144],"290":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,80,82,83,96,98,99,100,103,104,105,108,109,110,111,113,114,116,119,120,121,122,124,126,127,129,130,131,132,133,136,138,140,142,144],"298":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,80,82,83,96,98,99,100,103,104,105,108,109,110,111,113,114,116,119,120,121,122,124,126,127,129,130,131,132,133,136,138,140,142,144],"306":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,80,82,83,96,98,99,100,103,104,105,108,109,110,111,113,114,116,119,120,121,122,124,126,127,129,130,131,132,133,136,138,140,142,144],"338":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,80,82,83,96,98,99,100,103,104,105,108,109,110,111,113,114,116,119,120,121,122,124,126,127,129,130,131,132,133,136,138,140,142,144],"374":[3,8,12,21,23,28,37,53,55,57,60,67,96,98,100,103,104,105,109,110,111,119,121,124,127,129,130,131,132,136,140],"379":[3,8,12,21,23,28,37,53,55,57,60,67,96,98,100,103,104,105,109,110,111,119,121,124,127,129,130,131,132,136,140],"389":[3,8,12,21,23,28,37,53,57,60,67,96,98,100,103,104,105,109,110,111,119,121,124,127,129,130,131,132,136,140]},"packages/frontend/editor-ui/src/features/shared/nodeCreator/composables/useActionsGeneration.ts":{"31":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"37":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"45":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"48":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"61":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"67":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"82":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"102":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"103":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"106":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"120":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"126":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"130":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"148":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"153":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"161":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"179":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"182":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"203":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"214":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"233":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"235":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"239":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"241":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"242":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"246":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"261":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"271":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"309":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"310":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"328":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"331":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"342":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"372":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"379":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"401":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"402":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"407":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"413":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"424":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"425":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"429":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/features/shared/nodeCreator/composables/useGetNodeCreatorFilter.ts":{"9":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"13":[7,8,52,126,127],"30":[7,8,52,126,127],"49":[7,52,126]},"packages/frontend/editor-ui/src/features/shared/nodeCreator/composables/useKeyboardNavigation.ts":{"14":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"20":[21,54,103,127],"43":[21,103],"46":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"49":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"50":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"53":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"56":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"62":[21,54,103,127],"64":[21,54,103,127],"66":[21,54,103,127],"79":[1,21,53,54,103,105,109,127],"102":[21,54,103,127],"127":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"131":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"141":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"147":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"151":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"156":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"157":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"166":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"171":[3,7,8,12,21,23,28,37,52,53,54,55,56,57,58,60,67,96,98,100,103,104,105,109,110,111,119,121,124,125,127,129,130,131,132,136,140],"172":[3,7,8,12,21,23,28,37,52,53,54,55,56,57,58,60,67,96,98,100,103,104,105,109,110,111,119,121,124,125,127,129,130,131,132,136,140]},"packages/frontend/editor-ui/src/features/shared/nodeCreator/composables/useNodeCreatorShortcutCoachmark.ts":{"12":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"22":[5,7,10,42,50,100,105,112,113,114,115,117,133,139,141,142]},"packages/frontend/editor-ui/src/features/shared/nodeCreator/composables/useViewStacks.ts":{"106":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"113":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"122":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"154":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,144],"161":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"174":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"178":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,144],"182":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,144],"185":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"189":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"193":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"197":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,144],"198":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,144],"204":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"222":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,144],"223":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,144],"236":[11,54,103],"251":[54,55],"253":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,144],"257":[7,8,37,52,80,126,127],"258":[7,8,37,52,80,126,127],"269":[7,8,52,126,127],"270":[7,8,52,126],"284":[7,52,126],"292":[7,52,126],"293":[7,52,126],"296":[7,52,126],"310":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"315":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"327":[7,8,37,52,126,127],"368":[7,52,126],"400":[7,52,126],"415":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,144],"416":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,144],"432":[7,8,52,126,127],"451":[7,8,52,126,127],"481":[7,8,52,126,127],"497":[7,52,126],"504":[7,8,52,126,127],"518":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"547":[54],"548":[54],"569":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"591":[54,56],"598":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"600":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"604":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"613":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144]},"packages/frontend/editor-ui/src/features/shared/nodeCreator/nodeCreator.store.ts":{"49":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"51":[1,3,21,54,57,58,105,109,111,114,121,126,127,142,144],"70":[7,8,52,126,127],"71":[7,8,52,126,127],"74":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"82":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"86":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"90":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"94":[126,127],"115":[126,127],"140":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"179":[7,8,21,52,54,55,56,82,83,103,104,116,126,127,131],"268":[1,3,21,54,57,58,105,109,111,114,121,142,144],"334":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"338":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"345":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"365":[3,7,8,11,23,24,28,37,38,52,55,60,61,67,82,99,100,103,104,105,109,110,111,113,114,119,121,122,124,126,127,129,130,131,132,136,138,140],"381":[3,7,8,11,23,24,28,37,38,52,55,60,61,67,82,99,100,103,104,105,109,110,111,113,114,119,121,122,124,126,127,129,130,131,132,136,138,140],"421":[57],"425":[3,8,12,21,23,28,37,53,56,57,60,67,96,98,100,103,104,105,109,110,111,119,121,124,125,127,129,130,131,132,136,140],"438":[7,52,54,55],"445":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,126,127,129,130,131,132,133,136,138,140,142,144],"461":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/features/shared/nodeCreator/nodeCreator.utils.ts":{"51":[1,3,7,8,147,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,144],"72":[147,54,55],"78":[147,54,55],"82":[147,54,55],"94":[147,54,55],"105":[3,7,8,147,12,21,23,28,37,52,53,54,55,56,57,60,67,80,96,98,100,103,104,105,109,110,111,119,121,124,125,126,127,129,130,131,132,136,140],"106":[3,7,8,147,12,21,23,28,37,52,53,54,55,56,57,60,67,96,98,100,103,104,105,109,110,111,119,121,124,125,126,127,129,130,131,132,140],"118":[1,3,7,8,147,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,144],"123":[1,3,7,147,21,23,28,37,38,54,55,56,58,61,65,96,98,99,100,103,104,105,109,110,111,113,114,119,120,121,122,124,127,129,130,133,136,140],"130":[1,3,7,8,147,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,144],"137":[147],"148":[1,3,7,8,147,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,144],"151":[1,3,7,8,147,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"152":[1,3,7,8,147,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"154":[1,3,7,8,147,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"168":[7,147,52,126],"173":[7,147,52,126],"187":[7,147,52,126],"202":[7,8,147,37,52,55,80,126,127],"207":[7,8,147,37,52,55,126,127],"211":[7,8,147,37,52,55,80,126,127],"212":[7,8,147,37,52,55,126,127],"213":[7,8,147,37,52,55,126,127],"222":[7,8,147,37,52,55,80,126,127],"226":[7,8,147,37,52,55,126,127],"237":[7,8,147,37,52,55,126,127],"238":[7,8,147,37,52,55,126,127],"254":[7,8,147,37,52,55,80,126,127],"256":[7,8,147,126,127],"270":[7,8,147,37,52,55,80,126,127],"278":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"286":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,87,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"289":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,34,37,38,42,45,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,89,96,97,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"291":[1,3,7,8,147,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"327":[1,3,7,8,147,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"329":[1,3,7,8,147,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"336":[147],"342":[147],"347":[1,3,7,8,147,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"372":[147],"373":[147],"377":[1,3,7,8,147,11,12,21,23,24,28,37,38,53,54,55,56,57,58,60,61,62,65,67,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,144],"382":[147,58],"405":[147],"431":[147,56],"449":[147,127],"468":[1,3,7,8,147,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"472":[1,3,7,8,147,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"478":[1,3,7,8,147,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"486":[147,55],"487":[147,55]},"packages/frontend/editor-ui/src/features/shared/nodeCreator/views/NodeCreation.vue":{"40":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"66":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"73":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,58,60,61,62,65,67,68,80,82,96,98,99,100,103,104,105,109,110,111,113,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140],"80":[68,108],"94":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,68,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,144],"101":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,68,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,116,119,120,121,122,124,126,127,129,130,131,132,133,136,138,140,142,144],"106":[68,84,106],"118":[1,4,68],"135":[68],"138":[68],"154":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"158":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,104,105,106,107,108,110,111,112,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,131,132,134,135,136,137,138,139,140,141,143,144,145,146],"173":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"187":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"201":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"214":[1,2,3,4,5,10],"223":[1,2,3,4,5,10]},"packages/frontend/editor-ui/src/features/shared/nodeCreator/views/viewsData.ts":{"122":[127],"139":[127],"141":[127],"145":[127],"148":[127],"174":[127],"197":[127],"250":[7,8,52,126,127],"253":[7,8,52,126,127],"263":[7,8,52,126,127],"389":[1,3,7,8,11,12,21,23,24,28,37,38,52,53,54,55,56,57,58,60,61,62,65,67,80,82,83,96,98,99,100,103,104,105,109,110,111,113,114,119,120,121,122,124,126,127,129,130,131,132,133,136,138,140,142,144],"515":[1,3,7,8,11,12,21,23,28,37,38,54,55,56,58,60,61,67,80,82,83,96,98,100,103,104,105,109,110,111,113,116,119,120,121,122,124,125,127,129,130,131,132,133,136,140],"526":[1,3,7,8,11,12,21,23,28,37,38,54,55,56,58,60,61,67,80,82,83,96,98,100,103,104,105,109,110,111,113,116,119,120,121,122,124,125,127,129,130,131,132,133,136,140],"528":[1,3,7,8,11,12,21,23,28,37,38,54,55,56,58,60,61,67,80,82,83,96,98,100,103,104,105,109,110,111,113,116,119,120,121,122,124,125,127,129,130,131,132,133,136,140],"529":[1,3,7,8,11,12,21,23,28,37,38,54,55,56,58,60,61,67,80,82,83,96,98,100,103,104,105,109,110,111,113,116,119,120,121,122,124,125,127,129,130,131,132,133,136,140],"651":[1,3,7,8,11,12,21,23,28,37,38,54,55,56,58,60,61,67,80,82,83,96,98,100,103,104,105,109,110,111,113,116,119,120,121,122,124,125,127,129,130,131,132,133,136,140]},"packages/frontend/editor-ui/src/features/shared/tags/tags.api.ts":{"8":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"10":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"13":[147,84,133,137,143],"19":[147],"26":[147,137]},"packages/frontend/editor-ui/src/features/shared/tags/tags.store.ts":{"15":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"19":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"31":[147,68,137,144],"32":[147,137,144],"35":[147,68,137,144],"37":[147],"41":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"42":[147,92,95,97,100,105,125,133,137,139,142,143,144],"50":[0,1,2,6,7,8,9,147,13,14,22,26,27,28,42,45,48,49,50,59,60,62,63,64,66,67,68,74,75,76,79,81,82,84,96,98,99,102,104,105,106,107,110,112,114,115,116,117,118,119,120,123,124,125,126,127,128,129,133,134,135,137,138,139,141,142,143,144,145,146],"51":[147,84,133,137,143],"72":[147,137],"77":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"96":[147,84,133,137,143],"104":[147],"115":[147],"121":[147,137]},"packages/frontend/editor-ui/src/features/workflows/canvas/canvas.types.ts":{"22":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"49":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/features/workflows/canvas/canvas.utils.ts":{"34":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"41":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"46":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"48":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,55,57,58,59,60,61,62,63,64,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,141,142,143,145,146],"54":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,55,57,58,59,60,61,62,63,64,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,141,142,143,145,146],"56":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,55,57,58,59,60,61,62,63,64,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,141,142,143,145,146],"57":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,55,57,58,59,60,61,62,63,64,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,141,142,143,145,146],"114":[147,109,135],"146":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,141,142,143,144,145,146],"166":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"181":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,55,57,58,59,60,61,62,63,64,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,141,142,143,145,146],"188":[1,2,3,4,5,7,8,147,11,12,21,23,24,27,28,37,38,52,53,55,57,58,60,61,62,64,67,74,77,80,82,83,84,85,96,98,100,103,104,105,107,108,109,110,111,113,116,117,119,120,121,122,124,125,126,127,129,130,131,132,133,135,136,138,140,143],"222":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"231":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"239":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"256":[147,83,108,134],"274":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"291":[0,1,2,3,4,5,6,7,8,9,147,11,12,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"301":[0,1,2,3,4,5,6,7,8,9,147,11,12,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"305":[0,1,2,3,4,5,6,7,8,9,147,11,12,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"319":[1,2,4,5,7,147,21,23,27,37,40,47,51,53,57,64,69,70,71,74,77,80,82,83,84,85,88,89,97,98,102,103,104,105,107,108,109,116,117,121,123,124,125,126,127,129,133,135,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/features/workflows/canvas/components/Canvas.vue":{"190":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"192":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"238":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"255":[147,103,104,105,107,108,109,124,135,138,139,145,146],"261":[1,4,5,147,103,104,105,107,108,109,111,119,121,122,124,127,129,130,131,135,138,139,141,145,146],"281":[147],"296":[5,7,147,21,53,57,80,82,83,103,104,105,107,108,109,116,126,133,135,138,139,140,141,142,144,145,146],"298":[147,103],"306":[147,103],"314":[147],"316":[147],"325":[147],"327":[147],"336":[147,135],"338":[147,135],"341":[147,103],"343":[147,103],"346":[147],"358":[147,107],"362":[147,107],"374":[147],"377":[147],"382":[5,147,103,104,105,107,108,109,135,138,139,140,141,142,145,146],"384":[147],"386":[147,103,138,145],"387":[147,103,138,145],"389":[147],"390":[147,103,104,105,109,138,145],"392":[147],"393":[147],"394":[147],"395":[147],"402":[147],"403":[147],"404":[147],"409":[147],"415":[147],"416":[147,103,104,109],"417":[147,105],"418":[147,105,109,140,141,142],"419":[147],"420":[147,105],"421":[147],"423":[147],"424":[147],"428":[147,108],"429":[147],"430":[147],"431":[147,146],"434":[147],"435":[147],"436":[147],"437":[147],"438":[147],"439":[147],"440":[147],"441":[147],"446":[147],"450":[147],"451":[147],"466":[147,103,104,105,109,138,140,141,142,145],"467":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"470":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,14,21,22,27,49,52,54,55,56,57,58,60,62,66,67,74,75,76,77,79,81,82,83,84,85,100,103,104,105,106,107,108,109,110,111,112,113,114,116,117,118,119,120,121,123,124,125,126,127,128,129,131,134,135,138,139,140,141,142,143,144,145],"471":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,14,21,22,27,49,52,54,55,56,57,58,60,62,66,67,74,75,76,77,79,81,82,83,84,85,100,103,104,105,106,107,108,109,110,111,112,113,114,116,117,118,119,120,121,123,124,125,126,127,128,129,131,134,135,138,139,140,141,142,143,144,145],"477":[0,1,2,4,6,7,8,9,147,11,12,14,21,22,27,49,52,54,55,56,60,62,66,67,74,75,76,77,79,81,82,83,84,85,100,103,104,105,106,107,109,110,111,112,113,114,116,117,118,119,120,121,123,124,125,126,127,128,129,131,134,135,138,139,140,141,142,143,145],"484":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"485":[1,2,3,4,6,7,8,9,147,11,12,21,22,23,24,27,28,37,38,49,52,55,58,60,61,62,64,65,66,67,74,75,76,77,79,80,81,82,83,84,85,96,98,99,100,103,104,105,107,108,109,110,111,113,114,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,141,142,145],"490":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"496":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"497":[1,2,3,4,5,147,10],"505":[7,8,147,21,52,54,55,56,103,104,116,131],"509":[147,81,103,104,107,109,138],"513":[147],"517":[147,81,103,104,107,109,138],"518":[147,81,103,104,107,109,138],"521":[1,2,4,8,9,147,11,12,14,22,27,49,60,62,66,67,74,75,76,79,81,84,85,103,104,105,106,107,109,110,111,113,114,116,117,118,119,120,121,123,124,125,126,127,128,129,134,135,138,139,140,141,142,145],"535":[147],"536":[147],"539":[0,6,9,147,21,67,81,103,104,105,106,107,108,117,124,125,135],"547":[1,2,4,8,9,147,11,12,14,22,27,49,60,62,66,74,75,76,79,81,84,85,105,110,111,113,114,116,117,118,119,120,121,123,124,125,126,127,128,129,134,135],"552":[147],"556":[1,2,3,4,6,7,8,147,11,12,21,23,24,27,28,37,38,52,53,54,55,56,57,58,60,61,62,64,65,67,74,77,80,81,82,83,84,85,96,98,99,100,103,104,105,107,108,109,110,111,113,114,116,117,119,120,121,122,124,125,126,127,129,130,131,132,133,135,136,138,140,142,143,144],"560":[1,2,3,4,6,7,8,9,147,11,12,14,21,22,23,24,27,28,37,38,49,52,53,54,55,56,57,58,60,61,62,64,65,66,67,74,75,76,77,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145],"564":[1,2,3,4,6,7,8,147,11,12,21,23,24,27,28,37,38,52,53,54,55,56,57,58,60,61,62,64,65,67,74,77,80,81,82,83,84,85,96,98,99,100,103,104,105,107,108,109,110,111,113,114,116,117,119,120,121,122,124,125,126,127,129,130,131,132,133,135,136,138,140,142,143,144],"581":[147,100,103,117],"585":[147,77,103,117],"589":[147],"593":[7,147],"597":[7,147],"600":[147,24,67,104],"604":[147,24,67,104],"607":[147],"620":[147],"624":[147],"629":[147],"645":[7,8,147,21,52,54,55,56,103,104,116,131,135],"652":[147,104,135],"659":[7,8,147,21,52,54,55,56,103,104,116,131,135],"670":[147,103,109],"674":[147,82,83,103],"687":[147,82,83,84,103,109,117,133,135],"693":[147,82,83,84,103,109],"711":[147,82,83,84,103,109,117],"716":[147,82,83,84,103,109,117],"723":[0,1,2,3,4,5,7,8,9,147,10,11,12,14,21,22,27,49,52,54,55,56,57,58,60,62,66,67,74,75,76,77,79,81,83,84,85,100,103,104,105,106,107,108,109,110,111,113,114,116,117,118,119,120,121,123,124,125,126,127,128,129,131,134,135,138,139,140,141,142,143,144,145],"727":[1,2,3,4,5,7,8,9,147,10,11,12,14,21,22,27,49,52,54,55,56,57,58,60,62,66,67,74,75,76,79,81,83,84,85,100,103,104,105,106,107,109,110,111,113,114,116,117,118,119,120,121,123,124,125,126,127,128,129,131,134,135,138,139,140,141,142,143,144],"735":[0,9,147,49,79,103,114,118,119,121],"743":[5,147,103,104,105,107,108,109,135,138,139,140,141,142,145,146],"751":[5,147,103,104,105,107,108,109,135,138,139,140,141,142,145,146],"768":[0,1,2,4,6,7,8,9,147,11,12,14,21,22,27,49,52,54,55,56,60,62,66,67,74,75,76,79,81,84,85,103,104,105,106,107,108,109,110,111,113,114,116,117,118,119,120,121,123,124,125,126,127,128,129,131,134,135,138,139,140,141,142,145],"778":[0,6,9,147,21,67,81,103,104,105,106,107,108,117,124,125,135],"782":[147],"786":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"794":[147,105],"798":[147,105,112],"802":[147,105],"806":[147,105],"810":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"819":[147],"823":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"829":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"830":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"842":[147,104,105,108,135],"850":[147],"854":[7,147,81,104,105,107,109,129,135],"869":[7,147,81,104,105,107,108,109,129,135],"918":[5,147,101],"949":[147,103],"953":[147,103],"963":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"967":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"971":[147],"979":[147],"988":[147],"989":[147],"994":[147],"998":[147],"1006":[147,141],"1025":[147,22,69,104,105,107,116,133,135,138,144],"1032":[147,13,14,102,112],"1040":[147,13,14,102,112],"1048":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"1053":[147],"1059":[7,147,42,50,100,105,112,113,114,115,117,133,139,141,142,146],"1069":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"1078":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"1094":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"1104":[0,6,9,147,21,67,81,103,104,105,106,107,108,117,124,125,135],"1108":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"1111":[147],"1118":[147],"1145":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"1184":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"1211":[147],"1218":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,55,57,58,59,60,61,62,63,64,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,141,142,143,145,146],"1228":[147,82,83,84,103,109,117],"1233":[7,8,147,21,52,54,55,56,103,104,116,131,135],"1235":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"1239":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"1256":[147],"1260":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/features/workflows/canvas/components/WorkflowCanvas.vue":{"44":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"50":[0,1,2,3,4,5,6,7,8,9,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"54":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"59":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"69":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"83":[68],"85":[68,105,109,129,138,143],"93":[68,105,109,129,138,143],"99":[68,105,109,129,138,143],"150":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/background/CanvasBackground.vue":{"13":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/buttons/CanvasControlButtons.vue":{"10":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"36":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"38":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"40":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"42":[147,105],"46":[147,105,112],"50":[147,105],"54":[0,6,7,9,147,81,84,85,103,104,105,106,107,109,114,116,117,118,124,125,128,134,135,143],"58":[147],"62":[147],"64":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"71":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"82":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"92":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"107":[147],"126":[9,147,42,45,48,49,50,101,105,112,114,117,125,126,128,134],"140":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"149":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"157":[147],"170":[147]},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/buttons/CanvasRunWorkflowButton.vue":{"40":[0,1,2,3,4,5,7,9,11,12,21,22,23,24,26,27,28,37,38,42,45,48,49,50,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,82,83,84,85,96,98,99,100,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"44":[0,1,2,3,4,5,7,9,11,12,21,22,23,24,26,27,28,37,38,42,45,48,49,50,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,82,83,84,85,96,98,99,100,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"45":[0,1,2,3,4,5,7,9,11,12,21,22,23,24,26,27,28,37,38,42,45,48,49,50,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,82,83,84,85,96,98,99,100,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"49":[0,1,2,3,4,5,7,9,11,12,21,22,23,24,26,27,28,37,38,42,45,48,49,50,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,82,83,84,85,96,98,99,100,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"60":[5,66,109,114,118,129],"62":[5,66,109,114,118,129],"63":[5,66,109,114,118,129],"69":[5,66,109,114,118,129],"76":[0,1,2,3,4,5,7,9,11,12,21,22,23,24,26,27,28,37,38,42,45,48,49,50,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,82,83,84,85,96,98,99,100,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"97":[0,1,2,3,4,5,7,9,11,12,21,22,23,24,26,27,28,37,38,42,45,48,49,50,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,82,83,84,85,96,98,99,100,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"108":[4,7,11,12,26,27,28,38,49,50,59,60,62,63,64,66,67,74,82,85,104,105,113,114,115,116,117,118,123,124,125,127,128,129,134,135,141,142],"109":[4,7,11,12,26,27,28,38,49,50,59,60,62,63,64,66,67,74,82,85,104,105,113,114,115,116,117,118,123,124,125,127,128,129,134,135,141,142],"111":[0,1,2,3,4,5,7,9,11,12,21,22,23,24,26,27,28,37,38,42,45,48,49,50,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,82,83,84,85,96,98,99,100,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"118":[5,66,109,114,118,129],"136":[5,66,109,114,118,129]},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/edges/CanvasArrowHeadMarker.vue":{"6":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/edges/CanvasEdge.vue":{"35":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,55,57,58,59,60,61,62,63,64,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,141,142,143,145,146],"43":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,55,57,58,59,60,61,62,63,64,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,141,142,143,145,146],"45":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,55,57,58,59,60,61,62,63,64,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,141,142,143,145,146],"46":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,55,57,58,59,60,61,62,63,64,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,141,142,143,145,146],"52":[0,1,2,3,4,5,6,7,8,9,147,11,12,22,23,24,26,27,28,37,38,42,49,50,52,55,58,59,60,61,62,63,64,66,67,74,75,76,78,79,80,81,82,83,84,85,100,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,141,142,145,146],"60":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,55,57,58,59,60,61,62,63,64,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,141,142,143,145,146],"62":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,55,57,58,59,60,61,62,63,64,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,141,142,143,145,146],"64":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,55,57,58,59,60,61,62,63,64,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,141,142,143,145,146],"66":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,55,57,58,59,60,61,62,63,64,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,141,142,143,145,146],"71":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,55,57,58,59,60,61,62,63,64,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,141,142,143,145,146],"77":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,55,57,58,59,60,61,62,63,64,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,141,142,143,145,146],"82":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,55,57,58,59,60,61,62,63,64,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,141,142,143,145,146],"89":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,55,57,58,59,60,61,62,63,64,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,141,142,143,145,146],"95":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,55,57,58,59,60,61,62,63,64,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,141,142,143,145,146],"97":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,55,57,58,59,60,61,62,63,64,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,141,142,143,145,146],"99":[147,82,83,103,109],"106":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,55,57,58,59,60,61,62,63,64,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,141,142,143,145,146],"116":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,55,57,58,59,60,61,62,63,64,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,141,142,143,145,146],"117":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,55,57,58,59,60,61,62,63,64,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,141,142,143,145,146],"121":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,55,57,58,59,60,61,62,63,64,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,141,142,143,145,146],"132":[147,82,83,103],"136":[147,103,109],"140":[147,82,83,84,103,109,117],"144":[147,82,83,84,103],"146":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,55,57,58,59,60,61,62,63,64,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,141,142,143,145,146],"160":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,55,57,58,59,60,61,62,63,64,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,141,142,143,145,146]},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/edges/utils/getEdgeRenderData.ts":{"11":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,141,142,143,145,146],"13":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,141,142,143,145,146]},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/handles/CanvasHandleRenderer.vue":{"15":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"43":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"47":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"53":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"57":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"63":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"69":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"77":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"87":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"89":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"113":[7,8,147,21,52,54,55,56,103,104,116,131],"142":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/handles/render-types/CanvasHandleMainInput.vue":{"14":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,55,57,58,59,60,61,62,63,64,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,141,142,143,145,146],"22":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,55,57,58,59,60,61,62,63,64,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,141,142,143,145,146],"26":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,55,57,58,59,60,61,62,63,64,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,141,142,143,145,146]},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/handles/render-types/CanvasHandleMainOutput.vue":{"22":[0,1,2,3,4,5,6,7,8,9,147,11,12,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"27":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"29":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"38":[0,1,2,3,4,5,6,7,8,9,147,11,12,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"40":[0,1,2,7,8,9,147,11,26,27,28,38,45,49,50,59,60,61,62,63,64,66,67,74,75,79,82,85,104,105,110,113,114,115,116,117,118,119,120,121,123,124,125,127,128,129,131,134,135,141,142],"49":[0,1,2,3,4,5,6,7,8,9,147,11,12,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"51":[0,1,2,3,4,5,6,7,8,9,147,11,12,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"53":[0,1,2,3,4,5,6,7,8,9,147,11,12,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"58":[5,147,14,21,24,26,55,62,66,67,74,77,82,83,104,109,112,114,117,118,120,123,124,125,128,129,143,144,146],"63":[0,1,2,7,8,9,147,11,26,27,28,38,45,49,50,59,60,61,62,63,64,66,67,74,75,79,82,85,104,105,110,113,114,115,116,117,118,119,120,121,123,124,125,127,128,129,131,134,135,141,142],"70":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"75":[147,21,54,55,56,103,104,105,116,131],"79":[147,21,55,56,103,104,116,131],"83":[147,21,54,55,56,103,104,116,131],"85":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/handles/render-types/parts/CanvasHandleDot.vue":{"4":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"13":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"14":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/handles/render-types/parts/CanvasHandlePlus.vue":{"6":[0,1,2,3,4,5,6,7,8,9,147,11,12,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"34":[0,1,2,3,4,5,6,7,8,9,147,11,12,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"41":[0,1,2,3,4,5,6,7,8,9,147,11,12,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"57":[0,1,2,3,4,5,6,7,8,9,147,11,12,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"64":[0,1,2,3,4,5,6,7,8,9,147,11,12,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"89":[0,1,2,3,4,5,6,7,8,9,147,11,12,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"102":[7,8,147,21,52,54,55,56,103,104,116,131],"104":[0,1,2,3,4,5,6,7,8,9,147,11,12,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/nodes/CanvasNode.vue":{"49":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"89":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"90":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"91":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"105":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"107":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"115":[147],"118":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"120":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"136":[1,2,4,8,9,147,11,12,14,22,27,49,60,62,66,74,75,76,79,81,84,85,105,110,111,113,114,116,117,118,119,120,121,123,124,125,126,127,128,129,134,135],"146":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"150":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"154":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"161":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"165":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"172":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"249":[7,8,147,21,52,54,55,56,103,104,116,131],"253":[147,77,103,117],"257":[0,9,147,49,79,103,114,118,119,121],"261":[147,100,103,117],"265":[1,2,4,8,9,147,11,12,14,22,27,49,60,62,66,74,75,76,79,81,84,85,110,111,113,114,116,117,118,119,120,121,123,124,125,126,127,128,129,134,135],"269":[147],"273":[147,105],"277":[7,147,81,104,105,107,109,129,135],"281":[147],"285":[147],"289":[147],"293":[147],"297":[147],"301":[147],"304":[147],"326":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"331":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"340":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"341":[1,2,3,4,6,7,8,9,147,11,12,14,21,22,23,24,27,28,37,38,49,52,53,54,55,56,57,58,60,61,62,64,65,66,67,74,75,76,77,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145],"347":[7,147,74,78,109,124,125,127,129,135,143,145,146],"353":[147,24,67,74,78,104,109,124,125,127,129,135,143,145,146],"359":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"364":[1,2,3,4,5,7,8,147,10,11,12,13,21,23,24,27,28,37,38,42,50,52,53,54,55,56,57,58,60,61,62,64,65,67,74,77,78,80,82,83,84,85,96,98,99,100,102,103,104,105,107,108,109,110,111,112,113,114,115,117,119,120,121,122,124,125,126,127,129,130,131,132,133,135,136,138,139,140,141,142,143,144,145,146],"368":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"378":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"395":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,55,57,58,59,60,61,62,63,64,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,141,142,143,145,146]},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/nodes/CanvasNodeRenderer.vue":{"10":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"12":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"33":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/nodes/CanvasNodeToolbar.vue":{"16":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"49":[0,7,8,9,147,37,52,79,80,117,126,127],"52":[0,7,8,9,147,37,52,79,80,117,126,127],"54":[0,1,2,3,4,5,6,7,8,9,147,11,12,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"61":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"68":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"77":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"81":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"83":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"85":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"87":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"91":[0,9,147,49,79,103,114,118,119,121],"95":[147,100,103,117],"99":[147,77,103,117],"103":[147],"109":[147,105],"113":[0,9,147,77,79,100,103,105,114,117,118,119,121,135],"117":[9,147,79,100,105,114,117,118,119,121,135],"121":[147],"127":[147],"130":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"140":[0,9,147,77,79,100,103,105,114,117,118,119,121],"141":[147],"149":[0,1,2,3,4,5,6,7,8,9,147,11,12,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"192":[147]},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/nodes/render-types/CanvasNodeAddNodes.vue":{"18":[1,2,3,4,7,8,147,11,12,21,23,24,26,27,28,36,37,38,52,53,54,55,56,57,58,60,61,62,64,65,67,68,69,74,77,78,80,82,83,84,85,96,98,99,100,103,104,105,108,109,110,111,113,114,117,119,120,121,122,124,125,126,127,129,130,131,132,133,136,137,138,139,140,142,143,144,145,146],"26":[1,2,3,4,7,8,147,11,12,21,23,24,26,27,28,36,37,38,52,53,54,55,56,57,58,60,61,62,64,65,67,68,69,74,77,78,80,82,83,84,85,96,98,99,100,103,104,105,108,109,110,111,113,114,117,119,120,121,122,124,125,126,127,129,130,131,132,133,136,137,138,139,140,142,143,144,145,146],"30":[1,2,3,4,7,8,147,11,12,21,23,24,26,27,28,36,37,38,52,53,54,55,56,57,58,60,61,62,64,65,67,68,69,74,77,78,80,82,83,84,85,96,98,99,100,103,104,105,108,109,110,111,113,114,117,119,120,121,122,124,125,126,127,129,130,131,132,133,136,137,138,139,140,142,143,144,145,146],"35":[1,2,3,4,7,8,147,11,12,21,23,24,27,28,37,38,52,53,54,55,56,57,58,60,61,62,64,65,67,74,77,78,80,82,83,84,85,96,98,99,100,103,104,105,108,109,110,111,113,114,117,119,120,121,122,124,125,126,127,129,130,131,132,133,136,138,140,142,143,144,145,146],"40":[147],"44":[147],"48":[1,3,147,21,54,57,58,105,109,111,114,121,144],"55":[147],"63":[1,2,3,4,7,8,147,11,12,21,23,24,26,27,28,36,37,38,52,53,54,55,56,57,58,60,61,62,64,65,67,68,69,74,77,78,80,82,83,84,85,96,98,99,100,103,104,105,108,109,110,111,113,114,117,119,120,121,122,124,125,126,127,129,130,131,132,133,136,137,138,139,140,142,143,144,145,146],"71":[147],"83":[147]},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/nodes/render-types/CanvasNodeDefault.vue":{"22":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"52":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"53":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"54":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"57":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"66":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"67":[147],"69":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"90":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"96":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"109":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"117":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"130":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"139":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"151":[0,6,7,9,147,13,14,22,26,42,45,48,49,50,59,60,62,63,66,75,76,78,79,81,98,101,102,104,105,106,107,112,113,114,115,116,117,118,120,123,124,125,126,127,128,133,134,135,138,139,141,142,144,145,146],"157":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,55,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"159":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,55,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"164":[7,147,81,104,105,107,109,129,135],"168":[1,2,4,8,9,147,11,12,14,22,27,49,60,62,66,74,75,76,79,81,84,85,110,111,113,114,116,117,118,119,120,121,123,124,125,126,127,128,129,134,135],"175":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/nodes/render-types/parts/CanvasNodeSettingsIcons.vue":{"16":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"17":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"19":[147],"23":[147],"30":[147],"43":[147],"46":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"51":[147],"60":[147,124],"68":[147],"77":[147],"85":[147],"94":[147],"104":[147],"113":[147],"121":[147],"131":[147]},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/nodes/render-types/parts/CanvasNodeStatusIcons.vue":{"23":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"39":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"42":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"43":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"46":[0,1,2,3,4,5,7,8,147,11,12,21,22,23,24,37,38,52,53,55,57,58,60,61,67,74,76,78,79,80,83,96,98,100,103,105,111,113,114,117,120,124,126,127,128,129,130,132,136,140,141,142,143,145,146],"47":[147],"48":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"52":[0,1,2,3,4,5,6,7,8,9,147,11,12,14,21,22,23,24,26,27,28,37,38,45,49,50,52,53,55,57,58,59,60,61,62,63,64,65,66,67,74,75,76,78,79,80,81,82,83,85,96,98,100,102,103,104,105,106,109,110,111,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,134,135,136,140,141,142,143,145,146],"58":[147],"59":[147],"67":[147],"71":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"80":[147],"81":[147],"93":[147],"95":[0,1,2,7,8,147,38,113,114,117,124,141,142],"105":[147],"107":[1,2,3,4,5,7,8,147,11,12,21,22,23,24,37,38,52,53,55,57,58,60,61,67,74,76,78,79,80,83,96,98,100,103,105,111,113,114,117,120,124,126,127,128,129,130,132,136,140,141,142,143,145,146],"123":[147],"126":[147,67,75,82,110,118,127,129,131,135]},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/nodes/render-types/parts/CanvasNodeTrigger.vue":{"33":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"34":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"45":[0,1,2,3,4,5,6,7,8,9,147,11,12,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"53":[147],"54":[147],"58":[6,7,8,9,147,37,52,80,81,117,126],"63":[147],"64":[6,7,8,9,147,37,52,80,81,117,126],"67":[0,1,2,3,4,5,6,7,8,9,147,11,12,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"68":[0,1,2,3,4,5,6,7,8,9,147,11,12,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"70":[147],"78":[147],"86":[147,66,114],"89":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"94":[147,66,114],"116":[6,7,8,9,147,37,52,80,81,117,126]},"packages/frontend/editor-ui/src/features/workflows/canvas/composables/useCanvas.ts":{"4":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/features/workflows/canvas/composables/useCanvasLayout.ts":{"54":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"67":[5,147,101],"74":[5,147,101],"79":[5,147,101],"80":[5,147,101],"81":[5,147,101],"88":[5,147,101],"92":[5,147,101],"96":[5,147,101],"122":[5,147],"123":[5,147],"125":[5,147],"126":[5,147],"142":[5,147,101],"144":[5,147,101],"147":[5,147,101],"151":[5,147,101],"153":[5,147,101],"160":[5,147,101],"162":[5,147,101],"164":[5,147,101],"169":[5,147,101],"183":[147],"188":[5,147,101],"189":[5,147,101],"195":[5,147,101],"196":[5,147,101],"201":[5,147,101],"210":[5,147],"212":[5,147,101],"216":[5,147,101],"224":[147],"238":[147],"243":[147],"244":[147],"250":[147],"251":[147],"257":[5,147,101],"258":[5,147,101],"279":[5,147,101],"289":[5,147,101],"298":[5,147,101],"300":[5,147,101],"304":[5,147,101],"309":[147],"323":[147],"329":[147],"347":[5,147,101],"355":[147],"359":[147],"369":[147],"370":[147],"371":[147],"377":[5,147,101],"381":[5,147,101],"382":[5,147,101],"387":[5,147,101],"394":[5,147,101],"398":[5,147,101],"403":[147],"414":[147],"417":[147],"425":[147],"436":[5,147,101],"445":[5,147,101],"448":[147],"454":[5,147,101],"467":[147],"478":[147],"497":[5,147,101],"509":[5,147,101],"510":[147],"513":[147],"519":[147],"520":[147],"531":[5,147,101],"535":[5,147,101],"543":[5,147,101],"544":[147],"548":[147],"550":[147],"558":[147],"559":[147],"577":[5,147,101],"579":[5,147,101]},"packages/frontend/editor-ui/src/features/workflows/canvas/composables/useCanvasMapping.ts":{"61":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"75":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"83":[147,74,83,108,114,134,143,146],"95":[1,2,3,4,7,8,147,11,12,21,23,24,26,27,28,36,37,38,52,53,54,55,56,57,58,60,61,62,64,65,67,68,69,74,77,78,80,82,83,84,85,96,98,99,100,103,104,105,108,109,110,111,113,114,117,119,120,121,122,124,125,126,127,129,130,131,132,133,136,137,138,139,140,142,143,144,145,146],"102":[5,147,10],"109":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"137":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"139":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"158":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"159":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"168":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"169":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"175":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"176":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"196":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"197":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"203":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"208":[0,1,2,4,6,7,8,9,147,11,12,26,27,28,38,45,49,50,59,60,61,62,63,64,65,66,67,74,75,79,81,82,85,102,103,104,105,110,112,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135,141,142,146],"219":[0,1,2,4,6,7,8,9,147,11,12,26,27,28,38,45,49,50,59,60,61,62,63,64,65,66,67,74,75,79,81,82,85,102,103,104,105,110,112,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135,141,142,146],"250":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"251":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"257":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"258":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"268":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"269":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"281":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"282":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"289":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,55,57,58,59,60,61,62,63,64,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,141,142,143,145,146],"293":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"294":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"296":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"380":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"381":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"394":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"395":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"417":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"418":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"419":[0,1,2,4,6,7,8,9,147,11,12,26,27,28,38,45,49,50,59,60,61,62,63,64,65,66,67,74,75,79,81,82,85,102,103,104,105,110,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135,141,142],"476":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"485":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"506":[147,83,108,134],"507":[147,74,83,108,114,134,143,146],"527":[147,74,83,108,114,134,143,146],"541":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"542":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"561":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"566":[0,1,2,4,6,7,8,9,147,11,12,26,27,28,38,45,49,50,59,60,61,62,63,64,65,66,67,74,75,79,81,82,85,102,103,104,105,110,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135,141,142],"569":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"575":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"621":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"622":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,55,57,58,59,60,61,62,63,64,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,141,142,143,145,146],"639":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,55,57,58,59,60,61,62,63,64,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,141,142,143,145,146],"674":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,55,57,58,59,60,61,62,63,64,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,141,142,143,145,146],"675":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,55,57,58,59,60,61,62,63,64,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,141,142,143,145,146],"690":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,55,57,58,59,60,61,62,63,64,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,141,142,143,145,146],"694":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,55,57,58,59,60,61,62,63,64,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,141,142,143,145,146]},"packages/frontend/editor-ui/src/features/workflows/canvas/composables/useCanvasNode.ts":{"8":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"10":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"33":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"34":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"36":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"37":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"38":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"40":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"41":[147,74,83,108,114,134,143,146],"42":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"44":[147],"45":[147],"46":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"48":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"49":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"50":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"51":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"53":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"54":[0,1,2,4,6,7,8,9,147,11,26,27,28,38,45,49,50,59,60,61,62,63,64,65,66,67,74,75,79,81,82,85,102,103,104,105,110,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135,141,142],"55":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"57":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"59":[147,74,83,108,114,134,143,146],"63":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/features/workflows/canvas/composables/useCanvasNodeGroupActions.ts":{"10":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"18":[147,107],"20":[147,107],"23":[147,107],"26":[147,107],"31":[147],"41":[147],"43":[147,107],"51":[147]},"packages/frontend/editor-ui/src/features/workflows/canvas/composables/useCanvasNodeHandle.ts":{"11":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"14":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"15":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"16":[0,1,2,3,4,5,6,7,8,9,147,11,12,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"17":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"18":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"19":[0,7,8,9,147,52,79,117,126],"20":[147],"21":[147],"22":[147],"23":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/features/workflows/canvas/composables/useCanvasNodeHover.ts":{"10":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"17":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,14,21,22,27,49,52,54,55,56,57,58,60,62,66,67,74,75,76,77,79,81,82,83,84,85,100,103,104,105,106,107,108,109,110,111,112,113,114,116,117,118,119,120,121,123,124,125,126,127,128,129,131,134,135,138,139,140,141,142,143,144,145],"31":[0,1,2,4,6,7,8,9,147,11,12,14,21,22,27,49,52,54,55,56,60,62,66,67,74,75,76,77,79,81,82,83,84,85,100,103,104,105,106,107,109,110,111,112,113,114,116,117,118,119,120,121,123,124,125,126,127,128,129,131,134,135,138,139,140,141,142,143,145],"64":[147],"73":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"77":[7,147,42,50,100,105,112,113,114,115,117,133,139,141,142,146]},"packages/frontend/editor-ui/src/features/workflows/canvas/composables/useCanvasTraversal.ts":{"4":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"5":[147,103],"6":[147],"9":[147,103],"13":[147,103],"17":[147],"18":[147],"21":[147],"26":[147],"27":[147],"32":[147,135],"42":[147,135],"43":[147,135],"46":[147,103],"56":[147,103],"57":[147,103]},"packages/frontend/editor-ui/src/features/workflows/canvas/composables/useViewportAutoAdjust.ts":{"7":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"21":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"27":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"46":[7,147,42,50,100,105,112,113,114,115,117,133,139,141,142,146],"51":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/features/workflows/canvas/composables/useZoomAdjustedValues.ts":{"8":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"17":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"39":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"40":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"60":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"61":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"76":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"77":[0,1,2,3,4,5,6,7,8,9,147,11,12,13,14,21,22,23,24,26,27,28,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/features/workflows/canvas/experimental/composables/useIsInExperimentalNdv.ts":{"4":[1,2,3,4,5,7,8,9,11,12,14,21,22,23,24,27,28,30,33,34,37,38,39,49,51,52,53,55,57,58,60,61,62,65,66,67,74,75,76,79,80,81,82,83,84,85,89,90,91,96,97,98,100,103,104,105,106,109,110,111,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,140,144,145],"8":[3,23,30,33,37,38,39,51,84,89,91,97,98,106,119,120,121,122,127,128,129,130,131,145]},"packages/frontend/editor-ui/src/features/workflows/canvas/experimental/experimentalNdv.store.ts":{"17":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"19":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"24":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,69,74,75,76,77,78,79,80,81,82,83,84,85,90,91,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"54":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"62":[5,84,106],"140":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"141":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/features/workflows/readyToRun/components/ReadyToRunButton.vue":{"13":[3,15,16,18,19,20,22,23,26,37,38,39,40,41,68,69,70,71,72,73,88,89,93,94,96,97,98,133,138,139,144,146],"25":[3,15,16,18,19,20,22,23,26,37,38,39,40,41,68,69,70,71,72,73,88,89,93,94,96,97,98,133,138,139,144,146],"31":[3,15,16,18,19,20,22,23,26,37,38,39,40,41,68,69,70,71,72,73,88,89,93,94,96,97,98,133,138,139,144,146],"53":[3,15,16,18,19,20,22,23,26,37,38,39,40,41,68,69,70,71,72,73,88,89,93,94,96,97,98,133,138,139,144,146]},"packages/frontend/editor-ui/src/features/workflows/readyToRun/composables/useEmptyStateDetection.ts":{"9":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"22":[15,16,18,19,20,22,26,40,41,68,69,70,71,72,73,93,94,96,98,133,138,139,144,146]},"packages/frontend/editor-ui/src/features/workflows/readyToRun/stores/readyToRun.store.ts":{"22":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"59":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"66":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"74":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"90":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"91":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"110":[3,15,16,18,19,20,22,23,26,37,38,39,40,41,68,69,70,71,72,73,88,89,93,94,96,97,98,133,138,139,144,146],"208":[3,15,16,18,19,20,22,23,26,37,38,39,40,41,68,69,70,71,72,73,88,89,93,94,96,97,98,133,138,139,144,146],"220":[15,16,18,19,20,22,26,40,41,68,69,70,71,72,73,93,94,96,98,133,138,139,144,146],"224":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/features/workflows/templates/components/SetupWorkflowCredentialsButton.vue":{"28":[68,78],"32":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"36":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"46":[0,1,2,3,4,5,7,8,11,12,21,22,23,24,26,27,28,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,76,77,78,79,80,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"49":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"55":[68,78,145,146],"59":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"76":[68,78,145,146],"84":[3,7,8,21,23,24,37,52,53,55,57,58,61,67,68,74,80,83,96,98,100,105,111,117,124,126,127,129,130,132,140,143,145],"94":[68],"99":[68,78,145],"103":[68,78,145],"111":[5,7,10,42,50,68,100,105,112,113,114,115,117,133,139,141,142],"115":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/features/workflows/templates/templates.store.ts":{"48":[146],"54":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"89":[146],"90":[146],"95":[145],"96":[145],"99":[145,146],"100":[145,146],"106":[145],"108":[146],"109":[146],"112":[146],"113":[146],"120":[146],"124":[146],"125":[146],"132":[146],"136":[146],"137":[146],"165":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"169":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"178":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"193":[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,18,19,20,21,22,23,24,26,27,28,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,88,89,93,94,96,97,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"198":[127],"205":[146],"209":[145,146],"212":[145,146],"213":[145,146],"224":[145,146],"225":[145,146],"231":[146],"235":[146],"243":[146],"248":[146],"293":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"298":[78,145,146],"304":[145,146],"320":[145],"338":[146],"354":[146],"369":[146],"374":[146],"420":[78,145,146],"428":[78,145,146],"436":[78,145,146]},"packages/frontend/editor-ui/src/features/workflows/templates/utils/typeGuards.ts":{"8":[147,145],"14":[147,145],"20":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/frontend/editor-ui/src/features/workflows/templates/utils/workflowSamples.ts":{"14":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"22":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"26":[0,1,2,3,4,5,6,7,8,9,147,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"43":[147],"54":[147],"94":[147],"100":[147],"103":[147]},"packages/frontend/editor-ui/src/features/workflows/workflowHistory/components/WorkflowHistoryButton.vue":{"12":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"24":[1,2,3,5,7,8,11,27,28,38,60,64,67,68,74,82,85,99,100,103,104,105,109,110,111,113,114,117,120,121,124,125,126,127,128,129,131,135,136,140,141,142,144,145],"31":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"32":[1,2,3,4,5,7,8,10,11,12,22,27,28,37,38,52,60,61,64,65,67,68,69,74,75,81,82,85,99,100,103,104,105,107,109,110,111,113,114,117,118,119,120,121,122,124,125,126,127,128,129,131,133,135,136,137,138,140,141,142,144,145,146],"42":[0,6,7,8,9,22,26,27,38,42,45,48,49,50,59,60,62,63,66,68,74,75,76,79,81,96,98,99,100,104,105,106,107,110,111,112,113,114,115,116,117,118,120,121,123,124,125,126,127,128,133,134,135,136,138,139,141,142,144,145,146],"49":[0,1,2,3,4,5,6,7,8,9,10,11,12,22,26,27,28,37,38,42,45,48,49,50,52,59,60,61,62,63,64,65,66,67,68,69,74,75,76,79,81,82,85,96,98,99,100,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,131,133,134,135,136,137,138,139,140,141,142,144,145,146],"52":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"55":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"62":[0,1,2,3,4,5,6,7,8,9,10,11,12,21,22,23,24,26,27,28,36,37,38,42,45,48,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,74,75,76,77,78,79,80,81,82,83,84,85,96,98,99,100,104,105,106,107,108,110,111,112,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,131,132,134,135,136,137,138,139,140,141,143,144,145,146]},"packages/frontend/editor-ui/src/features/workflows/workflowHistory/workflowHistory.store.ts":{"22":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146],"28":[112],"30":[5,112],"34":[112],"38":[112],"44":[5,105,112,113,114,115,117,141,142]},"packages/localhost-44213/assets/_plugin-vue_export-helper-Da88TEg1.js":{"2":[3,6,14,20,22,69,70,75,77,83,111,113]},"packages/localhost-44213/assets/chunk-CC9Q-vWm.js":{"8":[3,6,14,20,22,69,70,75,77,83,111,113],"9":[3,6,14,20,22,69,70,75,77,83,111,113],"10":[3,6,14,20,22,69,70,75,77,83,111,113],"19":[3,6,14,20,22,69,70,75,77,83,111,113],"23":[3,6,14,20,22,69,70,75,77,83,111,113],"29":[3,6,14,20,22,69,70,75,77,83,111,113],"33":[3,6,14,20,22,69,70,75,77,83,111,113],"34":[3,6,14,20,22,69,70,75,77,83,111,113]},"packages/localhost-44213/assets/shield-alt-J5nzuCWH.js":{"8":[3,111]},"packages/vite/source-map-js-shim.ts":{"1":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146]},"packages/@n8n/chat/src/api/generic.ts":{"1":[6,7,8,9,68,81,102,117],"5":[6,7,8,9,68,81,102,117],"38":[68],"49":[6,7,8,9,68,81,102,117],"56":[68]},"packages/@n8n/chat/src/api/message.ts":{"9":[68],"24":[6,7,8,9,68,81,102,117],"68":[68],"73":[68],"82":[68],"119":[68],"151":[68],"211":[68],"245":[68]},"packages/@n8n/chat/src/components/Chat.vue":{"14":[6,7,8,9,68,81,102,117],"20":[6,7,8,9,68,81,102,117],"25":[68],"27":[68],"28":[68],"31":[6,7,8,9,68,81,102,117],"36":[6,7,8,9,68,81,102,117],"41":[6,7,8,9,68,81,102,117],"46":[6,7,8,9,68,81,102,117],"51":[68],"55":[68],"106":[6,7,8,9,68,81,102,117],"108":[7,68,117],"116":[6,7,8,9,68,81,102,117],"122":[68],"127":[6,7,8,9,68,81,102,117],"131":[6,7,8,9,68,81,102,117],"149":[6,7,8,9,68,81,102,117]},"packages/@n8n/chat/src/components/GetStartedFooter.vue":{"5":[6,7,8,9,68,81,102,117]},"packages/@n8n/chat/src/components/Input.vue":{"23":[6,7,8,9,68,81,102,117],"48":[6,7,8,9,68,81,102,117],"54":[6,7,8,9,68,81,102,117],"55":[68],"58":[6,7,8,9,68,81,102,117],"59":[68],"61":[6,7,8,9,68,81,102,117],"77":[68],"93":[68],"97":[6,7,8,9,68,81,102,117],"104":[6,7,8,9,68,81,102,117],"117":[68],"129":[68],"135":[6,7,8,9,68,81,102],"141":[68],"146":[6,7,8,9,68,81,102,117],"157":[68],"170":[68],"189":[68],"202":[68],"205":[68],"208":[68],"211":[68],"218":[68],"228":[68],"249":[6,7,8,9,68,81,102,117],"279":[68,102],"288":[68],"301":[68,102],"312":[68],"317":[6,7,8,9,68,81,102,117],"325":[6,7,8,9,68,81,102,117],"336":[6,7,8,9,68,81,102,117],"364":[68]},"packages/@n8n/chat/src/components/Layout.vue":{"6":[6,7,8,9,68,81,102,117],"8":[6,7,8,9,68,81,102,117],"15":[6,7,8,9,68,81,102,117],"20":[68],"24":[6,7,8,9,68,81,102,117]},"packages/@n8n/chat/src/components/MarkdownRenderer.vue":{"16":[6,7,8,9,81,102,117],"22":[6,7,8,9,81,102,117],"42":[6,7,8,9,81,102,117]},"packages/@n8n/chat/src/components/Message.vue":{"20":[6,7,8,9,68,81,102,117],"25":[6,7,8,9,68,81,102,117],"29":[6,7,8,9,68,81,102,117],"37":[6,7,8,9,68,81,102,117],"49":[68],"50":[68],"52":[68],"57":[6,7,8,9,68,81,102,117],"69":[6,7,8,9,68,81,102,117]},"packages/@n8n/chat/src/components/MessageActions.vue":{"8":[6,7,8,9,68,81,102,117],"16":[68],"30":[68],"35":[6,7,8,9,68,81,102,117],"43":[68]},"packages/@n8n/chat/src/components/MessageTyping.vue":{"8":[6,7,8,9,68,81,102,117],"23":[6,7,8,9,68,81,102,117],"31":[6,7,8,9,68,81,102,117],"34":[6,7,8,9,68,81,102,117]},"packages/@n8n/chat/src/components/MessagesList.vue":{"19":[6,7,8,9,68,81,102,117],"23":[6,7,8,9,68,81,102,117],"24":[6,7,8,9,68,81,102,117],"32":[6,7,8,9,68,81,102,117],"41":[68],"48":[68],"53":[6,7,8,9,68,81,102,117],"55":[6,7,8,9,68,81,102,117]},"packages/@n8n/chat/src/components/PoweredBy.vue":{"2":[6,7,8,9,68,81,102,117]},"packages/@n8n/chat/src/composables/useI18n.ts":{"5":[6,7,8,9,81,102,117],"9":[6,7,8,9,81,102,117],"17":[6,7,8,9,81,102,117]},"packages/@n8n/chat/src/composables/useOptions.ts":{"6":[6,7,8,9,81,102,117]},"packages/@n8n/chat/src/plugins/chat.ts":{"26":[6,7,8,9,68,81,102,117],"41":[6,7,8,9,68,81,102,117],"69":[68],"77":[68],"100":[68],"130":[68],"143":[68],"146":[68],"149":[68],"193":[6,7,8,9,68,81,102,117],"210":[6,7,8,9,68,81,102,117],"218":[6,7,8,9,68,81,102,117],"219":[68],"226":[6,7,8,9,68,81,102,117],"235":[6,7,8,9,68,81,102,117],"295":[6,7,8,9,68,81,102,117],"302":[6,7,8,9,68,81,102,117],"318":[68],"334":[6,7,8,9,68,81,102,117]},"packages/@n8n/chat/src/utils/streaming.ts":{"22":[6,7,8,9,68,81,102,117],"24":[68],"31":[68],"46":[68],"51":[68],"57":[68],"66":[68],"82":[68],"88":[68],"89":[68],"92":[68],"96":[68],"100":[68],"102":[68],"103":[68],"106":[68],"113":[6,7,8,9,68,81,102,117],"122":[68],"127":[68]},"packages/@n8n/design-system/src/components/N8nIcon/custom/node-success.svg":{"11":[0,1,2,4,6,7,8,9,11,26,27,28,38,45,49,50,59,60,61,62,63,64,65,66,67,74,75,79,81,82,85,102,103,104,105,110,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135,141,142]},"packages/@n8n/design-system/src/components/N8nIcon/custom/schema.svg":{"8":[6,7,8,9,81,102,117]},"packages/@n8n/design-system/src/components/N8nIcon/nodes/edit-fields.svg":{"11":[1,2,6,7,9,13,14,24,26,42,45,49,50,62,63,66,67,76,77,79,81,82,83,85,101,102,103,104,106,107,109,112,114,116,117,118,120,122,123,124,125,126,127,128,129,132,133,134,135,138,143]},"packages/frontend/editor-ui/src/app/composables/usePushConnection/handlers/executionFinished.ts":{"66":[0,1,2,4,6,7,8,9,11,26,27,28,38,45,49,50,59,60,61,62,63,64,65,66,67,68,74,75,79,81,82,85,102,103,104,105,110,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135,141,142],"175":[0,1,2,4,6,7,8,9,11,26,27,28,38,45,49,50,59,60,61,62,63,64,65,66,67,68,74,75,79,81,82,85,102,103,104,105,110,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135,141,142],"184":[4,6,7,9,11,26,27,28,45,49,50,59,60,62,63,64,66,67,68,74,81,82,85,102,104,105,113,114,115,116,117,118,123,124,125,127,128,129,134,135,141,142],"212":[0,1,2,4,6,7,8,9,11,26,27,28,38,45,49,50,59,60,61,62,63,64,65,66,67,68,74,75,79,81,82,85,102,103,104,105,110,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135,141,142],"243":[0,1,2,4,6,7,8,9,11,26,27,28,38,45,49,50,59,60,61,62,63,64,65,66,67,68,74,75,79,81,82,85,102,103,104,105,110,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135,141,142],"256":[0,1,2,4,6,7,8,9,11,26,27,28,38,45,49,50,59,60,61,62,63,64,65,66,67,68,74,75,79,81,82,85,102,103,104,105,110,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135,141,142],"282":[68],"302":[68],"317":[0,1,2,7,8,38,68,113,114,117,124,141,142],"397":[1,4,6,7,9,11,26,27,28,45,49,50,59,60,61,62,63,64,65,66,67,68,74,75,79,81,82,85,102,103,104,105,110,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135,141,142],"415":[1,4,6,7,9,11,26,27,28,45,49,50,59,60,61,62,63,64,65,66,67,68,74,75,79,81,82,85,102,103,104,105,110,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135,141,142],"481":[0,1,2,4,6,7,8,9,11,26,27,28,38,45,49,50,59,60,61,62,63,64,65,66,67,68,74,75,79,81,82,85,102,103,104,105,110,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135,141,142]},"packages/frontend/editor-ui/src/app/composables/usePushConnection/handlers/executionStarted.ts":{"16":[0,1,2,4,6,7,8,9,11,12,26,27,28,38,45,49,50,59,60,61,62,63,64,65,66,67,68,74,75,79,81,82,85,102,103,104,105,110,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135,141,142]},"packages/frontend/editor-ui/src/app/composables/usePushConnection/handlers/nodeExecuteAfter.ts":{"18":[0,1,2,4,6,7,8,9,11,12,26,27,28,38,45,49,50,59,60,61,62,63,64,65,66,67,68,74,75,79,81,82,85,102,103,104,105,110,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135,141,142],"46":[0,1,2,4,6,7,8,9,11,12,26,27,28,38,45,49,50,59,60,61,62,63,64,65,66,67,68,74,75,79,81,82,85,102,103,104,105,110,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135,141,142],"47":[0,1,2,4,6,7,8,9,11,12,26,27,28,38,45,49,50,59,60,61,62,63,64,65,66,67,68,74,75,79,81,82,85,102,103,104,105,110,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135,141,142]},"packages/frontend/editor-ui/src/app/composables/usePushConnection/handlers/nodeExecuteAfterData.ts":{"15":[0,1,2,4,6,7,8,9,11,12,26,27,28,38,45,49,50,59,60,61,62,63,64,65,66,67,68,74,75,79,81,82,85,102,103,104,105,110,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135,141,142],"17":[0,1,2,4,6,7,8,9,11,12,26,27,28,38,45,49,50,59,60,61,62,63,64,65,66,67,68,74,75,79,81,82,85,102,103,104,105,110,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135,141,142]},"packages/frontend/editor-ui/src/app/composables/usePushConnection/handlers/nodeExecuteBefore.ts":{"11":[0,1,2,4,6,7,8,9,11,12,26,27,28,38,45,49,50,59,60,61,62,63,64,65,66,67,68,74,75,79,81,82,85,102,103,104,105,110,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135,141,142]},"packages/frontend/editor-ui/src/app/composables/usePushConnection/handlers/testWebhookReceived.ts":{"10":[6,7,8,9,12,26,60,67,68,81,102,114,117,129]},"packages/frontend/editor-ui/src/app/composables/usePushConnection/handlers/trackNodeExecution.ts":{"11":[0,1,2,4,6,7,8,9,11,12,26,27,28,38,45,49,50,59,60,61,62,63,64,65,66,67,68,74,75,79,81,82,85,102,103,104,105,110,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135,141,142]},"packages/frontend/editor-ui/src/app/composables/useRunWorkflow.ts":{"82":[0,1,2,4,6,7,8,9,11,12,26,27,28,38,49,50,59,60,61,62,63,64,65,66,67,74,75,79,81,82,85,102,103,104,105,110,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135,141,142,146],"98":[0,1,2,4,6,7,8,9,11,12,26,27,28,38,49,50,59,60,61,62,63,64,65,66,67,74,75,79,81,82,85,102,103,104,105,110,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135,141,142,146],"113":[0,1,2,4,6,7,8,9,11,12,26,27,28,38,49,50,59,60,61,62,63,64,65,66,67,74,75,79,81,82,85,102,103,104,105,110,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135,141,142,146],"145":[0,1,2,4,6,7,8,9,11,12,26,27,28,38,49,50,59,60,61,62,63,64,65,66,67,74,75,79,81,82,85,102,103,104,105,110,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135,141,142,146],"267":[0,1,2,4,6,7,8,9,11,12,26,27,28,38,49,50,59,60,61,62,63,64,65,66,67,74,75,79,81,82,85,102,103,104,105,110,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135,141,142,146],"270":[0,1,2,4,6,7,8,9,11,12,26,27,28,38,49,50,59,60,61,62,63,64,65,66,74,75,79,81,82,85,102,103,104,105,110,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135,141,142,146],"302":[6,7,9,81,102,117],"313":[1,65,67,103,114,129],"337":[1,65,67,103,114,129],"380":[67,75,110,118,131],"433":[12,60],"471":[0,1,2,4,6,7,8,9,11,12,26,27,28,38,49,50,59,60,61,62,63,64,65,66,67,74,75,79,81,82,85,102,103,104,105,110,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135,141,142,146],"522":[117],"569":[117],"597":[4,7,11,12,26,27,28,38,49,50,59,60,62,63,64,66,67,74,82,85,104,105,113,114,115,116,117,118,123,124,125,127,128,129,134,135,141,142,146]},"packages/frontend/editor-ui/src/app/stores/executionData.store.ts":{"41":[0,1,2,4,6,7,8,9,147,11,12,13,14,26,27,28,38,42,45,49,50,59,60,61,62,63,64,65,66,67,74,75,79,81,82,85,101,102,103,104,105,110,112,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,131,133,134,135,139,141,142,146],"48":[0,1,2,4,6,7,8,9,147,11,12,13,14,26,27,28,38,42,45,49,50,59,60,61,62,63,64,65,66,67,74,75,79,81,82,85,101,102,103,104,105,110,112,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,131,133,134,135,139,141,142,146],"58":[0,1,2,4,6,7,8,9,147,11,12,13,14,26,27,28,38,42,45,49,50,59,60,61,62,63,64,65,66,67,74,75,79,81,82,85,101,102,103,104,105,110,112,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,131,133,134,135,139,141,142,146],"59":[0,1,2,4,6,7,8,9,147,11,12,13,14,26,27,28,38,42,45,49,50,59,60,61,62,63,64,65,66,67,74,75,79,81,82,85,101,102,103,104,105,110,112,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,131,133,134,135,139,141,142,146],"67":[0,1,2,4,6,7,8,9,147,11,12,13,14,26,27,28,38,42,45,49,50,59,60,61,62,63,64,65,66,67,74,75,79,81,82,85,101,102,103,104,105,110,112,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,131,133,134,135,139,141,142,146],"71":[147],"84":[0,1,2,4,6,7,8,9,147,11,12,26,27,28,38,45,49,50,59,60,61,62,63,64,65,66,67,74,75,79,81,82,85,102,103,104,105,110,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135,141,142],"101":[0,1,2,4,6,7,8,9,147,11,12,26,27,28,38,45,49,50,59,60,61,62,63,64,65,66,67,74,75,79,81,82,85,102,103,104,105,110,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135,141,142],"104":[0,1,2,4,6,7,8,9,147,11,12,26,27,28,38,45,49,50,59,60,61,62,63,64,65,66,67,74,75,79,81,82,85,102,103,104,105,110,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135,141,142],"107":[0,1,2,4,6,7,8,9,147,11,12,26,27,28,38,45,49,50,59,60,61,62,63,64,65,66,67,74,75,79,81,82,85,102,103,104,105,110,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135,141,142],"110":[1,2,147,67,75,105,110,114,117,118,125,128,131,142],"113":[1,2,147,67,75,105,110,114,117,118,125,128,131,142],"119":[0,1,2,4,6,7,8,9,147,11,12,13,14,26,27,28,38,42,45,49,50,59,60,61,62,63,64,65,66,67,74,75,79,81,82,85,101,102,103,104,105,110,112,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,131,133,134,135,139,141,142,146],"127":[0,1,2,4,6,7,8,9,147,11,12,13,14,26,27,28,38,42,45,49,50,59,60,61,62,63,64,65,66,67,74,75,79,81,82,85,101,102,103,104,105,110,112,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,131,133,134,135,139,141,142,146],"140":[0,1,2,4,6,7,8,9,147,11,12,26,27,28,38,45,49,50,59,60,61,62,63,64,65,66,67,74,75,79,81,82,85,102,103,104,105,110,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135,141,142,146],"147":[147],"161":[0,1,2,4,6,7,8,9,147,11,26,27,28,38,45,49,50,59,60,61,62,63,64,65,66,67,74,75,79,81,82,85,102,103,104,105,110,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135,141,142],"165":[0,1,2,4,6,7,8,9,147,11,12,26,27,28,38,45,49,50,59,60,61,62,63,64,65,66,67,74,75,79,81,82,85,102,103,104,105,110,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135,141,142,146],"177":[0,1,2,4,6,7,8,9,147,11,12,26,27,28,38,45,49,50,59,60,61,62,63,64,65,66,67,74,75,79,81,82,85,102,103,104,105,110,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135,141,142],"185":[0,1,2,4,6,7,8,9,147,11,12,26,27,28,38,45,49,50,59,60,61,62,63,64,65,66,67,74,75,79,81,82,85,102,103,104,105,110,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135,141,142],"200":[147,117],"205":[0,1,2,4,6,7,8,9,147,11,12,26,27,28,38,45,49,50,59,60,61,62,63,64,65,66,67,74,75,79,81,82,85,102,103,104,105,110,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135,141,142],"224":[9,147,11,60,66,117,125,128,134,135],"229":[9,147,11,60,66,117,125,128,134,135],"248":[0,1,2,4,6,7,8,9,147,11,12,26,27,28,38,45,49,50,59,60,61,62,63,64,65,66,67,74,75,79,81,82,85,102,103,104,105,110,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135,141,142],"252":[147],"270":[0,1,2,4,6,7,8,9,147,11,12,26,27,28,38,45,49,50,59,60,61,62,63,64,65,66,67,74,75,79,81,82,85,102,103,104,105,110,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135,141,142],"273":[0,1,2,4,6,7,8,9,147,11,12,26,27,28,38,45,49,50,59,60,61,62,63,64,65,66,67,74,75,79,81,82,85,102,103,104,105,110,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135,141,142],"285":[147],"296":[147,105],"316":[147],"317":[147],"321":[147],"333":[147,105],"334":[147,105],"342":[147,105],"378":[147,117],"386":[147,117],"402":[147],"446":[147,13,14,42,45,50,102,112,117,133,139,141,142]},"packages/frontend/editor-ui/src/app/utils/formatters/dateFormatter.ts":{"4":[1,2,9,11,27,49,60,61,62,65,66,67,75,85,110,113,114,117,118,120,122,123,124,125,127,128,129,131,134,135],"15":[105,113,114,115,117,141,142],"27":[6,7,8,9,81,102,117],"29":[6,7,8,9,81,102,117]},"packages/frontend/editor-ui/src/app/utils/mappingUtils.ts":{"11":[1,2,6,7,9,147,11,12,14,27,49,60,61,62,65,66,67,74,75,79,81,82,85,102,104,106,110,111,113,114,116,117,118,119,120,121,122,123,124,125,127,128,129,131,132,134,135],"15":[1,2,6,7,9,147,11,12,14,27,49,60,61,62,65,66,67,74,75,79,81,82,85,102,104,106,110,111,113,114,116,117,118,119,120,121,122,123,124,125,127,128,129,131,132,134,135],"16":[1,2,6,7,9,147,11,12,14,27,49,60,61,62,65,66,67,74,75,79,81,82,85,102,104,106,110,111,113,114,116,117,118,119,120,121,122,123,124,125,127,128,129,131,132,134,135],"29":[6,7,9,147,11,12,14,27,60,61,62,65,66,67,74,75,79,81,85,102,104,106,110,111,113,114,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135],"33":[6,7,9,147,11,12,14,27,60,61,62,65,66,67,75,79,81,85,102,110,111,113,114,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135],"53":[6,7,9,147,11,12,14,27,60,61,62,65,66,67,74,75,79,81,85,102,104,106,110,111,113,114,116,117,118,119,120,121,122,123,124,125,127,128,129,131,132,134,135],"70":[147],"82":[147,120],"96":[147,120]},"packages/frontend/editor-ui/src/app/utils/pairedItemUtils.ts":{"19":[0,1,2,4,6,7,8,9,147,11,12,14,26,27,28,38,45,49,50,59,60,61,62,63,64,65,66,67,74,75,79,81,82,85,102,103,104,105,110,111,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135,141,142],"23":[147,120,128],"48":[147,120,128],"58":[147,120,128],"61":[0,1,2,4,6,7,8,9,147,11,26,27,28,38,45,49,50,59,60,61,62,63,64,65,66,67,74,75,79,81,82,85,102,103,104,105,110,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135,141,142],"89":[0,4,6,7,9,147,26,27,28,45,49,50,59,61,62,63,64,67,74,75,79,81,82,85,102,104,105,110,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135,141,142],"95":[0,1,2,4,6,7,8,9,147,11,26,27,28,38,45,49,50,59,60,61,62,63,64,65,66,67,74,75,79,81,82,85,102,103,104,105,110,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135,141,142],"124":[0,4,6,7,9,147,11,26,27,28,45,49,50,59,60,61,62,63,64,66,67,74,75,79,81,82,85,102,104,105,110,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135,141,142],"138":[0,1,2,4,6,7,8,9,147,11,26,27,28,38,45,49,50,59,60,61,62,63,64,65,66,67,74,75,79,81,82,85,102,103,104,105,110,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135,141,142],"143":[0,1,2,4,6,7,8,9,147,11,26,27,28,38,45,49,50,59,60,61,62,63,64,65,66,67,74,75,79,81,82,85,102,103,104,105,110,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135,141,142],"152":[147,63],"168":[0,1,2,4,6,7,8,9,147,11,12,26,27,28,38,45,49,50,59,60,61,62,63,64,65,66,67,74,75,79,81,82,85,102,103,104,105,110,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135,141,142,146],"171":[0,1,2,4,6,7,8,9,147,11,26,27,28,38,45,49,50,59,60,61,62,63,64,65,66,67,74,75,79,81,82,85,102,103,104,105,110,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135,141,142],"172":[0,1,2,4,6,7,8,9,147,11,26,27,28,38,45,49,50,59,60,61,62,63,64,65,66,67,74,75,79,81,82,85,102,103,104,105,110,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135,141,142],"173":[0,1,2,4,6,7,8,9,147,11,26,27,28,38,45,49,50,59,60,61,62,63,64,65,66,67,74,75,79,81,82,85,102,103,104,105,110,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135,141,142],"188":[0,1,2,4,6,7,8,9,147,11,12,26,27,28,38,45,49,50,59,60,61,62,63,64,65,66,67,74,75,79,81,82,85,102,103,104,105,110,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135,141,142,146],"197":[0,1,2,4,6,7,8,9,147,11,26,27,28,38,45,49,50,59,60,61,62,63,64,65,66,67,74,75,79,81,82,85,102,103,104,105,110,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135,141,142],"209":[0,1,2,4,6,7,8,9,147,11,12,26,27,28,38,45,49,50,59,60,61,62,63,64,65,66,67,74,75,79,81,82,85,102,103,104,105,110,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135,141,142,146],"229":[0,1,2,4,6,7,8,9,147,11,26,27,28,38,45,49,50,59,60,61,62,63,64,65,66,67,74,75,79,81,82,85,102,103,104,105,110,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135,141,142],"230":[0,1,2,4,6,7,8,9,147,11,26,27,28,38,45,49,50,59,60,61,62,63,64,65,66,67,74,75,79,81,82,85,102,103,104,105,110,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135,141,142]},"packages/frontend/editor-ui/src/app/utils/workflowUtils.ts":{"11":[0,1,2,6,7,8,9,147,13,14,22,26,27,28,42,45,48,49,50,59,60,62,63,64,66,67,68,74,75,76,79,81,82,96,98,99,102,104,105,106,107,110,112,114,115,116,117,118,119,120,123,124,125,126,127,128,129,133,134,135,138,139,141,142,144,145,146],"15":[147],"26":[147,101],"36":[147,101],"49":[0,1,2,4,6,7,8,9,147,13,14,22,26,27,28,42,45,48,49,50,59,60,62,63,64,66,67,74,75,76,77,79,81,82,83,84,85,98,99,102,104,105,106,107,109,110,112,114,115,116,117,118,119,120,123,124,125,126,127,128,129,133,134,135,138,139,141,142,143,144,145,146],"60":[0,1,2,4,6,7,8,9,147,13,14,22,26,27,28,42,45,48,49,50,59,60,62,63,64,66,74,75,76,77,79,81,82,83,84,85,102,104,105,106,107,109,110,112,114,115,116,117,118,119,120,123,124,125,126,127,128,129,133,134,135,138,141,142,143,145,146],"80":[0,1,2,4,6,7,8,9,147,13,14,22,26,27,28,42,45,48,49,50,59,60,62,63,64,66,67,68,74,75,76,77,79,81,82,83,84,85,96,98,99,102,104,105,106,107,109,110,112,114,115,116,117,118,119,120,123,124,125,126,127,128,129,133,134,135,138,139,141,142,143,144,145,146],"100":[0,1,2,4,6,7,8,9,147,13,14,22,26,27,28,42,45,48,49,50,59,60,62,63,64,66,74,75,76,77,79,81,82,83,84,85,102,104,105,106,107,109,110,112,114,115,116,117,118,119,120,123,124,125,126,127,128,129,133,134,135,138,141,142,143,145,146],"103":[0,1,2,4,6,7,8,9,147,13,14,22,26,27,28,42,45,48,49,50,59,60,62,63,64,66,74,75,76,77,79,81,82,83,84,85,102,104,105,106,107,109,110,112,114,115,116,117,118,119,120,123,124,125,126,127,128,129,133,134,135,138,141,142,143,145,146],"138":[5,147],"145":[5,147],"146":[5,147],"158":[5,147],"167":[5,147]},"packages/frontend/editor-ui/src/features/agents/composables/useMessageAgentSessionLink.ts":{"19":[68],"32":[6,7,8,9,68,81,102,117],"60":[6,7,8,9,68,81,102,117],"65":[6,7,8,9,68,81,102,117],"89":[68]},"packages/frontend/editor-ui/src/features/ai/assistant/components/Agent/BuildModeEmptyState.vue":{"5":[0,6,7,8,9,11,12,13,14,21,22,23,24,26,27,28,37,38,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,90,91,96,98,99,100,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,140,141,142,143,144,145,146],"6":[0,6,7,8,9,11,12,13,14,21,22,23,24,26,27,28,38,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,74,75,76,77,78,79,80,81,82,83,84,85,90,91,96,98,99,100,104,105,106,107,108,110,111,112,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,131,132,134,135,136,138,139,140,141,143,144,145,146]},"packages/frontend/editor-ui/src/features/execution/logs/components/ChatMessagesPanel.vue":{"30":[6,7,8,9,37,52,68,80,81,102,117,126],"57":[6,7,8,9,68,81,102,117],"61":[6,7,8,9,37,52,68,80,81,102,117,126],"67":[6,68],"76":[6,7,8,9,68,81,102,117],"96":[6,7,8,9,68,81,102,117],"105":[6,7,8,9,37,52,68,80,81,102,117,126],"107":[6,7,8,9,68,81,102,117],"117":[6,7,8,9,37,52,68,80,81,102,117,126],"119":[7,8,68,117],"135":[6,7,8,9,37,52,68,80,81,102,117,126],"137":[6,7,8,9,37,52,68,80,81,102,117,126],"145":[68],"154":[6,7,8,9,37,52,68,80,81,102,117,126],"156":[68],"166":[6,7,8,9,37,52,68,80,81,102,117,126],"168":[68,117],"182":[6,7,8,9,37,52,68,80,81,102,117,126],"190":[6,7,9,68,117],"193":[6,7,8,9,37,52,68,80,81,102,117,126],"208":[6,7,8,9,37,52,68,80,81,102,117,126],"210":[68],"214":[6,7,8,9,37,52,68,80,81,102,117,126],"221":[6,7,8,9,37,52,68,80,81,102,117,126],"227":[6,7,8,9,37,52,68,80,81,102,117,126]},"packages/frontend/editor-ui/src/features/execution/logs/components/LogDetailsPanel.vue":{"32":[6,7,8,9,68,81,102,117],"70":[6,7,8,9,68,81,102,117],"71":[6,7,8,9,68,81,102,117],"72":[6,7,8,9,68,81,102,117],"73":[6,7,8,9,68,81,102,117],"77":[7,68,117],"79":[68],"83":[7,68,117],"84":[6,7,8,9,68,81,102,117],"92":[68],"102":[6,7,8,9,68,81,102,117],"113":[6,7,8,9,68,81,102,117],"130":[6,7,8,9,68,81,102,117],"138":[68],"145":[6,7,8,9,68,81,102,117],"151":[6,7,8,9,68,81,102,117],"158":[6,7,8,9,68,81,102,117],"164":[6,7,8,9,68,81,102,117],"175":[68],"193":[7,68,117],"202":[68],"215":[68],"226":[68]},"packages/frontend/editor-ui/src/features/execution/logs/components/LogsOverviewRow.vue":{"42":[6,7,8,9,68,81,102,117],"43":[6,7,8,9,68,81,102,117],"44":[6,7,8,9,68,81,102,117],"45":[6,7,8,9,68,81,102,117],"46":[6,7,8,9,68,81,102,117],"47":[6,7,8,9,68,81,102,117],"50":[6,7,8,9,68,81,102,117],"63":[6,7,8,9,68,81,102,117],"64":[6,7,8,9,68,81,102,117],"75":[6,7,8,9,68,81,102,117],"79":[6,7,8,9,68,81,102,117],"81":[6,7,8,9,68,81,102,117],"98":[6,7,8,9,68,81,102,117],"99":[6,7,8,9,68,81,102,117],"101":[6,7,8,9,68,81,102,117],"135":[7,8,68,117],"152":[6,7,8,9,68,81,102,117],"153":[6,7,8,9,68,81,102,117],"155":[6,7,8,9,68,81,102,117],"161":[6,7,8,9,68,81,102,117],"171":[6,7,8,9,68,81,102,117],"179":[68]},"packages/frontend/editor-ui/src/features/execution/logs/components/LogsOverviewRows.vue":{"40":[6,7,8,9,68,81,102,117],"41":[6,7,8,9,68,81,102,117],"47":[6,7,8,9,68,81,102,117],"51":[68,117],"67":[6,7,8,9,68,81,102,117],"68":[6,7,8,9,68,81,102,117],"69":[6,7,8,9,68,81,102,117],"79":[6,7,8,9,68,81,102,117],"81":[6,7,8,9,68,81,102,117],"82":[6,7,8,9,68,81,102,117],"87":[6,7,8,9,68,81,102,117],"89":[68],"98":[6,7,8,9,68,81,102,117],"114":[68],"115":[68,117],"116":[68,117],"117":[6,68,117]},"packages/frontend/editor-ui/src/features/execution/logs/components/LogsViewExecutionSummary.vue":{"18":[6,7,8,9,68,81,102,117],"20":[6,7,8,9,68,81,102,117],"37":[6,7,8,9,68,81,102,117]},"packages/frontend/editor-ui/src/features/execution/logs/components/LogsViewNodeName.vue":{"12":[6,7,8,9,68,81,102,117],"18":[6,7,8,9,68,81,102,117]},"packages/frontend/editor-ui/src/features/execution/logs/components/LogsViewRunData.vue":{"37":[6,7,8,9,68,81,102,117],"49":[6,7,8,9,68,81,102,117],"52":[6,7,8,9,68,81,102,117],"75":[6,7,8,9,68,81,102,117],"82":[68],"86":[7,68,117],"88":[6,7,8,9,68,81,102,117],"116":[68],"118":[6,7,8,9,68,81,102,117],"120":[6,7,8,9,68,81,102,117],"124":[6,7,8,9,68,81,102,117],"131":[7,68,117],"135":[68,117],"137":[68,117],"146":[68],"154":[68],"160":[68],"164":[68],"167":[68]},"packages/frontend/editor-ui/src/features/ndv/runData/components/RunDataItemCount.vue":{"16":[1,2,6,7,8,9,11,12,14,27,49,60,61,62,65,66,67,75,79,81,85,102,110,111,113,114,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135],"17":[1,2,6,7,8,9,11,12,14,27,60,61,62,65,66,67,75,79,81,85,102,110,111,114,117,118,119,120,121,122,123,124,125,127,128,131,134,135],"21":[123,125],"29":[1,2,6,7,8,9,11,12,14,27,49,60,61,62,65,66,67,75,79,81,85,102,110,111,113,114,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135]},"packages/frontend/editor-ui/src/features/ndv/runData/components/RunDataSearch.vue":{"44":[1,2,6,7,9,11,12,14,27,49,60,61,62,65,66,67,74,75,79,81,82,85,102,104,106,110,111,113,114,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135],"50":[1,2,6,7,9,11,12,14,27,49,60,61,62,65,66,67,74,75,79,81,82,85,102,104,106,110,111,113,114,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135],"68":[1,2,6,7,9,11,12,14,27,49,60,61,62,65,66,67,74,75,79,81,82,85,102,104,106,110,111,113,114,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135],"72":[75,82,119,120,121,122,123,125,127,129],"99":[123,125],"104":[123,125],"109":[123,125],"115":[123,125],"121":[123,125],"134":[75,82,119,120,121,122,123,125,127,129],"152":[1,2,6,7,9,11,12,14,27,49,60,61,62,65,66,67,74,75,79,81,82,85,102,104,106,110,111,113,114,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135],"153":[123,125]},"packages/frontend/editor-ui/src/features/ndv/runData/components/RunDataTable.vue":{"87":[9,11,12,14,27,49,60,61,62,65,66,67,75,85,110,111,113,114,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135],"88":[6,7,9,11,12,14,27,49,60,61,62,65,66,67,75,81,85,102,110,111,113,114,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135],"89":[6,7,9,11,12,14,27,49,60,61,62,65,66,67,75,81,85,102,110,111,113,114,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135],"91":[6,7,9,11,12,14,27,60,61,62,65,66,67,75,81,85,102,110,111,113,114,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135],"92":[6,7,9,11,12,14,27,60,61,62,65,66,67,75,81,85,102,110,111,113,114,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135],"93":[120,123,125,128],"94":[6,7,9,11,12,14,27,49,60,61,62,65,66,67,75,81,85,102,110,111,113,114,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135],"95":[6,7,9,11,12,14,27,49,60,61,62,65,66,67,75,81,85,102,110,111,113,114,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135],"103":[6,7,9,11,12,14,27,49,60,61,62,65,66,67,75,81,85,102,110,111,113,114,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135],"114":[6,7,9,11,12,14,27,49,60,61,62,65,66,67,75,81,85,102,110,111,113,114,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135],"151":[134],"163":[120,123,125,128],"185":[120,125,128],"192":[120],"196":[120],"200":[120,123],"206":[6,7,9,11,12,14,27,60,61,62,65,66,67,75,81,85,102,110,111,113,114,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135],"219":[6,7,9,11,12,14,27,60,61,62,65,66,67,75,81,85,102,110,111,113,114,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135],"226":[9,14,62,67,113,117,120,122,123,125,128],"239":[9,14,62,67,113,117,120,122,123,125,128],"252":[6,7,9,11,12,14,27,60,61,62,65,66,67,75,81,85,102,110,111,113,114,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135],"262":[6,7,9,11,12,14,27,60,61,62,65,66,67,75,81,85,102,110,111,113,114,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135],"284":[120],"294":[120],"302":[120],"308":[9,14,62,67,113,117,120,122,123,125,128],"316":[120],"318":[120],"340":[6,7,9,11,12,14,27,60,61,62,65,66,67,75,81,85,102,110,111,113,114,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135],"349":[9,14,62,67,113,117,120,122,123,125,128],"353":[6,7,9,11,12,14,27,60,61,62,65,66,67,75,81,85,102,110,111,113,114,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135],"357":[6,7,9,11,12,14,27,49,60,61,62,65,66,67,75,81,85,102,110,111,113,114,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135],"369":[6,7,9,11,12,14,27,49,60,61,62,65,66,67,75,81,85,102,110,111,113,114,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135],"394":[62,75,114,117,120,123,124,125,127,128,129,134],"412":[6,7,9,11,12,14,27,60,61,62,65,66,67,75,81,85,102,110,111,113,114,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135],"428":[6,7,9,11,12,14,27,49,60,61,62,65,66,67,75,81,85,102,110,111,113,114,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135],"456":[67,75,120,127,128,129],"457":[67,75,120,127,128,129],"466":[6,7,9,11,12,14,27,49,60,61,62,65,66,67,75,81,85,102,110,111,113,114,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135],"511":[49,117,124,125,129],"568":[6,7,9,11,12,14,27,60,61,62,65,66,67,75,81,85,102,110,111,113,114,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135],"580":[6,7,9,11,12,14,27,60,61,62,65,66,67,75,81,85,102,110,111,113,114,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135],"589":[120],"591":[6,7,9,11,12,14,27,60,61,62,65,66,67,75,81,85,102,110,111,113,114,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135],"594":[6,7,9,11,12,14,27,60,61,62,65,66,67,75,81,85,102,110,111,113,114,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135],"611":[6,7,9,11,12,14,27,60,61,62,65,66,67,75,81,85,102,110,111,113,114,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135],"667":[6,7,9,11,12,14,27,60,61,62,65,66,67,75,81,85,102,110,111,113,114,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135],"697":[134],"711":[6,7,9,11,12,14,27,60,61,62,65,66,67,75,81,85,102,110,111,113,114,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135],"729":[9,14,62,67,113,117,120,122,123,125,128],"743":[120],"752":[9,14,62,67,113,117,120,122,123,125,128]},"packages/frontend/editor-ui/src/features/ndv/runData/components/TextWithHighlights.vue":{"11":[1,2,6,7,9,11,12,14,27,49,60,61,62,65,66,67,74,75,79,81,82,85,102,104,106,110,111,113,114,116,117,118,119,120,121,122,123,124,125,127,128,129,131,132,134,135],"20":[123,125],"29":[1,2,6,7,9,11,12,14,27,49,60,61,62,65,66,67,74,75,79,81,82,85,102,104,106,110,111,113,114,116,117,118,119,120,121,122,123,124,125,127,128,129,131,132,134,135]},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/buttons/CanvasChatButton.vue":{"9":[6,7,8,9,37,52,68,80,81,102,117,126]},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/buttons/CanvasStopCurrentExecutionButton.vue":{"6":[0,1,2,4,6,7,8,9,11,12,26,27,28,38,45,49,50,59,60,61,62,63,64,65,66,67,68,74,75,79,81,82,85,102,103,104,105,110,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135,141,142,146],"13":[0,1,2,4,6,7,8,9,11,12,26,27,28,38,45,49,50,59,60,61,62,63,64,65,66,67,68,74,75,79,81,82,85,102,103,104,105,110,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135,141,142,146],"18":[0,1,2,4,6,7,8,9,11,12,26,27,28,38,45,49,50,59,60,61,62,63,64,65,66,67,68,74,75,79,81,82,85,102,103,104,105,110,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135,141,142,146]},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/buttons/CanvasStopWaitingForWebhookButton.vue":{"5":[6,7,8,9,12,26,60,67,68,81,102,114,117,129],"9":[6,7,8,9,12,26,60,67,68,81,102,114,117]},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/nodes/render-types/parts/CanvasNodeTooltip.vue":{"11":[6,7,8,9,147,12,26,60,67,81,102,114,117,129,146],"13":[6,7,8,9,147,12,26,60,67,81,114,117,129,146],"14":[6,7,8,9,147,12,26,60,67,81,102,114,117,129,146],"26":[6,7,8,9,147,12,26,60,67,81,114,117,129,146],"28":[6,7,8,9,147,12,26,60,67,81,102,114,117,129,146]},"packages/@n8n/api-types/src/schemas/agent-run-reducer.ts":{"70":[42,43,44,45,46,47,48,49,50,51],"96":[42,43,44,45,46,47,48,49,50,51],"105":[42,43,44,45,46,47,48,49,50,51],"110":[42,43,44,45,46,47,48,49,50,51],"120":[42,43,45,46,48,49,50,51],"130":[42,45,46,48,49,50],"141":[42,43,44,45,46,47,48,49,50,51],"162":[42,43,44,45,46,47,48,49,50,51],"426":[42,43,44,45,46,47,48,49,50,51],"430":[42,43,44,45,46,47,48,49,50,51],"445":[42,45,46,48,49,50],"448":[42,43,45,46,48,49,50,51],"451":[42,43,45,46,48,49,50,51],"458":[42,43,45,46,48,49,50,51],"459":[42,43,45,46,48,49,50,51],"461":[42,45,46,48,49,50]},"packages/@n8n/api-types/src/schemas/instance-ai.schema.ts":{"98":[42,43,44,45,46,47,48,49,50,51],"1051":[42,43,45,46,48,49,50,51]},"packages/@n8n/design-system/src/components/AskAssistantChat/messages/MessageRating.vue":{"15":[5,42,43,44,45,46,47,48,49,50,51],"62":[5,42,43,44,45,46,47,48,49,50,51]},"packages/@n8n/design-system/src/components/N8nCard/Card.vue":{"9":[15,16,18,19,20,23,29,30,37,38,39,40,41,42,45,48,49,50,68,69,70,71,72,73,89,90,91,93,94,96,97,98,133,138,139,144,146],"14":[15,16,18,19,20,23,29,30,37,38,39,40,41,42,45,48,49,50,68,69,70,71,72,73,89,90,91,93,94,96,97,98,133,138,139,144,146],"19":[15,16,18,19,20,23,29,30,37,38,39,40,41,42,45,48,49,50,68,69,70,71,72,73,89,90,91,93,94,96,97,98,133,138,139,144,146]},"packages/frontend/editor-ui/src/app/components/WorkflowCanvasHost.vue":{"12":[42,45,48,49,50],"34":[42,45,48,49,50],"48":[42,45,48,49,50],"53":[42,45,48,49,50],"61":[42,45,48,49,50]},"packages/frontend/editor-ui/src/app/components/WorkflowCanvasHostBody.vue":{"15":[42,45,48,49,50],"46":[42,45,48,49,50],"53":[42,45,48,49,50],"59":[42,45,48,49,50],"61":[45],"66":[42,50],"80":[42,45,48,49,50],"86":[42,45,48,49,50],"87":[42,45,48,49,50]},"packages/frontend/editor-ui/src/app/layouts/InstanceAiLayout.vue":{"9":[42,43,44,45,46,47,48,49,50,51],"20":[42,43,44,45,46,47,48,49,50,51],"22":[42,43,44,45,46,47,48,49,50,51]},"packages/frontend/editor-ui/src/experiments/instanceAiProactiveAgent/useInstanceAiProactiveAgentExperiment.ts":{"6":[42,43,44,45,46,47,48,49,50,51],"9":[42,43,44,45,46,47,48,49,50,51]},"packages/frontend/editor-ui/src/experiments/instanceAiPromptSuggestionsV2/useInstanceAiPromptSuggestionsV2Experiment.ts":{"6":[42,43,44,45,46,47,48,49,50,51],"9":[42,43,44,45,46,47,48,49,50,51]},"packages/frontend/editor-ui/src/features/ai/chatHub/composables/useChatHubMarkdownOptions.ts":{"25":[45,51,68],"40":[29,30,31,32,34,35,42,43,44,45,46,47,48,49,50,51,68],"56":[29,30,31,32,34,35,42,43,44,45,46,47,48,49,50,51,68],"75":[29,30,31,32,34,35,42,43,44,45,46,47,48,49,50,51,68],"85":[29,68],"104":[68],"116":[68],"117":[68],"138":[29,30,31,32,34,35,42,43,44,45,46,47,48,49,50,51,68],"139":[29,30,31,32,34,35,42,43,44,45,46,47,48,49,50,51,68],"141":[45,51,68],"144":[45,51,68],"156":[29,30,31,32,34,35,42,43,44,45,46,47,48,49,50,51,68],"161":[29,68],"179":[29,30,31,32,34,35,42,43,44,45,46,47,48,49,50,51,68],"183":[51,68],"190":[51,68],"199":[29,30,31,32,34,35,42,43,44,45,46,47,48,49,50,51,68],"206":[29,30,31,32,34,35,42,43,44,45,46,47,48,49,50,51,68],"215":[68],"226":[68],"227":[68],"228":[68],"229":[68],"230":[68]},"packages/frontend/editor-ui/src/features/ai/instanceAi/InstanceAiEmptyView.vue":{"48":[42,43,44,45,46,47,48,49,50,51],"50":[42,43,44,45,46,47,48,49,50,51],"68":[42,43,44,45,46,47,48,49,50,51],"77":[42,43,44,45,46,47,48,49,50,51],"78":[42,43,44,45,46,47,48,49,50,51],"81":[42,43,44,45,46,47,48,49,50,51]},"packages/frontend/editor-ui/src/features/ai/instanceAi/InstanceAiThreadView.vue":{"77":[42,43,44,45,46,47,48,49,50,51],"82":[42,43,44,45,46,47,48,49,50,51],"87":[42,43,44,45,46,47,48,49,50,51],"99":[42,43,44,45,46,47,48,49,50,51],"114":[42,43,44,45,46,47,48,49,50,51],"115":[42,43,44,45,46,47,48,49,50,51],"119":[42,44,45,46,47,48,49,50,51],"130":[42,43,44,45,46,47,48,49,50,51],"138":[42,43,44,45,46,47,48,49,50,51],"149":[42,43,44,45,46,47,48,49,50,51],"150":[42,43,44,45,46,47,48,49,50,51],"156":[42,43,44,45,46,47,48,49,50,51],"159":[42,43,44,45,46,47,48,49,50,51],"164":[42,43,44,45,46,47,48,49,50,51],"171":[42,43,44,45,46,47,48,49,50,51],"175":[42,50],"187":[51],"198":[51],"218":[42,43,44,45,46,47,48,49,50,51],"223":[44,47],"233":[42,43,44,45,46,47,48,49,50,51],"236":[42,43,44,45,46,47,48,49,50,51],"239":[42,43,44,45,46,47,48,49,50,51],"242":[42,43,44,45,46,47,48,49,50,51],"246":[42,43,44,45,46,47,48,49,50,51],"249":[42,43,44,45,46,47,48,49,50,51],"252":[42,43,44,45,46,47,48,49,50,51],"258":[42,43,44,45,46,47,48,49,50,51],"264":[42,43,44,45,46,47,48,49,50,51],"267":[42,43,44,45,46,47,48,49,50,51],"273":[42,43,44,45,46,47,48,49,50,51],"274":[42,43,44,45,46,47,48,49,50,51],"284":[42,43,44,45,46,47,48,49,50,51],"294":[42,45,48,49,50],"302":[42],"308":[42,45,48,49,50],"324":[42,43,44,45,46,47,48,49,50,51],"336":[44,47],"342":[42,43,44,45,46,47,48,49,50,51],"351":[42,43,44,45,46,47,48,49,50,51],"352":[44,47],"367":[42,43,44,45,46,47,48,49,50,51],"378":[42,43,44,45,46,47,48,49,50,51],"379":[42,43,44,45,46,47,48,49,50,51],"385":[42,43,44,45,46,47,48,49,50,51],"400":[42,43,44,45,46,47,48,49,50,51],"404":[42,43,44,45,46,47,48,49,50,51],"418":[42,43,44,45,46,47,48,49,50,51],"432":[42,43,44,45,46,47,48,49,50,51],"439":[42,43,44,45,46,47,48,49,50,51],"449":[44,47],"450":[44,47],"460":[42,43,44,45,46,47,48,49,50,51],"467":[42,43,44,45,46,47,48,49,50,51],"476":[42,43,44,45,46,47,48,49,50,51],"482":[47],"567":[42,43,44,45,46,47,48,49,50,51],"569":[42,43,44,45,46,47,48,49,50,51],"580":[42,43,44,45,46,47,48,49,50,51],"630":[42,43,44,45,46,47,48,49,50,51],"633":[42,43,44,45,46,47,48,49,50,51],"644":[42,45,46,48,49,50],"655":[42,43,44,45,46,47,48,49,50,51],"676":[42,43,44,45,46,47,48,49,50,51],"703":[42,43,44,45,46,47,48,49,50,51],"747":[42,43,44,45,46,47,48,49,50,51],"781":[42,43,44,45,46,47,48,49,50,51],"800":[42,43,44,45,46,47,48,49,50,51]},"packages/frontend/editor-ui/src/features/ai/instanceAi/InstanceAiView.vue":{"28":[47],"61":[42,43,44,45,46,47,48,49,50,51],"72":[42,43,44,45,46,47,48,49,50,51],"74":[42,43,44,45,46,47,48,49,50,51],"82":[42,43,44,45,46,47,48,49,50,51],"105":[42,43,44,45,46,47,48,49,50,51],"115":[47]},"packages/frontend/editor-ui/src/features/ai/instanceAi/agentTimeline.utils.ts":{"16":[42,45,46,48,49,50]},"packages/frontend/editor-ui/src/features/ai/instanceAi/builderAgents.ts":{"4":[42,43,44,45,46,47,48,49,50,51],"9":[42,43,44,45,46,47,48,49,50,51],"20":[42,43,44,45,46,47,48,49,50,51],"46":[42,45,46,48,49,50,51],"58":[42,43,44,45,46,47,48,49,50,51],"60":[42,43,44,45,46,47,48,49,50,51]},"packages/frontend/editor-ui/src/features/ai/instanceAi/canvasPreview.utils.ts":{"38":[42,43,44,45,46,47,48,49,50,51],"68":[42,43,44,45,46,47,48,49,50,51],"93":[42,43,44,45,46,47,48,49,50,51],"137":[42,43,44,45,46,47,48,49,50,51],"217":[42,43,44,45,46,47,48,49,50,51],"241":[42,43,44,45,46,47,48,49,50,51]},"packages/frontend/editor-ui/src/features/ai/instanceAi/components/AgentActivityTree.vue":{"17":[42,43,44,45,46,47,48,49,50,51],"30":[42,43,44,45,46,47,48,49,50,51],"37":[42,43,44,45,46,47,48,49,50,51],"40":[42,43,45,46,48,49,50,51],"48":[42,45,48,49,50],"51":[42,43,44,45,46,47,48,49,50,51],"77":[42,43,45,46,48,49,50,51],"88":[42,45,48,49,50]},"packages/frontend/editor-ui/src/features/ai/instanceAi/components/AgentSection.vue":{"12":[42,45,46,48,49,50],"18":[42,45,46,48,49,50],"21":[42,45,46,48,49,50],"23":[42,45,46,48,49,50],"28":[42,45,46,48,49,50],"38":[42,45,46,48,49,50],"39":[42,45,48,49,50],"46":[42,45,46,48,49,50],"52":[42,45,46,48,49,50],"53":[42,45,46,48,49,50],"54":[42,45,46,48,49,50],"56":[42,45,46,48,49,50],"69":[45,46,49,50]},"packages/frontend/editor-ui/src/features/ai/instanceAi/components/AgentTimeline.vue":{"25":[42,43,44,45,46,47,48,49,50,51],"31":[42,45,48,49,50],"36":[42,45,48,49,50],"58":[42,45,48,49,50],"67":[42,45,48,49,50],"93":[42,43,44,45,46,47,48,49,50,51],"100":[42,43,45,46,48,49,50,51],"108":[42,45,48,49,50],"117":[42,45,48,49,50],"133":[42,45,48,49,50],"144":[42,45,48,49,50],"152":[42,45,46,48,49,50],"160":[42,45,48,49,50],"236":[42,45,48,49,50],"237":[42,45,48,49,50],"262":[42,45,48,49,50],"263":[42,45,48,49,50],"276":[42,43,44,45,46,47,48,49,50,51],"288":[42,44,45,46,47,48,49,50,51],"390":[42,45,48,49,50],"398":[42,45,48,49,50]},"packages/frontend/editor-ui/src/features/ai/instanceAi/components/AnimatedCollapsibleContent.vue":{"6":[42,43,45,46,48,49,50,51],"7":[42,45,48,49,50]},"packages/frontend/editor-ui/src/features/ai/instanceAi/components/ArtifactCard.vue":{"6":[42,45,48,49,50],"28":[42,45,48,49,50],"30":[42],"47":[42,45,48,49,50],"58":[42,45,48,49,50],"61":[42,45,48,49,50],"65":[42,45,48,49,50],"67":[42,45,48,49,50]},"packages/frontend/editor-ui/src/features/ai/instanceAi/components/ButtonLike.vue":{"2":[42,45,46,48,49,50]},"packages/frontend/editor-ui/src/features/ai/instanceAi/components/ConfirmationFooter.vue":{"15":[42,45,48,49,50,51]},"packages/frontend/editor-ui/src/features/ai/instanceAi/components/ConnectionsCard.vue":{"18":[42,43,44,45,46,47,48,49,50,51],"27":[42,43,44,45,46,47,48,49,50,51],"91":[42,43,44,45,46,47,48,49,50,51]},"packages/frontend/editor-ui/src/features/ai/instanceAi/components/InstanceAiArtifactsPanel.vue":{"17":[42,43,44,45,46,47,48,49,50,51],"48":[42,43,44,45,46,47,48,49,50,51],"49":[42,43,44,45,46,47,48,49,50,51],"50":[42,43,44,45,46,47,48,49,50,51],"64":[42,43,44,45,46,47,48,49,50,51],"79":[42,50],"89":[42,50],"93":[42,43,44,45,46,47,48,49,50,51],"98":[42,43,44,45,46,47,48,49,50,51],"107":[42,43,44,45,46,47,48,49,50,51],"114":[42,43,44,45,46,47,48,49,50,51],"131":[42,50],"162":[42,45,48,49,50],"168":[42,45,48,49,50]},"packages/frontend/editor-ui/src/features/ai/instanceAi/components/InstanceAiConfirmationPanel.vue":{"35":[42,43,44,45,46,47,48,49,50,51],"43":[45],"50":[45],"102":[42,43,44,45,46,47,48,49,50,51],"119":[45],"132":[45],"154":[45],"165":[45],"193":[45],"215":[45],"392":[42,43,44,45,46,47,48,49,50,51],"572":[45],"579":[45]},"packages/frontend/editor-ui/src/features/ai/instanceAi/components/InstanceAiEmptyState.vue":{"5":[42,43,44,45,46,47,48,49,50,51],"20":[42,43,44,45,46,47,48,49,50,51]},"packages/frontend/editor-ui/src/features/ai/instanceAi/components/InstanceAiInput.vue":{"32":[42,43,44,45,46,47,48,49,50,51],"76":[42,43,44,45,46,47,48,49,50,51],"79":[42,43,44,45,46,47,48,49,50,51],"82":[42,43,44,45,46,47,48,49,50,51],"84":[42,43,44,45,46,47,48,49,50,51],"85":[42,43,44,45,46,47,48,49,50,51],"86":[42,43,44,45,46,47,48,49,50,51],"87":[42,43,44,45,46,47,48,49,50,51],"88":[42,43,44,45,46,47,48,49,50,51],"96":[42,43,44,45,46,47,48,49,50,51],"99":[42,43,44,45,46,47,48,49,50,51],"103":[42,43,44,45,46,47,48,49,50,51],"105":[42,43,44,45,46,47,48,49,50,51],"127":[42,43,44,45,46,47,48,49,50,51],"143":[42,43,44,45,46,47,48,49,50,51],"149":[42,43,44,45,46,47,48,49,50,51],"159":[42,43,44,45,46,47,48,49,50,51],"164":[42,43,44,45,46,47,48,49,50,51],"169":[42,43,44,45,46,47,48,49,50,51],"173":[42,43,44,45,46,47,48,49,50,51],"183":[42,43,44,45,46,47,48,49,50,51],"192":[43],"212":[43],"231":[42,43,44,45,46,47,48,49,50,51],"296":[42,43,44,45,46,47,48,49,50,51],"302":[42,43,44,45,46,47,48,49,50,51],"322":[42,43,44,45,46,47,48,49,50,51],"355":[43],"365":[42,43,44,45,46,47,48,49,50,51]},"packages/frontend/editor-ui/src/features/ai/instanceAi/components/InstanceAiMarkdown.vue":{"6":[42,43,44,45,46,47,48,49,50,51],"39":[45,51],"56":[42,43,44,45,46,47,48,49,50,51],"58":[45,51],"70":[42,45,48,49,51],"112":[42,45,48,49,50,51],"143":[42,43,44,45,46,47,48,49,50,51],"149":[42,45,48,49,50,51],"150":[45],"154":[42,45,48,49,50,51],"175":[45,51],"185":[42,43,44,45,46,47,48,49,50,51],"214":[45,51],"225":[45,51],"243":[45,51],"268":[42,43,44,45,46,47,48,49,50,51],"289":[45,51],"337":[42,44,45,46,47,48,49,50,51],"350":[42,44,45,46,47,48,49,50,51],"355":[42,43,44,45,46,47,48,49,50,51]},"packages/frontend/editor-ui/src/features/ai/instanceAi/components/InstanceAiMessage.vue":{"12":[42,43,44,45,46,47,48,49,50,51],"21":[42,43,44,45,46,47,48,49,50,51],"22":[42,43,44,45,46,47,48,49,50,51],"23":[42,43,44,45,46,47,48,49,50,51],"25":[42,43,44,45,46,47,48,49,50,51],"31":[42,44,45,46,48,49,50],"37":[42,44,45,46,48,49,50],"39":[42,44,45,46,48,49,50],"46":[42,44,45,46,48,49,50],"56":[42,43,44,45,46,47,48,49,50,51],"59":[42,43,44,45,46,47,48,49,50,51],"65":[42,43,44,45,46,47,48,49,50,51],"67":[42,43,44,45,46,47,48,49,50,51],"74":[42,44,45,46,47,48,49,50,51],"87":[42,43,44,45,46,47,48,49,50,51],"97":[43],"117":[42,44,45,46,48,49,50],"129":[42,44,45,46,48,49,50]},"packages/frontend/editor-ui/src/features/ai/instanceAi/components/InstanceAiPreviewTabBar.vue":{"19":[42,43,44,45,46,47,48,49,50,51],"41":[42,43,44,45,46,47,48,49,50,51],"47":[42,45,48,49,50],"53":[42,45,48,49,50],"57":[42,45,48,49,50],"84":[42,43,44,45,46,47,48,49,50,51],"85":[42,45,48,49,50],"88":[42,45,48,49,50],"114":[42,43,44,45,46,47,48,49,50,51],"134":[42,43,44,45,46,47,48,49,50,51],"136":[42,45,48,49,50],"138":[42,45,48,49,50],"140":[42,45,48,49,50],"141":[42,45,48,49,50]},"packages/frontend/editor-ui/src/features/ai/instanceAi/components/InstanceAiPromptSuggestions.vue":{"12":[42,43,44,45,46,47,48,49,50,51],"38":[42,43,44,45,46,47,48,49,50,51],"88":[42,43,44,45,46,47,48,49,50,51],"92":[42,43,44,45,46,47,48,49,50,51],"185":[42,43,44,45,46,47,48,49,50,51],"192":[42,43,44,45,46,47,48,49,50,51],"222":[42,43,44,45,46,47,48,49,50,51]},"packages/frontend/editor-ui/src/features/ai/instanceAi/components/InstanceAiStatusBar.vue":{"9":[42,43,44,45,46,47,48,49,50,51],"20":[42,44,45,46,47,48,49,50,51],"21":[42,44,45,46,47,48,49,50,51],"27":[42,45,46,48,49,50],"30":[42,45,48,49,50],"39":[42,45,46,48,49,50,51],"48":[42,44,45,46,47,48,49,50,51],"55":[42,43,44,45,46,47,48,49,50,51],"57":[42,44,45,46,47,48,49,50,51],"65":[42,43,44,45,46,47,48,49,50,51],"67":[42,44,45,46,47,48,49,50,51],"74":[42,43,44,45,46,47,48,49,50,51],"77":[49],"88":[47],"93":[42,43,44,45,46,47,48,49,50,51]},"packages/frontend/editor-ui/src/features/ai/instanceAi/components/InstanceAiViewHeader.vue":{"17":[42,43,44,45,46,47,48,49,50,51],"23":[42,43,44,45,46,47,48,49,50,51]},"packages/frontend/editor-ui/src/features/ai/instanceAi/components/InstanceAiWorkflowPreview.vue":{"19":[42,45,48,49,50],"34":[42,45,48,49,50],"57":[42,45,49,50],"69":[42,45,49,50],"97":[42,50],"127":[42,45,48,49,50],"152":[42,45,48,49,50],"165":[42,45,48,49,50]},"packages/frontend/editor-ui/src/features/ai/instanceAi/components/PlanReviewPanel.vue":{"28":[42,45,48,49,50],"52":[42,45,48,49,50],"58":[42,45,48,49,50],"64":[42,45,48,49,50],"74":[42,45,48,49,50],"78":[42,45,48,49,50],"80":[42,45,48,49,50],"84":[42,45,48,49,50],"88":[42,45,48,49,50],"100":[42,45,48,49,50],"117":[42,45,48,49,50],"129":[42,45,48,49,50],"135":[42,45,48,49,50],"166":[42,45,48,49],"182":[42,45,48,49,50],"189":[42,45,48,49,50],"192":[42,45,48,49,50],"204":[42,45,48,49,50],"211":[42,45,48,49,50],"217":[42,45,48,49,50],"227":[42,45,48,49,50],"236":[42,45,48,49,50]},"packages/frontend/editor-ui/src/features/ai/instanceAi/components/ResponseGroup.vue":{"12":[42,43,45,46,48,49,50,51],"21":[42,45,46,48,49,50],"56":[42,43,45,46,48,49,50,51],"57":[42,43,45,46,48,49,50,51],"59":[42,43,45,46,48,49,50,51],"65":[42,43,45,46,48,49,50,51],"66":[42,43,45,46,48,49,50,51],"68":[42,45,46,48,49,50],"74":[42,43,45,46,48,49,50,51],"77":[42,43,45,46,48,49,50,51],"84":[42,43,45,46,48,49,50,51],"90":[42,45,46,48,49,50],"91":[42,45,46,48,49,50],"93":[42,45,46,48,49,50]},"packages/frontend/editor-ui/src/features/ai/instanceAi/components/SubagentStepTimeline.vue":{"18":[42,45,46,48,49,50],"61":[42,45,46,48,49,50],"66":[42,45,46,48,49,50],"74":[42,45,46,48,49,50],"76":[42,45,46,48,49,50],"109":[42,45,46,48,49,50]},"packages/frontend/editor-ui/src/features/ai/instanceAi/components/TimelineStepButton.vue":{"26":[42,43,45,46,48,49,50,51],"27":[42,43,45,46,48,49,50,51]},"packages/frontend/editor-ui/src/features/ai/instanceAi/components/TimelineStepChevron.vue":{"10":[42,43,45,46,48,49,50,51]},"packages/frontend/editor-ui/src/features/ai/instanceAi/components/ToolCallStep.vue":{"13":[42,43,45,46,48,49,50,51],"25":[42,43,45,46,49,51],"46":[42,43,45,46,48,49,50,51],"52":[42,43,45,46,48,49,50,51],"53":[42,43,45,46,48,49,50,51],"55":[42,43,45,46,48,49,50,51]},"packages/frontend/editor-ui/src/features/ai/instanceAi/composables/useCreditWarningBanner.ts":{"9":[42,43,44,45,46,47,48,49,50,51],"12":[42,43,44,45,46,47,48,49,50,51],"23":[42,43,44,45,46,47,48,49,50,51]},"packages/frontend/editor-ui/src/features/ai/instanceAi/emptyStateSuggestions.ts":{"36":[42,43,44,45,46,47,48,49,50,51]},"packages/frontend/editor-ui/src/features/ai/instanceAi/instanceAi.api.ts":{"14":[42,43,44,45,46,47,48,49,50,51],"35":[42,43,44,45,46,47,48,49,50,51],"93":[42,45,48,49,50,51],"105":[42,43,44,45,46,47,48,49,50,51]},"packages/frontend/editor-ui/src/features/ai/instanceAi/instanceAi.memory.api.ts":{"10":[42,43,44,45,46,47,48,49,50,51],"16":[47],"20":[47],"40":[44,47],"57":[44,47]},"packages/frontend/editor-ui/src/features/ai/instanceAi/instanceAi.reducer.ts":{"35":[42,43,44,45,46,47,48,49,50,51],"42":[42,43,44,45,46,47,48,49,50,51],"47":[42,43,44,45,46,47,48,49,50,51],"63":[42,43,44,45,46,47,48,49,50,51],"71":[42,43,44,45,46,47,48,49,50,51],"89":[42,43,44,45,46,47,48,49,50,51],"106":[42,43,44,45,46,47,48,49,50,51],"111":[42,43,44,45,46,47,48,49,50,51],"133":[42,43,44,45,46,47,48,49,50,51],"143":[42,43,44,45,46,47,48,49,50,51],"195":[42,43,44,45,46,47,48,49,50,51],"225":[42,43,44,45,46,47,48,49,50,51],"287":[42,44,45,46,47,48,49,50,51],"296":[42,44,45,46,47,48,49,50,51],"323":[42,45,48,49,50],"324":[42,45,48,49,50],"325":[42,44,45,48,49,50,51],"330":[42,45,48,49,50,51],"331":[42,45,48,49,50,51],"350":[42,43,44,45,46,47,48,49,50,51],"364":[42,43,44,45,46,47,48,49,50,51]},"packages/frontend/editor-ui/src/features/ai/instanceAi/instanceAi.settings.api.ts":{"24":[42,43,44,45,46,47,48,49,50,51]},"packages/frontend/editor-ui/src/features/ai/instanceAi/instanceAi.threadRuntime.ts":{"69":[42,43,44,45,46,47,48,49,50,51],"103":[51],"117":[42,43,44,45,46,47,48,49,50,51],"207":[44],"239":[42,43,44,45,46,47,48,49,50,51],"271":[42,43,44,45,46,47,48,49,50,51],"272":[42,43,44,45,46,47,48,49,50,51],"273":[42,43,44,45,46,47,48,49,50,51],"274":[42,43,44,45,46,47,48,49,50,51],"276":[42,43,44,45,46,47,48,49,50,51],"277":[42,45,48,49,50],"278":[42,43,44,45,46,47,48,49,50,51],"292":[42,43,44,45,46,47,48,49,50,51],"300":[42,43,44,45,46,47,48,49,50,51],"303":[42,43,44,45,46,47,48,49,50,51],"309":[42,45,46,48,49,50],"320":[42,43,44,45,46,47,48,49,50,51],"330":[42,43,44,45,46,47,48,49,50,51],"332":[42,45,48,49,50,51],"340":[51],"391":[42,43,44,45,46,47,48,49,50,51],"431":[42,43,44,45,46,47,48,49,50,51],"498":[42,44,45,46,47,48,49,50,51],"516":[42,44,45,46,47,48,49,50,51],"578":[42,43,44,45,46,47,48,49,50,51],"596":[42,43,44,45,46,47,48,49,50,51],"601":[42,43,44,45,46,47,48,49,50,51],"608":[42,44,45,46,47,48,49,50,51],"613":[44],"625":[47],"634":[47],"651":[47],"656":[44,47],"667":[44,47],"706":[44,47],"731":[42,43,44,45,46,47,48,49,50,51],"742":[42,43,44,45,46,47,48,49,50,51],"766":[42,43,44,45,46,47,48,49,50,51],"774":[42,43,44,45,46,47,48,49,50,51],"813":[42,43,44,45,46,47,48,49,50,51],"883":[42,43,44,45,46,47,48,49,50,51],"891":[42,45,48,49,50,51]},"packages/frontend/editor-ui/src/features/ai/instanceAi/instanceAiPromptSuggestions.telemetry.ts":{"42":[42,43,44,45,46,47,48,49,50,51],"45":[42,43,44,45,46,47,48,49,50,51],"59":[42,43,44,45,46,47,48,49,50,51],"64":[42,43,44,45,46,47,48,49,50,51],"112":[42,43,44,45,46,47,48,49,50,51]},"packages/frontend/editor-ui/src/features/ai/instanceAi/module.descriptor.ts":{"10":[42,43,44,45,46,47,48,49,50,51],"11":[42,43,44,45,46,47,48,49,50,51],"12":[42,43,44,45,46,47,48,49,50,51],"81":[42,43,44,45,46,47,48,49,50,51]},"packages/frontend/editor-ui/src/features/ai/instanceAi/toolLabels.ts":{"98":[42,45,46,48,49,50],"132":[42,43,44,45,46,47,48,49,50,51],"135":[42,43,45,46,48,49,50,51],"179":[42,45,46,48,49,50],"187":[42,45,46,48,49,50]},"packages/frontend/editor-ui/src/features/ai/instanceAi/useCanvasPreview.ts":{"34":[42,43,44,45,46,47,48,49,50,51],"43":[42,43,44,45,46,47,48,49,50,51],"64":[42,43,44,45,46,47,48,49,50,51],"65":[42,45,48,49,50],"69":[42,43,44,45,46,47,48,49,50,51],"70":[42,45,48,49,50],"81":[42,43,44,45,46,47,48,49,50,51],"89":[42,50],"98":[42],"119":[42,44,45,46,47,48,49,50,51],"121":[42,45,48,49,50],"145":[42,43,44,45,46,47,48,49,50,51],"165":[42,43,44,45,46,47,48,49,50,51],"166":[42,45,48,49,50],"184":[42,43,44,45,46,47,48,49,50,51],"195":[42,43,44,45,46,47,48,49,50,51],"196":[45],"210":[42,43,44,45,46,47,48,49,50,51],"221":[42,43,44,45,46,47,48,49,50,51],"237":[42,43,44,45,46,47,48,49,50,51],"248":[42,43,44,45,46,47,48,49,50,51],"262":[42,43,44,45,46,47,48,49,50,51],"282":[42,43,44,45,46,47,48,49,50,51],"295":[42,43,44,45,46,47,48,49,50,51],"326":[42,43,44,45,46,47,48,49,50,51],"327":[42,45,48,49,50]},"packages/frontend/editor-ui/src/features/ai/instanceAi/useResourceRegistry.ts":{"35":[42,45,48,49,50,51],"47":[42,45,48,49,50],"66":[45,51],"70":[45,51],"99":[42,43,45,46,48,49,50,51],"210":[42,43,44,45,46,47,48,49,50,51],"220":[42,43,44,45,46,47,48,49,50,51],"230":[42,43,44,45,46,47,48,49,50,51],"262":[42,43,44,45,46,47,48,49,50,51],"267":[42,43,44,45,46,47,48,49,50,51],"295":[42,43,44,45,46,47,48,49,50,51],"296":[42,43,44,45,46,47,48,49,50,51]},"packages/frontend/editor-ui/src/features/ai/instanceAi/useResponseFeedback.ts":{"11":[42,43,44,45,46,47,48,49,50,51],"13":[42,45,46,48,49,50],"16":[42,43,44,45,46,47,48,49,50,51],"17":[42,43,45,46,48,49,50,51],"18":[42,45,46,48,49,50],"21":[42,43,44,45,46,47,48,49,50,51],"22":[42,43,45,46,48,49,50,51],"24":[42,45,46,48,49,50],"47":[42,43,44,45,46,47,48,49,50,51],"72":[42,43,44,45,46,47,48,49,50,51],"161":[47]},"packages/frontend/editor-ui/src/features/ai/instanceAi/useTimelineGrouping.ts":{"14":[42,43,45,46,48,49,50,51],"55":[42,43,44,45,46,47,48,49,50,51],"58":[42,43,44,45,46,47,48,49,50,51],"68":[42,43,44,45,46,47,48,49,50,51],"76":[42,43,45,46,48,49,50,51],"106":[42,43,45,46,48,49,50,51],"119":[42,45,46,48,49,50],"140":[42,43,44,45,46,47,48,49,50,51],"146":[42,43,44,45,46,47,48,49,50,51]},"packages/frontend/editor-ui/src/features/ai/instanceAi/useTransitionGate.ts":{"3":[42,43,44,45,46,47,48,49,50,51],"7":[42,43,44,45,46,47,48,49,50,51],"9":[42,43,44,45,46,47,48,49,50,51],"10":[42,43,44,45,46,47,48,49,50,51],"18":[44,47],"23":[44,47]},"packages/frontend/editor-ui/src/features/ai/shared/components/ChatInputBase.vue":{"77":[43],"116":[42,43,44,45,46,47,48,49,50,51],"141":[42,43,44,45,46,47,48,49,50,51],"154":[42,43,44,45,46,47,48,49,50,51]},"packages/frontend/editor-ui/src/features/core/dataTable/components/dataGrid/ColumnHeader.vue":{"31":[40,41],"32":[40,41],"34":[40,41,42,43,44,45,46,47,48,49,50,51],"55":[40],"64":[40],"68":[40],"72":[40],"76":[40,41],"86":[40,41],"90":[40,41],"97":[40,41],"102":[40,41],"113":[40,41],"122":[40,41],"124":[40],"130":[40,41],"150":[40,41],"154":[40,41],"172":[40],"182":[40,41],"194":[40,41],"200":[40,41],"253":[40]},"packages/localhost-44671/assets/_plugin-vue_export-helper-Da88TEg1.js":{"2":[42,43,48,50,51]},"packages/localhost-44671/assets/chunk-CC9Q-vWm.js":{"8":[42,43,48,50,51],"9":[42,43,48,50,51],"10":[42,43,48,50,51],"19":[42,43,48,50,51],"23":[42,43,48,50,51],"29":[42,43,48,50,51],"33":[42,43,48,50,51],"34":[42,43,48,50,51]},"packages/@n8n/api-types/src/push/heartbeat.ts":{"9":[0,34,46,49]},"packages/@n8n/design-system/src/components/N8nIcon/custom/node-execution-error.svg":{"11":[0,1,2,7,8,38,113,114,117,124,141,142]},"packages/@n8n/design-system/src/components/N8nIcon/nodes/character-text-splitter.svg":{"11":[0,9]},"packages/@n8n/design-system/src/components/N8nIcon/nodes/code.svg":{"11":[0,1,2,9,21,28,62,64,83,84,101,103,104,105,109,110,112,114,115,117,124,125,128,133,141,142]},"packages/@n8n/design-system/src/components/N8nIcon/nodes/default-data-loader.svg":{"11":[0,9,127]},"packages/@n8n/design-system/src/components/N8nIcon/nodes/simple-vector-store.svg":{"11":[0,9,56,120,127]},"packages/frontend/editor-ui/src/app/components/NodeExecutionErrorMessage.vue":{"4":[0,147]},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/handles/render-types/CanvasHandleNonMainInput.vue":{"19":[0,7,8,9,147,37,52,79,80,100,103,117,126,127],"21":[0,7,8,9,147,37,52,79,80,100,103,117,126,127],"27":[0,7,8,9,147,37,52,79,80,100,103,117,126,127],"33":[7,8,147,37,52,79,80,100,103,117,126,127],"39":[0,7,8,9,147,37,52,79,80,100,103,117,126,127],"44":[7,8,147,52],"48":[7,8,147,52],"52":[7,8,147,52],"54":[0,7,8,9,147,37,52,79,80,100,103,117,126,127]},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/handles/render-types/CanvasHandleNonMainOutput.vue":{"13":[0,7,8,9,147,37,52,79,80,117,126,127],"15":[0,7,8,9,147,37,52,79,80,117,126,127],"23":[0,7,8,9,147,37,52,79,80,117,126,127],"27":[0,7,8,9,147,37,52,79,80,117,126,127]},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/handles/render-types/parts/CanvasHandleDiamond.vue":{"13":[0,7,8,9,147,37,52,79,80,100,103,117,126,127]},"packages/localhost-41859/assets/_plugin-vue_export-helper-Da88TEg1.js":{"2":[0,23,53,57,80,88,120,127,130]},"packages/localhost-41859/assets/chunk-CC9Q-vWm.js":{"8":[0,23,53,57,80,88,120,127,130],"9":[0,23,53,57,80,88,120,127,130],"10":[0,23,53,57,80,88,120,127,130],"19":[0,23,53,57,80,88,120,127,130],"23":[0,23,53,57,80,88,120,127,130],"29":[0,23,53,57,80,88,120,127,130],"33":[0,23,53,57,80,88,120,127,130],"34":[0,23,53,57,80,88,120,127,130]},"packages/@n8n/design-system/src/components/N8nBadge/Badge.vue":{"23":[7,15,16,18,20,23,33,35,37,38,39,40,41,52,69,71,72,88,89,96,97,98,99,100,126,133,138,139,141,144,146],"25":[7,15,16,18,20,23,33,35,38,39,40,41,52,69,71,72,88,89,96,97,98,99,100,126,138,139,141,144,146]},"packages/@n8n/design-system/src/components/N8nIcon/nodes/data-table.svg":{"11":[7,23,34,37,96,98,111,124,127,140]},"packages/@n8n/design-system/src/components/N8nIcon/nodes/information-extractor.svg":{"11":[23,37,62,96,98,127,140]},"packages/@n8n/design-system/src/components/N8nIcon/nodes/no-operation.svg":{"11":[23,37,55,62,67,74,79,82,83,96,98,109,114,119,120,121,127,128,129,140,143,146]},"packages/@n8n/design-system/src/components/N8nIconPicker/types.ts":{"13":[5,15,23,26,33,35,37,38,39,41,68,69,70,71,72,89,94,96,97,98,136,138,144]},"packages/@n8n/design-system/src/components/N8nRecycleScroller/RecycleScroller.vue":{"14":[23,37,38,39,72,89,97,98],"30":[23,37,38,39,72,89,97,98],"31":[23,37,38,39,72,89,97,98],"48":[23,37,38,39,72,89,97,98],"50":[23,37,38,39,72,89,97,98],"60":[23,37,38,39,72,89,97,98],"61":[23,37,38,39,72,89,97,98],"72":[23,37,38,39,72,89,97,98],"76":[23,37,38,39,72,89,97,98],"77":[23,37,38,39,72,89,97,98],"79":[23,37,38,39,72,89,97,98],"81":[23,37,38,39,72,89,97,98],"94":[23,37,38,39,72,89,97,98],"102":[23,37,38,39,72,89,97,98],"106":[23,37,38,39,72,89,97,98],"116":[23,37,38,39,72,89,97,98],"120":[23,37,38,39,72,89,97,98],"132":[23,37,38,39,72,89,97,98],"133":[23,37,38,39,72,89,97,98],"141":[23,37,38,39,72,89,97,98],"147":[23,37,38,39,72,89,97,98],"148":[23,37,38,39,72,89,97,98],"167":[23,37,38,39,72,89,97,98],"170":[23,37,38,39,72,89,97,98],"184":[23,37,38,39,72,89,97,98],"192":[23,38,39,72,89,97,98],"194":[23,37,38,39,72,89,97,98]},"packages/@n8n/design-system/src/directives/n8n-truncate.ts":{"19":[15,16,18,20,23,37,38,39,40,41,69,71,72,88,89,97,98,133,138,139,144,146]},"packages/@n8n/utils/src/assert.ts":{"4":[1,2,4,7,8,10,23,30,32,33,37,38,39,51,80,89,90,91,97,98,127,130,145,146]},"packages/@n8n/utils/src/string/truncate.ts":{"1":[15,16,18,20,23,29,30,31,32,34,35,37,38,39,40,41,69,71,72,79,88,89,97,98,117,120,123,124,125,128,133,138,139,144,146],"11":[5,29,30,31,32,34,35,66,109,114,118,129]},"packages/frontend/editor-ui/src/app/components/TimeAgo.vue":{"20":[15,16,18,20,23,33,37,38,39,40,41,68,69,70,71,72,89,97,98,133,138,139,144,145,146],"21":[15,16,18,20,23,33,37,38,39,40,41,68,69,70,71,72,89,97,98,133,138,139,144,145,146],"31":[15,16,18,20,23,33,37,38,39,40,41,68,69,70,71,72,89,97,98,133,138,139,144,145,146],"37":[15,16,18,20,23,33,37,38,39,40,41,68,69,70,71,72,89,97,98,133,138,139,144,145,146],"41":[15,16,18,20,23,33,37,38,39,40,41,68,69,70,71,72,89,97,98,133,138,139,144,145,146]},"packages/frontend/editor-ui/src/app/components/forms/ResourceFiltersDropdown.vue":{"51":[144],"63":[15,16,18,19,20,22,23,26,37,38,39,40,41,68,69,70,71,72,73,88,89,93,94,96,97,98,133,138,139,144,146],"66":[15,16,18,19,20,22,23,26,37,38,39,40,41,68,69,70,71,72,73,88,89,93,94,96,97,98,133,138,139,144,146],"89":[15,16,18,19,20,22,23,26,37,38,39,40,41,68,69,70,71,72,73,88,89,93,94,96,97,98,133,138,139,144,146],"91":[144],"115":[15,16,18,19,20,22,23,26,37,38,39,40,41,68,69,70,71,72,73,88,89,93,94,96,97,98,133,138,139,144,146],"119":[144],"126":[15,16,18,19,20,22,23,26,37,38,39,40,41,68,69,70,71,72,73,88,89,93,94,96,97,98,133,138,139,144,146],"130":[15,16,18,19,20,22,23,26,37,38,39,40,41,68,69,70,71,72,73,88,89,93,94,96,97,98,133,138,139,144,146],"142":[15,16,18,19,20,22,23,26,37,38,39,40,41,68,69,70,71,72,73,88,89,93,94,96,97,98,133,138,139,144,146],"148":[144],"164":[144],"182":[144]},"packages/frontend/editor-ui/src/app/components/layouts/PageViewLayoutList.vue":{"10":[15,16,18,19,20,22,23,26,37,38,39,40,41,68,69,70,71,72,73,88,89,93,94,96,97,98,133,138,139,144,146]},"packages/frontend/editor-ui/src/app/utils/expressions.ts":{"17":[147],"21":[147,120,121],"25":[147,89],"26":[147,89],"34":[1,7,8,147,37,52,74,80,81,103,117,119,121,124,126,128,130,131],"38":[1,7,8,147,37,80,81,103,117,119,126,130,131],"42":[1,7,8,147,37,80,81,103,111,117,119,121,122,126,130,131],"48":[1,147,130,131],"52":[1,147,130,131],"56":[1,147,130,131],"60":[1,147,130,131],"64":[1,147,130,131],"68":[1,7,8,147,37,52,66,74,76,80,81,85,89,103,111,114,117,119,120,121,122,124,126,127,128,129,130,131],"83":[1,7,147,52,74,119,121,126,128,130,131],"126":[1,7,8,147,37,52,66,74,76,80,81,85,89,103,114,117,119,120,121,122,124,126,127,128,129,130,131],"150":[2,4,7,8,147,11,12,21,23,24,27,28,30,34,37,38,39,51,58,60,61,62,67,75,80,84,89,90,91,97,98,103,104,105,109,110,111,113,119,120,121,122,124,127,129,130,131,135,136,145],"160":[4,7,8,147,11,12,21,23,24,28,30,34,37,38,39,51,60,61,62,67,75,80,84,89,90,91,97,98,103,104,105,109,110,111,113,120,122,124,127,129,130,131,136,145]},"packages/frontend/editor-ui/src/app/utils/parameterUtils.ts":{"13":[2,4,7,8,11,12,21,23,24,27,28,30,34,37,38,39,51,58,60,61,62,67,75,80,84,89,96,97,98,103,104,105,109,110,111,113,118,119,120,121,122,124,126,127,129,130,131,135,136,145]},"packages/frontend/editor-ui/src/features/credentials/components/CredentialCard.vue":{"68":[23,37,38,39,72,89,97,98],"69":[23,37,38,39,72,89,97,98],"72":[23,37,38,39,72,89,97,98],"74":[23,37,38,39,72,89,97,98],"82":[23,37,38,39,72,89,97,98],"89":[23,37,38,39,72,89,97,98],"120":[23,37,38,39,72,89,97,98],"129":[23,37,38,39,72,89,97,98],"131":[38],"158":[72],"222":[72],"231":[23,37,38,39,72,89,97,98],"236":[23,37,38,39,72,89,97,98],"239":[23,37,38,39,72,89,97,98],"243":[38],"270":[23,37,38,39,72,89,97,98],"279":[23,37,38,39,72,89,97,98]},"packages/localhost-41859/assets/shield-alt-J5nzuCWH.js":{"8":[23,53,57,80,120,127]},"packages/@n8n/design-system/src/components/N8nIcon/custom/mcp.svg":{"13":[7,15,16,18,20,25,33,36,40,41,52,68,69,70,71,72,87,89,90,91,92,93,94,95,126,133,138,139,144,146]},"packages/@n8n/design-system/src/components/N8nLogo/Logo.vue":{"8":[16,18,19,20,29,30,31,32,34,35,36,41,72,93,138],"24":[16,18,19,20,29,30,31,32,34,35,36,41,72,93,138],"30":[16,18,19,20,29,30,31,32,34,35,36,41,72,93,138],"42":[16,18,19,20,29,30,31,32,34,35,36,41,72,93,138],"57":[16,18,19,20,29,30,31,32,34,35,36,41,72,93,138]},"packages/@n8n/design-system/src/components/N8nLogo/logo-icon.svg":{"11":[16,18,19,20,29,30,31,32,34,35,36,41,72,93,138]},"packages/@n8n/design-system/src/components/N8nLogo/logo-text.svg":{"11":[16,18,19,20,29,30,31,32,34,35,36,41,72,93,138]},"packages/@n8n/design-system/src/components/PreviewTag/PreviewTag.vue":{"11":[16,19,25,33,36,41,72,87,89,90,91,92,93,94,95,138],"12":[16,19,25,33,36,41,72,87,89,90,91,92,93,94,95,138]},"packages/frontend/editor-ui/src/app/components/SettingsSidebar.vue":{"23":[25,33,36,87,89,90,91,92,93,94,95],"26":[25,33,36,87,89,90,91,92,93,94,95],"37":[25,33,36,87,89,90,91,92,93,94,95],"41":[25,33,36,87,89,90,91,92,93,94,95]},"packages/frontend/editor-ui/src/app/layouts/SettingsLayout.vue":{"27":[25,33,36,87,89,90,91,92,93,94,95],"34":[25,33,36,87,89,90,91,92,93,94,95],"36":[25,33,36,87,89,90,91,92,93,94,95]},"packages/frontend/editor-ui/src/app/utils/rbac/checks/isInstanceOwner.ts":{"4":[25,36,92,93]},"packages/frontend/editor-ui/src/app/utils/rbac/middleware/rbac.ts":{"11":[33,36,87,89,90,91,94,95]},"packages/frontend/editor-ui/src/app/utils/rbacUtils.ts":{"4":[33,36,87,89,90,91,94,95],"12":[33,36,87,89,90,91,94,95],"23":[33,36,87,89,90,91,94,95],"34":[89,94]},"packages/frontend/editor-ui/src/features/settings/apiKeys/apiKeys.store.ts":{"12":[36]},"packages/frontend/editor-ui/src/features/settings/apiKeys/views/SettingsApiView.vue":{"62":[36],"137":[36]},"packages/frontend/editor-ui/src/features/shared/banners/components/banners/BaseBanner.vue":{"18":[36],"34":[36],"44":[36],"59":[36]},"packages/frontend/editor-ui/src/features/shared/banners/components/banners/TrialBanner.vue":{"73":[36],"80":[36],"81":[36],"82":[36],"90":[36],"93":[36],"99":[36],"104":[36],"106":[36],"120":[36],"130":[36],"135":[36],"143":[36],"148":[36],"166":[36],"178":[36],"194":[36],"198":[36],"204":[36],"212":[36]},"packages/localhost-41315/assets/_plugin-vue_export-helper-Da88TEg1.js":{"2":[36]},"packages/localhost-41315/assets/chunk-CC9Q-vWm.js":{"8":[36],"9":[36],"10":[36],"19":[36],"23":[36],"29":[36],"33":[36],"34":[36]},"packages/@n8n/design-system/src/components/N8nIcon/nodes/edit-image.svg":{"11":[53,54,146]},"packages/@n8n/design-system/src/components/N8nIcon/nodes/ftp.svg":{"11":[53]},"packages/frontend/editor-ui/src/features/ndv/panel/components/TriggerPanel.vue":{"60":[12,21,24,60,67,114,118,124,129,144],"74":[12,21,24,37,53,60,67,114,118,124,129,130,132,144],"78":[12,21,24,37,53,60,67,114,118,124,129,130,132,144],"86":[12,21,24,60,67,114,118,124,129,144],"94":[12,21,24,60,67,114,118,124,129,144],"113":[12,21,24,37,53,60,67,114,118,124,129,130,132,144],"119":[21,24,67,118,124,129,144],"127":[12,60],"135":[12,60,67,114],"139":[12,21,24,37,53,60,67,114,118,124,129,130,132,144],"157":[12,21,24,37,53,60,67,114,118,124,129,130,132,144],"165":[12,21,24,60,67,114,118,124,129,144],"169":[12,60,67],"173":[12,21,24,60,67,114,118,124,129,144],"191":[12,21,24,60,67,118,124,129,144],"193":[12,21,24,60,67,118,124,129,144],"199":[12,21,24,60,67,118,124,129,144],"201":[12,60],"207":[12,60],"220":[12,21,24,60,67,118,124,129,144],"238":[12,21,24,60,67,118,124,129,144],"248":[12,21,24,60,67,118,124,129,144],"288":[12,21,24,60,67,118,124,129,144],"378":[114],"435":[12,60],"439":[12,60],"465":[21,24,60,67,118,124,129,144],"482":[21,24,60,67,118,124,129,144],"488":[21,24,60,67,118,124,129,144]},"packages/@n8n/design-system/src/components/N8nIcon/nodes/execute-sub-workflow.svg":{"11":[57,134,135,136]},"packages/@n8n/design-system/src/components/N8nIcon/nodes/n8n-trigger.svg":{"11":[57]},"packages/@n8n/design-system/src/components/N8nIcon/nodes/n8n.svg":{"11":[57,105]},"packages/frontend/editor-ui/src/features/shared/editors/components/CodeNodeEditor/theme.ts":{"91":[2,7,9,21,22,28,57,84,103,104,105,109,110,111,116,119,120,121,122,124,127,128,129,134]},"packages/frontend/editor-ui/src/features/shared/editors/components/JsonEditor/JsonEditor.vue":{"33":[9,22,57,105,111,116,119,120,121,122,127,128,129,134],"43":[9,22,57,105,111,116,119,120,121,122,127,128,129,134],"71":[9,22,57,105,111,116,119,120,121,122,127,128,129,134],"80":[9,22,57,105,111,116,119,120,121,122,127,128,129,134],"84":[9,57,111,119,120,121,122,127,128,129],"89":[9,22,57,105,111,116,119,120,121,122,127,128,129,134],"90":[111,119,120,121,122,128,129],"102":[9,22,57,105,111,116,119,120,121,122,127,128,129,134],"124":[9,22,57,105,111,116,119,120,121,122,127,128,129,134]},"packages/frontend/editor-ui/src/features/shared/editors/plugins/codemirror/dragAndDrop.ts":{"15":[1,2,7,8,9,21,22,28,37,52,57,66,74,76,80,81,84,85,89,103,104,105,109,110,111,114,116,117,119,120,121,122,124,126,127,128,129,130,131,134,136],"18":[1,2,7,8,28,37,52,66,74,76,80,81,84,85,89,103,110,111,114,116,117,119,120,121,122,124,126,127,128,129,130,131,134,136],"20":[1,2,7,8,28,37,52,66,74,76,80,81,85,89,103,110,111,114,116,117,119,120,121,122,124,126,127,128,129,130,131,134,136],"35":[1,2,7,8,9,21,22,28,37,52,57,66,74,76,80,81,84,85,89,103,104,105,109,110,111,114,116,117,119,120,121,122,124,126,127,128,129,130,131,134,136],"42":[1,2,7,8,9,21,22,28,37,52,57,66,74,76,80,81,84,85,89,103,104,105,109,110,111,114,116,117,119,120,121,122,124,126,127,128,129,130,131,134,136],"46":[1,2,7,8,9,21,22,28,37,52,57,66,74,76,80,81,84,85,89,103,104,105,109,110,111,114,116,117,119,120,121,122,124,126,127,128,129,130,131,134,136],"93":[1,7,8,9,21,28,37,52,57,76,80,81,84,89,103,104,105,109,110,111,114,117,119,120,121,122,124,126,127,128,129],"97":[8,28,76,89,111,119,120,121,122,124,127,128,129,130,131,134],"104":[89,110,111,119,120,121,122,124,127,128,129,130,131],"112":[8,28,76,89,111,119,120,121,122,127,128,129,130,131,134],"115":[89,111,119,120,121,122,124,127,128,129,130,131],"123":[120],"127":[120],"139":[120],"143":[120],"163":[1,2,7,8,9,21,22,28,37,52,57,66,74,76,80,81,84,85,89,103,104,105,109,110,111,114,116,117,119,120,121,122,124,126,127,128,129,130,131,134,136]},"packages/frontend/editor-ui/src/features/shared/editors/plugins/codemirror/n8nLang.ts":{"11":[76,120,121,122],"14":[1,7,8,37,52,66,74,76,80,81,85,89,103,114,117,119,120,121,122,124,126,127,128,129,130,131,136],"25":[1,7,8,37,52,66,74,76,80,81,85,89,103,114,117,119,120,121,122,124,126,127,128,129,130,131,136],"28":[1,7,8,37,52,66,74,76,80,81,85,89,103,114,117,119,120,121,122,124,126,127,128,129,130,131,136],"32":[1,7,8,9,22,37,52,57,66,74,76,80,81,85,89,103,105,111,114,116,117,119,120,121,122,124,126,127,128,129,130,131,134,136],"37":[119,120,127,129]},"packages/@n8n/design-system/src/components/N8nAvatar/Avatar.vue":{"15":[15,25,33,35,38,41,70,71,72,89,92,93,94,96,97,98,99,138,144],"28":[15,25,33,35,38,41,70,71,72,89,92,93,94,96,97,98,99,138,144],"29":[15,25,33,35,38,41,70,71,72,89,92,93,94,96,97,98,99,138,144],"31":[15,25,33,35,38,41,70,71,72,89,92,93,94,96,97,98,99,138,144],"33":[15,25,33,35,38,41,70,71,72,89,92,93,94,96,97,98,99,138,144],"43":[15,25,33,35,38,41,70,71,72,89,92,93,94,96,97,98,99,138,144],"44":[15,25,33,35,38,41,70,71,72,89,92,93,94,96,97,98,99,138,144]},"packages/@n8n/design-system/src/utils/labelUtil.ts":{"1":[15,25,33,35,38,41,70,71,72,89,92,93,94,96,97,98,99,138,144],"4":[15,25,33,35,38,41,70,71,72,89,92,93,94,96,97,98,99,138,144],"6":[15,25,33,35,38,41,70,71,72,89,92,93,94,96,97,98,99,138,144],"11":[15,25,33,35,38,41,70,71,72,89,92,93,94,96,97,98,99,138,144]},"packages/frontend/editor-ui/src/app/api/workflow-dependencies.ts":{"9":[15,16,18,20,37,38,40,41,68,69,70,71,72,97,98,133,138,139,144,146]},"packages/frontend/editor-ui/src/app/api/workflows.ee.ts":{"7":[147,99],"20":[147,72],"28":[147]},"packages/frontend/editor-ui/src/app/components/WorkflowCard.vue":{"55":[15,16,18,20,40,41,68,69,70,71,72,133,138,139,144,146],"133":[15,16,18,20,40,41,68,69,70,71,72,133,138,139,144,146],"136":[15,16,18,20,40,41,71,72,133,138,139,144,146],"137":[144],"138":[15,16,18,20,40,41,68,69,70,71,72,133,138,139,144,146],"140":[15,16,18,20,40,41,68,69,70,71,72,133,138,139,144,146],"143":[138],"146":[138],"150":[15,16,18,20,40,41,68,69,70,71,72,133,138,139,144,146],"154":[15,16,18,20,40,41,71,72,133,138,139,144,146],"165":[15,16,18,20,40,41,71,72,133,138,139,144,146],"185":[15,16,18,20,40,41,68,69,70,71,72,133,138,139,144,146],"285":[15,16,18,20,40,41,68,69,70,71,72,133,138,139,144,146],"306":[15,16,18,20,40,41,68,69,70,71,72,133,138,139,144,146],"310":[15,16,18,20,40,41,71,72,133,138,139,144,146],"316":[15,16,18,20,40,41,68,69,70,71,72,133,138,139,144,146],"320":[15,16,18,20,40,41,68,69,70,71,72,133,138,139,144,146],"324":[15,16,18,20,40,41,68,69,70,71,72,133,138,139,144,146],"326":[138,144],"352":[68,70,72,144],"416":[144],"426":[144],"461":[144],"465":[144],"503":[144],"552":[144],"592":[144],"594":[144],"596":[15,16,18,20,40,41,68,69,70,71,72,133,138,139,144,146],"607":[15,16,18,20,40,41,68,69,70,71,72,133,138,139,144,146],"619":[138],"656":[15,16,18,20,40,41,68,69,70,71,72,133,138,139,144,146],"674":[15,16,18,20,40,41,68,69,70,71,72,133,138,139,144,146],"691":[15,16,18,20,40,41,71,72,133,138,139,144,146],"717":[144]},"packages/frontend/editor-ui/src/app/composables/useAutoScrollOnDrag.ts":{"13":[15,16,18,19,20,22,26,40,41,68,69,70,71,72,73,93,94,96,98,133,138,139,144,146],"20":[15,16,18,19,20,22,26,40,41,68,69,70,71,72,73,93,94,96,98,133,138,139,144,146],"99":[68],"103":[15,16,18,19,20,22,26,40,41,68,69,70,71,72,73,93,94,96,98,133,138,139,144,146],"108":[15,16,18,19,20,22,26,40,41,68,69,70,71,72,73,93,94,96,98,133,138,139,144,146],"117":[15,16,18,20,40,41,68,69,70,71,72,93,96,98,133,138,139,144,146],"125":[15,20,40,41,69,71,72,93,96,98,133,138,139,144]},"packages/frontend/editor-ui/src/app/composables/useLatestFetch.ts":{"1":[15,16,18,19,20,22,26,40,41,68,69,70,71,72,73,93,94,96,98,133,138,139,144,146],"4":[15,16,18,19,20,22,26,40,41,68,69,70,71,72,73,93,94,96,98,133,138,139,144,146],"6":[15,16,18,19,20,40,41,68,69,70,71,72,73,93,94,96,98,133,138,139,144,146]},"packages/frontend/editor-ui/src/app/views/WorkflowsView.vue":{"226":[68,69,70],"271":[68,69,70],"273":[68,69,70],"278":[68,69,70],"280":[68,69,70],"285":[15,16,18,19,20,22,26,40,41,68,69,70,71,72,73,93,94,96,98,133,138,139,144,146],"289":[15,16,18,19,20,22,26,40,41,68,69,70,71,72,73,93,94,96,98,133,138,139,144,146],"293":[15,16,18,20,40,41,68,69,70,71,72,96,98,133,138,139,144,146],"295":[15,16,18,20,40,41,68,69,70,71,72,133,138,139,144,146],"299":[15,16,18,20,40,41,68,69,70,71,72,133,138,139,144,146],"303":[15,16,18,20,40,41,68,69,70,71,72,133,138,139,144,146],"310":[15,16,18,19,20,22,26,40,41,68,69,70,71,72,73,93,94,96,98,133,138,139,144,146],"314":[15,16,18,19,20,22,26,40,41,68,69,70,71,72,73,93,94,96,98,133,138,139,144,146],"318":[15,40,41,68,69,70,72,96,98,138,144],"324":[15,16,18,19,20,22,26,40,41,68,69,70,71,72,73,93,94,96,98,133,138,139,144,146],"328":[15,16,18,19,20,22,26,40,41,68,69,70,71,72,73,93,94,96,98,133,138,139,144,146],"332":[15,16,18,20,40,41,68,69,70,71,72,133,138,139,144,146],"336":[15,16,18,19,20,22,26,40,41,68,69,70,71,72,73,93,94,96,98,133,138,139,144,146],"341":[15,16,18,19,20,22,26,40,41,68,69,70,71,72,73,93,94,96,98,133,138,139,144,146],"348":[15,40,41,68,69,70,72,96,98,138,144],"354":[15,16,18,20,40,41,68,69,70,71,72,133,138,139,144,146],"360":[68,69,70],"366":[68,69,70],"371":[15,40,41,68,69,70,72,96,98,138,144],"377":[15,16,18,20,40,41,68,69,70,71,72,96,98,133,138,139,144,146],"379":[15,40,41,68,69,70,72,96,98,138,144],"383":[15,40,41,68,69,70,72,96,98,138,144],"396":[15,40,41,68,69,70,72,96,98,138,144],"421":[15,40,41,68,69,70,72,96,98,138,144],"444":[15,40,41,68,69,70,72,96,98,138,144],"456":[15,40,41,68,69,70,72,96,98,138,144],"484":[15,40,41,68,69,70,72,96,98,138,144],"493":[68,69,70],"497":[15,16,18,19,20,22,26,40,41,68,69,70,71,72,73,93,94,96,98,133,138,139,144,146],"498":[15,16,18,20,40,41,68,69,70,71,72,133,138,139,144,146],"536":[144],"551":[15,16,18,19,20,22,26,40,41,68,69,70,71,72,73,93,94,96,98,133,138,139,144,146],"565":[15,16,18,19,20,22,26,40,41,68,69,70,71,72,73,93,94,96,98,133,138,139,144,146],"576":[15,16,18,19,20,22,26,40,41,68,69,70,71,72,73,93,94,96,98,133,138,139,144,146],"585":[15,16,18,19,20,22,26,40,41,68,69,70,71,72,73,93,94,96,98,133,138,139,144,146],"591":[15,16,18,19,20,22,26,40,41,68,69,70,71,72,73,93,94,96,98,133,138,139,144,146],"595":[15,16,18,19,20,22,26,40,41,68,69,70,71,72,73,93,94,96,98,133,138,139,144,146],"608":[15,16,18,19,20,22,26,40,41,68,69,70,71,72,73,93,94,96,98,133,138,139,144,146],"612":[15,16,18,19,20,22,26,40,41,68,69,70,71,72,73,93,94,96,98,133,138,139,144,146],"617":[15,16,18,19,20,22,26,40,41,68,69,70,71,72,73,93,94,96,98,133,138,139,144,146],"625":[15,19,41,69,70,72,73,93,94,96,98,138,144],"638":[15,16,18,19,20,22,26,40,41,68,69,70,71,72,73,93,94,96,98,133,138,139,144,146],"642":[15,16,18,19,20,22,26,40,41,68,69,70,71,72,73,93,94,96,98,133,138,139,144,146],"644":[68,69,70],"663":[72,144],"673":[70],"706":[15,16,18,19,20,22,26,40,41,68,69,70,71,72,73,93,94,96,98,133,138,139,144,146],"716":[15,19,41,69,70,72,73,93,94,96,98,138,144],"720":[15,19,41,69,70,72,73,93,94,96,98,138,144],"728":[15,16,18,19,20,22,26,40,41,68,69,70,71,72,73,93,94,96,98,133,138,139,144,146],"742":[15,20,40,41,69,71,72,93,96,98,133,138,139,144],"757":[15,16,18,19,20,22,26,40,41,68,69,70,71,72,73,93,94,96,98,133,138,139,144,146],"780":[15,16,18,19,20,22,26,40,41,68,69,70,71,72,73,93,94,96,98,133,138,139,144,146],"794":[144],"828":[15,16,18,20,40,41,68,69,70,71,72,133,138,139,144,146],"829":[68,69,70],"847":[15,16,18,20,40,41,68,69,70,71,72,133,138,139,144,146],"848":[15,16,18,20,40,41,68,69,70,71,72,133,138,139,144,146],"881":[15,16,18,19,20,22,26,40,41,68,69,70,71,72,73,93,94,96,98,133,138,139,144,146],"902":[40,68,69,70,72,138,144],"910":[69,144],"921":[15,16,18,19,20,22,26,40,41,68,69,70,71,72,73,93,94,96,98,133,138,139,144,146],"951":[40,68,69,70,72,138,144],"991":[15,16,18,19,20,22,26,40,41,68,69,70,71,72,73,93,94,96,98,133,138,139,144,146],"996":[15,16,18,19,20,22,26,40,41,68,69,70,71,72,73,93,94,96,98,133,138,139,144,146],"1025":[144],"1203":[144],"1204":[144],"1213":[68,70],"1214":[68,70],"1220":[70],"1244":[68,69,70],"1267":[68],"1289":[68],"1297":[68],"1316":[68],"1348":[69,70],"1579":[69,70],"1640":[69,70],"1678":[69],"1724":[70],"1759":[69,70],"1778":[70],"1794":[68,70],"1921":[70,72],"1948":[72],"1995":[68,70],"2008":[68],"2066":[70],"2141":[15,16,18,19,20,22,26,40,41,68,69,70,71,72,73,93,94,96,98,133,138,139,144,146],"2178":[15,16,18,19,20,22,26,40,41,68,69,70,71,72,73,93,94,96,98,133,138,139,144,146],"2245":[15,16,18,19,20,22,26,40,41,68,69,70,71,72,73,93,94,96,98,133,138,139,144,146],"2281":[15,16,18,20,40,41,68,69,70,71,72,133,138,139,144,146],"2291":[68,69,70],"2294":[68,69,70],"2295":[68,69,70],"2335":[15,16,18,20,40,41,68,69,70,71,72,133,138,139,144,146],"2338":[15,16,18,20,40,41,68,69,70,71,72,133,138,139,144,146],"2339":[15,16,18,20,40,41,68,69,70,71,72,133,138,139,144,146],"2377":[15,19,41,69,70,72,73,93,94,96,98,138,144],"2390":[15,19,41,69,70,72,73,93,94,96,98,138,144],"2393":[15,19,41,69,70,72,73,93,94,96,98,138,144],"2402":[15,19,41,69,70,72,73,93,94,96,98,138,144],"2411":[15,19,41,69,70,72,73,93,94,96,98,138,144],"2420":[144],"2433":[144],"2448":[144],"2464":[144],"2468":[15,16,18,19,20,22,26,40,41,68,69,70,71,72,73,93,94,96,98,133,138,139,144,146],"2476":[15,16,18,20,40,41,68,69,70,71,72,133,138,144,146],"2478":[15,16,18,20,40,41,68,69,70,71,72,133,138,144,146]},"packages/frontend/editor-ui/src/experiments/credentialsAppSelection/stores/credentialsAppSelection.store.ts":{"14":[15,16,18,19,20,22,26,40,41,68,69,70,71,72,73,93,94,96,98,133,138,139,144,146],"23":[18,19,73,93,94,138],"25":[18,19,73,93,94,138],"29":[18,19,73,93,94,138],"35":[18,19,73,93,94,138]},"packages/frontend/editor-ui/src/experiments/personalizedTemplates/stores/personalizedTemplates.store.ts":{"66":[15,16,18,19,20,22,26,40,41,68,69,70,71,72,73,93,94,96,98,133,138,139,144,146],"91":[15,16,18,19,20,40,41,68,69,70,71,72,73,93,94,96,98,133,138,139,144,146],"164":[15,16,18,19,20,22,26,40,41,68,69,70,71,72,73,93,94,96,98,133,138,139,144,146]},"packages/frontend/editor-ui/src/experiments/personalizedTemplatesV3/stores/personalizedTemplatesV3.store.ts":{"12":[15,16,18,19,20,22,26,40,41,68,69,70,71,72,73,93,94,96,98,133,138,139,144,146],"26":[15,16,18,19,20,22,26,40,41,69,70,71,72,73,93,94,96,98,133,138,139,144,146],"35":[15,16,18,19,20,22,26,40,41,68,69,70,71,72,73,93,94,96,98,133,138,139,144,146],"129":[15,16,18,19,20,22,26,40,41,68,69,70,71,72,73,93,94,96,98,133,138,139,144,146]},"packages/frontend/editor-ui/src/experiments/templateRecoV2/stores/templateRecoV2.store.ts":{"14":[15,16,18,19,20,22,26,40,41,68,69,70,71,72,73,93,94,96,98,133,138,139,144,146],"21":[15,16,18,19,20,22,26,40,41,69,70,71,72,73,93,94,96,98,133,138,139,144,146]},"packages/frontend/editor-ui/src/features/ai/mcpAccess/mcp.store.ts":{"33":[15,16,18,19,20,22,26,40,41,68,69,70,71,72,73,93,94,96,98,133,138,139,144,146]},"packages/frontend/editor-ui/src/features/collaboration/projects/components/ProjectMoveResourceModal.vue":{"41":[72],"66":[72],"73":[72],"90":[72],"94":[72],"97":[72],"98":[72],"99":[72],"102":[72],"112":[72],"115":[72],"120":[72],"124":[72],"173":[72],"189":[72],"192":[72],"194":[72],"202":[72],"206":[72],"207":[72],"213":[72],"214":[72],"222":[72],"240":[72],"245":[72],"329":[72],"332":[72],"340":[72]},"packages/frontend/editor-ui/src/features/collaboration/projects/components/ProjectMoveSuccessToastMessage.vue":{"19":[72],"20":[72],"21":[72],"24":[72]},"packages/frontend/editor-ui/src/features/collaboration/projects/components/ProjectSharing.vue":{"67":[33,38,70,72,94,96,97,98,99,144],"75":[33,38,70,72,94,97,98,99,144],"78":[33,38,70,72,94,97,98,99,144],"87":[33,38,70,72,94,97,98,99,144],"97":[33,38,72,97,98,99,144],"103":[33,38,97,98,99,144],"109":[33,38,70,72,94,97,98,99,144],"116":[33,38,70,72,94,97,98,99,144],"120":[33,38,70,72,94,97,98,99,144],"122":[33,38,70,72,94,97,98,99,144],"136":[33,38,70,72,94,96,97,98,99,144],"152":[33,38,72,94,97,98,99],"158":[33,38,70,72,94,96,97,98,99,144],"162":[33,38,72,94,97,98,99],"168":[72,94,97,98,99],"182":[38],"199":[33,38,70,72,94,96,97,98,99,144],"200":[33,38,70,72,94,96,97,98,99,144],"215":[33,38,70,72,94,96,97,98,99,144],"232":[33,38,70,72,94,97,98,99,144],"240":[33,38,70,72,94,97,98,99,144],"243":[33,38,70,72,94,97,98,99,144],"247":[33,38,70,72,94,97,98,99,144],"271":[33,38,96,97,98,99,144],"272":[33,38,96,97,98,99,144],"294":[33,38,97,98,99],"311":[38]},"packages/frontend/editor-ui/src/features/collaboration/projects/components/ProjectSharingInfo.vue":{"14":[33,38,70,72,94,96,97,98,99,144],"25":[33,38,70,72,94,96,97,98,99,144],"31":[33,38,70,72,94,96,97,98,99,144]},"packages/frontend/editor-ui/src/features/collaboration/projects/composables/useMoveResourceToProjectToast.ts":{"26":[72]},"packages/frontend/editor-ui/src/features/core/folders/components/MoveToFolderDropdown.vue":{"40":[70,72],"41":[70,72],"42":[70,72],"54":[70,72],"64":[70],"94":[70,72],"95":[70,72],"105":[70,72],"107":[70],"109":[70,72],"128":[70,72],"130":[70,72],"132":[70,72],"137":[70,72],"141":[70,72],"148":[70],"151":[70]},"packages/frontend/editor-ui/src/features/core/folders/components/MoveToFolderModal.vue":{"65":[70,72],"81":[70,72],"84":[70,72],"90":[70,72],"100":[70,72],"101":[70,72],"108":[70,72],"127":[70,72],"130":[70,72],"134":[70,72],"143":[70,72],"153":[70,72],"167":[70,72],"168":[72],"174":[70,72],"175":[70,72],"182":[70,72],"186":[72],"192":[72],"200":[70,72],"354":[70],"379":[70,72],"381":[70,72],"386":[70,72],"390":[70,72],"417":[70,72],"427":[70,72],"436":[70,72],"438":[70,72],"452":[72],"457":[72],"478":[70,72],"556":[70,72]},"packages/frontend/editor-ui/src/features/core/folders/composables/useFolders.ts":{"12":[68],"16":[68],"20":[15,16,18,19,20,22,26,40,41,68,69,70,71,72,73,93,94,96,98,133,138,139,144,146],"25":[68,69,70],"29":[69,70],"63":[68],"80":[68],"86":[68,69,70],"101":[41,68,69,70,72,138,144],"109":[68],"130":[68,69,70]},"packages/frontend/editor-ui/src/features/core/folders/folders.api.ts":{"11":[69,70],"23":[68,69,70],"35":[70],"46":[70],"57":[70,72],"87":[70],"100":[68,70],"111":[70]},"packages/frontend/editor-ui/src/features/credentials/credentials.ee.api.ts":{"6":[147,97,98],"19":[147,72]},"packages/frontend/editor-ui/src/features/settings/usage/usage.store.ts":{"38":[15,16,18,19,20,22,26,40,41,68,69,70,71,72,73,93,94,96,98,100,133,138,139,144,146],"48":[100],"51":[100],"73":[15,16,18,19,20,40,41,68,69,70,71,72,73,93,94,96,98,100,133,138,139,144,146],"77":[15,16,18,19,20,22,26,40,41,68,69,70,71,72,73,93,94,96,98,100,133,138,139,144,146]},"packages/frontend/editor-ui/src/features/workflows/composables/useWorkflowsEmptyState.ts":{"17":[15,16,18,19,20,22,26,40,41,68,69,70,71,72,73,93,94,96,98,133,138,139,144,146],"26":[15,18,19,41,69,70,72,73,93,94,96,98,138,144],"27":[15,16,18,19,20,22,26,40,41,71,72,73,93,94,133,138,139,144,146],"28":[15,16,18,19,20,22,26,40,41,68,69,70,71,72,73,93,94,96,98,133,138,139,144,146],"30":[15,16,18,19,20,22,26,40,41,68,69,70,71,72,73,93,94,96,98,133,138,139,144,146],"36":[18,19,73,93,94,138],"40":[15,16,18,19,20,22,26,40,41,68,69,70,71,72,73,93,94,96,98,133,138,139,144,146],"48":[18,19,73,93,94,138],"56":[18,19,73,93,94,138],"74":[15,18,19,41,69,70,72,73,93,94,96,98,138,144],"94":[15,19,41,69,70,72,73,93,94,96,98,138,144]},"packages/frontend/editor-ui/src/features/workflows/templates/recommendations/recommendedTemplates.store.ts":{"17":[15,16,18,19,20,22,26,40,41,68,69,70,71,72,73,93,94,96,98,133,138,139,144,146],"25":[15,16,18,19,20,22,26,40,41,68,69,70,71,72,73,93,94,96,98,133,138,139,144,146]},"packages/localhost-32899/assets/_plugin-vue_export-helper-Da88TEg1.js":{"2":[72]},"packages/localhost-32899/assets/chunk-CC9Q-vWm.js":{"8":[72],"9":[72],"10":[72],"19":[72],"23":[72],"29":[72],"33":[72],"34":[72]},"packages/frontend/editor-ui/src/app/components/layouts/EmptyStateLayout.vue":{"25":[18,19,73,93,94,138],"63":[18,19,73,93,94,138],"74":[18,19,73,93,94,138],"100":[18,19,73,93,94,138],"116":[18,19,73,93,94,138],"202":[18,19,73,93,94,138],"277":[18,19,73,93,94,138],"286":[18,19,73,93,94,138]},"packages/frontend/editor-ui/src/experiments/surfaceMcpToNewCloudUsers/composables/useSurfaceMcpEmptyState.ts":{"21":[18,19,73,93,94,138],"33":[18,19,73,93,94,138],"59":[18,19,73,93,94,138],"63":[18,19,73,93,94,138],"71":[18,19,73,93,94,138],"88":[18,19,73,93,94,138]},"packages/frontend/editor-ui/src/experiments/surfaceMcpToNewCloudUsers/composables/useSurfaceMcpToNewCloudUsersEligibility.ts":{"7":[18,19,73,93,94,138],"13":[18,19,73,93,94,138]},"packages/frontend/editor-ui/src/experiments/surfaceMcpToNewCloudUsers/stores/surfaceMcpToNewCloudUsers.store.ts":{"24":[18,19,73,93,94,138]},"packages/localhost-34613/assets/_plugin-vue_export-helper-Da88TEg1.js":{"2":[73]},"packages/localhost-34613/assets/chunk-CC9Q-vWm.js":{"8":[73],"9":[73],"10":[73],"19":[73],"23":[73],"29":[73],"33":[73],"34":[73]},"packages/@n8n/design-system/src/components/N8nIcon/nodes/ai-agent.svg":{"11":[7,8,37,51,52,79,80,103,117,126,127]},"packages/@n8n/errors/src/application.error.ts":{"18":[1,7,8,13,14,15,18,20,21,30,35,37,41,52,62,71,74,80,81,89,92,93,94,98,103,104,111,112,117,119,121,122,124,126,128,130,131,145,146]},"packages/frontend/editor-ui/src/app/composables/useAutocompleteTelemetry.ts":{"11":[1,7,8,37,52,66,74,76,80,81,85,89,103,114,117,119,120,121,122,124,126,127,128,129,130,131,136],"55":[89,119,120,121,122,127,129,130,131],"59":[89,119,120,121,122,127,129,130,131],"94":[89,119,120,121,122,127,129,130,131],"101":[1,7,8,37,52,66,74,76,80,81,85,89,103,114,117,119,120,121,122,124,126,127,128,129,130,131,136],"107":[1,7,8,37,52,66,74,76,80,81,85,89,103,114,117,119,120,121,122,124,126,127,128,129,130,131,136]},"packages/frontend/editor-ui/src/features/ndv/panel/components/InputNodeSelect.vue":{"18":[8,37,79,80,117,120,123,124,125,127,128],"29":[8,37,79,80,117,120,123,124,125,127,128],"33":[8,37,79,80,117,120,123,124,125,127,128],"40":[8,37,79,80,117,120,123,124,125,127,128],"43":[79,117,120,123,124,125,128],"56":[79,117,120,123,124,125,128],"58":[79,117,120,123,124,125,128],"65":[79,117,120,123,124,125,128],"70":[79,117,120,123,124,125,128],"79":[79,117,120,123,124,125,128],"106":[79,117,120,123,124,125,128],"110":[79,117,120,123,124,125,128],"116":[120,128],"118":[8,37,79,80,117,120,123,124,125,127,128],"133":[8,37,79,80,117,120,123,124,125,127,128],"139":[8,37,79,80,117,120,123,124,125,127,128],"143":[79,117,120,123,124,125,128],"149":[79,117,120,123,124,125,128]},"packages/frontend/editor-ui/src/features/ndv/panel/components/WireMeUp.vue":{"8":[8,21,37,67,80,98,104,124,127,129,133]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/ExpressionFunctionIcon.vue":{"8":[7,8,37,52,74,76,80,89,103,114,119,120,121,124,126,128,130,131,136]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/ExpressionParameterInput.vue":{"26":[1,7,8,37,52,66,74,76,80,81,85,89,103,114,117,119,120,121,122,124,126,127,128,129,130,131,136],"67":[1,7,8,37,52,66,74,76,80,81,85,89,103,114,117,119,120,121,122,124,126,127,128,129,130,131,136],"68":[1,7,8,37,52,66,74,76,80,81,85,89,103,114,117,119,120,121,122,124,126,127,128,129,130,131,136],"78":[89,119,120,121,122,127,128,129,130,131],"84":[89,119,120,121,122,127,128,129,130,131],"89":[89,119,120,121,122,127,128,130,131],"97":[1,7,8,37,52,76,81,89,114,117,119,120,121,122,124,126,127,128,130,131],"100":[1,7,89,114,117,119,120,121,122,126,127,128,130,131],"128":[1,7,52,66,74,76,85,89,114,117,119,120,121,122,124,126,127,128,129,130,131],"137":[1,7,8,37,52,66,74,76,80,81,85,89,103,114,117,119,120,121,122,124,126,127,128,129,130,131,136],"148":[120],"160":[120],"166":[120],"175":[120],"181":[1,7,8,37,52,66,74,76,80,81,85,89,103,114,117,119,120,121,122,124,126,127,128,129,130,131,136],"185":[1,7,8,37,52,76,80,81,89,103,114,117,119,121,126,128],"189":[120],"196":[1,7,8,37,52,76,81,89,114,117,119,120,121,122,124,126,127,128,130,131],"199":[1,7,8,37,52,66,74,76,80,81,85,89,103,114,117,119,120,121,122,124,126,127,128,129,130,131,136],"219":[1,7,8,37,52,66,74,76,80,81,85,89,103,114,117,119,120,121,122,124,126,127,128,129,130,131,136],"244":[121]},"packages/frontend/editor-ui/src/features/shared/editors/components/InlineExpressionEditor/InlineExpressionEditorInput.vue":{"26":[1,7,8,37,52,66,74,76,80,81,85,89,103,114,117,119,120,121,122,124,126,127,128,129,130,131,136],"39":[1,7,8,37,52,66,74,76,80,81,85,89,103,114,117,119,120,121,122,124,126,127,128,129,130,131,136],"51":[1,7,8,37,52,66,74,76,80,81,85,89,103,114,117,119,120,121,122,124,126,127,128,129,130,131,136],"75":[1,7,8,37,52,66,74,76,80,81,85,89,103,114,117,119,120,121,122,124,126,127,128,129,130,131,136],"81":[1,7,52,66,74,76,85,89,114,117,119,120,121,122,124,126,127,128,129,130,131],"88":[1,7,8,37,52,66,74,76,80,81,85,89,103,114,117,119,120,121,122,124,126,127,128,129,130,131,136],"97":[89,119,120,121,122,127,128,129,130,131],"104":[89,119,120,121,122,127,128,129,130,131],"107":[89,119,120,121,122,127,129,130,131],"118":[1,7,8,37,52,66,74,76,80,81,85,89,103,114,117,119,120,121,122,124,126,127,128,129,130,131,136]},"packages/frontend/editor-ui/src/features/shared/editors/components/InlineExpressionEditor/InlineExpressionEditorOutput.vue":{"32":[1,7,8,37,52,66,74,76,80,81,85,89,103,111,114,117,119,120,121,122,124,126,127,128,129,130,131,136],"38":[1,7,8,37,52,76,80,81,89,103,111,114,117,119,121,126,128],"45":[1,7,8,37,52,66,74,76,80,81,85,89,103,111,114,117,119,120,121,122,124,126,127,128,129,130,131,136],"62":[89,111,119,120,121,122,127,128,131],"66":[89,111,119,120,121,122,127,128,129,130,131],"72":[89,111,119,120,121,122,127,128,129,130,131]},"packages/frontend/editor-ui/src/features/shared/editors/components/InlineExpressionEditor/theme.ts":{"4":[1,7,8,37,52,66,74,76,80,81,85,89,103,111,114,117,119,120,121,122,124,126,127,128,129,130,131,136],"18":[1,7,8,37,52,66,74,76,80,81,85,89,103,114,117,119,120,121,122,124,126,127,128,129,130,131,136],"58":[1,7,8,37,52,66,74,76,80,81,85,89,103,111,114,117,119,120,121,122,124,126,127,128,129,130,131,136]},"packages/frontend/editor-ui/src/features/shared/editors/composables/useExpressionEditor.ts":{"59":[1,7,8,37,52,66,74,76,80,81,85,89,103,111,114,117,119,120,121,122,124,126,127,128,129,130,131,136],"70":[89,119,120,121,122,127,129,130,131],"103":[1,7,8,37,52,66,74,76,80,81,85,89,103,111,114,117,119,120,121,122,124,126,127,128,129,130,131,136],"108":[1,7,8,37,52,66,74,76,80,81,85,89,103,111,114,117,119,120,121,122,124,126,127,128,129,130,131],"122":[1,7,8,37,52,66,74,76,80,81,85,89,103,111,114,117,119,120,121,122,124,126,127,128,129,130,131],"142":[1,7,8,37,52,66,74,76,80,81,85,89,103,111,114,117,119,120,121,122,124,126,127,128,129,130,131],"176":[1,7,8,37,52,66,74,76,80,81,85,89,103,111,114,117,119,120,121,122,124,126,127,128,129,130,131,136],"180":[1,7,52,66,74,76,85,89,111,114,117,119,120,121,122,124,126,127,128,129,130,131],"186":[1,7,8,37,52,66,74,76,80,81,85,89,103,111,114,117,119,120,121,122,124,126,127,128,129,130,131,136],"197":[1,7,8,37,52,66,74,76,80,81,85,89,103,111,114,117,119,120,121,122,124,126,127,128,129,130,131,136],"201":[1,7,8,37,52,66,74,76,80,81,85,89,103,111,114,117,119,120,121,122,124,126,127,128,129,130,131,136],"212":[1,7,8,37,52,80,89,103,111,119,120,121,122,124,126,127,128,130,131],"220":[1,7,8,37,52,80,89,103,111,119,120,121,122,124,126,127,128,129,130,131],"227":[111,119,120,121,122,127,129,130,131],"238":[1,7,8,37,52,66,74,76,80,81,85,89,103,114,117,119,120,121,122,124,126,127,128,129,130,131,136],"249":[1,7,8,37,52,66,74,76,80,81,85,89,103,111,114,117,119,120,121,122,124,126,127,128,129,130,131,136],"276":[89,111,119,120,121,122,127,128,129,130,131],"281":[89,119,120,121,122,127,128,129,130,131],"293":[89,111,119,121,122,127,128,129,130,131],"309":[1,7,8,37,52,66,74,76,80,81,85,89,103,111,114,117,119,120,121,122,124,126,127,128,129,130,131,136],"317":[1,7,8,37,52,66,74,76,80,81,85,89,103,111,114,117,119,120,121,122,124,126,127,128,129,130,131,136],"327":[1,7,8,37,52,66,74,76,80,81,85,89,103,111,114,117,119,120,121,122,124,126,127,128,129,130,131,136],"339":[1,7,8,37,52,66,74,76,80,81,85,89,103,111,114,117,119,120,121,122,124,126,127,128,129,130,131,136],"350":[1,7,8,37,52,66,74,76,80,81,85,89,103,111,114,117,119,120,121,122,124,126,127,128,129,130,131,136],"354":[1,7,8,37,52,76,80,81,89,103,111,114,117,119,121,126,128],"361":[7,8,37,80,81,103,117,119,126],"363":[7,8,37,80,81,103,117,119,126],"369":[7,8,37,80,81,103,117,119,126],"379":[1,7,8,37,52,66,74,76,80,81,85,89,103,111,114,117,119,120,121,122,124,126,127,128,129,130,131],"441":[1,7,8,37,52,66,74,76,80,81,85,89,103,111,114,117,119,120,121,122,124,126,127,128,129,130,131,136],"443":[1,7,8,37,52,66,74,76,80,81,85,89,103,111,114,117,119,120,121,122,124,126,127,128,129,130,131,136],"444":[1,7,52,66,74,76,85,89,111,114,117,119,120,121,122,124,126,127,128,129,130,131],"447":[1,7,52,66,74,76,85,89,111,114,117,119,120,121,122,124,126,127,128,129,130,131],"448":[1,7,52,66,74,76,85,89,111,114,117,119,120,121,122,124,126,127,128,129,130,131],"478":[1,7,8,37,52,66,74,76,80,81,85,89,103,114,117,119,120,121,122,124,126,127,128,129,130,131,136],"481":[1,7,52,66,74,76,85,89,114,117,119,120,121,122,124,126,127,128,129,130,131],"511":[1,7,52,66,74,76,85,89,114,117,119,120,121,122,124,126,127,128,129,130,131],"527":[1,7,8,37,52,66,74,76,80,81,85,89,103,111,114,117,119,120,121,122,124,126,127,128,129,130,131,136],"535":[89,119,120,121,122,127,129,130,131],"555":[89,119,120,121,122,127,129,130,131]},"packages/frontend/editor-ui/src/features/shared/editors/plugins/codemirror/completions/addCompletions.ts":{"8":[1,7,8,37,52,66,74,76,80,81,85,89,103,111,114,117,119,120,121,122,124,126,127,128,129,130,131,136],"15":[1,7,8,37,52,66,74,76,80,81,85,89,103,111,114,117,119,120,121,122,124,126,127,128,129,130,131,136]},"packages/frontend/editor-ui/src/features/shared/editors/plugins/codemirror/expressionCloseBrackets.ts":{"10":[1,7,8,37,52,66,74,76,80,81,85,89,103,111,114,117,119,120,121,122,124,126,127,128,129,130,131,136],"14":[89,111,119,120,121,122,127,129,130,131],"36":[1,7,8,37,52,66,74,76,80,81,85,89,103,111,114,117,119,120,121,122,124,126,127,128,129,130,131,136]},"packages/@n8n/design-system/src/components/N8nDatatable/Datatable.vue":{"23":[88],"37":[88],"45":[88],"76":[88],"80":[88],"89":[88],"99":[88],"133":[88],"134":[88],"135":[88]},"packages/@n8n/design-system/src/components/N8nFormInput/FormInput.vue":{"56":[15,18,20,25,35,41,71,88,89,92,93,98,135,138,144],"82":[15,18,20,25,35,41,71,88,89,92,93,98,135,138,144],"122":[15,20,41,71,88,92,93,98,135,138,144],"128":[15,20,41,71,88,92,93,98,138,144],"133":[15,18,20,41,71,88,92,93,98,135,138,144],"137":[93],"143":[15,18,20,25,35,41,71,88,89,92,93,98,135,138,144],"161":[15,18,20,25,35,41,71,88,89,92,93,98,135,138,144],"167":[15,18,20,25,35,41,71,88,89,92,93,98,135,138,144],"173":[20,25,71,88,92,93],"176":[15,18,20,25,35,41,71,88,89,92,93,98,135,138,144],"214":[15,18,20,25,35,41,71,88,89,92,93,98,135,138,144],"215":[71,93]},"packages/@n8n/design-system/src/components/TableBase/TableBase.vue":{"4":[88]},"packages/frontend/editor-ui/src/app/composables/useMessage.ts":{"14":[91,113,130,133,145],"48":[32,37,40,41,88,91,100,113,114,130,133,139,144,145],"63":[32,37,40,41,88,91,100,113,114,130,133,139,144,145],"110":[69,70,105]},"packages/frontend/editor-ui/src/features/collaboration/projects/views/ProjectVariables.vue":{"68":[88],"78":[88],"82":[88],"87":[88],"91":[88],"93":[88],"94":[88],"109":[88],"114":[88],"150":[88],"184":[88],"193":[88],"197":[88],"216":[88],"222":[88],"269":[88],"281":[88],"290":[88],"314":[88],"400":[88],"434":[88],"435":[88],"451":[88],"452":[88],"463":[88]},"packages/frontend/editor-ui/src/features/settings/environments.ee/components/VariableModal.vue":{"57":[88],"80":[88],"84":[88],"103":[88],"118":[88],"119":[88],"122":[88],"128":[88],"168":[88],"169":[88],"173":[88],"178":[88],"182":[88],"218":[88],"222":[88],"239":[88],"252":[88],"265":[88],"272":[88],"295":[88],"300":[88],"306":[88],"313":[88],"315":[88],"320":[88],"334":[88]},"packages/frontend/editor-ui/src/features/settings/environments.ee/environments.api.ts":{"10":[147,88,120,127,130],"21":[147,88],"28":[147,88],"40":[147,88]},"packages/@n8n/design-system/src/components/N8nIcon/custom/status-waiting.svg":{"8":[117]},"packages/@n8n/design-system/src/components/N8nIcon/custom/text.svg":{"8":[7,117]},"packages/@n8n/design-system/src/components/N8nIcon/nodes/if.svg":{"11":[5,62,112,114,117,123,124,125,128,143,146]},"packages/@n8n/design-system/src/components/N8nIcon/nodes/loop-over-items.svg":{"11":[55,74,82,83,109,117,120,143]},"packages/@n8n/design-system/src/components/N8nIcon/nodes/wait.svg":{"11":[11,13,14,50,74,114,117]},"packages/@n8n/design-system/src/components/N8nInfoAccordion/InfoAccordion.vue":{"29":[7,21,24,60,67,105,113,114,115,117,118,124,129,141,142,144],"40":[7,21,24,60,67,105,113,114,115,117,118,124,129,141,142,144],"54":[7,21,24,60,67,105,113,114,115,117,118,124,129,141,142,144],"61":[7,21,24,60,67,105,113,114,115,117,118,124,129,141,142,144]},"packages/@n8n/design-system/src/components/N8nTree/Tree.vue":{"20":[9,14,62,67,113,117,120,122,123,125,128],"28":[9,14,62,67,113,117,120,122,123,125,128],"32":[9,14,62,67,113,117,120,122,123,125,128],"36":[9,14,62,67,113,117,120,122,123,125,128],"52":[9,14,62,67,113,117,120,122,123,125,128],"61":[9,14,62,67,113,117,120,122,123,125,128],"68":[9,14,62,67,117,120,122,123,125,128],"87":[117,120,123,128],"95":[117,120,123,128]},"packages/@n8n/design-system/src/types/binary.ts":{"24":[1,2,5,9,11,14,27,49,61,62,66,67,74,75,79,82,85,104,106,110,111,113,114,116,117,118,119,120,121,122,123,124,125,127,128,129,131,132,134,135]},"packages/@n8n/design-system/src/v2/components/Checkbox/Checkbox.vue":{"12":[7,66,87,100,101,105,113,114,115,117,139,140,141,142,144,146],"15":[7,66,87,100,101,105,113,114,115,117,139,140,141,142,144,146],"20":[7,66,87,100,101,105,113,114,115,117,139,140,141,142,144,146],"23":[7,66,87,100,101,105,113,114,115,117,139,140,141,142,144,146],"24":[7,66,87,100,101,105,113,114,115,117,139,140,141,142,144,146],"26":[87,100,117,144,146],"30":[7,66,87,100,101,105,113,114,115,117,139,140,141,142,144,146],"38":[7,66,87,100,101,105,114,115,117,139,140,141,144,146],"47":[7,66,87,100,101,105,113,114,115,117,139,140,141,142,144,146],"49":[7,87,100,101,105,114,115,117,141,144,146],"58":[7,66,87,100,101,105,113,114,115,117,139,140,141,142,144,146],"59":[7,101,105,114,115,117,141,144,146]},"packages/frontend/editor-ui/src/app/components/DropArea/DropArea.vue":{"4":[1,7,24,49,66,67,76,81,82,85,103,104,106,109,114,116,117,118,120,122,124,125,127,129,132,133,138],"8":[1,7,24,49,66,67,76,81,82,85,103,104,106,109,114,116,117,118,120,122,124,125,127,129,132,133,138],"13":[1,7,24,66,67,76,81,82,85,104,106,114,116,117,118,120,122,124,125,127,132,138]},"packages/frontend/editor-ui/src/app/components/WorkflowPreview.vue":{"63":[105,112,113,114,115,117,141,142,146],"76":[105,112,113,114,115,117,141,142,146],"92":[112],"123":[117,141,142],"160":[141],"170":[112,117,141,142],"190":[112,117,141,142],"194":[112,117,141,142],"206":[112,117,141,142],"220":[105,112,113,114,115,117,141,142,146],"225":[105,112,113,114,142,146],"230":[105,112,113,114,115,117,141,142,146],"231":[112,117,141,142],"243":[105,112,113,114,115,117,141,142,146],"266":[105,112,113,114,115,117,141,142,146],"275":[105,112,113,114,115,117,141,142,146],"276":[112,146]},"packages/frontend/editor-ui/src/app/composables/useReportWorkflowFailuresToParent.ts":{"33":[13,14,101,102,112,117,141,142]},"packages/frontend/editor-ui/src/app/layouts/DemoLayout.vue":{"17":[13,14,101,102,112,117,141,142],"60":[13,14,101,102,112,117,141,142],"87":[13,14,101,102,112,117,141,142]},"packages/frontend/editor-ui/src/features/execution/executions/components/ExecutionStopAllText.vue":{"10":[7,105,113,114,115,117,141,142],"17":[7,105,113,114,115,117,141,142],"18":[105,113,114,115,117,141,142],"26":[7,105,113,114,115,117,141,142]},"packages/frontend/editor-ui/src/features/execution/executions/components/ExecutionsFilter.vue":{"41":[7,105,113,114,115,117,141,142],"63":[141],"66":[141],"67":[141],"69":[7,105,113,114,115,117,141,142],"87":[141],"104":[141],"113":[141],"120":[141],"127":[141],"139":[141],"155":[7,105,113,114,115,117,141,142],"205":[141],"219":[7,105,113,114,115,117,141,142],"222":[7,105,113,114,115,117,141,142],"233":[7,105,113,114,115,117,141,142],"249":[141],"256":[141],"300":[141],"352":[141],"364":[141],"373":[141],"375":[141],"378":[141],"410":[141],"429":[141],"455":[141],"477":[141],"501":[141]},"packages/frontend/editor-ui/src/features/execution/executions/components/ViewSubExecution.vue":{"9":[9,11,117,134,135],"23":[9,11,117,134,135],"27":[134,135],"41":[9,11,117,134,135]},"packages/frontend/editor-ui/src/features/execution/executions/components/workflow/WorkflowExecutionsCard.vue":{"41":[105,113,114,115,117,141,142],"44":[105,113,114,115,117,141,142],"47":[113,141,142],"57":[105,113,114,115,117,141,142],"60":[105,113,114,115,117,141,142],"61":[105,113,114,115,117,141,142],"63":[105,113,114,115,117,141,142],"69":[105,113,114,115,117,141,142],"104":[105,113,114,115,117,141,142],"119":[142],"137":[105,113,114,115,117,141,142],"175":[105,113,114,115,117,141,142]},"packages/frontend/editor-ui/src/features/execution/executions/components/workflow/WorkflowExecutionsInfoAccordion.vue":{"58":[7,105,113,114,115,117,141,142],"78":[7,105,113,114,115,117,141,142],"88":[7,105,113,114,115,117,141,142],"96":[7,105,113,114,115,117,141,142],"109":[7,105,113,114,115,117,141,142],"110":[7,105,113,114,115,117,141,142],"119":[114,117],"123":[7,105,113,114,115,117,141,142],"130":[7,105,113,114,115,117,141,142]},"packages/frontend/editor-ui/src/features/execution/executions/components/workflow/WorkflowExecutionsLandingPage.vue":{"22":[7,105,113,114,115,117,141,142],"23":[7,105,113,114,115,117,141,142],"25":[142],"43":[142],"46":[142],"54":[7,105,113,114,115,117,141,142]},"packages/frontend/editor-ui/src/features/execution/executions/components/workflow/WorkflowExecutionsList.vue":{"12":[7,105,113,114,115,117,141,142],"42":[7,105,113,114,115,117,141,142],"43":[105,113,114,115,117,141,142],"48":[7,105,113,114,115,117,141,142],"52":[114],"73":[7,105,113,142],"81":[7,105,113,114,115,117,141,142],"92":[117],"94":[141]},"packages/frontend/editor-ui/src/features/execution/executions/components/workflow/WorkflowExecutionsPreview.vue":{"51":[105,113,114,115,117,141,142],"55":[105,113,114,115,117,141,142],"56":[105,113,114,115,117,141,142],"57":[105,113,114,115,117,141,142],"60":[105,113,114,115,117,141,142],"71":[105,113,114,115,117,141,142],"75":[105,113,114,115,117,141,142],"79":[114],"90":[105,113,114,115,117,141,142],"96":[105,113,114,115,117,141,142],"106":[105,113,114,115,117,141,142],"118":[105,113,114,115,117,141,142],"140":[105,113,114,115,117,141,142],"142":[105,113,114,115,117,141,142],"169":[114],"239":[142],"247":[142],"260":[105,113,114,115,117,141,142],"280":[105,113,114,115,117,141,142],"310":[105,113,114,115,117,141,142],"321":[105,113,114,115,117,141,142],"355":[105,113,114,115,117,141,142],"367":[105,113,114,115,117,141,142],"370":[113],"395":[113,141],"398":[113,141],"401":[113,141]},"packages/frontend/editor-ui/src/features/execution/executions/components/workflow/WorkflowExecutionsSidebar.vue":{"26":[7,105,113,114,115,117,141,142],"63":[115,142],"70":[7,105,113,114,115,117,141,142],"79":[105,113,114,115,117,141,142],"83":[7,105,113,114,115,117,141,142],"87":[7,105,113,114,115,117,141,142],"97":[7,105,113,114,115,117,141,142],"98":[105,113,114,115,117,141,142],"107":[105,113,114,115,117,141,142],"116":[105,113,114,115,117,141,142],"125":[105,113,114,115,117,141,142],"136":[141],"143":[117],"147":[105,113,141],"169":[7,105,113,114,115,117,141,142],"176":[7,105,113,114,115,117,141,142],"216":[7,105,113,114,115,117,141,142],"221":[114,141],"229":[7,105,113,114,115,117,141,142],"232":[105,113,114,115,117,141,142]},"packages/frontend/editor-ui/src/features/execution/executions/composables/useExecutionHelpers.ts":{"24":[105,113,114,115,117,141,142],"69":[105,113,114,115,117,141,142],"74":[105,113,114,115,117,141,142],"87":[134,135]},"packages/frontend/editor-ui/src/features/execution/executions/views/WorkflowExecutionsView.vue":{"37":[7,105,113,114,115,117,141,142],"42":[7,105,113,114,115,117,141,142],"51":[7,105,113,114,115,117,141,142],"52":[105,113,114,115,117,141,142],"70":[7,105,113,114,115,117,141,142],"74":[7,105,113,114,115,117,141,142],"81":[7,105,113,114,115,117,141,142],"83":[105,113,114,115,117,141,142],"88":[7,105,113,114,115,117,141,142],"99":[7,105,113,142],"104":[7,105,113,114,115,117,141,142],"137":[7,105,113,114,115,117,141,142],"149":[7,105,113,114,115,117,141,142],"161":[117],"196":[141],"223":[114],"229":[114],"300":[115,142],"306":[7,105,113,114,115,117,141,142],"312":[115,142]},"packages/frontend/editor-ui/src/features/execution/logs/components/DemoFooter.vue":{"9":[13,14,101,102,112,117,141,142],"10":[13,14,101,102,112,117,141,142],"11":[13,14,101,102,112,117,141,142]},"packages/frontend/editor-ui/src/features/execution/logs/components/LogsViewConsumedTokenCountText.vue":{"8":[68,117],"20":[68]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/AssignmentCollection/Assignment.vue":{"32":[1,24,66,67,76,81,85,106,114,117,118,120,122,125,127,129],"36":[1,24,66,67,76,81,85,106,114,117,118,120,122,125,127,129],"54":[1,24,66,67,76,81,85,106,114,117,118,120,122,125,127,129],"78":[1,24,66,67,76,81,85,106,114,117,118,120,122,125,127,129],"87":[1,24,66,67,76,81,85,106,114,117,118,120,122,125,127,129],"101":[1,24,66,67,76,81,85,106,114,117,118,120,122,125,127,129],"103":[1,24,66,67,76,81,85,106,114,117,118,120,122,125,127,129],"112":[1,24,66,67,76,81,85,106,114,117,118,120,122,125,127,129],"114":[1,66,76,85,114,117,120,122,127,129],"116":[24,67,120],"120":[24,67],"128":[24,67,120,122,127,129],"136":[24,67,106,120,122,127],"140":[120],"153":[1,24,66,67,76,81,85,106,114,117,118,120,122,125,127,129],"185":[1,24,66,67,76,81,85,106,114,117,118,120,122,125,127,129],"201":[1,24,66,67,76,81,85,106,114,117,118,120,122,125,127,129],"205":[1,24,66,67,76,81,85,106,114,117,118,120,122,125,127,129],"215":[1,24,66,67,76,81,85,106,114,117,118,120,122,125,127,129]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/AssignmentCollection/AssignmentCollection.vue":{"36":[1,7,24,49,66,67,76,81,82,85,103,104,106,109,114,116,117,118,120,122,124,125,127,129,132,133,138],"50":[1,7,24,49,66,67,76,81,82,85,103,104,106,109,114,116,117,118,120,122,124,125,127,129,132,133,138],"53":[1,66,76,81,85,106,114,117,118,120,125,127],"69":[1,24,66,67,76,81,85,106,114,117,118,120,122,125,127,129],"74":[1,7,24,49,66,67,76,81,82,85,103,104,106,109,114,116,117,118,120,122,124,125,127,129,132,133,138],"75":[120],"76":[1,7,24,49,66,67,76,81,82,85,103,104,106,109,114,116,117,118,120,122,124,125,127,129,132,133,138],"77":[1,7,24,49,66,67,76,81,82,85,103,104,106,109,114,116,117,118,120,122,124,125,127,129,132,133,138],"92":[1,7,24,49,66,67,76,81,82,85,103,104,106,109,114,116,117,118,120,122,124,125,127,129,132,133,138],"93":[125],"101":[1,7,24,49,66,67,76,81,82,85,103,104,106,109,114,116,117,118,120,122,124,125,127,129,132,133,138],"102":[24,67,118,120,122,127,129],"104":[24,67,118,120,122,127,129],"114":[24,67,118,122,129],"135":[24,67,106,120,122,127],"143":[1,24,66,67,76,81,85,106,114,117,118,120,122,125,127,129],"153":[1,7,24,49,66,67,76,81,82,85,103,104,106,109,114,116,117,118,120,122,124,125,127,129,132,133,138],"169":[1,7,24,49,66,67,76,81,82,85,103,104,106,109,114,116,117,118,120,122,124,125,127,129,132,133,138],"203":[1,24,66,67,76,81,85,106,114,117,118,120,122,125,127,129],"212":[24,67,106,120,122,127],"226":[1,7,24,49,66,67,76,81,82,85,103,104,106,109,114,116,117,118,120,122,124,125,127,129,132,133,138]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/AssignmentCollection/TypeSelect.vue":{"17":[1,24,66,67,76,81,85,106,114,117,118,120,122,125,127,129],"30":[1,24,66,67,76,81,85,106,114,117,118,120,122,125,127,129],"32":[1,24,66,67,76,81,85,106,114,117,118,120,122,125,127,129],"33":[1,24,66,67,76,81,85,106,114,117,118,120,122,125,127,129],"43":[24,67],"45":[1,24,66,67,76,81,85,106,114,117,118,120,122,125,127,129],"58":[1,24,66,67,76,81,85,106,114,117,118,120,122,125,127],"60":[1,24,66,67,76,81,85,106,114,117,118,120,122,125,127]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/InputTriple/InputTriple.vue":{"10":[1,24,62,66,67,76,81,85,104,106,114,117,118,120,122,125,127,129],"13":[1,24,62,66,67,76,81,85,104,106,114,117,118,120,122,125,127,129],"21":[1,24,62,66,67,76,81,85,104,106,114,117,118,120,122,125,127,129],"22":[1,24,62,66,67,76,81,85,104,106,114,117,118,120,122,125,127,129]},"packages/frontend/editor-ui/src/features/ndv/runData/components/RunDataJson.vue":{"22":[79,114,117,120,125],"59":[79,114,117,120,125],"61":[79,114,117,120,125],"63":[120],"71":[79,114,117,120,125],"82":[79,114,117,120,125],"83":[79,114,117,120,125],"85":[120],"98":[120],"122":[79,114,117,120,125],"126":[79,114,117,120,125],"130":[79,114,117,120,125],"166":[79,114,117,120,125],"181":[79,114,117,120,125]},"packages/frontend/editor-ui/src/features/ndv/runData/components/RunDataJsonActions.vue":{"63":[79,114,117,120,125]},"packages/frontend/editor-ui/src/features/ndv/runData/components/RunDataParsedAiContent.vue":{"31":[117],"33":[117],"54":[117],"63":[117],"72":[117],"76":[117]},"packages/frontend/editor-ui/src/features/ndv/runData/components/RunDataPinButton.vue":{"6":[1,11,12,14,27,49,60,61,62,65,66,67,75,85,110,111,113,114,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135],"24":[1,11,12,14,27,49,60,61,62,65,66,67,75,85,110,111,113,114,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135],"27":[1,11,12,14,27,49,60,61,62,65,66,67,75,85,110,111,113,114,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135],"31":[60,67],"49":[1,11,12,14,27,49,60,61,62,65,66,67,75,85,110,111,113,114,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135],"66":[113,129]},"packages/frontend/editor-ui/src/features/ndv/runData/components/RunInfo.vue":{"7":[1,2,9,11,27,49,60,61,62,65,66,67,75,85,110,113,114,117,118,120,122,123,124,125,127,128,129,131,134,135],"15":[1,2,9,11,27,49,60,61,62,65,66,67,75,85,110,113,114,117,118,120,122,123,124,125,127,128,129,131,134,135],"19":[1,2,9,11,27,49,60,61,62,65,66,67,75,85,110,113,114,117,118,120,122,123,124,125,127,128,129,131,134,135],"23":[1,2,9,11,27,49,60,61,62,65,66,67,75,85,110,113,114,117,118,120,122,123,124,125,127,128,129,131,134,135],"33":[1,2,9,11,27,49,60,61,62,65,66,67,75,85,110,113,114,117,118,120,122,123,124,125,127,128,129,131,134,135]},"packages/frontend/editor-ui/src/features/ndv/runData/components/VirtualSchema.vue":{"107":[1,2,9,11,27,49,61,62,66,74,75,79,82,85,104,106,110,111,113,114,116,117,118,119,120,121,122,123,124,125,127,128,129,131,132,134,135],"108":[1,2,9,11,27,49,61,62,66,74,75,79,82,85,104,106,110,111,113,114,116,117,118,119,120,121,122,123,124,125,127,128,129,131,132,134,135],"114":[120],"117":[120],"123":[1,2,11,27,49,61,62,66,74,75,79,82,85,104,106,110,111,113,114,116,117,118,119,120,121,122,123,124,125,127,128,129,131,132,134,135],"134":[1,2,11,27,49,61,62,66,74,75,79,82,85,104,106,110,111,113,114,116,117,118,119,120,121,122,123,124,125,127,128,129,131,132,134,135],"143":[1,2,11,27,49,61,62,66,74,75,79,82,85,104,106,110,111,113,114,116,117,118,119,120,121,122,123,124,125,127,128,129,131,132,134,135],"159":[117,124,128],"165":[1,2,11,27,49,61,62,66,74,75,79,82,85,104,110,113,114,116,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135],"176":[1,2,11,27,49,61,62,66,74,75,79,82,85,104,110,113,114,116,117,118,119,120,121,122,123,124,125,127,128,129,131,134,135],"205":[1,2,11,27,49,61,62,66,74,75,79,82,85,104,106,110,111,113,114,116,117,118,119,120,121,122,123,124,125,127,128,129,131,132,134,135],"209":[1,2,11,27,49,61,62,66,74,75,79,82,85,104,106,110,111,113,114,116,117,118,119,120,121,122,123,124,125,127,128,129,131,132,134,135],"231":[1,2,11,27,49,61,62,66,74,75,79,82,85,104,106,110,111,113,114,116,117,118,119,120,121,122,123,124,125,127,128,129,131,132,134,135],"254":[1,2,11,27,49,61,62,66,74,75,79,82,85,104,106,110,111,113,114,116,117,118,119,120,121,122,123,124,125,127,128,129,131,132,134,135],"286":[1,2,9,11,27,49,61,62,66,74,75,79,82,85,104,106,110,111,113,114,116,117,118,119,120,121,122,123,124,125,127,128,129,131,132,134,135],"298":[1,2,11,27,49,61,62,66,74,75,79,82,85,104,110,113,114,116,117,118,121,124,125,128,129,131,132,134],"320":[1,2,9,11,27,49,61,62,66,74,75,79,82,85,104,106,110,111,113,114,116,117,118,119,120,121,122,123,124,125,127,128,129,131,132,134,135],"366":[1,2,11,27,49,61,62,66,74,75,79,82,85,104,106,110,111,113,114,116,117,118,119,120,121,122,123,124,125,127,128,129,131,132,134,135],"384":[1,2,11,27,49,61,62,66,74,75,79,82,85,104,106,110,111,113,114,116,117,118,119,120,121,122,123,124,125,127,128,129,131,132,134,135],"388":[9,117,125],"403":[1,2,9,11,27,49,61,62,66,74,75,79,82,85,104,106,110,111,113,114,116,117,118,119,120,121,122,123,124,125,127,128,129,131,132,134,135],"405":[1,2,9,11,27,49,61,62,66,74,75,79,82,85,104,106,110,111,113,114,116,117,118,119,120,121,122,123,124,125,127,128,129,131,132,134,135],"431":[1,2,9,11,27,49,61,62,66,74,75,79,82,85,104,106,110,111,113,114,116,117,118,119,120,121,122,123,124,125,127,128,129,131,132,134,135],"439":[1,2,9,11,27,49,61,62,66,74,75,79,82,85,104,106,110,111,113,114,116,117,118,119,120,121,122,123,124,125,127,128,129,131,132,134,135],"443":[1,2,9,11,27,49,61,62,66,74,75,79,82,85,104,106,110,111,113,114,116,117,118,119,120,121,122,123,124,125,127,128,129,131,132,134,135],"444":[125],"456":[1,2,9,11,27,49,61,62,66,74,75,79,82,85,104,106,110,111,113,114,116,117,118,119,120,121,122,123,124,125,127,128,129,131,132,134,135],"461":[1,2,11,27,49,61,62,66,74,75,79,82,85,104,106,110,111,113,114,116,117,118,119,120,121,122,123,124,125,127,128,129,131,132,134,135],"463":[1,2,11,27,49,61,62,66,74,75,79,82,85,104,106,110,111,113,114,116,117,118,119,120,121,122,123,124,125,127,128,129,131,132,134,135],"466":[1,2,9,11,27,49,61,62,66,74,75,79,82,85,104,106,110,111,113,114,116,117,118,119,120,121,122,123,124,125,127,128,129,131,132,134,135],"473":[120],"482":[120],"484":[120],"486":[120],"523":[125],"524":[125],"543":[1,2,9,11,27,49,61,62,66,74,75,79,82,85,104,106,110,111,113,114,116,117,118,119,120,121,122,123,124,125,127,128,129,131,132,134,135],"564":[120],"574":[125],"579":[118,132],"602":[114],"628":[114,116,121]},"packages/frontend/editor-ui/src/features/ndv/runData/components/VirtualSchemaHeader.vue":{"22":[1,2,11,27,49,61,62,66,74,75,79,82,85,104,106,110,111,113,114,116,117,118,119,120,121,122,123,124,125,127,128,129,131,132,134,135],"24":[1,2,11,27,49,61,62,66,74,75,79,82,85,104,106,110,111,113,114,116,117,118,119,120,121,122,123,124,125,127,128,129,131,132,134,135],"70":[116],"72":[116],"77":[118,132],"79":[118,132],"82":[118,132],"84":[118,132]},"packages/frontend/editor-ui/src/features/ndv/runData/components/VirtualSchemaItem.vue":{"36":[1,2,9,11,27,49,61,62,66,74,75,79,82,85,104,106,110,111,113,114,116,117,118,119,120,121,122,123,124,125,127,128,129,131,132,134,135],"72":[1,2,9,11,27,49,61,62,66,74,75,79,82,85,104,106,110,111,113,114,116,117,118,119,120,121,122,123,124,125,127,128,129,131,132,134,135],"109":[1,2,11,27,49,61,62,66,74,75,79,82,85,104,110,111,113,114,116,117,118,119,121,122,124,125,128,129,131,132,134,135]},"packages/frontend/editor-ui/src/features/ndv/runData/components/ai/utils.ts":{"38":[117],"51":[117],"52":[117],"53":[117]},"packages/frontend/editor-ui/src/features/ndv/runData/components/error/NodeErrorView.vue":{"45":[1,2,7,8,113,117,124],"68":[1,2,7,8,113,117,124],"72":[124],"85":[1,2,7,8,113,117,124],"96":[1,2,7,8,113,117,124],"100":[8,113],"109":[1,2,7,8,113,117,124],"116":[8,113],"137":[1,2,7,8,113,117,124],"146":[1,2],"153":[1,2,7,8,113,117,124],"160":[1,8,113,124],"176":[1,2,7,8,124],"180":[1,2,7,8,124],"205":[1,2,7,8,113,117,124],"217":[1,2,7,8,113,117,124],"220":[1,2,7,8,113,117,124],"245":[124],"255":[124],"261":[124],"275":[124],"397":[1,2],"431":[1,2],"458":[1,2,7,8,113,117,124],"504":[1,2,7,8,113,117,124],"543":[8,113]},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/background/CanvasBackgroundStripedPattern.vue":{"6":[5,147,10,13,14,45,102,112,117,138,139,141,142],"13":[5,147,10,13,14,45,102,112,117,138,139,141,142],"14":[5,147,10,13,14,45,102,112,117,138,139,141,142],"15":[5,147,10,13,14,45,102,112,117,138,139,141,142]},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/edges/CanvasEdgeToolbar.vue":{"12":[147,82,83,84,103,109,117,133,135],"27":[147,82,83,84,103,109,117,133,135],"31":[147,82,83,84,103,109,117,133,135],"41":[147,82,83,103],"45":[147,103,109],"47":[147,82,83,84,103,109,117,133,135],"55":[147,82,83,84,103,109,117,133,135],"72":[147,82,83,84,103,109,117,133,135]},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/edges/CanvasEdgeTooltip.vue":{"9":[147,82,83,84,103,109,117,133,135],"20":[147,82,83,84,103,109,117,133,135]},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/nodes/render-types/parts/CanvasNodeDisabledStrikeThrough.vue":{"6":[147,100,103,105,109,115,117,140,141,142],"10":[147,100,103,105,109,115,117,140,141,142],"19":[147,100,103,105,109,115,117,140,141,142]},"packages/localhost-40801/assets/_plugin-vue_export-helper-Da88TEg1.js":{"2":[117]},"packages/localhost-40801/assets/chunk-CC9Q-vWm.js":{"8":[117],"9":[117],"10":[117],"19":[117],"23":[117],"29":[117],"33":[117],"34":[117]},"packages/@n8n/chat/src/components/ChatFile.vue":{"28":[29,43],"33":[29]},"packages/frontend/editor-ui/src/app/utils/fileUtils.ts":{"5":[29,43],"6":[29,43]},"packages/frontend/editor-ui/src/features/ai/instanceAi/components/AttachmentPreview.vue":{"7":[43],"19":[43],"21":[43],"23":[43],"38":[43],"56":[43],"61":[43]},"packages/@n8n/design-system/src/components/N8nIcon/custom/node-pin.svg":{"11":[14,74,106,109,111,113,114,118,119,120,121,122,123,124,125,127,128,129,135,143,146]},"packages/@n8n/design-system/src/components/N8nIcon/nodes/sort.svg":{"11":[120,125,128]},"packages/@n8n/design-system/src/components/N8nIcon/nodes/switch.svg":{"11":[62,77,104,109,120,125,128,143]},"packages/frontend/editor-ui/src/app/utils/telemetryUtils.ts":{"5":[89,119,120,121,122,127,130,131],"13":[89,119,120,121,122,127,131],"14":[89,119,120,121,122,131],"21":[89,119,120,121,122,131],"27":[119,121,131],"28":[119,121,131],"71":[89,119,120,121,122,131]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/FixedCollection/FixedCollectionParameter.vue":{"39":[11,12,60,67,104,119,120,127]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/ParameterIssues.vue":{"9":[4,11,12,22,34,37,38,51,60,76,111,120,124,126,127,130,136],"10":[4,11,12,22,34,38,51,60,76,111,120,124,126,127,136],"17":[4,11,12,34,51,60,76,111,120,124,126,127,130,136]},"packages/frontend/editor-ui/src/features/ndv/parameters/utils/assignmentCollection.utils.ts":{"8":[120],"18":[120]},"packages/frontend/editor-ui/src/features/shared/editors/components/InlineExpressionEditor/ExpressionOutput.vue":{"20":[89,111,119,120,121,122,127,128,129,130,131],"30":[89,111,119,120,121,122,127,128,129,130,131],"35":[89,111,119,120,121,122,127,128,129,131],"49":[89,111,119,120,121,122,127,128,129,130,131],"50":[89,111,119,120,121,122,127,128,129,131],"53":[89,111,119,120,121,122,127,128,129,130,131],"71":[89,111,119,120,121,122,127,128,129,131],"82":[89,111,119,120,121,122,127,128,129,131],"85":[89,111,119,120,121,122,127,128,129,130,131],"95":[121],"105":[89,111,119,120,121,122,127,128,129,130,131],"106":[89,111,119,120,121,122,127,128,129,131],"119":[89,111,119,120,121,122,127,128,129,130,131],"132":[89,111,119,120,121,122,127,128,129,130,131],"137":[89,111,119,120,121,122,127,130,131],"141":[121],"142":[89,111,119,120,121,122,127,128,129,130,131]},"packages/frontend/editor-ui/src/features/shared/editors/components/InlineExpressionEditor/InlineExpressionTip.vue":{"21":[4,11,12,24,27,38,60,61,62,67,89,111,113,119,120,121,122,127,128,129,130,131],"33":[89,111,119,120,121,122,127,128,129,130,131],"37":[119,120,121,122,127,128,129],"39":[4,11,12,24,27,38,60,61,62,67,89,111,113,119,120,121,122,127,128,129,130,131],"57":[89,119,120,121,122,127,128,129,130,131],"83":[4,11,12,24,27,38,60,61,62,67,89,111,113,119,120,121,122,127,130,131],"88":[4,11,12,24,27,38,60,61,62,67,89,111,113,119,120,121,122,127,128,129,130,131],"96":[4,11,12,24,27,38,60,61,62,67,89,111,113,119,120,121,122,127,128,129,130,131],"97":[89,119,120,121,122,127,128,129,130,131],"106":[4,11,12,24,27,38,60,61,62,67,89,111,113,119,120,121,122,127,128,129,130,131],"110":[4,11,12,24,27,38,60,61,62,67,89,111,113,119,120,121,122,127,128,129,130,131],"114":[120,122,127,129],"120":[120,122,127,129]},"packages/frontend/editor-ui/src/features/shared/editors/components/InlineExpressionEditor/OutputItemSelect.vue":{"7":[89,111,119,120,121,122,127,128,129,130,131],"10":[89,111,119,120,121,122,127,128,129,130,131],"11":[89,111,119,120,121,122,127,128,129,130,131],"12":[89,111,119,120,121,122,127,128,129,130,131],"13":[89,111,119,120,121,122,127,128,129,130,131],"14":[89,111,119,120,121,122,127,128,129,130,131],"17":[89,111,119,120,121,122,127,128,129,130,131],"18":[89,111,119,120,121,122,127,128,129,130,131],"19":[89,111,119,120,121,122,127,128,129,130,131],"20":[89,111,119,120,121,122,127,128,129,130,131],"21":[89,111,119,120,121,122,127,128,129,130,131],"25":[89,111,119,120,121,122,127,128,129,130,131],"31":[127,128],"35":[127],"37":[89,111,119,120,121,122,127,128,129,130,131],"43":[89,111,119,120,121,122,127,128,129,130,131],"70":[89,111,119,120,121,122,127,128,129,130,131]},"packages/frontend/editor-ui/src/features/shared/editors/plugins/codemirror/completions/blank.completions.ts":{"8":[89,111,119,120,121,122,127,129,130,131]},"packages/frontend/editor-ui/src/features/shared/editors/plugins/codemirror/completions/bracketAccess.completions.ts":{"17":[89,111,119,120,121,122,127,129,130,131],"53":[119,120,121,127],"62":[120],"70":[119,120,121,127],"74":[119,120,121,127],"75":[119,120,121,127]},"packages/frontend/editor-ui/src/features/shared/editors/plugins/codemirror/completions/dollar.completions.ts":{"29":[89,111,119,120,121,122,127,129,130,131],"43":[89,111,119,120,121,122,127,129,131],"60":[89,111,119,120,121,122,127,129,131],"138":[111,119,120,121,122,127,129,131],"153":[111,119,120,121,122,127,129,131],"155":[111,119,120,121,122,127,129,131]},"packages/frontend/editor-ui/src/features/shared/editors/plugins/codemirror/completions/nonDollar.completions.ts":{"9":[89,111,119,120,121,122,127,129,130,131]},"packages/@n8n/design-system/src/components/N8nIcon/custom/grip-lines-vertical.svg":{"9":[7,8,52,126,127]},"packages/@n8n/design-system/src/components/N8nIcon/custom/node-dirty.svg":{"11":[67,75,82,110,118,127,129,131,135]},"packages/@n8n/design-system/src/components/N8nIcon/custom/triangle.svg":{"8":[2,67,75,110,113,118,127,129,131,135]},"packages/@n8n/design-system/src/components/N8nIcon/custom/vector-square.svg":{"9":[7,8,52,126,127]},"packages/@n8n/design-system/src/components/N8nIcon/nodes/ai-transform.svg":{"11":[21,28,62,103,104,105,109,110,124,127]},"packages/@n8n/design-system/src/components/N8nIcon/nodes/basic-llm-chain.svg":{"11":[8,126,127]},"packages/@n8n/design-system/src/components/N8nIcon/nodes/contextual-compression-retriever.svg":{"11":[127]},"packages/@n8n/design-system/src/components/N8nIcon/nodes/guardrails.svg":{"11":[127]},"packages/@n8n/design-system/src/components/N8nIcon/nodes/multiquery-retriever.svg":{"11":[127]},"packages/@n8n/design-system/src/components/N8nIcon/nodes/question-and-answer-chain.svg":{"11":[9,127]},"packages/@n8n/design-system/src/components/N8nIcon/nodes/sentiment-analysis.svg":{"11":[127]},"packages/@n8n/design-system/src/components/N8nIcon/nodes/structured-output-parser.svg":{"11":[7,127]},"packages/@n8n/design-system/src/components/N8nIcon/nodes/summarization-chain.svg":{"11":[127]},"packages/@n8n/design-system/src/components/N8nIcon/nodes/text-classifier.svg":{"11":[127]},"packages/@n8n/design-system/src/components/N8nIcon/nodes/token-splitter.svg":{"11":[127]},"packages/@n8n/design-system/src/components/N8nIcon/nodes/vector-store-retriever.svg":{"11":[9,127]},"packages/@n8n/design-system/src/components/N8nIcon/nodes/workflow-retriever.svg":{"11":[127]},"packages/frontend/editor-ui/src/features/shared/nodeCreator/components/ItemTypes/LinkItem.vue":{"13":[68,127]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/ResourceMapper/MappingModeSelect.vue":{"20":[130,131],"54":[130,131],"61":[130,131],"103":[130,131],"113":[131],"121":[130,131],"123":[131],"128":[131],"140":[130,131],"150":[130,131],"153":[131]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/ResourceMapper/ResourceMapper.vue":{"50":[130,131,135,136],"90":[131],"110":[130,131,135,136],"112":[131],"130":[131],"142":[130,131,135,136],"144":[131],"156":[130,131,135,136],"192":[131],"222":[131],"226":[130,131,135,136],"233":[130,131,135,136],"237":[130,131,135,136],"241":[130,131,135,136],"245":[130,131,135,136],"253":[130,131,135,136],"263":[131],"273":[131],"289":[130,131,135,136],"292":[131],"300":[135,136],"307":[130,131,135,136],"332":[130,131,135,136],"357":[130,131,135,136],"380":[130,131,135,136],"388":[131],"389":[131],"416":[130,131,135,136],"419":[131],"439":[130,131,135,136],"452":[130,131,135,136],"458":[131],"469":[131],"489":[131],"495":[131],"503":[131],"504":[131],"521":[131],"568":[130,131,135,136],"580":[130,131,135,136],"586":[131],"597":[130,131,135,136],"630":[131],"633":[135,136],"666":[135,136]},"packages/frontend/editor-ui/src/features/ndv/parameters/composables/useNodeSpecificationValues.ts":{"5":[130,131],"6":[130,131],"10":[130,131],"16":[131],"20":[130,131],"24":[131]},"packages/localhost-38661/assets/_plugin-vue_export-helper-Da88TEg1.js":{"2":[130,132,143]},"packages/localhost-38661/assets/chunk-CC9Q-vWm.js":{"8":[130,132,143],"9":[130,132,143],"10":[130,132,143],"19":[130,132,143],"23":[130,132,143],"29":[130,132,143],"33":[130,132,143],"34":[130,132,143]},"packages/frontend/editor-ui/src/features/ndv/runData/schemaPreview.api.ts":{"13":[66,74,76,82,83,111,116,118,121,125,129,132,134],"17":[83,118,132],"27":[66,74,76,82,83,111,116,118,121,125,129,132,134]},"packages/localhost-38661/assets/shield-alt-J5nzuCWH.js":{"8":[132]},"packages/@n8n/design-system/src/components/N8nMarkdown/Markdown.vue":{"37":[74,83,108,114,134,143,145,146],"82":[74,83,108,114,134,143,145,146],"89":[146],"110":[108,143,146],"143":[74,83,108,114,134,143,145,146],"218":[74,83,108,114,134,143,145,146],"236":[145,146]},"packages/@n8n/design-system/src/components/N8nMarkdown/youtube.ts":{"34":[74,83,108,114,134,143,145,146],"42":[74,108,114,134,143,146]},"packages/@n8n/design-system/src/components/N8nSticky/Sticky.vue":{"16":[74,83,108,114,134,143,146],"28":[74,83,108,114,134,143,146],"32":[74,83,108,114,134,143,146],"36":[74,83,108,114,134,143,146],"38":[74,83,108,114,134,143,146],"43":[74,83,108,114,134,143,146],"58":[74,83,108,114,134,143,146],"65":[74,83,108,114,134,143,146],"99":[74,83,108,114,134,143,146]},"packages/frontend/editor-ui/src/app/components/ImportWorkflowUrlModal.vue":{"10":[109,143],"16":[109,143],"20":[109,143],"24":[143],"29":[109,143],"32":[109,143],"45":[109,143],"60":[109,143],"68":[109,143],"76":[109,143]},"packages/frontend/editor-ui/src/app/components/IntersectionObserved.vue":{"6":[68,84,133,137,143],"19":[68,84,133,137,143],"29":[68,137],"34":[68,84,133,137,143]},"packages/frontend/editor-ui/src/app/components/IntersectionObserver.vue":{"6":[68,84,133,137,138,139,143,145,146],"26":[68,137,139],"32":[68,84,133,137,138,139,143,145,146],"43":[68,84,133,137,143],"44":[68,84,133,137,143],"54":[68,84,133,137,143],"60":[68,137],"64":[68,84,133,137,138,139,143,145,146]},"packages/frontend/editor-ui/src/features/shared/tags/components/TagsContainer.vue":{"20":[68,84,133,137,138,139,143,145,146],"37":[68,84,133,137,138,139,143,145,146],"41":[68,84,133,137,138,139,143,145,146],"42":[68,84,133,137,143],"48":[68,84,133,137,143],"55":[68,84,133,137,143],"63":[68,84,133,137,143],"81":[68,84,133,137,138,139,143,145,146],"87":[68,84,133,137,138,139,143,145,146],"95":[68,84,133,137,143],"101":[68,137],"112":[68,84,133,137,138,139,143,145,146],"117":[68,137,139],"120":[68,84,133,137,138,139,143,145,146],"131":[68,84,137,138,139,143,145,146],"134":[68,84,137,143],"137":[68,137],"152":[68,84,133,137,143]},"packages/frontend/editor-ui/src/features/shared/tags/components/WorkflowTagsContainer.vue":{"16":[68,84,133,137,138,139,143,145,146],"22":[68,84,133,137,138,139,143,145,146],"24":[68,137],"26":[68,84,133,137,138,139,143,145,146]},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/nodes/render-types/CanvasNodeStickyNote.vue":{"15":[147,74,83,108,114,134,143,146],"27":[147,74,83,108,114,134,143,146],"29":[147,74,83,108,114,134,143,146],"39":[147],"57":[147],"63":[147],"75":[147],"83":[147],"91":[147,74,83,108,114,134,143,146],"95":[147],"98":[147,74,83,108,114,134,143,146]},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/nodes/toolbar/CanvasNodeStickyColorSelector.vue":{"10":[147,74,83,108,114,134,143,146],"17":[147],"21":[147],"27":[147],"31":[147],"35":[147],"40":[147],"44":[147],"49":[147],"53":[147],"60":[147],"61":[147],"66":[147,74,83,108,114,134,143,146],"70":[147],"73":[147,74,83,108,114,134,143,146],"86":[147,74,83,108,114,134,143,146],"95":[147],"98":[147],"135":[147]},"packages/@n8n/design-system/src/components/AskAssistantChat/messages/EventMessage.vue":{"24":[1],"40":[1],"44":[1]},"packages/@n8n/design-system/src/components/N8nIcon/nodes/stop-and-error.svg":{"11":[1,2]},"packages/frontend/editor-ui/src/features/ai/assistant/components/Chat/NewAssistantSessionModal.vue":{"14":[1],"27":[1],"31":[1],"44":[1],"56":[1],"62":[1],"65":[1],"68":[1],"72":[1]},"packages/localhost-45903/assets/_plugin-vue_export-helper-Da88TEg1.js":{"2":[1,4,16,37]},"packages/localhost-45903/assets/chunk-CC9Q-vWm.js":{"8":[1,4,16,37],"9":[1,4,16,37],"10":[1,4,16,37],"19":[1,4,16,37],"23":[1,4,16,37],"29":[1,4,16,37],"33":[1,4,16,37],"34":[1,4,16,37]},"packages/@n8n/design-system/src/components/N8nIcon/nodes/http-request.svg":{"11":[4,7,21,22,24,27,34,37,38,51,52,61,67,83,89,97,103,113,126,129,146]},"packages/frontend/editor-ui/src/app/composables/usePushConnection/handlers/sendConsoleMessage.ts":{"7":[4,27,38,61,68,113]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/ImportCurlParameter.vue":{"11":[4,22,24,27,37,38,61,67,83,103,113,126,129],"16":[4,22,24,27,37,38,61,67,83,103,113,126,129]},"packages/@n8n/design-system/src/components/N8nIcon/custom/status-warning.svg":{"8":[16]},"packages/@n8n/design-system/src/types/menu.ts":{"55":[16,93,109]},"packages/frontend/editor-ui/src/app/components/VersionUpdateCTA.vue":{"13":[16],"30":[16]},"packages/localhost-34447/assets/_plugin-vue_export-helper-Da88TEg1.js":{"2":[19]},"packages/localhost-34447/assets/chunk-CC9Q-vWm.js":{"8":[19],"9":[19],"10":[19],"19":[19],"23":[19],"29":[19],"33":[19],"34":[19]},"packages/frontend/editor-ui/src/app/components/AiStarsIcon.vue":{"11":[34,37,51,79,126],"17":[34,51,79,126]},"packages/frontend/editor-ui/src/features/credentials/components/CredentialsSelect.vue":{"21":[22,37,38],"36":[22,37,38],"37":[22,37,38],"43":[22,37,38],"44":[22,37,38],"47":[37,38],"57":[22,37,38],"84":[22,37,38],"92":[22,37],"101":[22,37,38],"102":[22,37,38],"125":[22,37,38],"139":[37,38],"141":[37,38],"142":[37,38],"143":[22,37,38],"145":[22,38],"151":[22,38],"173":[22,37,38]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/ParameterInputOverrides/FromAiOverrideButton.vue":{"6":[34,37,51,79,126],"16":[34,51,79,126],"24":[34,37,51,79,126],"29":[34]},"packages/localhost-38751/assets/_plugin-vue_export-helper-Da88TEg1.js":{"2":[37,54,56,62,67,76,79,101,112,129]},"packages/localhost-38751/assets/chunk-CC9Q-vWm.js":{"8":[37,54,56,62,67,76,79,101,112,129],"9":[37,54,56,62,67,76,79,101,112,129],"10":[37,54,56,62,67,76,79,101,112,129],"19":[37,54,56,62,67,76,79,101,112,129],"23":[37,54,56,62,67,76,79,101,112,129],"29":[37,54,56,62,67,76,79,101,112,129],"33":[37,54,56,62,67,76,79,101,112,129],"34":[37,54,56,62,67,76,79,101,112,129]},"packages/localhost-45903/assets/shield-alt-J5nzuCWH.js":{"8":[37]},"packages/localhost-45193/assets/_plugin-vue_export-helper-Da88TEg1.js":{"2":[46]},"packages/localhost-45193/assets/chunk-CC9Q-vWm.js":{"8":[46],"9":[46],"10":[46],"19":[46],"23":[46],"29":[46],"33":[46],"34":[46]},"packages/frontend/editor-ui/src/features/shared/nodeCreator/components/Panel/NoResults.vue":{"20":[54,68,105,109],"41":[54,68,105,109],"46":[54,68,105,109],"56":[54,68,105,109]},"packages/frontend/editor-ui/src/features/shared/nodeCreator/components/Panel/NoResultsIcon.vue":{"8":[54,68,105,109]},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/edges/CanvasConnectionLine.vue":{"11":[7,8,147,21,52,54,55,56,103,104,116,131,135],"17":[7,8,147,21,52,54,55,56,103,104,116,131,135],"21":[7,8,147,21,52,54,55,56,103,104,116,131,135],"28":[7,8,147,21,52,54,55,56,103,104,116,131,135],"34":[7,8,147,21,52,54,55,56,103,104,116,131,135],"38":[7,8,147,21,52,54,55,56,103,104,116,131,135],"46":[7,8,147,21,52,54,55,56,103,104,116,131,135],"47":[7,8,147,21,52,55,56,103,104,116,131,135],"51":[7,8,147,21,52,54,55,56,103,104,116,131,135]},"packages/localhost-38751/assets/shield-alt-J5nzuCWH.js":{"8":[54,62,67,129]},"packages/frontend/editor-ui/src/features/shared/nodeCreator/components/ItemTypes/OpenTemplateItem.vue":{"14":[56,68],"23":[56,68],"27":[68]},"packages/@n8n/design-system/src/components/N8nIcon/nodes/read-write-files-from-disk.svg":{"11":[62,64]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/FilterConditions/CombinatorSelect.vue":{"14":[62],"22":[62],"31":[62],"32":[62]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/FilterConditions/Condition.vue":{"43":[62,104],"63":[62,104],"67":[62,104],"79":[62,104],"97":[62,104],"110":[62,104],"120":[62,104],"131":[62,104],"143":[62],"145":[62],"166":[62],"170":[62],"215":[62,104],"221":[62,104],"250":[62,104],"269":[62,104],"278":[62,104],"306":[62,104],"316":[62]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/FilterConditions/FilterConditions.vue":{"39":[62,104],"62":[62,104],"71":[62],"75":[62,104],"78":[62,104],"90":[62],"94":[62,104],"96":[62],"100":[62,104],"105":[62,104],"134":[62,104],"135":[62,104],"144":[62,104],"145":[62,104],"152":[62,104],"160":[62],"164":[62],"172":[62],"176":[62,104],"178":[62,104],"210":[62,104],"232":[62],"233":[62]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/FilterConditions/OperatorSelect.vue":{"19":[62,104],"30":[62,104],"31":[62,104],"34":[62,104],"36":[62,104],"38":[62,104],"41":[62,104],"42":[62,104],"55":[62,104],"73":[62,104],"86":[62,104],"88":[62,104]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/FilterConditions/utils.ts":{"19":[62,104],"81":[62,104],"124":[62,104],"145":[62,104]},"packages/@n8n/design-system/src/components/N8nIcon/nodes/convert-to-file.svg":{"11":[21,28,67,103,104,105,109,110,111,124]},"packages/@n8n/design-system/src/components/N8nIcon/nodes/respond-to-webhook.svg":{"11":[21,24,67,124,129,144]},"packages/@n8n/design-system/src/components/N8nPulse/Pulse.vue":{"6":[12,60,67,114]},"packages/@n8n/design-system/src/components/N8nSelectableList/SelectableList.vue":{"7":[34,79],"37":[34,79],"39":[34,79],"43":[34,79],"63":[34,79],"70":[34,79],"76":[34,79]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/ParameterInputOverrides/FromAiOverrideField.vue":{"10":[34,79],"11":[34,79]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/ParameterInputOverrides/ParameterOverrideSelectableList.vue":{"16":[34,79],"22":[34,79],"23":[34,79],"47":[34,79]},"packages/@n8n/design-system/src/components/N8nDataTableServer/N8nDataTableServer.vue":{"52":[15,33,35,41,71,89,94,98,138,144],"95":[15,33,35,41,71,89,94,98,138,144],"96":[33,35,41,71,89,94,98],"104":[15,33,35,41,71,89,94,98,138,144],"111":[15,33,35,41,71,89,94,98,138,144],"115":[15,33,35,41,71,89,94,98,138,144],"121":[15,33,35,41,71,89,94,98,138,144],"133":[15,33,35,41,71,89,94,98,138,144],"137":[15,33,35,41,71,89,94,98,138,144],"146":[15,33,35,41,71,89,94,98,138,144],"151":[15,33,35,41,71,89,94,98,138,144],"180":[15,33,35,41,71,89,94,98,138,144],"181":[15,33,35,41,71,89,94,98,138,144],"192":[15,35,41,71,89,94,98,138,144],"218":[15,33,35,41,71,89,94,98,138,144],"226":[35,71],"229":[35,71],"241":[15,33,35,41,71,89,94,98,138,144],"290":[15,33,35,41,71,89,94,98,138,144],"322":[35,71],"340":[15,33,35,41,71,89,94,98,138,144],"344":[94],"356":[35,71],"389":[15,33,35,41,71,89,94,98,138,144],"406":[15,33,35,41,71,89,94,98,138,144],"407":[15,33,35,41,71,89,94,98,138,144],"466":[15,33,35,41,71,89,94,98,138,144],"467":[15,33,35,41,71,89,94,98,138,144],"470":[35,94],"472":[15,33,35,41,71,89,94,98,138,144],"511":[33],"513":[33]},"packages/@n8n/design-system/src/components/N8nIconPicker/IconPicker.vue":{"26":[15,32,35,41,71,89,98,138,144],"118":[15,32,35,41,71,98,138,144],"167":[15,32,35,41,71,89,98,138,144],"189":[15,32,35,41,71,89,98,138,144]},"packages/@n8n/design-system/src/components/N8nUserInfo/UserInfo.vue":{"22":[15,35,41,71,89,94,98,138,144],"29":[15,35,41,71,89,94,98,138,144],"35":[15,35,41,71,89,94,98,138,144],"50":[15,35,41,71,89,94,98,138,144],"58":[15,35,41,71,89,94,98,138,144]},"packages/@n8n/design-system/src/components/N8nUserSelect/UserSelect.vue":{"22":[15,35,41,71,89,98,138,144],"40":[15,35,41,71,89,98,138,144],"43":[35,41,71,89,98],"63":[15,35,41,71,89,98,138,144],"64":[35,41,71,89,98],"80":[35,71],"88":[35],"89":[35,71],"91":[35,41,71,89,98],"93":[15,35,41,71,89,98,138,144],"112":[15,35,41,71,89,98,138,144],"114":[15,35,41,71,89,98,138,144],"117":[35,41,71,89,98],"124":[35,41,71,89,98]},"packages/frontend/editor-ui/src/features/collaboration/projects/components/ProjectDeleteDialog.vue":{"61":[15,35,41,71,89,98,138,144]},"packages/frontend/editor-ui/src/features/collaboration/projects/components/ProjectExternalSecrets.vue":{"27":[15,35,41,71,89,98,138,144],"53":[15,35,41,71,89,98,138,144],"58":[15,35,41,71,89,98,138,144],"62":[89],"66":[15,35,41,71,89,98,138,144],"70":[15,35,41,71,89,98,138,144],"77":[15,35,41,71,89,98,138,144],"90":[15,35,41,71,89,98,138,144],"117":[15,35,41,71,89,98,138,144],"121":[15,35,41,71,89,98,138,144],"132":[15,35,41,71,89,98,138,144],"149":[89],"150":[89],"162":[89],"172":[89],"180":[15,35,41,71,89,98,138,144],"183":[89],"184":[89],"188":[15,35,41,71,89,98,138,144],"264":[15,35,41,71,89,98,138,144],"265":[15,35,41,71,89,98,138,144],"275":[15,35,41,71,89,98,138,144],"291":[15,35,41,71,89,98,138,144],"303":[15,35,41,71,89,98,138,144],"305":[15,35,41,71,89,98,138,144],"308":[15,35,41,71,89,98,138,144],"311":[15,35,41,71,89,98,138,144],"320":[15,35,41,71,89,98,138,144],"328":[15,35,41,71,89,98,138,144],"345":[89],"356":[89],"372":[89],"393":[89],"397":[89]},"packages/frontend/editor-ui/src/features/collaboration/projects/components/ProjectMembersActionsCell.vue":{"6":[15,35,41,71,89,98,138,144],"17":[15,35,41,71,89,98,138,144]},"packages/frontend/editor-ui/src/features/collaboration/projects/components/ProjectMembersTable.vue":{"11":[15,35,41,71,89,98,138,144],"36":[15,35,41,71,89,98,138,144],"43":[15,35,41,71,89,98,138,144],"57":[15,35,41,71,89,98,138,144],"63":[15,35,41,71,89,98,138,144],"66":[35],"70":[15,35,41,71,89,98,138,144],"72":[35,71],"73":[15,35,41,71,89,98,138,144],"87":[35,71],"89":[15,35,41,71,89,98,138,144],"94":[15,35,41,71,89,98,138,144],"102":[15,35,41,71,89,98,138,144],"105":[15,35,41,71,89,98,138,144]},"packages/frontend/editor-ui/src/features/collaboration/projects/components/ProjectRoleUpgradeDialog.vue":{"13":[15,35,41,71,89,98,138,144],"21":[15,35,41,71,89,98,138,144]},"packages/frontend/editor-ui/src/features/collaboration/projects/views/ProjectSettings.vue":{"63":[15,35,41,71,89,98,138,144],"78":[15,35,41,71,89,98,138,144],"118":[35,41,71,89,98],"120":[15,35,41,71,89,98,138,144],"121":[35,41,71,89,98],"122":[35,41,71,89,98],"128":[35,71],"129":[35,71],"132":[15,35,41,71,89,98,138,144],"140":[35,71],"146":[35,71],"166":[35,71],"189":[35],"194":[35],"225":[15,41,71,98,138,144],"274":[15,35,41,71,89,98,138,144],"286":[71],"291":[15,41,71,98,138,144],"314":[15,41,71,98,138,144],"315":[15,41,71,98,138,144],"322":[15,41,71,98,138,144],"353":[15,41,71,98,138,144],"372":[15,41,71,98,138,144],"419":[15,35,41,71,89,98,138,144],"442":[15,35,41,71,89,98,138,144],"444":[15,35,41,71,89,98,138,144],"461":[15,35,41,71,89,98,138,144],"462":[15,35,41,71,89,98,138,144],"478":[15,35,41,71,89,98,138,144],"483":[15,35,41,71,89,98,138,144],"497":[15,35,41,71,89,98,138,144],"515":[35,71],"519":[35,41,71,89,98],"559":[15,35,41,71,89,98,138,144],"564":[15,35,41,71,89,98,138,144],"568":[15,35,41,71,89,98,138,144],"572":[15,35,41,71,89,98,138,144],"588":[15,35,41,71,89,98,138,144],"598":[15,35,41,71,89,98,138,144],"605":[15,35,41,71,89,98,138,144],"632":[15,35,41,71,89,98,138,144],"652":[15,35,41,71,89,98,138,144],"681":[15,35,41,71,89,98,138,144],"754":[15,35,41,71,89,98,138,144]},"packages/frontend/editor-ui/src/features/integrations/externalSecrets.ee/assets/images/aws-secrets-manager.svg":{"8":[89]},"packages/frontend/editor-ui/src/features/integrations/secretsProviders.ee/components/DeleteSecretsProviderModal.ee.vue":{"28":[89],"41":[89],"43":[89],"47":[89],"54":[89],"64":[89],"74":[89],"90":[89],"128":[89],"142":[89],"145":[89],"157":[89],"162":[89],"163":[89],"179":[89],"190":[89],"195":[89],"198":[89],"206":[89]},"packages/frontend/editor-ui/src/features/integrations/secretsProviders.ee/components/SecretsProviderConnectionCard.ee.vue":{"49":[89],"57":[89],"61":[89],"63":[89],"74":[89],"85":[89],"87":[89],"95":[89],"115":[89],"156":[89],"167":[89],"180":[89],"183":[89],"205":[89],"231":[89],"237":[89]},"packages/frontend/editor-ui/src/features/integrations/secretsProviders.ee/components/SecretsProviderConnectionModal.ee.vue":{"43":[89],"75":[89],"76":[89],"77":[89],"78":[89],"92":[89],"93":[89],"103":[89],"120":[89],"130":[89],"146":[89],"150":[89],"151":[89],"157":[89],"166":[89],"171":[89],"175":[89],"179":[89],"183":[89],"208":[89],"228":[89],"235":[89],"248":[89],"264":[89],"270":[89],"303":[89],"308":[89],"313":[89],"344":[89],"418":[89],"439":[89],"441":[89],"451":[89],"460":[89],"477":[89],"481":[89],"490":[89],"502":[89],"505":[89],"510":[89]},"packages/frontend/editor-ui/src/features/integrations/secretsProviders.ee/components/SecretsProviderImage.ee.vue":{"17":[89]},"packages/frontend/editor-ui/src/features/integrations/secretsProviders.ee/components/SecretsProvidersEmptyState.ee.vue":{"8":[89],"16":[89],"45":[89],"56":[89],"62":[89],"64":[89],"73":[89],"95":[89],"101":[89],"108":[89],"112":[89]},"packages/frontend/editor-ui/src/features/integrations/secretsProviders.ee/composables/useConnectionModal.ee.ts":{"33":[89],"37":[89],"63":[89],"69":[89],"95":[89],"121":[89],"141":[89],"145":[89],"154":[89],"162":[89],"167":[89],"169":[89],"170":[89],"180":[89],"186":[89],"187":[89],"194":[89],"200":[89],"207":[89],"212":[89],"213":[89],"220":[89],"221":[89],"225":[89],"226":[89],"228":[89],"238":[89],"246":[89],"252":[89],"270":[89],"289":[89],"294":[89],"296":[89],"304":[89],"311":[89],"319":[89],"320":[89],"370":[89],"414":[89],"455":[89],"463":[89],"491":[89],"529":[89]},"packages/frontend/editor-ui/src/features/integrations/secretsProviders.ee/composables/useSecretsProviderConnection.ee.ts":{"34":[89],"39":[89],"62":[89],"79":[89],"100":[89]},"packages/frontend/editor-ui/src/features/integrations/secretsProviders.ee/composables/useSecretsProvidersList.ee.ts":{"21":[89],"22":[89],"24":[15,35,41,71,89,98,138,144],"35":[15,35,41,71,89,98,138,144],"64":[89],"68":[89],"72":[15,35,41,71,89,98,138,144],"77":[89]},"packages/frontend/editor-ui/src/features/integrations/secretsProviders.ee/views/SettingsSecretsProviders.ee.vue":{"47":[89],"49":[89],"52":[89],"97":[89],"101":[89],"105":[89],"137":[89],"138":[89],"141":[89],"154":[89],"193":[89],"194":[89],"205":[89],"212":[89],"237":[89],"243":[89],"251":[89],"266":[89],"269":[89],"285":[89],"298":[89],"310":[89]},"packages/frontend/editor-ui/src/features/project-roles/projectRoleScopes.ts":{"67":[15,35,41,71,89,98,138,144],"69":[15,35,41,71,89,98,138,144]},"packages/frontend/editor-ui/src/features/settings/sso/provisioning/composables/userRoleProvisioning.store.ts":{"13":[15,35,41,71,89,94,98,138,144],"18":[35,41,71,89,94,98]},"packages/localhost-35141/assets/_plugin-vue_export-helper-Da88TEg1.js":{"2":[89]},"packages/localhost-35141/assets/chunk-CC9Q-vWm.js":{"8":[89],"9":[89],"10":[89],"19":[89],"23":[89],"29":[89],"33":[89],"34":[89]},"packages/frontend/editor-ui/src/app/views/DemoDiffView.vue":{"19":[101],"26":[101],"35":[101],"62":[101]},"packages/frontend/editor-ui/src/features/workflows/workflowDiff/HighlightedEdge.vue":{"6":[101]},"packages/frontend/editor-ui/src/features/workflows/workflowDiff/SyncedWorkflowCanvas.vue":{"16":[101],"39":[101],"49":[101],"68":[101],"71":[101],"76":[101],"90":[101],"98":[101],"102":[101],"131":[101],"146":[101],"149":[101],"152":[101]},"packages/frontend/editor-ui/src/features/workflows/workflowDiff/WorkflowDiffContent.vue":{"15":[101],"41":[101],"46":[101],"48":[101],"59":[101],"70":[101],"75":[101],"87":[101],"102":[101],"113":[101],"118":[101],"130":[101]},"packages/frontend/editor-ui/src/features/workflows/workflowDiff/WorkflowDiffView.vue":{"64":[101],"65":[101],"84":[101],"85":[101],"102":[101],"148":[101],"169":[101],"174":[101],"176":[101],"183":[101]},"packages/frontend/editor-ui/src/features/workflows/workflowDiff/useViewportSync.ts":{"30":[101],"47":[101],"53":[101],"72":[101]},"packages/frontend/editor-ui/src/features/workflows/workflowDiff/useWorkflowDiff.ts":{"18":[101],"19":[101],"29":[101],"33":[101],"38":[101],"43":[101],"64":[101],"80":[101],"91":[101],"97":[101],"114":[101],"123":[101],"149":[101],"199":[101],"221":[101],"249":[101]},"packages/frontend/editor-ui/src/features/workflows/workflowDiff/useWorkflowDiffUI.ts":{"25":[101],"40":[101],"94":[101],"97":[101],"98":[101],"130":[101],"167":[101],"182":[101],"221":[101],"225":[101]},"packages/frontend/editor-ui/src/app/composables/useIntersectionObserver.ts":{"45":[7,105,112,113,115,142],"56":[115,142],"62":[115,142],"82":[7,105,112,113,142]},"packages/frontend/editor-ui/src/features/workflows/workflowHistory/components/WorkflowHistoryContent.vue":{"39":[112],"60":[112],"71":[112],"74":[112],"87":[112],"91":[112],"97":[112],"119":[112],"120":[112],"125":[112],"141":[112],"143":[112],"163":[112]},"packages/frontend/editor-ui/src/features/workflows/workflowHistory/components/WorkflowHistoryList.vue":{"22":[112],"49":[112],"61":[112],"73":[112],"82":[112],"86":[112],"92":[112],"119":[112],"151":[112],"179":[112],"184":[112]},"packages/frontend/editor-ui/src/features/workflows/workflowHistory/components/WorkflowHistoryListItem.vue":{"26":[112],"58":[112],"63":[112],"74":[112],"83":[112],"99":[112],"165":[112],"172":[112],"203":[112],"211":[112],"214":[112]},"packages/frontend/editor-ui/src/features/workflows/workflowHistory/utils.ts":{"9":[112],"15":[66,100,139,140,144],"19":[112],"37":[112],"69":[112],"74":[112]},"packages/frontend/editor-ui/src/features/workflows/workflowHistory/views/WorkflowHistory.vue":{"61":[112],"78":[112],"81":[112],"92":[112],"93":[112],"100":[112],"101":[112],"106":[112],"112":[112],"117":[112],"127":[112],"128":[112],"143":[112],"154":[112],"169":[112],"177":[112],"181":[112],"199":[112],"228":[112],"572":[112],"587":[112],"624":[112],"643":[112]},"packages/@n8n/design-system/src/components/N8nKeyboardShortcut/N8nKeyboardShortcut.vue":{"7":[7,81,84,104,105,107,108,109,129,135],"10":[7,81,84,104,105,107,108,109,129,135],"11":[7,81,84,104,105,107,108,109,129,135],"27":[7,81,84,104,105,107,108,109,129,135],"31":[7,81,84,104,105,107,108,135]},"packages/localhost-35227/assets/_plugin-vue_export-helper-Da88TEg1.js":{"2":[129,135,140]},"packages/localhost-35227/assets/chunk-CC9Q-vWm.js":{"8":[129,135,140],"9":[129,135,140],"10":[129,135,140],"19":[129,135,140],"23":[129,135,140],"29":[129,135,140],"33":[129,135,140],"34":[129,135,140]},"packages/frontend/editor-ui/src/app/components/WorkflowExtractionNameModal.vue":{"21":[135],"31":[135],"37":[135],"57":[135],"59":[135],"64":[135],"79":[135],"90":[135]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/WorkflowSelectorParameterInput/WorkflowSelectorParameterInput.vue":{"59":[135,136],"96":[135,136],"120":[135,136],"130":[135,136],"144":[135,136],"156":[135,136],"164":[135,136],"168":[135,136],"175":[135,136],"193":[136],"203":[136],"208":[136],"216":[136],"229":[135,136],"245":[135,136],"252":[135],"256":[135,136],"257":[136],"266":[135,136],"267":[135,136],"279":[135,136],"283":[136],"288":[136],"321":[135,136],"359":[136],"367":[135,136],"385":[135,136],"387":[135,136],"393":[135,136],"410":[135,136],"446":[135,136],"470":[135,136]},"packages/frontend/editor-ui/src/features/ndv/parameters/composables/useWorkflowResourceLocatorDropdown.ts":{"4":[135,136],"11":[136],"19":[136],"23":[136]},"packages/frontend/editor-ui/src/features/ndv/parameters/composables/useWorkflowResourceLocatorModes.ts":{"12":[135,136],"19":[135,136],"32":[135,136],"33":[135,136],"35":[136],"52":[135,136]},"packages/frontend/editor-ui/src/features/ndv/parameters/composables/useWorkflowResourcesLocator.ts":{"11":[135,136],"25":[135,136],"27":[135,136],"36":[135,136],"44":[136],"52":[135,136],"57":[135,136],"67":[135,136],"92":[135,136],"98":[136],"103":[136]},"packages/@n8n/design-system/src/components/N8nUserStack/UserStack.vue":{"9":[138],"23":[138],"35":[138],"39":[138],"49":[138],"55":[138],"59":[138],"62":[138],"73":[138],"83":[138],"85":[138],"92":[138],"96":[138]},"packages/localhost-42697/assets/_plugin-vue_export-helper-Da88TEg1.js":{"2":[138]},"packages/localhost-42697/assets/chunk-CC9Q-vWm.js":{"8":[138],"9":[138],"10":[138],"19":[138],"23":[138],"29":[138],"33":[138],"34":[138]},"packages/frontend/editor-ui/src/app/components/ActivationModal.vue":{"22":[66,100,139,140,144],"31":[66,100,139,140,144],"33":[66,100,139,140,144],"94":[100],"98":[66,100,139,140,144],"103":[66,100,139,140,144],"105":[66,100,139,140,144],"110":[66,100,139,140,144],"122":[66,100,139,140,144],"125":[66,100,139,140,144]},"packages/frontend/editor-ui/src/app/components/MainHeader/WorkflowPublishModal.vue":{"32":[66,100,139,140,144],"48":[66,100,139,140,144],"52":[66,100,139,140,144],"56":[66,100,139,140,144],"66":[66,100,139,140,144],"68":[66,100,139,140,144],"74":[66,100,139,140,144],"80":[66,100,139,140,144],"96":[66,100,139,140,144],"100":[66,100,139,140,144],"118":[66,100,139,140,144],"122":[66,100,139,140,144],"125":[66],"147":[66,100,139,140,144],"160":[66,100,139,140,144],"203":[66,100,139,140,144],"251":[66,100,139,140,144],"264":[66,100,139,140,144],"265":[66,100,139,140,144],"267":[66,100,139,140,144],"309":[66,100,139,140,144]},"packages/frontend/editor-ui/src/app/components/WorkflowVersionForm.vue":{"16":[66,100,139,140,144],"26":[66,100,139,140,144],"38":[66,100,139,140,144],"47":[66,100,139,140,144],"62":[66,100,139,140,144]},"packages/frontend/editor-ui/src/app/composables/useWorkflowActivate.ts":{"85":[66,100,139,140,144],"178":[144]},"packages/localhost-35227/assets/shield-alt-J5nzuCWH.js":{"8":[140]},"packages/frontend/editor-ui/src/features/ai/evaluation.ee/evaluation.api.ts":{"55":[147,100],"59":[147,100],"64":[147],"77":[147],"96":[147],"112":[147],"120":[147],"124":[147],"137":[147]},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/groups/CanvasNodeGroupOverlay.vue":{"17":[147,107],"42":[147,107],"61":[147,107],"65":[147,107],"69":[147],"74":[147,107],"82":[147,107],"86":[147,107],"87":[147,107],"92":[147,107],"118":[147,107],"140":[147,107]},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/groups/CanvasNodeGroupsLayer.vue":{"32":[147,107],"41":[147,107],"45":[147,107],"46":[147,107],"56":[147,107],"61":[147],"68":[147],"74":[147],"87":[147],"95":[147],"103":[147],"105":[147],"116":[147],"122":[147,107]},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/nodes/render-types/CanvasNodeChoicePrompt.vue":{"19":[5,147,10],"28":[5,147,10],"32":[5,147,10],"36":[147],"47":[5,147,10],"57":[147],"65":[5,147,10],"69":[5,147,10],"94":[147]},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/selection/CanvasSelectionToolbar.vue":{"14":[147,107],"30":[147,107],"31":[147,107],"39":[147,107],"41":[147,107],"45":[147,107],"49":[147,107],"53":[147,107],"61":[147,107],"66":[147],"68":[147,107],"80":[147,107],"87":[147,107],"103":[147,107]},"packages/frontend/editor-ui/src/features/workflows/canvas/composables/useVueFlowTransformPaneTeleport.ts":{"9":[147,107],"14":[147,107],"16":[147,107]},"packages/frontend/editor-ui/src/features/workflows/canvas/experimental/components/ExperimentalCanvasNodeSettings.vue":{"21":[147,84,106],"31":[147,84,106],"32":[147,84,106],"35":[147,84,106],"36":[147,84,106],"41":[147,84,106],"43":[147],"49":[147],"70":[147,84,106],"92":[147],"94":[147]},"packages/frontend/editor-ui/src/features/workflows/canvas/experimental/components/ExperimentalEmbeddedNdvActions.vue":{"6":[147]},"packages/frontend/editor-ui/src/features/workflows/canvas/experimental/components/ExperimentalEmbeddedNodeDetails.vue":{"25":[147],"28":[147],"34":[147],"35":[147],"43":[147],"56":[147],"62":[147],"66":[147],"70":[147],"78":[147],"81":[147],"107":[147],"119":[147],"122":[147]},"packages/frontend/editor-ui/src/features/workflows/canvas/experimental/composables/useExpressionResolveCtx.ts":{"7":[5,147,84,106],"12":[5,147,84,106],"21":[5,147,84,106]},"packages/frontend/editor-ui/src/features/workflows/canvas/experimental/experimentalNdv.utils.ts":{"5":[147],"25":[147],"26":[147]},"packages/localhost-45439/assets/_plugin-vue_export-helper-Da88TEg1.js":{"2":[17,24,41,60,61,68,81,85,106,109]},"packages/localhost-45439/assets/chunk-CC9Q-vWm.js":{"8":[17,24,41,60,61,68,81,85,106,109],"9":[17,24,41,60,61,68,81,85,106,109],"10":[17,24,41,60,61,68,81,85,106,109],"19":[17,24,41,60,61,68,81,85,106,109],"23":[17,24,41,60,61,68,81,85,106,109],"29":[17,24,41,60,61,68,81,85,106,109],"33":[17,24,41,60,61,68,81,85,106,109],"34":[17,24,41,60,61,68,81,85,106,109]},"packages/localhost-45439/assets/shield-alt-J5nzuCWH.js":{"8":[24,109]},"packages/@n8n/design-system/src/components/N8nBreadcrumbs/Breadcrumbs.vue":{"34":[40,41,68,69,70],"59":[40,41,68,69,70],"65":[40,41,68,69,70],"69":[69],"73":[69],"74":[69],"81":[69],"107":[40,41,68,69,70],"108":[69],"114":[69],"123":[69],"124":[69],"142":[69],"143":[69],"158":[69],"172":[40,41,68,69,70],"211":[69],"212":[69],"238":[69],"245":[40,41,68,69,70],"257":[69],"258":[69],"259":[69],"261":[40,41,68,69,70]},"packages/frontend/editor-ui/src/features/core/dataTable/DataTableDetailsView.vue":{"49":[40,41],"51":[40,41],"69":[40,41],"88":[40],"96":[40],"103":[40],"111":[40],"143":[40,41],"150":[40,41],"157":[41],"200":[40,41],"203":[40,41],"207":[40,41],"218":[40,41]},"packages/frontend/editor-ui/src/features/core/dataTable/DataTableView.vue":{"64":[40,41],"65":[40,41],"73":[40,41],"75":[41],"82":[40,41],"100":[40,41],"120":[40,41],"125":[40,41],"142":[41],"161":[40,41],"165":[40,41],"166":[40,41],"201":[40,41],"211":[40,41]},"packages/frontend/editor-ui/src/features/core/dataTable/components/AddDataTableModal.vue":{"120":[40,41],"140":[40,41],"141":[40,41],"149":[40,41],"188":[40,41],"267":[40,41],"334":[40,41],"339":[40,41],"345":[40,41],"357":[40,41],"358":[40,41],"361":[40,41]},"packages/frontend/editor-ui/src/features/core/dataTable/components/DataTableActions.vue":{"53":[40,41],"54":[40,41],"56":[40,41],"91":[41],"153":[41]},"packages/frontend/editor-ui/src/features/core/dataTable/components/DataTableBreadcrumbs.vue":{"16":[40,41],"38":[40,41],"42":[40,41],"46":[40,41],"81":[40],"103":[40,41],"109":[40,41],"119":[40,41],"122":[40,41]},"packages/frontend/editor-ui/src/features/core/dataTable/components/DataTableCard.vue":{"34":[40,41],"44":[40,41],"49":[40,41],"50":[40,41],"55":[40,41],"64":[40,41],"67":[40,41],"74":[40,41],"81":[40,41],"93":[40,41],"105":[40,41],"114":[40,41],"120":[40,41]},"packages/frontend/editor-ui/src/features/core/dataTable/components/DownloadDataTableModal.vue":{"25":[40,41]},"packages/frontend/editor-ui/src/features/core/dataTable/components/ImportCsvModal.vue":{"21":[40,41],"143":[40,41],"154":[40,41]},"packages/frontend/editor-ui/src/features/core/dataTable/components/dataGrid/AddColumnButton.vue":{"31":[40,41],"48":[40,41],"67":[40,41],"69":[40],"72":[40],"78":[40],"114":[40],"123":[40],"129":[40],"142":[40,41],"154":[40,41],"160":[40,41],"174":[40],"184":[40],"217":[40],"221":[40],"222":[40],"243":[40]},"packages/frontend/editor-ui/src/features/core/dataTable/components/dataGrid/AddRowButton.vue":{"5":[40,41]},"packages/frontend/editor-ui/src/features/core/dataTable/components/dataGrid/DataTableTable.vue":{"49":[40,41],"51":[40,41],"69":[40,41],"90":[40,41],"117":[40,41],"120":[40],"128":[40],"132":[40],"136":[40],"140":[40,41],"157":[40],"162":[40,41],"163":[40],"193":[40,41]},"packages/frontend/editor-ui/src/features/core/dataTable/components/dataGrid/registerAgGridModulesOnce.ts":{"27":[40,41]},"packages/frontend/editor-ui/src/features/core/dataTable/composables/useAgGrid.ts":{"23":[40,41],"34":[40,41],"81":[40,41],"93":[40,41],"113":[40],"119":[40],"128":[40],"130":[40],"140":[40],"148":[40],"168":[40],"207":[40,41],"226":[40,41]},"packages/frontend/editor-ui/src/features/core/dataTable/composables/useDataTableColumnFilters.ts":{"19":[40,41]},"packages/frontend/editor-ui/src/features/core/dataTable/composables/useDataTableColumns.ts":{"40":[40,41],"59":[40,41],"66":[40],"97":[40],"123":[40,41],"132":[40,41],"159":[40,41],"161":[40,41],"214":[40,41],"218":[40],"219":[40],"226":[40],"234":[40],"242":[40],"244":[40],"245":[40]},"packages/frontend/editor-ui/src/features/core/dataTable/composables/useDataTableOperations.ts":{"57":[40,41],"113":[40],"114":[40],"132":[40],"135":[40],"204":[40],"228":[40],"238":[40],"254":[40],"277":[40],"330":[40,41],"354":[40],"390":[40]},"packages/frontend/editor-ui/src/features/core/dataTable/composables/useDataTablePagination.ts":{"11":[40,41],"17":[40,41],"21":[40],"32":[40]},"packages/frontend/editor-ui/src/features/core/dataTable/composables/useDataTableSelection.ts":{"5":[40,41],"13":[40,41],"18":[40],"19":[40,41],"23":[40],"27":[40],"36":[40,41]},"packages/frontend/editor-ui/src/features/core/dataTable/composables/useDataTableTypes.ts":{"8":[40,41],"9":[40,41],"18":[40,41],"25":[40,41]},"packages/frontend/editor-ui/src/features/core/dataTable/module.descriptor.ts":{"13":[40,41],"14":[40,41],"15":[40,41],"25":[40,41],"37":[41]},"packages/frontend/editor-ui/src/features/core/dataTable/typeGuards.ts":{"11":[40],"21":[40,41]},"packages/frontend/editor-ui/src/features/core/dataTable/utils/columnUtils.ts":{"26":[40],"29":[40],"35":[40,41],"36":[40,41],"51":[40,41],"52":[40,41],"65":[40,41],"66":[40,41],"94":[40,41],"95":[40],"119":[40],"126":[40,41],"135":[40],"141":[40],"149":[40,41],"156":[40,41],"163":[40,41],"170":[40,41],"177":[40],"184":[40,41],"191":[40,41],"198":[40,41],"205":[40,41],"212":[40,41],"219":[40,41],"229":[40,41],"241":[40],"253":[40]},"packages/@n8n/chat/src/components/GetStarted.vue":{"5":[68]},"packages/@n8n/chat/src/utils/streamingHandlers.ts":{"11":[68],"55":[68],"64":[68],"78":[68],"98":[68]},"packages/frontend/editor-ui/src/app/components/ConsumedTokensDetails.vue":{"7":[68],"13":[68],"24":[68]},"packages/frontend/editor-ui/src/app/components/DuplicateWorkflowDialog.vue":{"20":[68],"58":[68],"64":[68],"72":[68],"76":[68],"147":[68],"156":[68],"161":[68],"172":[68],"192":[68]},"packages/frontend/editor-ui/src/app/components/FocusPanel.vue":{"57":[68,84,106],"87":[68,84,106],"91":[68,84,106],"111":[68,84,106],"127":[68,84,106],"135":[68,84,106],"138":[68,84,106],"140":[68,84,106],"153":[68],"163":[68],"169":[68],"173":[68],"177":[68],"184":[68],"186":[68],"190":[68],"194":[68,84,106],"200":[68,84,106],"207":[68],"211":[68,84,106],"213":[68,84,106],"219":[68],"227":[68],"231":[68,84,106],"233":[68,106],"239":[68,106],"252":[68],"266":[68],"280":[68],"325":[68],"348":[68],"355":[68],"361":[68],"362":[68],"367":[68,84,106],"371":[68,84,106],"372":[68,84,106],"384":[68],"390":[68],"393":[68,84,106],"420":[68],"422":[68],"453":[68],"469":[68],"482":[68],"573":[68],"599":[68,106],"602":[68,106]},"packages/frontend/editor-ui/src/app/components/MainHeader/utils.ts":{"1":[68]},"packages/frontend/editor-ui/src/app/components/NodeViewUnfinishedWorkflowMessage.vue":{"3":[68],"4":[68]},"packages/frontend/editor-ui/src/app/composables/usePushConnection/handlers/builderCreditsUpdated.ts":{"4":[68]},"packages/frontend/editor-ui/src/app/composables/usePushConnection/handlers/executionRecovered.ts":{"17":[68]},"packages/frontend/editor-ui/src/app/composables/usePushConnection/handlers/nodeDescriptionUpdated.ts":{"10":[68]},"packages/frontend/editor-ui/src/app/composables/usePushConnection/handlers/reloadNodeType.ts":{"9":[68]},"packages/frontend/editor-ui/src/app/composables/usePushConnection/handlers/removeNodeType.ts":{"10":[68],"17":[68]},"packages/frontend/editor-ui/src/app/composables/usePushConnection/handlers/sendWorkerStatusMessage.ts":{"8":[68]},"packages/frontend/editor-ui/src/app/composables/usePushConnection/handlers/testWebhookDeleted.ts":{"10":[68]},"packages/frontend/editor-ui/src/app/composables/usePushConnection/handlers/workflowActivated.ts":{"9":[68]},"packages/frontend/editor-ui/src/app/composables/usePushConnection/handlers/workflowAutoDeactivated.ts":{"9":[68]},"packages/frontend/editor-ui/src/app/composables/usePushConnection/handlers/workflowDeactivated.ts":{"8":[68]},"packages/frontend/editor-ui/src/app/composables/usePushConnection/handlers/workflowFailedToActivate.ts":{"8":[68],"21":[68]},"packages/frontend/editor-ui/src/app/composables/usePushConnection/handlers/workflowSettingsUpdated.ts":{"11":[68]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/CanvasChatFloatingMenu.vue":{"10":[68],"26":[68],"27":[68],"32":[68],"34":[68],"43":[68],"75":[68],"108":[68],"120":[68],"133":[68],"148":[68],"149":[68],"154":[68]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/CanvasChatFloatingWindow.vue":{"23":[68],"28":[68],"37":[68],"46":[68],"58":[68],"59":[68],"62":[68],"66":[68],"70":[68],"78":[68],"90":[68],"92":[68],"100":[68],"105":[68],"122":[68],"125":[68],"130":[68],"140":[68]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/CanvasChatHubPanel.vue":{"30":[68],"50":[68],"51":[68],"61":[68],"62":[68],"63":[68],"66":[68],"72":[68],"100":[68],"101":[68],"136":[68],"138":[68],"144":[68],"150":[68],"159":[68],"164":[68],"174":[68],"175":[68],"181":[68],"196":[68],"200":[68],"214":[68],"218":[68],"222":[68],"243":[68],"254":[68],"266":[68],"278":[68],"279":[68],"280":[68],"281":[68],"282":[68],"294":[68],"308":[68],"312":[68],"322":[68],"324":[68],"334":[68],"336":[68],"361":[68],"372":[68],"382":[68]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/CanvasChatOverlay.vue":{"9":[68],"18":[68],"19":[68],"26":[68],"31":[68],"39":[68],"42":[68],"51":[68],"59":[68],"60":[68],"68":[68],"72":[68],"76":[68],"81":[68]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/CanvasChatSessionDropdown.vue":{"19":[68],"32":[68],"33":[68],"40":[68],"42":[68],"51":[68],"52":[68],"54":[68],"67":[68],"72":[68],"77":[68],"78":[68],"91":[68],"99":[68],"100":[68],"103":[68],"112":[68],"117":[68],"129":[68],"131":[68],"137":[68],"150":[68],"156":[68],"161":[68],"164":[68],"167":[68],"168":[68]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/ChatButtons.vue":{"11":[68],"14":[68],"27":[68],"33":[68],"40":[68],"41":[68]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/ChatMarkdownChunk.vue":{"33":[68],"38":[68],"47":[68],"84":[68],"91":[68]},"packages/frontend/editor-ui/src/features/core/folders/components/FolderCard.vue":{"68":[68,69,70],"72":[69],"74":[68,69,70],"98":[68,69,70],"106":[68,69,70],"119":[68,69,70],"130":[68,69,70],"134":[68,69,70],"145":[69],"165":[69],"169":[68,69,70],"180":[68,69,70],"213":[68,69,70],"220":[68,69,70],"221":[68,69,70],"230":[68,69,70],"233":[68,69,70],"240":[68,69,70],"248":[68,70],"259":[68,69,70],"271":[68,69,70],"280":[68,69,70],"286":[68,69,70],"287":[68,69,70],"299":[69],"329":[68,69,70],"339":[68,69,70],"360":[68,69,70]},"packages/frontend/editor-ui/src/features/settings/communityNodes/components/nodeCreator/CommunityNodeDetails.vue":{"19":[58,68],"28":[68],"30":[68],"39":[58,68],"41":[68],"43":[68],"74":[68],"79":[68],"97":[58,68],"115":[68],"118":[68]},"packages/frontend/editor-ui/src/features/settings/communityNodes/components/nodeCreator/CommunityNodeDocsLink.vue":{"9":[58,68],"11":[68],"14":[58,68],"23":[58,68]},"packages/frontend/editor-ui/src/features/settings/communityNodes/components/nodeCreator/CommunityNodeInfo.vue":{"17":[58,68],"29":[58,68],"33":[58,68],"41":[58,68],"43":[68],"48":[58,68],"65":[68],"101":[68],"109":[58,68],"114":[58,68],"119":[58,68],"130":[68],"132":[68],"138":[68],"144":[68],"145":[58,68],"148":[58,68],"156":[68],"163":[68],"168":[68],"169":[68],"172":[68]},"packages/frontend/editor-ui/src/features/settings/communityNodes/components/nodeCreator/CommunityNodeInstallHint.vue":{"10":[68],"11":[68]},"packages/frontend/editor-ui/src/features/settings/orchestration.ee/orchestration.store.ts":{"26":[68,95],"34":[68],"47":[68],"56":[68,95],"59":[68],"65":[68],"71":[68],"74":[68],"77":[68]},"packages/frontend/editor-ui/src/features/setupPanel/components/FocusSidebarTabs.vue":{"9":[68],"30":[68],"41":[68],"43":[68],"57":[68]},"packages/frontend/editor-ui/src/features/setupPanel/components/SetupPanel.vue":{"7":[68],"9":[68],"18":[68]},"packages/frontend/editor-ui/src/features/setupPanel/components/SetupPanelCards.vue":{"15":[68],"31":[68],"40":[68],"48":[68],"52":[68],"54":[68],"57":[68],"73":[68],"76":[68],"77":[68],"79":[68],"85":[68],"97":[68],"132":[68],"153":[68],"162":[68],"182":[68],"198":[68],"202":[68],"207":[68],"212":[68],"221":[68],"232":[68]},"packages/frontend/editor-ui/src/features/setupPanel/components/cards/NodeGroupSetupCard.vue":{"24":[68],"56":[68],"62":[68],"64":[68],"72":[68],"74":[68],"82":[68],"89":[68],"95":[68],"97":[68],"101":[68],"105":[68],"107":[68],"109":[68],"124":[68],"126":[68],"132":[68],"133":[68],"136":[68],"162":[68],"166":[68],"167":[68],"172":[68],"182":[68],"193":[68],"209":[68]},"packages/frontend/editor-ui/src/features/setupPanel/components/cards/NodeSetupCard.vue":{"22":[68],"42":[68],"46":[68],"51":[68],"60":[68],"65":[68],"69":[68],"77":[68],"80":[68],"85":[68],"89":[68],"99":[68],"106":[68],"111":[68],"124":[68],"125":[68],"134":[68],"151":[68],"158":[68],"159":[68],"161":[68],"178":[68],"188":[68],"189":[68],"191":[68],"196":[68],"202":[68],"206":[68],"207":[68],"210":[68],"227":[68]},"packages/frontend/editor-ui/src/features/setupPanel/components/cards/SetupCard.vue":{"16":[68],"49":[68],"53":[68],"57":[68],"63":[68],"69":[68],"84":[68],"90":[68],"92":[68],"97":[68],"101":[68],"102":[68],"116":[68],"150":[68],"166":[68],"172":[68],"188":[68]},"packages/frontend/editor-ui/src/features/shared/nodeCreator/components/ItemTypes/CommunityNodeItem.vue":{"11":[58,68]},"packages/frontend/editor-ui/src/features/shared/tags/components/TagsDropdown.vue":{"64":[137,144],"65":[137,144],"70":[137,144],"71":[137,144],"74":[137,144],"78":[68,137,144],"87":[137,144],"88":[137],"96":[137,144],"104":[137],"122":[137,144],"126":[137],"131":[137,144],"133":[137,144],"136":[137],"152":[137,144],"153":[137,144],"154":[137,144],"163":[137,144],"172":[137,144],"183":[137],"190":[137,144],"199":[137],"200":[137],"206":[137,144],"240":[137],"247":[68,137,144],"255":[137,144],"265":[68,137,144]},"packages/frontend/editor-ui/src/features/workflows/canvas/experimental/components/ExperimentalFocusPanelHeader.vue":{"18":[68,84,106],"27":[68,84,106],"28":[68,84,106],"32":[68,84,106],"36":[68],"38":[68],"48":[68],"56":[68],"58":[68],"70":[68]},"packages/frontend/editor-ui/src/features/workflows/canvas/experimental/components/ExperimentalNodeDetailsDrawer.vue":{"21":[68,84,106],"26":[68,84,106],"27":[68,84],"33":[68,84,106],"36":[68,84,106],"37":[68,84],"46":[68,84,106],"51":[68,84],"53":[68,84],"57":[68],"58":[68,84]},"packages/localhost-45735/assets/_plugin-vue_export-helper-Da88TEg1.js":{"2":[86]},"packages/localhost-45735/assets/chunk-CC9Q-vWm.js":{"8":[86],"9":[86],"10":[86],"19":[86],"23":[86],"29":[86],"33":[86],"34":[86]},"packages/frontend/editor-ui/src/features/workflows/canvas/experimental/components/ExperimentalEmbeddedNdvMapper.vue":{"19":[5,84,106],"39":[5,84,106],"43":[5,84,106],"45":[106],"54":[106],"80":[5,84,106],"87":[84,106],"96":[5,84,106],"111":[106]},"packages/@n8n/design-system/src/components/N8nIcon/nodes/compare-datasets.svg":{"11":[21,28,103,104,105,109,110,124]},"packages/@n8n/design-system/src/components/N8nIcon/nodes/extract-from-file.svg":{"11":[21,28,64,103,104,105,109,110,111,124]},"packages/frontend/editor-ui/src/app/components/AboutModal.vue":{"16":[109],"24":[109],"28":[109],"57":[109],"68":[109],"72":[109],"75":[109],"80":[109],"83":[109],"88":[109],"91":[109],"98":[109],"101":[109],"108":[109],"111":[109],"116":[109],"119":[109],"127":[109]},"packages/frontend/editor-ui/src/features/shared/editors/components/CodeNodeEditor/AskAI/AskAI.vue":{"28":[2,21,28,84,103,104,105,109,110,124],"57":[2,21,28,84,103,104,105,109,110,124],"64":[110],"67":[110],"70":[2,21,28,84,103,104,105,109,110,124],"76":[110],"93":[2,21,28,84,103,104,105,109,110,124],"100":[2,21,28,84,103,104,105,109,110,124],"101":[2,21,28,84,103,104,105,109,110,124],"103":[2,21,28,84,103,104,105,109,110,124],"104":[2,21,28,84,103,104,105,109,110,124],"107":[110],"108":[110],"110":[110],"118":[110],"133":[110],"141":[110],"145":[110],"150":[110],"216":[110],"221":[110],"243":[2,21,28,84,103,104,105,109,110,124],"250":[110],"254":[2,21,28,84,103,104,105,109,110,124],"259":[2,21,28,84,103,104,105,109,110,124],"293":[110],"304":[2,21,28,84,103,104,105,109,110,124],"308":[110]},"packages/frontend/editor-ui/src/features/shared/editors/components/CodeNodeEditor/CodeNodeEditor.vue":{"43":[2,21,28,84,103,104,105,109,110,124],"71":[110,124],"72":[2,21,28,84,103,104,105,109,110,124],"73":[2,110,124],"76":[2,21,28,84,103,104,105,109,110,124],"77":[21,28,103,104,105,109,110,124],"78":[2,21,28,84,103,104,105,109,110,124],"85":[2,21,28,84,103,104,105,109,110,124],"86":[2,21,28,84,103,104,105,109,110,124],"87":[2,21,28,84,103,104,105,109,110,124],"90":[2,21,28,84,103,104,105,109,110,124],"97":[2,21,28,84,103,104,105,109,110,124],"100":[2,21,28,84,103,104,105,109,110,124],"109":[21,28,84,103,104,105,109,110,124],"114":[2,21,28,84,103,104,105,109,110,124],"118":[2,21,28,84,103,104,105,109,110,124],"124":[110],"140":[110],"152":[2,84,110,124],"158":[2],"165":[2,84,110,124],"166":[2,84,110,124],"199":[110],"203":[110],"225":[2,21,28,84,103,104,105,109,110,124],"239":[2,21,28,84,103,104,105,109,110,124],"245":[2,21,28,84,103,104,105,109,110,124],"252":[2,21,28,84,103,104,105,109,110,124],"271":[2,21,28,84,103,104,105,109,110,124],"291":[28]},"packages/frontend/editor-ui/src/features/shared/editors/components/CodeNodeEditor/linter.ts":{"23":[2,21,28,84,103,104,105,109,110,124],"29":[2,21,28,84,103,104,105,109,110,124],"38":[2,110,124],"62":[110],"68":[110],"95":[110,124],"136":[110,124],"138":[110,124],"142":[110,124],"144":[110,124],"146":[110,124],"151":[110],"180":[110],"222":[110],"230":[110],"257":[110,124],"264":[110],"288":[110,124],"298":[110],"321":[110,124],"328":[110],"329":[110],"346":[110],"352":[110],"377":[110,124],"399":[110,124],"415":[110,124],"422":[110],"466":[110],"513":[110,124],"554":[110,124],"588":[110,124],"599":[110],"626":[110],"632":[110],"633":[110]},"packages/frontend/editor-ui/src/features/shared/editors/composables/useCodeEditor.ts":{"70":[2,21,28,84,103,104,105,109,110,124],"113":[2,21,28,84,103,104,105,109,110,124],"114":[2,21,28,84,103,104,105,109,110,124],"125":[2,21,28,84,103,104,105,109,110,124],"134":[2,21,28,84,103,104,105,109,110,124],"166":[2,21,28,84,103,104,105,109,110,124],"170":[2,21,28,84,103,104,105,109,110,124],"181":[2,21,28,84,103,104,105,109,110,124],"185":[2,28,84,110,124],"195":[2,21,28,84,103,104,105,109,110,124],"203":[2,21,28,84,103,104,105,109,110,124],"224":[2,21,28,84,103,104,105,109,110,124],"239":[2,21,28,84,103,104,105,109,110,124],"253":[2,84,110,124],"262":[124],"267":[124],"275":[2,21,28,84,103,104,105,109,110,124],"370":[2,21,28,103,104,105,109,110,124],"382":[2,21,28,84,103,104,105,109,110,124],"386":[21,28,84,103,104,105,109,110,124],"417":[2,110,124],"443":[2,110,124]},"packages/frontend/editor-ui/src/features/shared/editors/plugins/codemirror/typescript/client/useTypescript.ts":{"28":[2,21,28,84,103,104,105,109,110,124],"44":[2,21,28,84,103,104,105,109,110,124],"68":[2,110],"116":[2,110],"124":[2,110],"134":[2,21,28,84,103,104,105,109,110,124],"138":[110],"146":[21,28,84,103,104,105,109,110,124]},"packages/localhost-42219/assets/_plugin-vue_export-helper-Da88TEg1.js":{"2":[109,128,144]},"packages/localhost-42219/assets/chunk-CC9Q-vWm.js":{"8":[109,128,144],"9":[109,128,144],"10":[109,128,144],"19":[109,128,144],"23":[109,128,144],"29":[109,128,144],"33":[109,128,144],"34":[109,128,144]},"packages/@n8n/design-system/src/components/N8nCommandBar/CommandBarItem.vue":{"6":[144],"17":[144],"21":[144],"27":[144]},"packages/@n8n/design-system/src/components/N8nTags/Tags.vue":{"21":[144,145],"37":[144,145],"45":[144],"50":[144,145],"56":[144,145]},"packages/frontend/editor-ui/src/app/components/WorkflowShareModal.ee.vue":{"42":[96,99,144],"60":[96,99,144],"63":[96,99,144],"64":[96,99,144],"65":[99,144],"68":[96,99,144],"71":[96,99,144],"74":[96,99,144],"86":[96,99,144],"90":[96,99,144],"92":[96,99,144],"111":[96,99,144],"115":[96,99,144],"127":[99,144],"130":[96],"132":[96,99,144],"137":[96,99,144],"138":[96,99,144],"154":[99],"161":[99],"175":[99],"182":[99],"217":[99],"241":[96,99,144],"256":[96,99,144],"261":[99],"267":[96,99,144],"279":[96,99,144],"323":[96],"324":[96],"327":[96],"360":[96,99,144],"372":[96,99,144],"374":[96,99,144],"377":[96],"386":[99,144]},"packages/frontend/editor-ui/src/app/stores/workflows.ee.store.ts":{"13":[96,99,100,144],"18":[100],"19":[100],"34":[99],"43":[99],"49":[99]},"packages/frontend/editor-ui/src/features/shared/commandBar/components/CommandBarItemTitle.vue":{"23":[144]},"packages/frontend/editor-ui/src/features/shared/tags/components/WorkflowTagsDropdown.vue":{"33":[137,144],"34":[137,144],"37":[137,144],"38":[137,144],"39":[137,144],"41":[137],"45":[137],"53":[137,144]},"packages/frontend/editor-ui/src/features/workflows/workflowHistory/components/WorkflowHistoryVersionUnpublishModal.vue":{"15":[144],"36":[144],"42":[144],"45":[144],"49":[144],"51":[144],"58":[144],"62":[144],"70":[144],"73":[144],"76":[144]},"packages/localhost-42219/assets/shield-alt-J5nzuCWH.js":{"8":[144]},"packages/frontend/editor-ui/src/app/components/GoBackButton.vue":{"11":[145]},"packages/frontend/editor-ui/src/app/components/NodeList.vue":{"19":[145,146],"23":[146],"27":[145,146],"31":[145,146],"36":[145,146],"42":[145,146]},"packages/frontend/editor-ui/src/app/utils/formatters/listFormatter.ts":{"15":[78,145]},"packages/frontend/editor-ui/src/features/credentials/components/CredentialPicker/CredentialPicker.vue":{"48":[31,33,78,145],"61":[31,33,78,145],"62":[31,33,145],"70":[31,33,78,145],"99":[31,33,78,145],"104":[31,33,78,145],"110":[33],"113":[145],"124":[33],"167":[145],"196":[31,33,145],"206":[31,33,78,145],"207":[31,33,78,145],"233":[31,33,145],"252":[31]},"packages/frontend/editor-ui/src/features/credentials/components/CredentialPicker/CredentialsDropdown.vue":{"39":[31,33,145],"48":[31,33],"52":[33],"86":[31,33,145],"91":[31,33,145],"92":[31,33,145],"97":[31,33,145]},"packages/frontend/editor-ui/src/features/workflows/templates/components/AppsRequiringCredsNotice.vue":{"10":[78,145],"17":[78,145],"24":[78,145],"27":[78,145],"33":[78,145],"38":[78,145]},"packages/frontend/editor-ui/src/features/workflows/templates/components/IconSuccess.vue":{"2":[78,145]},"packages/frontend/editor-ui/src/features/workflows/templates/components/SetupTemplateFormStep.vue":{"42":[78,145],"44":[78,145],"48":[78,145],"52":[78,145],"53":[78,145],"60":[78,145],"71":[145],"85":[78,145],"98":[78,145]},"packages/frontend/editor-ui/src/features/workflows/templates/components/SetupWorkflowCredentialsModal.vue":{"13":[78,145],"29":[78,145],"46":[78,145],"52":[145],"61":[78,145],"65":[78,145],"67":[78,145],"71":[78,145],"83":[78,145],"90":[145],"98":[78,145],"105":[145]},"packages/frontend/editor-ui/src/features/workflows/templates/components/TemplateCard.vue":{"12":[145,146],"37":[145],"41":[146],"43":[145,146],"65":[145,146],"71":[145,146],"75":[145,146]},"packages/frontend/editor-ui/src/features/workflows/templates/components/TemplateDetails.vue":{"21":[145],"32":[145],"34":[145],"49":[145],"59":[145],"62":[145],"79":[145],"86":[145],"89":[145]},"packages/frontend/editor-ui/src/features/workflows/templates/components/TemplateList.vue":{"38":[145,146],"47":[145,146],"71":[146],"74":[145],"83":[145,146],"90":[145,146],"97":[146],"98":[145]},"packages/frontend/editor-ui/src/features/workflows/templates/composables/useCredentialSetupState.ts":{"29":[78,145],"34":[78,145],"38":[78,145],"43":[78,145],"77":[78,145],"103":[78,145],"115":[78,145],"123":[78,145],"126":[78,145],"132":[78,145],"136":[78,145],"140":[78,145],"144":[145],"163":[78,145],"171":[145]},"packages/frontend/editor-ui/src/features/workflows/templates/composables/useSetupWorkflowCredentialsModalState.ts":{"9":[78,145],"15":[78,145],"34":[78,145],"40":[145],"52":[145],"66":[145]},"packages/frontend/editor-ui/src/features/workflows/templates/setupTemplate.store.ts":{"39":[145],"56":[145],"60":[145],"80":[145],"98":[145],"115":[145],"128":[145],"149":[145],"176":[145]},"packages/frontend/editor-ui/src/features/workflows/templates/utils/templateActions.ts":{"30":[145],"72":[145],"100":[146],"128":[145,146],"132":[145,146],"137":[145,146]},"packages/frontend/editor-ui/src/features/workflows/templates/utils/templateTransforms.ts":{"38":[78,145],"47":[78,145],"55":[145],"73":[145],"99":[145],"122":[145],"127":[145]},"packages/frontend/editor-ui/src/features/workflows/templates/views/SetupWorkflowFromTemplateView.vue":{"22":[145],"25":[145],"26":[145],"28":[145],"49":[145],"57":[145],"79":[145],"89":[145],"109":[145],"135":[145],"143":[145],"151":[145]},"packages/frontend/editor-ui/src/features/workflows/templates/views/TemplatesCollectionView.vue":{"32":[145],"37":[145],"39":[145],"44":[145],"45":[145],"48":[145],"49":[145],"64":[145],"87":[145],"88":[145],"98":[145],"117":[145],"121":[145],"124":[145]},"packages/localhost-45347/assets/_plugin-vue_export-helper-Da88TEg1.js":{"2":[145]},"packages/localhost-45347/assets/chunk-CC9Q-vWm.js":{"8":[145],"9":[145],"10":[145],"19":[145],"23":[145],"29":[145],"33":[145],"34":[145]},"packages/frontend/editor-ui/src/features/ai/instanceAi/confirmationKinds.ts":{"16":[45,51]},"packages/frontend/editor-ui/src/features/ai/instanceAi/workflowSetup/InstanceAiWorkflowSetup.vue":{"8":[51]},"packages/frontend/editor-ui/src/features/ai/instanceAi/workflowSetup/components/WorkflowSetupCard.vue":{"14":[51],"23":[51],"25":[51],"26":[51],"28":[51],"32":[51],"36":[51],"44":[51],"56":[51],"64":[51],"74":[51]},"packages/frontend/editor-ui/src/features/ai/instanceAi/workflowSetup/components/WorkflowSetupGroupCard.vue":{"13":[51],"24":[51],"31":[51],"33":[51],"35":[51],"43":[51],"51":[51],"68":[51],"79":[51],"89":[51]},"packages/frontend/editor-ui/src/features/ai/instanceAi/workflowSetup/components/WorkflowSetupSectionBody.vue":{"21":[51],"30":[51],"32":[51],"38":[51],"49":[51],"50":[51],"53":[51],"60":[51],"64":[51],"67":[51],"72":[51],"79":[51],"81":[51],"82":[51],"85":[51],"89":[51],"93":[51],"102":[51],"112":[51],"119":[51],"128":[51],"134":[51],"138":[51],"160":[51],"162":[51],"166":[51]},"packages/frontend/editor-ui/src/features/ai/instanceAi/workflowSetup/components/WorkflowSetupStatus.vue":{"7":[51],"41":[51],"42":[51],"53":[51]},"packages/frontend/editor-ui/src/features/ai/instanceAi/workflowSetup/components/WorkflowSetupWizard.vue":{"8":[51],"10":[51],"14":[51],"18":[51],"22":[51],"23":[51],"27":[51],"32":[51]},"packages/frontend/editor-ui/src/features/ai/instanceAi/workflowSetup/components/WorkflowSetupWizardFooter.vue":{"9":[51],"12":[51],"13":[51],"14":[51],"15":[51],"17":[51],"21":[51],"25":[51],"30":[51],"34":[51],"36":[51],"39":[51],"41":[51],"47":[51],"57":[51],"63":[51],"70":[51],"87":[51],"118":[51]},"packages/frontend/editor-ui/src/features/ai/instanceAi/workflowSetup/composables/useWorkflowSetupActions.ts":{"36":[51],"63":[51],"66":[51],"75":[51],"87":[51],"89":[51],"94":[51],"102":[51],"109":[51]},"packages/frontend/editor-ui/src/features/ai/instanceAi/workflowSetup/composables/useWorkflowSetupApply.ts":{"12":[51],"26":[51],"30":[51],"34":[51],"42":[51],"53":[51],"59":[51],"67":[51],"72":[51],"85":[51],"88":[51],"131":[51]},"packages/frontend/editor-ui/src/features/ai/instanceAi/workflowSetup/composables/useWorkflowSetupBootstrap.ts":{"5":[51],"14":[51]},"packages/frontend/editor-ui/src/features/ai/instanceAi/workflowSetup/composables/useWorkflowSetupContext.ts":{"70":[51],"75":[51],"92":[51],"96":[51],"97":[51],"98":[51],"100":[51],"106":[51],"112":[51],"153":[51],"162":[51],"202":[51]},"packages/frontend/editor-ui/src/features/ai/instanceAi/workflowSetup/composables/useWorkflowSetupGroupSections.ts":{"15":[51],"18":[51],"22":[51],"28":[51],"37":[51],"41":[51],"42":[51],"47":[51],"52":[51]},"packages/frontend/editor-ui/src/features/ai/instanceAi/workflowSetup/composables/useWorkflowSetupInputs.ts":{"14":[51],"36":[51],"43":[51],"46":[51],"62":[51],"72":[51],"76":[51],"80":[51],"84":[51],"91":[51],"97":[51],"102":[51],"119":[51],"123":[51],"131":[51],"135":[51],"139":[51],"146":[51],"147":[51],"149":[51],"161":[51],"178":[51],"194":[51],"206":[51],"217":[51],"226":[51],"229":[51],"240":[51],"243":[51],"244":[51],"266":[51]},"packages/frontend/editor-ui/src/features/ai/instanceAi/workflowSetup/composables/useWorkflowSetupSections.ts":{"10":[51],"15":[51],"20":[51],"61":[51],"88":[51]},"packages/frontend/editor-ui/src/features/ai/instanceAi/workflowSetup/composables/useWorkflowSetupSteps.ts":{"15":[51],"19":[51]},"packages/frontend/editor-ui/src/features/ai/instanceAi/workflowSetup/composables/useWorkflowSetupTelemetry.ts":{"42":[51],"58":[51],"68":[51],"69":[51],"76":[51],"80":[51],"100":[51],"122":[51],"137":[51],"144":[51],"158":[51],"168":[51],"173":[51],"182":[51],"207":[51],"226":[51],"230":[51]},"packages/frontend/editor-ui/src/features/ai/instanceAi/workflowSetup/workflowSetup.helpers.ts":{"8":[51],"16":[51],"21":[51]},"packages/frontend/editor-ui/src/features/ai/instanceAi/workflowSetup/workflowSetupParameterIssues.ts":{"6":[51],"25":[51],"44":[51],"59":[51]},"packages/frontend/editor-ui/src/features/credentials/composables/useCredentialTestInBackground.ts":{"4":[5,51],"12":[5,51],"17":[51],"18":[51],"28":[5,51],"79":[51]},"packages/frontend/editor-ui/src/features/setupPanel/setupPanel.utils.ts":{"7":[5,51],"25":[5],"50":[5],"103":[5],"136":[5],"227":[5],"267":[5],"310":[5],"318":[5]},"packages/localhost-35673/assets/_plugin-vue_export-helper-Da88TEg1.js":{"2":[66]},"packages/localhost-35673/assets/chunk-CC9Q-vWm.js":{"8":[66],"9":[66],"10":[66],"19":[66],"23":[66],"29":[66],"33":[66],"34":[66]},"packages/frontend/editor-ui/src/features/core/folders/components/DeleteFolderModal.vue":{"16":[70],"41":[70],"46":[70],"50":[70],"55":[70],"74":[70],"82":[70],"105":[70],"141":[70],"143":[70],"155":[70],"162":[70],"165":[70],"168":[70],"181":[70],"197":[70],"199":[70],"227":[70]},"packages/frontend/editor-ui/src/features/ndv/runData/components/RunDataPaginationBar.vue":{"12":[75,123,125],"16":[75,123,125],"28":[75],"39":[75,123,125],"40":[75,123,125]},"packages/@n8n/codemirror-lang-sql/src/complete.ts":{"192":[111],"193":[111]},"packages/@n8n/design-system/src/components/N8nIcon/nodes/html.svg":{"11":[111]},"packages/frontend/editor-ui/src/features/shared/editors/components/HtmlEditor/HtmlEditor.vue":{"51":[111],"63":[111],"68":[111],"97":[111],"100":[111],"237":[111],"243":[111],"247":[111],"260":[111],"265":[111]},"packages/frontend/editor-ui/src/features/shared/editors/components/HtmlEditor/utils.ts":{"44":[111]},"packages/frontend/editor-ui/src/features/shared/editors/components/SqlEditor/SqlEditor.vue":{"42":[111],"80":[111],"82":[111],"88":[111],"130":[111],"135":[111],"140":[111],"146":[111],"154":[111],"158":[111],"160":[111],"163":[111],"208":[111],"213":[111]},"packages/frontend/editor-ui/src/app/utils/rbac/checks/isEnterpriseFeatureEnabled.ts":{"4":[113],"15":[113]},"packages/frontend/editor-ui/src/app/utils/rbac/middleware/enterprise.ts":{"6":[113]},"packages/frontend/editor-ui/src/features/execution/executions/composables/useExecutionDebugging.ts":{"46":[113],"50":[113],"61":[113],"62":[113],"68":[113],"78":[113],"95":[113],"112":[113],"118":[113],"122":[113],"166":[113]},"packages/localhost-36655/assets/_plugin-vue_export-helper-Da88TEg1.js":{"2":[113,116,134]},"packages/localhost-36655/assets/chunk-CC9Q-vWm.js":{"8":[113,116,134],"9":[113,116,134],"10":[113,116,134],"19":[113,116,134],"23":[113,116,134],"29":[113,116,134],"33":[113,116,134],"34":[113,116,134]},"packages/@n8n/design-system/src/components/N8nIcon/nodes/calculator.svg":{"11":[7,34]},"packages/@n8n/design-system/src/components/N8nIcon/nodes/call-n8n-sub-workflow-tool.svg":{"11":[7,34,52,126]},"packages/@n8n/design-system/src/components/N8nIcon/nodes/compression.svg":{"11":[7,34]},"packages/@n8n/design-system/src/components/N8nIcon/nodes/date-and-time.svg":{"11":[7,34]},"packages/@n8n/design-system/src/components/N8nIcon/nodes/item-list-output-parser.svg":{"11":[7]},"packages/@n8n/design-system/src/components/N8nIcon/nodes/model-selector.svg":{"11":[7,8,126]},"packages/@n8n/design-system/src/components/N8nIcon/nodes/rss-read.svg":{"11":[7,34]},"packages/@n8n/design-system/src/components/N8nIcon/nodes/send-mail.svg":{"11":[7,11,34,55,59]},"packages/@n8n/design-system/src/components/N8nIcon/nodes/simple-memory.svg":{"11":[7,126]},"packages/@n8n/design-system/src/components/N8nIcon/nodes/think-tool.svg":{"11":[7,34]},"packages/@n8n/design-system/src/components/N8nIcon/nodes/totp.svg":{"11":[7,34]},"packages/@n8n/design-system/src/components/N8nIcon/nodes/vector-store-question-answer-tool.svg":{"11":[7]},"packages/frontend/editor-ui/src/features/shared/editors/components/JsEditor/JsEditor.vue":{"31":[7,124],"36":[7,124],"40":[7,124],"57":[7,124],"73":[7,124],"77":[7,124],"102":[7,124],"121":[7,124]},"packages/localhost-43307/assets/_plugin-vue_export-helper-Da88TEg1.js":{"2":[7,8]},"packages/localhost-43307/assets/chunk-CC9Q-vWm.js":{"8":[7,8],"9":[7,8],"10":[7,8],"19":[7,8],"23":[7,8],"29":[7,8],"33":[7,8],"34":[7,8]},"packages/localhost-43307/assets/shield-alt-J5nzuCWH.js":{"8":[7,8]},"packages/@n8n/design-system/src/components/N8nIcon/nodes/chat-memory-manager.svg":{"11":[8,104]},"packages/@n8n/design-system/src/components/N8nIcon/nodes/merge.svg":{"11":[11,104,114,126]},"packages/localhost-34159/assets/_plugin-vue_export-helper-Da88TEg1.js":{"2":[11,12,15,40,64,94,96,98,102,119,121]},"packages/localhost-34159/assets/chunk-CC9Q-vWm.js":{"8":[11,12,15,40,64,94,96,98,102,119,121],"9":[11,12,15,40,64,94,96,98,102,119,121],"10":[11,12,15,40,64,94,96,98,102,119,121],"19":[11,12,15,40,64,94,96,98,102,119,121],"23":[11,12,15,40,64,94,96,98,102,119,121],"29":[11,12,15,40,64,94,96,98,102,119,121],"33":[11,12,15,40,64,94,96,98,102,119,121],"34":[11,12,15,40,64,94,96,98,102,119,121]},"packages/localhost-34159/assets/shield-alt-J5nzuCWH.js":{"8":[11,96,98]},"packages/@n8n/design-system/src/components/N8nFormBox/FormBox.vue":{"34":[18,20,93],"41":[20,93],"42":[20,93],"43":[20,93],"45":[18,20,93],"51":[18,20,93],"80":[18,20,93]},"packages/@n8n/design-system/src/components/N8nFormInputs/FormInputs.vue":{"19":[18,20,25,92,93],"37":[18,20,25,92,93],"38":[18,20,25,92,93],"43":[20,92,93],"44":[20,92,93],"55":[18,20,25,92,93],"56":[18,20,25,92,93],"59":[18,20,25,92,93],"63":[18,20,25,92,93],"64":[93],"67":[93],"68":[93],"69":[93],"74":[20,92,93],"80":[18,20,25,92,93],"107":[93],"116":[20,92,93],"123":[20,92,93],"136":[18,20,25,92,93],"147":[18,20,25,92,93],"151":[18,20,25,92,93],"154":[18,20,25,92,93],"177":[20,92,93],"178":[18,20,25,92,93]},"packages/@n8n/design-system/src/components/ResizeObserver/ResizeObserver.vue":{"6":[18,20,25,92,93],"21":[18,20,25,92,93],"23":[18,20,25,92,93],"25":[18,20,25,92,93],"30":[18,20,25,92,93],"36":[18,20,25,92,93],"37":[18,20,25,92,93],"38":[18,20,25,92,93],"47":[20,93],"52":[18,20,25,92,93]},"packages/frontend/editor-ui/src/app/utils/rbac/checks/isGuest.ts":{"4":[18,20,93]},"packages/frontend/editor-ui/src/app/utils/rbac/middleware/guest.ts":{"6":[18,20,93]},"packages/frontend/editor-ui/src/features/core/auth/views/AuthView.vue":{"28":[20,93],"32":[20,93],"59":[18,20,93]},"packages/frontend/editor-ui/src/features/core/auth/views/SigninView.vue":{"45":[18,20,93],"46":[18,20,93],"89":[93],"98":[20,93],"102":[20,93],"119":[20,93],"127":[20,93],"190":[93],"195":[93]},"packages/frontend/editor-ui/src/features/settings/sso/components/SSOLogin.vue":{"23":[18,20,93]},"packages/frontend/editor-ui/src/app/components/Badge.vue":{"8":[15],"17":[15]},"packages/frontend/editor-ui/src/app/components/VersionCard.vue":{"13":[15],"17":[15]},"packages/frontend/editor-ui/src/app/components/common/SelectedItemsInfo.vue":{"17":[40],"24":[40],"28":[40],"32":[40]},"packages/frontend/editor-ui/src/features/core/dataTable/components/dataGrid/ElDatePickerCellEditor.vue":{"7":[40],"24":[40],"30":[40],"36":[40],"43":[40],"45":[40]},"packages/frontend/editor-ui/src/features/core/dataTable/components/dataGrid/NullEmptyCellRenderer.vue":{"2":[40]},"packages/frontend/editor-ui/src/features/core/dataTable/composables/useDatePickerCommon.ts":{"11":[40],"17":[40],"22":[40],"35":[40],"60":[40],"67":[40],"84":[40]},"packages/frontend/editor-ui/src/features/core/dataTable/utils/typeUtils.ts":{"13":[40],"49":[40]},"packages/frontend/editor-ui/src/features/core/dataTable/utils.ts":{"1":[40],"6":[40]},"packages/frontend/editor-ui/src/features/ai/chatHub/chat.utils.ts":{"25":[29,30,31,32,34,35,47],"46":[29,30,31,32,34,35],"64":[29,30,31,32,34,35],"71":[29,30,32,34,35],"82":[32,35],"110":[29,30,31,32,34,35],"122":[29,30,31,32,34,35],"158":[32,35],"196":[29,30,31,32,34,35],"200":[30,31,32],"215":[29,30,31,32,34,35],"227":[29,30,31,32,34,35],"280":[29,30,31,32,34,35],"331":[29,30,31,32,34,35],"335":[29,30,31,32,34,35],"341":[29,30,31,32,34,35],"348":[34],"352":[29,30,31,32,34],"361":[29,30,31,32,34],"381":[29,30,31,32,34,35],"412":[29,30,31,32,34,35],"442":[29,30,31,32,34,35],"459":[29],"467":[29],"487":[29,30,31,32,34,35],"491":[29,30,31,32,34,35],"505":[29,30,31,32,34,35],"515":[29,30,31,32,34,35],"608":[29,30,31,32,34,35]},"packages/frontend/editor-ui/src/features/ai/instanceAi/components/InstanceAiThreadList.vue":{"28":[47],"54":[47],"72":[47],"78":[47],"95":[47],"98":[47],"104":[47],"107":[47],"119":[47],"126":[47],"136":[47],"143":[47],"158":[47],"177":[47],"178":[47],"180":[47],"183":[47],"192":[47],"195":[47],"197":[47],"207":[47],"208":[47],"215":[47],"216":[47],"218":[47],"232":[47]},"packages/localhost-36639/assets/_plugin-vue_export-helper-Da88TEg1.js":{"2":[47]},"packages/localhost-36639/assets/chunk-CC9Q-vWm.js":{"8":[47],"9":[47],"10":[47],"19":[47],"23":[47],"29":[47],"33":[47],"34":[47]},"packages/frontend/editor-ui/src/app/utils/rbac/checks/isDefaultUser.ts":{"4":[94]},"packages/frontend/editor-ui/src/features/settings/users/components/DeleteUserModal.vue":{"15":[94],"32":[94],"35":[94],"38":[94],"40":[94],"49":[94],"65":[94],"71":[94],"105":[94],"118":[94],"122":[94],"128":[94],"132":[94],"134":[94],"137":[94],"142":[94],"154":[94],"155":[94],"156":[94],"165":[94],"174":[94]},"packages/frontend/editor-ui/src/features/settings/users/components/SettingsUsersActionsCell.vue":{"7":[94],"16":[94],"21":[94]},"packages/frontend/editor-ui/src/features/settings/users/components/SettingsUsersLastActiveCell.vue":{"7":[94],"10":[94],"13":[94]},"packages/frontend/editor-ui/src/features/settings/users/components/SettingsUsersProjectsCell.vue":{"6":[94],"13":[94],"19":[94],"22":[94],"26":[94],"30":[94]},"packages/frontend/editor-ui/src/features/settings/users/components/SettingsUsersRoleCell.vue":{"20":[94],"21":[94],"22":[94],"24":[94],"29":[94],"42":[94],"49":[94],"54":[94]},"packages/frontend/editor-ui/src/features/settings/users/components/SettingsUsersTable.vue":{"24":[94],"45":[94],"51":[94],"66":[94],"77":[94],"88":[94],"99":[94],"105":[94],"124":[94],"143":[94],"151":[94],"154":[94],"159":[94],"161":[94],"176":[94],"181":[94],"192":[94],"195":[94],"198":[94],"202":[94]},"packages/frontend/editor-ui/src/features/settings/users/views/SettingsUsersView.vue":{"73":[94],"75":[94],"79":[94],"83":[94],"85":[94],"95":[94],"100":[94],"109":[94],"115":[94],"122":[94],"131":[94],"136":[94],"140":[94],"144":[94],"163":[94],"198":[94],"203":[94],"318":[94],"319":[94],"328":[94],"340":[94],"363":[94],"368":[94],"415":[94],"418":[94],"423":[94],"432":[94],"492":[94],"499":[94]},"packages/frontend/editor-ui/src/app/components/DependencyPill.vue":{"37":[38,97,98,139],"39":[38,97,98,139],"45":[38,97,98,139],"47":[38,97,98,139],"53":[38,97,98,139],"95":[38,97,98,139],"219":[38,97,98,139],"222":[38,97,98,139]},"packages/frontend/editor-ui/src/features/credentials/components/CredentialEdit/CredentialSharing.ee.vue":{"37":[33,38,97,98],"56":[33,38,97,98],"64":[33,38,97,98],"65":[33,38,97,98],"77":[33,38,97,98],"81":[33,38,97,98],"85":[33,38,97,98],"91":[33,38,97,98],"97":[33,38,97,98],"98":[33,38,97,98],"111":[33,38,97,98],"117":[33,38,97,98],"123":[97,98],"134":[33,38,97,98],"160":[33,38,97,98],"189":[33,38]},"packages/localhost-46589/assets/_plugin-vue_export-helper-Da88TEg1.js":{"2":[115]},"packages/localhost-46589/assets/chunk-CC9Q-vWm.js":{"8":[115],"9":[115],"10":[115],"19":[115],"23":[115],"29":[115],"33":[115],"34":[115]},"packages/frontend/editor-ui/src/app/utils/forceParse.ts":{"9":[2,110,121]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/ExpressionEditorModal/ExpressionEditorModalInput.vue":{"27":[121],"39":[121],"49":[121],"57":[121],"65":[121],"66":[121],"72":[121],"79":[121],"85":[121],"90":[121],"93":[121]},"packages/@n8n/design-system/src/components/N8nIcon/custom/empty-output.svg":{"9":[124]},"packages/frontend/editor-ui/src/features/shared/editors/components/CodeNodeEditor/utils.ts":{"10":[110,124],"19":[110,124],"30":[110,124]},"packages/localhost-38233/assets/_plugin-vue_export-helper-Da88TEg1.js":{"2":[124,126,141]},"packages/localhost-38233/assets/chunk-CC9Q-vWm.js":{"8":[124,126,141],"9":[124,126,141],"10":[124,126,141],"19":[124,126,141],"23":[124,126,141],"29":[124,126,141],"33":[124,126,141],"34":[124,126,141]},"packages/localhost-38233/assets/shield-alt-J5nzuCWH.js":{"8":[124,126]},"packages/localhost-39175/assets/_plugin-vue_export-helper-Da88TEg1.js":{"2":[27]},"packages/localhost-39175/assets/chunk-CC9Q-vWm.js":{"8":[27],"9":[27],"10":[27],"19":[27],"23":[27],"29":[27],"33":[27],"34":[27]},"packages/frontend/editor-ui/src/features/shared/editors/components/CodeNodeEditor/completer.ts":{"23":[28],"27":[28]},"packages/localhost-40359/assets/_plugin-vue_export-helper-Da88TEg1.js":{"2":[28,55,65,84,92,95,97,100,105,125]},"packages/localhost-40359/assets/chunk-CC9Q-vWm.js":{"8":[28,55,65,84,92,95,97,100,105,125],"9":[28,55,65,84,92,95,97,100,105,125],"10":[28,55,65,84,92,95,97,100,105,125],"19":[28,55,65,84,92,95,97,100,105,125],"23":[28,55,65,84,92,95,97,100,105,125],"29":[28,55,65,84,92,95,97,100,105,125],"33":[28,55,65,84,92,95,97,100,105,125],"34":[28,55,65,84,92,95,97,100,105,125]},"packages/localhost-40359/assets/shield-alt-J5nzuCWH.js":{"8":[28,100,105]},"packages/@n8n/chat-hub/src/artifact.ts":{"3":[29,30,31,32,34,35]},"packages/@n8n/chat-hub/src/parser.ts":{"12":[29,30,31,32,34,35],"117":[29,30,31,32,34,35],"134":[29,30,31,32,34,35],"250":[29,30,31,32,34,35]},"packages/@n8n/design-system/src/components/N8nDropdownMenu/DropdownMenuSearch.vue":{"17":[30,31,32],"71":[30,31,32],"76":[30,31,32]},"packages/@n8n/utils/src/retry.ts":{"46":[29,30,31,32,34,35]},"packages/frontend/editor-ui/src/app/constants/localStorage.ts":{"22":[29,30,31,32,34,35],"24":[29,30,31,32,34,35],"28":[29,30,31,32,34,35]},"packages/frontend/editor-ui/src/app/layouts/ChatLayout.vue":{"8":[29,30,31,32,34,35],"10":[29,30,31,32,34,35]},"packages/frontend/editor-ui/src/features/ai/chatHub/ChatView.vue":{"76":[29,30,31,32,34,35],"84":[29,30,31,32,34,35],"91":[29,30,31,32,34,35],"94":[29,30,31,32,34,35],"96":[29,30,31,32,34,35],"99":[29,30,31,32,34,35],"101":[29,30,31,32,34,35],"106":[29,30,31,32,34,35],"108":[29,30,31,32,34,35],"134":[29,30],"141":[29,30,31,32,34,35],"146":[29,30,31,32,34,35],"150":[29,30,31,32,34,35],"182":[29,30,31,32,34,35],"214":[29,30,31,32,34,35],"218":[29,30,31,32,34,35],"225":[29,30,31,32,34],"236":[34],"245":[29,30,31,32,34,35],"253":[29,30,31,32,34,35],"258":[29,30,31,32,34,35],"267":[29,30,31,32,34,35],"293":[29,30,31,32,34,35],"308":[29,30,31,32,34,35],"323":[29,30,31,32,34,35],"335":[29,30,31,32,34,35],"363":[29,30,31,32,34,35],"364":[29,30,31,32,34,35],"382":[29,30,31,32,34,35],"400":[29,30,31,32,34,35],"408":[29,30,31,32,34,35],"417":[29,30,31,32,34,35],"428":[29,30,31,32,34,35],"448":[29,30,31,32,34,35],"464":[29,30,31,32,34,35],"472":[29,30,31,32,34,35],"483":[29,30,31,32,34,35],"517":[30],"525":[30],"553":[30],"576":[29,30,31,32,34],"600":[29,30,31,32,34],"604":[30],"628":[32],"707":[29,30,31,32,34,35],"736":[29,30,31,32,34,35],"748":[29,30,31,32,34,35],"769":[30]},"packages/frontend/editor-ui/src/features/ai/chatHub/chat.api.ts":{"32":[29,30,31,32,33,34,35],"44":[29,30,31,32,34,35],"79":[30],"120":[30],"160":[29,30,31,32,34,35],"183":[29,30,31,32,34,35],"232":[29,30,31,32,34,35],"240":[32],"248":[32],"256":[32],"265":[32],"299":[33],"309":[33],"322":[33],"340":[29],"395":[29,30,31,32,34,35],"399":[34]},"packages/frontend/editor-ui/src/features/ai/chatHub/chat.types.ts":{"114":[29,30]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/ChatAgentAvatar.vue":{"22":[29,30,31,32,34,35]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/ChatConversationHeader.vue":{"47":[29,30,31,32,34,35],"65":[29,30,31,32,34,35],"67":[29,30,31,32,34,35],"85":[29,30,31,32,34,35]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/ChatGreetings.vue":{"22":[29,30,31,32,34,35],"38":[32,35]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/ChatMessage.vue":{"68":[29,30,31,32,34,35],"96":[29,30,31,32,34,35],"116":[29,30,31,32,34,35],"117":[29,30,31,32,34,35],"144":[29,30,31,32,34,35],"149":[29,30,31,32,34,35],"150":[29,30,31,32,34,35],"159":[29,30,31,32,34,35],"169":[29,30,31,32,34,35],"170":[29],"181":[30],"188":[29,30,31,32,34,35],"190":[29,30,31,32,34,35],"198":[29,30,31,32,34,35],"200":[30],"208":[30],"276":[30],"290":[30],"295":[29,30,31,32,34,35],"296":[29,30,31,32,34,35],"307":[29,30,31,32,34,35],"309":[30],"317":[29,30,31,32,34,35],"320":[29,30,31,32,34,35],"389":[30],"397":[30],"407":[29],"419":[29,30,31,32,34,35]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/ChatMessageActions.vue":{"13":[29,30,31,32,34,35],"31":[30],"32":[30],"35":[29,30,31,32,34,35],"37":[29,30,31,32,34,35],"52":[29,30,31,32,34,35],"53":[29,30,31,32,34,35],"55":[30],"59":[30],"65":[29,30,31,32,34,35],"126":[30],"129":[30]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/ChatPrompt.vue":{"18":[29,30,31,32,34,35],"59":[29,30,31,32,34,35],"71":[29,30,31,32,34,35],"75":[29,30,31,32,34,35],"79":[29,30,31,32,34,35],"81":[29,30,31,32,34,35],"82":[29,30,31,32,34,35],"86":[29,30,31,32,34,35],"113":[29],"159":[29,30,31,32,34,35],"230":[29,30,31,32,34,35],"231":[29,30,31,32,34,35],"247":[29,30,31,32,34,35],"312":[29,30,31,32,34,35]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/ChatPromptCallouts.vue":{"19":[29,30,31,32,34,35],"35":[29,30],"45":[29,30],"62":[34],"72":[34],"81":[34]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/ChatPromptFull.vue":{"11":[29,30,31,32,34,35],"64":[29],"72":[29],"91":[29,30,31,32,34,35],"121":[29,30,31,32,34,35],"152":[29,30,31,32,34,35]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/ChatProviderAvatar.vue":{"13":[30,31,32],"23":[30,31,32]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/ChatSessionMenuItem.vue":{"20":[29,30,31,32,34,35],"34":[29,30,31,32,34,35],"44":[29,30,31,32,34,35],"87":[29,30,31,32,34,35],"89":[29,30,31,32,34,35],"101":[29,30,31,32,34,35],"122":[29,30,31,32,34,35]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/ChatSidebar.vue":{"15":[29,30,31,32,34,35],"45":[29,30,31,32,34,35],"55":[29,30,31,32,34,35],"56":[29,30,31,32,34,35],"65":[29,30,31,32,34,35]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/ChatSidebarContent.vue":{"25":[29,30,31,32,34,35],"32":[29,30,31,32,34,35],"39":[29,30,31,32,34,35],"43":[29,30,31,32,34,35],"45":[29,30,31,32,34,35],"57":[29,30,31,32,34,35],"69":[29,30,31,32,34,35],"80":[29,30,31,32,34,35],"138":[29,30,31,32,34,35],"141":[29,30,31,32,34,35],"156":[29,30,31,32,34,35],"176":[29,30,31,32,34,35],"181":[29,30,31,32,34,35],"184":[29,30,31,32,34,35],"195":[29,30,31,32,34,35],"199":[29,30,31,32,34,35]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/ChatSidebarLink.vue":{"26":[29,30,31,32,34,35],"45":[29,30,31,32,34,35],"62":[29,30,31,32,34,35]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/ChatStarter.vue":{"36":[29,30,31,32,34,35],"38":[29,30],"42":[29,30],"46":[29,30],"47":[29,30],"49":[29,30],"59":[29,30,31,32,34,35],"67":[29,30],"80":[29,30],"97":[29,30],"111":[29,30],"133":[29,30],"148":[29,30],"159":[29,30]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/CopyButton.vue":{"12":[29,30,31,32,34,35]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/ModelSelector.vue":{"83":[29,30,31,32,34,35],"89":[29,30,32,34,35],"90":[29,30,32,34,35],"98":[29,30,31,32,34,35],"108":[29,30,31,32,34,35],"110":[29,30,31,32,34,35],"114":[30],"118":[30,31],"149":[30,31,32],"180":[30,31,32],"203":[29,30,31,32,34,35],"225":[29,30,31,32,34],"245":[30,31,32],"254":[30,31,32],"271":[30,31,32]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/SkeletonMenuItem.vue":{"2":[29,30,31,32,34,35]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/ToolsSelector.vue":{"32":[34],"34":[29,30,31,32,34,35],"36":[34],"39":[34],"41":[34],"45":[34],"50":[29,30,31,32,34,35],"53":[34],"62":[34],"104":[34],"108":[34],"116":[34],"153":[29,30,31,32,34,35],"166":[29,30,31,32,34,35],"175":[29,30,31,32,34,35],"197":[34],"204":[34],"207":[34]},"packages/frontend/editor-ui/src/features/ai/chatHub/composables/useChatArtifacts.ts":{"6":[29,30,31,32,34,35],"12":[29,30,31,32,34,35],"13":[29,30,31,32,34,35],"21":[29,30,31,32,34,35],"24":[29,30,31,32,34,35],"31":[29,30,31,32,34,35],"81":[29,30,31,32,34,35],"82":[29,30,31,32,34,35]},"packages/frontend/editor-ui/src/features/ai/chatHub/composables/useChatCredentials.ts":{"38":[29,30,31,32,34,35],"43":[29,30,31,32,34,35],"47":[29,30,31,32,34,35],"49":[29,30,31,32,34,35],"66":[34],"72":[30,35],"81":[29,30,31,32,34,35],"83":[29,30,31,32,34,35],"100":[29,30,31,32,34,35],"102":[29,30,31,32,34,35]},"packages/frontend/editor-ui/src/features/ai/chatHub/composables/useChatInputFocus.ts":{"13":[29,30,31,32,34,35]},"packages/frontend/editor-ui/src/features/ai/chatHub/composables/useChatPushHandler.ts":{"31":[29,30,31,32,34,35],"42":[29,30,31,32,34,35],"50":[29,30,31,32,34,35],"62":[29,30,31,32,34,35],"93":[29,30,31,32],"118":[29,30,31,32,34,35],"133":[34,35],"148":[29,30,31,32,34,35],"155":[30],"162":[29,30,31,32,34,35],"179":[29,30,31,32,34,35],"211":[29,30,31,32,34,35],"220":[29,30,31,32,34,35],"222":[29,30,31,32,34,35],"233":[32],"268":[29,30,32,34]},"packages/frontend/editor-ui/src/features/ai/chatHub/composables/useChatSession.ts":{"29":[29,30,31,32,34,35],"37":[29,30,31,32,34,35],"41":[32],"46":[29,30,31,32,34,35],"47":[29,30,31,32,34,35],"51":[29,30,31,32,34,35],"71":[29,30,31,32,34,35],"78":[29,30],"85":[29,30,31,32,34,35],"95":[29,30,31,32,34,35],"111":[29,30,31,32,34,35],"112":[29,30,31,32,34,35]},"packages/frontend/editor-ui/src/features/ai/chatHub/composables/useCustomAgent.ts":{"7":[29,30,31,32,34,35],"8":[29,30,31,32,34],"18":[29,30,31,32,34,35]},"packages/frontend/editor-ui/src/features/ai/chatHub/composables/useDynamicCredentialsStatus.ts":{"29":[29,30,31,32,34,35],"35":[29,30,31,32,34,35],"36":[29,30,31,32,34,35],"170":[29,30,31,32,34,35]},"packages/frontend/editor-ui/src/features/ai/chatHub/composables/useFileDrop.ts":{"3":[29,30,31,32,34,35]},"packages/frontend/editor-ui/src/features/ai/chatHub/model-selector.utils.ts":{"113":[29,30,31,32,34,35],"127":[29,30,31,32,34,35],"137":[32,34],"165":[35],"177":[35],"194":[29,30,31,32,34,35],"218":[29,30,31,32,34,35],"255":[34],"262":[29,30,31,32,34,35],"269":[29,30,31,32,34,35],"279":[29,30,31,32,34,35],"329":[29,30,31,32,34,35],"371":[29,30,31,32,34,35],"388":[29,30,31,32,34,35]},"packages/localhost-45215/assets/_plugin-vue_export-helper-Da88TEg1.js":{"2":[30,35]},"packages/localhost-45215/assets/chunk-CC9Q-vWm.js":{"8":[30,35],"9":[30,35],"10":[30,35],"19":[30,35],"23":[30,35],"29":[30,35],"33":[30,35],"34":[30,35]},"packages/@n8n/design-system/src/v2/components/Select/Select.vue":{"45":[32,35,71],"63":[32,35,71],"69":[32,35,71],"84":[32,35,71],"91":[32,35,71],"99":[32,35,71],"106":[35,71],"108":[32,35,71],"110":[32,35,71],"126":[32,35,71],"137":[32,35,71],"144":[32,35,71],"147":[32,35,71],"158":[32,35,71],"166":[32,35,71],"167":[32,35,71],"169":[35,71],"181":[32,35],"182":[32,35],"185":[32,35],"188":[32,35]},"packages/@n8n/design-system/src/v2/components/Select/SelectItem.vue":{"10":[32,35,71],"13":[32,35,71],"17":[32,35,71],"21":[32,35,71],"25":[32,35,71],"32":[35],"33":[32,35,71],"35":[32,35,71],"39":[32,35,71],"46":[32,35,71]},"packages/@n8n/design-system/src/v2/utils/index.ts":{"6":[32,35,71],"12":[32,35,71]},"packages/frontend/editor-ui/src/features/ai/chatHub/ChatWorkflowAgentsView.vue":{"30":[35],"31":[35],"32":[35],"49":[35],"68":[35],"76":[35]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/ChatAgentCard.vue":{"24":[32,35],"30":[32,35],"36":[32],"43":[32,35],"53":[32,35],"56":[32,35],"74":[32],"76":[32]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/ChatAgentSearchSort.vue":{"8":[32,35],"18":[32,35],"27":[32,35],"45":[32,35],"57":[32,35]},"packages/frontend/editor-ui/src/features/collaboration/projects/components/ProjectCustomRolesUpgradeModal.vue":{"8":[35,71],"15":[35,71]},"packages/frontend/editor-ui/src/features/collaboration/projects/components/ProjectMembersRoleCell.vue":{"32":[35,71],"54":[35],"58":[35],"70":[35,71],"71":[35,71],"73":[35,71],"76":[35,71],"77":[35,71],"80":[35,71],"86":[35,71],"93":[35,71],"102":[35,71],"134":[35],"136":[35],"162":[35,71],"181":[35,71],"186":[35,71],"194":[35,71],"208":[35,71],"212":[35,71],"218":[35,71],"222":[35,71],"237":[35,71],"248":[35,71],"259":[35,71],"267":[35,71]},"packages/frontend/editor-ui/src/features/collaboration/projects/components/ProjectRoleContactAdminModal.vue":{"8":[35,71],"31":[35,71]},"packages/frontend/editor-ui/src/features/collaboration/projects/components/RoleHoverPopover.vue":{"14":[35,71],"51":[35,71]},"packages/localhost-34593/assets/_plugin-vue_export-helper-Da88TEg1.js":{"2":[44]},"packages/localhost-34593/assets/chunk-CC9Q-vWm.js":{"8":[44],"9":[44],"10":[44],"19":[44],"23":[44],"29":[44],"33":[44],"34":[44]},"packages/frontend/editor-ui/src/features/ai/instanceAi/components/ApprovalOptionList.vue":{"23":[45],"32":[45],"39":[45],"59":[45],"89":[45],"90":[45]},"packages/frontend/editor-ui/src/features/ai/instanceAi/components/ConfirmationPreview.vue":{"2":[45]},"packages/localhost-45131/assets/_plugin-vue_export-helper-Da88TEg1.js":{"2":[45]},"packages/localhost-45131/assets/chunk-CC9Q-vWm.js":{"8":[45],"9":[45],"10":[45],"19":[45],"23":[45],"29":[45],"33":[45],"34":[45]},"packages/localhost-44327/assets/_plugin-vue_export-helper-Da88TEg1.js":{"2":[29,31,32,33,34]},"packages/localhost-44327/assets/chunk-CC9Q-vWm.js":{"8":[29,31,32,33,34],"9":[29,31,32,33,34],"10":[29,31,32,33,34],"19":[29,31,32,33,34],"23":[29,31,32,33,34],"29":[29,31,32,33,34],"33":[29,31,32,33,34],"34":[29,31,32,33,34]},"packages/localhost-42485/assets/_plugin-vue_export-helper-Da88TEg1.js":{"2":[63]},"packages/localhost-42485/assets/chunk-CC9Q-vWm.js":{"8":[63],"9":[63],"10":[63],"19":[63],"23":[63],"29":[63],"33":[63],"34":[63]},"packages/frontend/editor-ui/src/features/core/auth/views/SettingsPersonalView.vue":{"90":[25,92,93],"94":[25,92,93],"98":[25,92,93],"109":[25,92,93],"113":[25,92,93],"116":[25,92,93],"119":[25,92,93],"123":[25,92,93],"127":[25,92,93],"131":[25,92,93],"160":[25,92,93],"162":[25,92,93],"205":[92,93],"209":[25,92,93],"214":[92,93],"230":[92,93],"237":[93],"267":[92,93],"282":[92,93],"290":[92,93],"298":[93],"317":[93],"337":[93],"359":[25,92,93],"360":[25,92,93],"399":[25,92,93],"408":[25,92,93],"414":[25,92,93],"449":[25,92,93]},"packages/frontend/editor-ui/src/features/settings/orchestration.ee/components/WorkerList.vue":{"25":[95],"35":[95],"39":[95],"41":[95],"49":[95],"60":[95]},"packages/frontend/editor-ui/src/features/settings/orchestration.ee/views/WorkerView.vue":{"30":[95],"33":[95]},"packages/@n8n/design-system/src/components/N8nDialog/Dialog.vue":{"95":[100],"99":[100],"108":[100]},"packages/@n8n/design-system/src/components/N8nDialog/DialogContent.vue":{"59":[100],"81":[100],"101":[100]},"packages/@n8n/design-system/src/components/N8nDialog/DialogOverlay.vue":{"15":[100]},"packages/frontend/editor-ui/src/app/components/RedactionMembersModal.vue":{"9":[100],"24":[100],"26":[100],"41":[100]},"packages/frontend/editor-ui/src/app/components/WorkflowSettings/WorkflowSettings.vue":{"68":[100],"209":[100],"216":[100],"219":[100],"222":[100],"223":[100],"224":[100],"225":[100],"228":[100],"233":[100],"243":[100],"247":[100],"249":[100],"255":[100],"262":[100],"277":[100],"281":[100],"285":[100],"286":[100],"294":[100],"313":[100],"329":[100],"345":[100],"379":[100],"381":[100],"386":[100],"390":[100],"401":[100],"415":[100],"440":[100],"470":[100],"494":[100],"518":[100],"541":[100],"564":[100],"591":[100],"647":[100],"807":[100],"958":[100],"973":[100],"981":[100],"984":[100],"992":[100],"995":[100],"999":[100],"1010":[100],"1011":[100],"1015":[100],"1020":[100],"1030":[100],"1032":[100],"1037":[100],"1112":[100],"1116":[100],"1122":[100],"1128":[100],"1130":[100],"1163":[100],"1167":[100],"1172":[100],"1179":[100],"1181":[100],"1192":[100],"1196":[100],"1201":[100],"1208":[100],"1210":[100],"1221":[100],"1225":[100],"1230":[100],"1237":[100],"1239":[100],"1250":[100],"1254":[100],"1259":[100],"1266":[100],"1268":[100],"1279":[100],"1283":[100],"1288":[100],"1295":[100],"1297":[100],"1308":[100],"1311":[100],"1334":[100],"1340":[100],"1348":[100],"1365":[100],"1381":[100],"1383":[100],"1405":[100],"1430":[100],"1436":[100],"1444":[100],"1469":[100],"1483":[100],"1485":[100],"1498":[100],"1502":[100],"1507":[100],"1597":[100],"1602":[100],"1608":[100],"1616":[100],"1618":[100],"1629":[100],"1719":[100]},"packages/frontend/editor-ui/src/features/ai/evaluation.ee/components/SetupWizard/SetupWizard.vue":{"19":[100],"38":[100],"49":[100],"93":[100],"112":[100],"117":[100],"127":[100],"235":[100],"262":[100]},"packages/frontend/editor-ui/src/features/ai/evaluation.ee/components/shared/StepHeader.vue":{"14":[100],"29":[100],"44":[100],"50":[100]},"packages/frontend/editor-ui/src/features/ai/evaluation.ee/components/shared/StepIndicator.vue":{"12":[100]},"packages/frontend/editor-ui/src/features/ai/evaluation.ee/composables/useWorkflowEvaluationState.ts":{"19":[100],"20":[100],"25":[100],"26":[100],"47":[100],"51":[100]},"packages/frontend/editor-ui/src/features/ai/evaluation.ee/views/EvaluationsRootView.vue":{"31":[100],"35":[100],"39":[100],"41":[100],"47":[100],"51":[100],"70":[100],"78":[100],"88":[100],"105":[100],"141":[100]},"packages/frontend/editor-ui/src/features/redaction-enforcement/composables/useRedactionEnforcementFeatureFlag.ts":{"8":[100]},"packages/frontend/editor-ui/src/app/utils/stringUtils.ts":{"8":[123,125],"16":[123,125],"21":[123,125],"22":[123,125]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/CredentialSelectorModal.vue":{"35":[31],"36":[31],"45":[31],"105":[31],"113":[31],"117":[31],"120":[31],"142":[31],"145":[31]},"packages/frontend/editor-ui/src/features/shared/tags/components/TagsManager/NoTagsView.vue":{"19":[137],"20":[137],"25":[137],"29":[137],"38":[137]},"packages/frontend/editor-ui/src/features/shared/tags/components/TagsManager/TagsManager.vue":{"29":[137],"42":[137],"46":[137],"48":[137],"49":[137],"51":[137],"55":[137],"59":[137],"63":[137],"67":[137],"117":[137],"118":[137],"130":[137],"133":[137],"148":[137],"161":[137],"183":[137]},"packages/frontend/editor-ui/src/features/shared/tags/components/TagsManager/TagsView/TagsTable.vue":{"33":[137],"42":[137],"46":[137],"73":[137],"84":[137],"88":[137],"92":[137],"93":[137],"100":[137],"101":[137],"109":[137],"118":[137],"119":[137],"127":[137],"132":[137],"145":[137],"147":[137],"148":[137],"150":[137],"169":[137],"171":[137],"181":[137],"183":[137],"234":[137]},"packages/frontend/editor-ui/src/features/shared/tags/components/TagsManager/TagsView/TagsTableHeader.vue":{"19":[137],"28":[137],"34":[137],"39":[137],"40":[137],"48":[137],"54":[137]},"packages/frontend/editor-ui/src/features/shared/tags/components/TagsManager/TagsView/TagsView.vue":{"13":[137],"33":[137],"47":[137],"49":[137],"50":[137],"57":[137],"58":[137],"72":[137],"81":[137],"108":[137],"112":[137],"116":[137],"118":[137],"128":[137],"133":[137],"138":[137],"141":[137],"152":[137],"173":[137]},"packages/frontend/editor-ui/src/features/shared/tags/components/TagsManager/WorkflowTagsManager.vue":{"10":[137],"14":[137],"15":[137],"17":[137],"27":[137],"62":[137],"83":[137]},"packages/localhost-46717/assets/_plugin-vue_export-helper-Da88TEg1.js":{"2":[137,139,142]},"packages/localhost-46717/assets/chunk-CC9Q-vWm.js":{"8":[137,139,142],"9":[137,139,142],"10":[137,139,142],"19":[137,139,142],"23":[137,139,142],"29":[137,139,142],"33":[137,139,142],"34":[137,139,142]},"packages/frontend/editor-ui/src/features/execution/executions/components/ExecutionsTime.vue":{"14":[142],"22":[142],"24":[142],"29":[142],"36":[142]},"packages/localhost-38831/assets/_plugin-vue_export-helper-Da88TEg1.js":{"2":[142,146]},"packages/localhost-38831/assets/chunk-CC9Q-vWm.js":{"8":[142,146],"9":[142,146],"10":[142,146],"19":[142,146],"23":[142,146],"29":[142,146],"33":[142,146],"34":[142,146]},"packages/@n8n/design-system/src/utils/markdown.ts":{"36":[146]},"packages/frontend/editor-ui/src/app/components/CollectionWorkflowCard.vue":{"12":[146],"13":[146],"17":[146]},"packages/frontend/editor-ui/src/app/views/WorkflowOnboardingView.vue":{"17":[146],"55":[146]},"packages/frontend/editor-ui/src/features/workflows/templates/components/TemplateFilters.vue":{"15":[146],"34":[146],"38":[146],"43":[146],"44":[146],"52":[146],"60":[146],"68":[146],"69":[146],"80":[146],"81":[146],"91":[146],"108":[146],"118":[146]},"packages/frontend/editor-ui/src/features/workflows/templates/components/TemplatesInfoCard.vue":{"21":[146],"29":[146]},"packages/frontend/editor-ui/src/features/workflows/templates/components/TemplatesInfoCarousel.vue":{"11":[146],"37":[146],"64":[146],"65":[146],"67":[146],"73":[146],"74":[146],"76":[146],"82":[146],"95":[146],"101":[146],"112":[146],"113":[146],"115":[146]},"packages/frontend/editor-ui/src/features/workflows/templates/recommendations/components/RecommendedTemplateCard.vue":{"35":[146],"38":[146],"43":[146],"46":[146],"71":[146],"82":[146],"101":[146],"109":[146],"121":[146],"137":[146],"148":[146],"177":[146],"187":[146]},"packages/frontend/editor-ui/src/features/workflows/templates/views/TemplatesSearchView.vue":{"51":[146],"54":[146],"61":[146],"65":[146],"69":[146],"73":[146],"87":[146],"105":[146],"106":[146],"110":[146],"115":[146],"125":[146],"129":[146],"137":[146],"149":[146],"156":[146],"166":[146],"173":[146],"178":[146],"192":[146],"196":[146],"206":[146],"220":[146],"258":[146],"277":[146],"285":[146],"297":[146],"310":[146],"319":[146],"330":[146],"379":[146],"386":[146],"410":[146]},"packages/frontend/editor-ui/src/features/workflows/templates/views/TemplatesWorkflowView.vue":{"35":[146],"39":[146],"41":[146],"58":[146],"68":[146],"69":[146],"80":[146],"102":[146],"119":[146],"126":[146],"160":[146],"165":[146]},"packages/@n8n/design-system/src/components/AskAssistantChat/messages/CodeDiffMessage.vue":{"19":[2],"20":[2],"32":[2],"40":[2],"41":[2]},"packages/@n8n/design-system/src/components/CodeDiff/CodeDiff.vue":{"10":[2],"43":[2],"48":[2],"85":[2],"93":[2],"120":[2],"121":[2],"137":[2],"138":[2]},"packages/frontend/editor-ui/src/features/ai/assistant/composables/useCodeDiff.ts":{"39":[2],"41":[2],"62":[2],"66":[2],"72":[2],"85":[2],"131":[2]},"packages/localhost-33645/assets/_plugin-vue_export-helper-Da88TEg1.js":{"2":[2,13,18,58,71,87,91,104,118,122,131]},"packages/localhost-33645/assets/chunk-CC9Q-vWm.js":{"8":[2,13,18,58,71,87,91,104,118,122,131],"9":[2,13,18,58,71,87,91,104,118,122,131],"10":[2,13,18,58,71,87,91,104,118,122,131],"19":[2,13,18,58,71,87,91,104,118,122,131],"23":[2,13,18,58,71,87,91,104,118,122,131],"29":[2,13,18,58,71,87,91,104,118,122,131],"33":[2,13,18,58,71,87,91,104,118,122,131],"34":[2,13,18,58,71,87,91,104,118,122,131]},"packages/localhost-33883/assets/_plugin-vue_export-helper-Da88TEg1.js":{"2":[9]},"packages/localhost-33883/assets/chunk-CC9Q-vWm.js":{"8":[9],"9":[9],"10":[9],"19":[9],"23":[9],"29":[9],"33":[9],"34":[9]},"packages/@n8n/design-system/src/components/CanvasPill/CanvasPill.vue":{"8":[5,10],"9":[5,10]},"packages/@n8n/design-system/src/components/CanvasThinkingPill/CanvasThinkingPill.vue":{"17":[5,10],"23":[5,10],"27":[5,10],"30":[5,10]},"packages/frontend/editor-ui/src/features/ai/assistant/assistant.types.ts":{"424":[5,10],"441":[5],"460":[5,10],"466":[5,10],"470":[5],"494":[5],"507":[5],"513":[5],"525":[5],"531":[5],"537":[5],"547":[5],"553":[5],"557":[5],"563":[5],"575":[5,10],"581":[5]},"packages/frontend/editor-ui/src/features/ai/assistant/builder.utils.ts":{"20":[5,10],"24":[5,10],"28":[5,10],"136":[5,10],"147":[5,10]},"packages/frontend/editor-ui/src/features/ai/assistant/components/HubSwitcher.vue":{"12":[5,10],"22":[5,10],"29":[5,10],"36":[5,10]},"packages/localhost-35193/assets/_plugin-vue_export-helper-Da88TEg1.js":{"2":[10]},"packages/localhost-35193/assets/chunk-CC9Q-vWm.js":{"8":[10],"9":[10],"10":[10],"19":[10],"23":[10],"29":[10],"33":[10],"34":[10]},"packages/localhost-34043/assets/_plugin-vue_export-helper-Da88TEg1.js":{"2":[49]},"packages/localhost-34043/assets/chunk-CC9Q-vWm.js":{"8":[49],"9":[49],"10":[49],"19":[49],"23":[49],"29":[49],"33":[49],"34":[49]},"packages/localhost-41601/assets/_plugin-vue_export-helper-Da88TEg1.js":{"2":[49]},"packages/localhost-41601/assets/chunk-CC9Q-vWm.js":{"8":[49],"9":[49],"10":[49],"19":[49],"23":[49],"29":[49],"33":[49],"34":[49]},"packages/localhost-46125/assets/_plugin-vue_export-helper-Da88TEg1.js":{"2":[49]},"packages/localhost-46125/assets/chunk-CC9Q-vWm.js":{"8":[49],"9":[49],"10":[49],"19":[49],"23":[49],"29":[49],"33":[49],"34":[49]},"packages/frontend/editor-ui/src/features/ai/chatHub/ChatPersonalAgentsView.vue":{"38":[32],"39":[32],"40":[32],"42":[32],"51":[32],"66":[32],"78":[32],"79":[32],"87":[32],"110":[32],"129":[32],"133":[32],"140":[32],"145":[32],"158":[32],"159":[32]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/AgentEditorModal.vue":{"116":[32],"119":[32],"125":[32],"126":[32],"127":[32],"132":[32],"138":[32],"145":[32],"152":[32],"156":[32],"162":[32],"172":[32],"195":[32],"197":[32],"210":[32],"238":[32],"243":[32],"426":[32],"435":[32],"449":[32],"471":[32],"485":[32],"520":[32],"540":[32],"555":[32],"571":[32],"581":[32],"600":[32],"687":[32],"690":[32]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/SuggestedPromptsEditor.vue":{"9":[32],"51":[32],"92":[32]},"packages/frontend/editor-ui/src/features/settings/communityNodes/communityNodes.utils.ts":{"10":[58]},"packages/frontend/editor-ui/src/features/settings/communityNodes/components/nodeCreator/CommunityNodeFooter.vue":{"15":[58],"32":[58],"52":[58],"57":[58],"72":[58],"73":[58],"79":[58],"80":[58]},"packages/frontend/editor-ui/src/features/settings/communityNodes/composables/useInstallNode.ts":{"38":[58,87],"60":[87]},"packages/localhost-43795/assets/_plugin-vue_export-helper-Da88TEg1.js":{"2":[59]},"packages/localhost-43795/assets/chunk-CC9Q-vWm.js":{"8":[59],"9":[59],"10":[59],"19":[59],"23":[59],"29":[59],"33":[59],"34":[59]},"packages/frontend/editor-ui/src/app/utils/formatters/textFormatter.ts":{"8":[71]},"packages/frontend/editor-ui/src/features/settings/communityNodes/components/CommunityPackageCard.vue":{"43":[87],"47":[87],"55":[87],"63":[87],"80":[87],"98":[87],"103":[87],"105":[87],"108":[87],"120":[87],"135":[87],"142":[87],"151":[87],"168":[87],"176":[87]},"packages/frontend/editor-ui/src/features/settings/communityNodes/components/CommunityPackageInstallModal.vue":{"32":[87],"39":[87],"47":[87],"54":[87],"78":[87],"82":[87],"86":[87],"98":[87],"111":[87],"119":[87],"134":[87],"167":[87],"172":[87],"178":[87]},"packages/frontend/editor-ui/src/features/settings/communityNodes/components/CommunityPackageManageConfirmModal.vue":{"32":[87],"54":[87],"57":[87],"68":[87],"69":[87],"72":[87],"108":[87],"112":[87],"120":[87],"124":[87],"147":[87],"151":[87],"190":[87],"192":[87],"203":[87],"216":[87],"226":[87],"232":[87],"240":[87],"252":[87],"253":[87],"261":[87],"270":[87]},"packages/frontend/editor-ui/src/features/settings/communityNodes/views/SettingsCommunityNodesView.vue":{"40":[87],"44":[87],"48":[87],"56":[87],"77":[87],"82":[87],"94":[87],"104":[87],"110":[87],"117":[87],"122":[87],"126":[87],"130":[87],"178":[87]},"packages/frontend/editor-ui/src/features/integrations/logStreaming.ee/components/EventDestinationCard.vue":{"44":[90,91],"52":[90,91],"56":[90,91],"72":[90,91],"76":[90,91],"87":[91],"110":[91],"135":[90,91],"141":[90,91],"144":[90,91],"148":[90,91],"153":[90,91],"157":[90,91],"160":[90,91]},"packages/frontend/editor-ui/src/features/integrations/logStreaming.ee/components/EventDestinationSettingsModal.vue":{"80":[90,91],"107":[90,91],"121":[90,91],"125":[90,91],"129":[90],"133":[90],"137":[90,91],"139":[90,91],"143":[90,91],"161":[90,91],"165":[90,91],"185":[90,91],"189":[90,91],"204":[90,91],"208":[90,91],"217":[90,91],"223":[90,91],"231":[90,91],"235":[90,91],"261":[90,91],"300":[90],"305":[91],"329":[91],"341":[90,91],"361":[90,91],"391":[90,91],"399":[90,91],"415":[90,91],"432":[90,91],"474":[90,91],"484":[90,91],"492":[90,91],"494":[90,91],"506":[90,91],"515":[90,91]},"packages/frontend/editor-ui/src/features/integrations/logStreaming.ee/logStreaming.store.ts":{"44":[90,91],"53":[90,91],"81":[90,91],"99":[90,91],"105":[90,91],"128":[90,91],"136":[90,91],"151":[90,91],"155":[90,91],"163":[90,91],"220":[90,91],"226":[91],"231":[90,91],"248":[90,91],"265":[90],"276":[90,91],"280":[90,91],"284":[91]},"packages/frontend/editor-ui/src/features/integrations/logStreaming.ee/logStreaming.utils.ts":{"8":[90,91]},"packages/frontend/editor-ui/src/features/integrations/logStreaming.ee/views/SettingsLogStreamingView.vue":{"37":[90,91],"45":[90,91],"50":[90,91],"54":[90,91],"58":[90,91],"60":[90,91],"73":[90,91],"75":[91],"88":[90,91],"94":[90,91],"98":[90,91],"103":[91],"108":[90,91],"133":[90,91],"137":[90,91],"152":[91],"161":[91],"182":[90,91],"204":[90,91],"208":[90,91],"214":[91],"215":[91],"230":[90,91],"248":[91]},"packages/localhost-33601/assets/_plugin-vue_export-helper-Da88TEg1.js":{"2":[90]},"packages/localhost-33601/assets/chunk-CC9Q-vWm.js":{"8":[90],"9":[90],"10":[90],"19":[90],"23":[90],"29":[90],"33":[90],"34":[90]},"packages/frontend/editor-ui/src/features/core/auth/components/MfaSetupModal.vue":{"26":[93],"57":[93],"61":[93],"68":[93],"77":[93],"90":[93],"105":[93],"133":[93],"152":[93],"155":[93],"174":[93],"178":[93],"183":[93],"184":[93],"187":[93],"203":[93],"212":[93],"231":[93],"235":[93],"236":[93],"240":[93],"241":[93],"244":[93],"246":[93],"263":[93]},"packages/frontend/editor-ui/src/features/core/auth/components/PromptMfaCodeModal.vue":{"12":[93],"31":[93],"48":[93],"52":[93],"54":[93],"67":[93],"78":[93]},"packages/frontend/editor-ui/src/features/core/auth/views/MfaView.vue":{"63":[93],"86":[93],"107":[93],"116":[93],"117":[93],"129":[93],"155":[93],"164":[93],"189":[93],"194":[93],"204":[93],"225":[93]},"packages/frontend/editor-ui/src/features/core/auth/views/SignoutView.vue":{"14":[93],"23":[93]},"packages/localhost-32853/assets/_plugin-vue_export-helper-Da88TEg1.js":{"2":[93]},"packages/localhost-32853/assets/chunk-CC9Q-vWm.js":{"8":[93],"9":[93],"10":[93],"19":[93],"23":[93],"29":[93],"33":[93],"34":[93]},"packages/localhost-33645/assets/shield-alt-J5nzuCWH.js":{"8":[104]},"packages/frontend/editor-ui/src/app/utils/json-schema.ts":{"5":[118],"9":[118],"12":[118],"25":[118],"32":[118],"35":[118]},"packages/@n8n/design-system/src/components/N8nPagination/Pagination.vue":{"10":[33]},"packages/@n8n/design-system/src/components/N8nSwitch/Switch.vue":{"10":[33],"14":[33],"21":[33],"22":[33],"23":[33],"30":[33],"40":[33]},"packages/frontend/editor-ui/src/features/ai/chatHub/SettingsChatHubView.vue":{"26":[33],"42":[33],"44":[33],"46":[33],"54":[33],"72":[33],"93":[33],"108":[33]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/ChatProvidersTable.vue":{"25":[33],"47":[33],"56":[33],"65":[33],"75":[33],"81":[33],"89":[33],"93":[33],"116":[33],"123":[33],"136":[33],"140":[33],"163":[33],"172":[33],"176":[33],"190":[33],"193":[33],"199":[33],"204":[33]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/ProviderSettingsModal.vue":{"123":[33],"127":[33],"141":[33],"156":[33],"164":[33],"184":[33],"217":[33],"227":[33],"229":[33],"240":[33],"243":[33],"250":[33],"254":[33],"265":[33],"279":[33],"308":[33],"319":[33],"372":[33],"375":[33],"398":[33],"401":[33]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/ResourceMapper/MappingFields.vue":{"49":[131],"74":[131],"83":[131],"85":[131],"86":[131],"101":[131],"104":[131],"117":[131],"118":[131],"121":[131],"122":[131],"131":[131],"132":[131],"134":[131],"161":[131],"164":[131],"178":[131],"182":[131],"186":[131],"196":[131],"204":[131],"214":[131],"238":[131],"252":[131],"267":[131],"279":[131],"283":[131],"287":[131],"295":[131],"314":[131],"327":[131],"365":[131],"396":[131],"441":[131]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/ResourceMapper/MatchingColumnsSelect.vue":{"27":[131],"39":[131],"50":[131],"51":[131],"62":[131],"63":[131],"69":[131],"84":[131],"103":[131],"117":[131],"130":[131],"156":[131],"169":[131],"182":[131],"191":[131],"200":[131],"202":[131],"206":[131],"211":[131]},"packages/frontend/editor-ui/src/features/ai/assistant/components/Agent/BuilderSetupCard.vue":{"28":[5],"53":[5],"57":[5],"59":[5],"82":[5],"89":[5],"95":[5],"99":[5],"103":[5],"104":[5],"105":[5],"109":[5],"110":[5],"111":[5],"112":[5],"114":[5],"120":[5],"136":[5],"149":[5],"182":[5],"189":[5],"205":[5],"206":[5],"209":[5],"218":[5],"219":[5]},"packages/frontend/editor-ui/src/features/ai/assistant/components/Agent/BuilderSetupWizard.vue":{"14":[5],"39":[5],"43":[5],"47":[5],"51":[5],"55":[5],"59":[5],"75":[5],"86":[5],"91":[5],"96":[5],"102":[5],"104":[5],"107":[5],"115":[5],"122":[5],"131":[5],"162":[5],"175":[5],"187":[5],"204":[5],"210":[5]},"packages/frontend/editor-ui/src/features/ai/assistant/components/Agent/ChatVersionCard.vue":{"14":[5],"44":[5],"60":[5],"110":[5]},"packages/frontend/editor-ui/src/features/ai/assistant/components/Agent/CreditsSettingsDropdown.vue":{"22":[5],"72":[5]},"packages/frontend/editor-ui/src/features/ai/assistant/components/Agent/ExecuteMessage.vue":{"34":[5],"51":[5],"58":[5],"87":[5],"136":[5],"146":[5],"191":[5],"223":[5]},"packages/frontend/editor-ui/src/features/ai/assistant/composables/useBuilderExecution.ts":{"22":[5],"55":[5]},"packages/frontend/editor-ui/src/features/ai/assistant/composables/useBuilderSetupCards.ts":{"10":[5],"21":[5],"26":[5],"30":[5],"45":[5],"59":[5],"60":[5],"65":[5],"67":[5],"71":[5],"74":[5],"77":[5],"89":[5],"90":[5],"104":[5],"110":[5],"157":[5]},"packages/frontend/editor-ui/src/features/setupPanel/components/TriggerExecuteButton.vue":{"6":[5],"18":[5],"22":[5],"30":[5]},"packages/frontend/editor-ui/src/features/setupPanel/components/cards/SetupCardBody.vue":{"22":[5],"57":[5],"61":[5],"63":[5],"70":[5],"77":[5],"94":[5],"97":[5],"106":[5],"110":[5],"111":[5],"113":[5],"124":[5],"135":[5],"136":[5],"183":[5],"197":[5],"200":[5],"206":[5]},"packages/frontend/editor-ui/src/features/setupPanel/components/cards/SetupCardSection.vue":{"9":[5],"13":[5],"16":[5]},"packages/frontend/editor-ui/src/features/setupPanel/composables/groupSetupCards.ts":{"20":[5],"81":[5]},"packages/frontend/editor-ui/src/features/setupPanel/composables/useTriggerExecution.ts":{"18":[5],"38":[5],"40":[5],"46":[5],"70":[5],"77":[5],"81":[5],"87":[5],"91":[5]},"packages/frontend/editor-ui/src/features/setupPanel/composables/useWebhookUrls.ts":{"21":[5],"25":[5],"27":[5],"33":[5],"35":[5],"83":[5]},"packages/frontend/editor-ui/src/features/setupPanel/composables/useWorkflowSetupState.ts":{"46":[5],"63":[5],"70":[5],"117":[5],"120":[5],"156":[5],"194":[5],"222":[5],"227":[5],"291":[5],"293":[5],"294":[5],"300":[5],"324":[5],"347":[5],"348":[5],"355":[5],"356":[5],"359":[5],"360":[5],"370":[5],"384":[5],"398":[5],"411":[5],"428":[5],"429":[5],"431":[5],"435":[5],"443":[5],"462":[5],"465":[5],"471":[5],"472":[5],"507":[5],"616":[5],"632":[5],"635":[5],"658":[5],"659":[5],"661":[5],"663":[5],"794":[5],"805":[5],"831":[5],"862":[5]},"packages/localhost-45111/assets/_plugin-vue_export-helper-Da88TEg1.js":{"2":[5,21,25,26,39,74,82,99,103]},"packages/localhost-45111/assets/chunk-CC9Q-vWm.js":{"8":[5,21,25,26,39,74,82,99,103],"9":[5,21,25,26,39,74,82,99,103],"10":[5,21,25,26,39,74,82,99,103],"19":[5,21,25,26,39,74,82,99,103],"23":[5,21,25,26,39,74,82,99,103],"29":[5,21,25,26,39,74,82,99,103],"33":[5,21,25,26,39,74,82,99,103],"34":[5,21,25,26,39,74,82,99,103]},"packages/localhost-45111/assets/shield-alt-J5nzuCWH.js":{"8":[21,103]},"packages/localhost-45747/assets/_plugin-vue_export-helper-Da88TEg1.js":{"2":[38]},"packages/localhost-45747/assets/chunk-CC9Q-vWm.js":{"8":[38],"9":[38],"10":[38],"19":[38],"23":[38],"29":[38],"33":[38],"34":[38]},"packages/localhost-41307/assets/_plugin-vue_export-helper-Da88TEg1.js":{"2":[52]},"packages/localhost-41307/assets/chunk-CC9Q-vWm.js":{"8":[52],"9":[52],"10":[52],"19":[52],"23":[52],"29":[52],"33":[52],"34":[52]},"packages/@n8n/design-system/src/components/N8nIcon/nodes/filter.svg":{"11":[74,114]},"packages/localhost-36729/assets/_plugin-vue_export-helper-Da88TEg1.js":{"2":[78]},"packages/localhost-36729/assets/chunk-CC9Q-vWm.js":{"8":[78],"9":[78],"10":[78],"19":[78],"23":[78],"29":[78],"33":[78],"34":[78]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/ToolListItem.vue":{"25":[34],"32":[34],"38":[34],"48":[34],"51":[34],"58":[34],"68":[34],"79":[34],"94":[34]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/ToolsManagerModal.vue":{"41":[34],"42":[34],"46":[34],"53":[34],"69":[34],"92":[34],"94":[34],"102":[34],"107":[34],"108":[34],"114":[34],"121":[34],"135":[34],"147":[34],"151":[34],"208":[34],"231":[34],"241":[34],"250":[34],"270":[34],"273":[34],"295":[34],"308":[34],"317":[34],"325":[34],"340":[34],"348":[34],"352":[34],"373":[34],"374":[34]},"packages/frontend/editor-ui/src/features/shared/toolConfig/NodeToolSettingsContent.vue":{"65":[34],"66":[34],"68":[34],"78":[34],"82":[34],"86":[34],"96":[34],"97":[34],"102":[34],"110":[34],"111":[34],"114":[34],"128":[34],"136":[34],"143":[34],"153":[34],"165":[34],"174":[34],"183":[34],"219":[34],"235":[34],"236":[34],"297":[34],"298":[34],"313":[34],"317":[34],"318":[34],"326":[34],"353":[34],"382":[34]},"packages/localhost-37013/assets/_plugin-vue_export-helper-Da88TEg1.js":{"2":[103,107,108,110,114,123,133]},"packages/localhost-37013/assets/chunk-CC9Q-vWm.js":{"8":[103,107,108,110,114,123,133],"9":[103,107,108,110,114,123,133],"10":[103,107,108,110,114,123,133],"19":[103,107,108,110,114,123,133],"23":[103,107,108,110,114,123,133],"29":[103,107,108,110,114,123,133],"33":[103,107,108,110,114,123,133],"34":[103,107,108,110,114,123,133]},"packages/localhost-37013/assets/shield-alt-J5nzuCWH.js":{"8":[103,110]},"packages/@n8n/design-system/src/components/N8nCircleLoader/CircleLoader.vue":{"3":[110],"15":[110],"16":[110],"18":[110],"22":[110],"23":[110],"24":[110],"28":[110]},"packages/frontend/editor-ui/src/features/shared/editors/plugins/codemirror/typescript/client/completions.ts":{"19":[110],"30":[110]},"packages/frontend/editor-ui/src/features/shared/editors/plugins/codemirror/typescript/client/linter.ts":{"4":[110],"8":[110]},"packages/localhost-33649/assets/_plugin-vue_export-helper-Da88TEg1.js":{"2":[133,136]},"packages/localhost-33649/assets/chunk-CC9Q-vWm.js":{"8":[133,136],"9":[133,136],"10":[133,136],"19":[133,136],"23":[133,136],"29":[133,136],"33":[133,136],"34":[133,136]}}} \ No newline at end of file +{"specs":["tests/e2e/api/discovery.spec.ts","tests/e2e/building-blocks/user-service.spec.ts","tests/e2e/journeys/admin-views-executions-list.spec.ts","tests/e2e/projects/project-settings.spec.ts","tests/e2e/sharing/access-control.spec.ts","tests/e2e/sharing/credential-visibility.spec.ts","tests/e2e/sharing/workflow-sharing.spec.ts","tests/e2e/settings/users/users.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/builder-setup-wizard.spec.ts","tests/e2e/ai/chat-session.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/ai/workflow-builder.spec.ts","tests/e2e/api/wait-form-resume.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/app-config/security-notifications.spec.ts","tests/e2e/app-config/versions.spec.ts","tests/e2e/auth/admin-smoke.spec.ts","tests/e2e/auth/authenticated.spec.ts","tests/e2e/auth/oidc.spec.ts","tests/e2e/auth/signin.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/node-details-configuration.spec.ts","tests/e2e/building-blocks/workflow-entry-points.spec.ts","tests/e2e/capabilities/proxy-server.spec.ts","tests/e2e/capabilities/task-runner.spec.ts","tests/e2e/chat-hub/chat-hub-attachment.spec.ts","tests/e2e/chat-hub/chat-hub-basic.spec.ts","tests/e2e/chat-hub/chat-hub-chat-user.spec.ts","tests/e2e/chat-hub/chat-hub-personal-agent.spec.ts","tests/e2e/chat-hub/chat-hub-settings.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/credentials/global.spec.ts","tests/e2e/credentials/oauth.spec.ts","tests/e2e/data-tables/details.spec.ts","tests/e2e/data-tables/tables.spec.ts","tests/e2e/mcp-registry/mcp-registry.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/email-send-node.spec.ts","tests/e2e/nodes/form-trigger-node.spec.ts","tests/e2e/nodes/http-request-node.spec.ts","tests/e2e/nodes/if-node.spec.ts","tests/e2e/nodes/kafka-nodes.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-advanced.spec.ts","tests/e2e/projects/folders-basic.spec.ts","tests/e2e/projects/folders-operations.spec.ts","tests/e2e/projects/projects-move-resources.spec.ts","tests/e2e/projects/projects.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-4462-template-setup-experiment.spec.ts","tests/e2e/regression/AI-1401-sub-nodes-input-panel.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-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/sentry/sentry-baseline.spec.ts","tests/e2e/settings/community-nodes/community-nodes.spec.ts","tests/e2e/settings/environments/source-control.spec.ts","tests/e2e/settings/environments/variables.spec.ts","tests/e2e/settings/external-secrets/secret-providers-connections-ui.spec.ts","tests/e2e/settings/log-streaming/log-streaming-ui-e2e.spec.ts","tests/e2e/settings/log-streaming/log-streaming.spec.ts","tests/e2e/settings/personal/personal.spec.ts","tests/e2e/settings/personal/two-factor-authentication.spec.ts","tests/e2e/settings/workers/workers.spec.ts","tests/e2e/sharing/credential-sharing.spec.ts","tests/e2e/workflows/checklist/production-checklist.spec.ts","tests/e2e/workflows/demo-diff.spec.ts","tests/e2e/workflows/demo-executable-chat-trigger.spec.ts","tests/e2e/workflows/editor/canvas/actions.spec.ts","tests/e2e/workflows/editor/canvas/canvas-nodes.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/node-groups.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/executions-list-infinite-scroll.spec.ts","tests/e2e/workflows/editor/execution/inject-previous.spec.ts","tests/e2e/workflows/editor/execution/logs.spec.ts","tests/e2e/workflows/editor/execution/partial.spec.ts","tests/e2e/workflows/editor/expressions/inline.spec.ts","tests/e2e/workflows/editor/expressions/mapping.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/ndv-data-display.spec.ts","tests/e2e/workflows/editor/ndv/ndv-floating-nodes.spec.ts","tests/e2e/workflows/editor/ndv/ndv-parameters.spec.ts","tests/e2e/workflows/editor/ndv/paired-item.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/routing.spec.ts","tests/e2e/workflows/editor/subworkflows/debugging.spec.ts","tests/e2e/workflows/editor/subworkflows/extraction.spec.ts","tests/e2e/workflows/editor/subworkflows/workflow-selector.spec.ts","tests/e2e/workflows/editor/tags.spec.ts","tests/e2e/workflows/editor/viewer-permissions.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/list/import.spec.ts","tests/e2e/workflows/list/workflows.spec.ts","tests/e2e/workflows/templates/credentials-setup.spec.ts","tests/e2e/workflows/templates/templates.spec.ts","tests/e2e/api/binary-data-xss.spec.ts","tests/e2e/api/form-endpoint-isolation.spec.ts","tests/e2e/api/webhook-external.spec.ts","tests/e2e/api/workflow-publication-service.spec.ts","tests/e2e/auth/password-reset.spec.ts","tests/e2e/auth/token-exchange.spec.ts","tests/e2e/dynamic-credentials/execution-status.spec.ts","tests/e2e/settings/external-secrets/aws-secrets-manager.spec.ts","tests/e2e/settings/log-streaming/log-streaming-observability.spec.ts","tests/e2e/credentials/api-operations.spec.ts","tests/e2e/dynamic-credentials/resolver-deletion.spec.ts","tests/e2e/ai/rag-callout.spec.ts","tests/e2e/nodes/n8n-trigger.spec.ts","tests/e2e/api/webhook-isolation.spec.ts","tests/e2e/dynamic-credentials/external-user-trigger.spec.ts","tests/e2e/workflows/editor/subworkflows/wait.spec.ts","tests/e2e/mcp/mcp-oauth.spec.ts","tests/e2e/mcp/mcp-service.spec.ts","tests/e2e/app-config/env-feature-flags.spec.ts","tests/e2e/nodes/mcp-trigger.spec.ts","tests/e2e/workflows/editor/subworkflows/subworkflow-version-resolution.spec.ts","tests/e2e/settings/external-secrets/secret-providers-connections.spec.ts","tests/e2e/nodes/code-node-api.spec.ts"],"files":{"packages/@n8n/api-types/src/dto/api-keys/create-api-key-request.dto.ts":{"5":[0,1,2,3,4,5,6]},"packages/@n8n/api-types/src/dto/api-keys/update-api-key-request.dto.ts":{"7":[0,1,2,3,4,5,6]},"packages/@n8n/api-types/src/dto/invitation/invite-users-request.dto.ts":{"12":[0,1,2,3,7,4,5,6]},"packages/@n8n/api-types/src/schemas/password.schema.ts":{"13":"b://////////////////////8PAAAA","18":[0,1,2,3,7,4,5,6],"21":[0,1,2,3,7,4,5,6]},"packages/@n8n/api-types/src/schemas/scopes.schema.ts":{"14":[0,1,2,3,4,5,6]},"packages/@n8n/api-types/src/zod-class.ts":{"32":"b:g9smCX9cApAwBBQEAFAAAYD0HwAA","39":"b:g9smCX9cApAwBBQEAFAAAYD0HwAA","44":"b:g9smCX9cApAwBBQEAFAAAYD0HwAA","48":"b:g9smCX9cApAwBBQEAFAAAYD0HwAA","52":"b:g9smCX9cApAwBBQEAFAAAYD0HwAA"},"packages/@n8n/db/src/entities/types-db.ts":{"311":"b:A9sGCX94ApEwBBQEAFAAAYD0PAAA","323":"b:A9sGCX94ApEwBBQEAFAAAYD0PAAA","461":"b:A9sGCX94ApEwBBQEAFAAAYD0PAAA"},"packages/@n8n/db/src/repositories/role.repository.ts":{"9":"b:/9sWK398ApFwBNQEAFAAAYgUUgAA","13":"b:/9sWK398ApFwBNQEAFAAAYgUUgAA","18":"b:/9sWK398ApFwBNQEAFAAAYgUUgAA","36":"b:/9sWK398ApFwBNQEAFAAAYgUUgAA","52":"b:/9sWK398ApFwBNQEAFAAAYgUUgAA","63":"b:/9sWK398ApFwBNQEAFAAAYgUUgAA","72":"b:/9sWK398ApFwBNQEAFAAAYgUUgAA","80":"b:/9sWK398ApFwBNQEAFAAAYgUUgAA","106":"b:/9sWK398ApFwBNQEAFAAAYgUUgAA","109":"b:/9sWK398ApFwBNQEAFAAAYgUUgAA","112":"b:/9sWK398ApFwBNQEAFAAAYgUUgAA","126":"b:/9sWK398ApFwBNQEAFAAAYgUUgAA","129":"b:/9sWK398ApFwBNQEAFAAAYgUUgAA","158":"b:/9sWK398ApFwBNQEAFAAAYgUUgAA","165":"b:/9sWK398ApFwBNQEAFAAAYgUUgAA","172":"b:/9sWK398ApFwBNQEAFAAAYgUUgAA","179":"b:/9sWK398ApFwBNQEAFAAAYgUUgAA","212":"b:/9sWK398ApFwBNQEAFAAAYgUUgAA","216":"b:/9sWK398ApFwBNQEAFAAAYgUUgAA"},"packages/@n8n/db/src/repositories/user.repository.ts":{"11":"b:/9sWqX98UpHwBHQEClCAEYgUoQEA","15":"b:/9sWqX98UpHwBHQEClCAEYgUoQEA","27":"b:/9sWqX98UpHwBHQEClCAEYgUoQEA","51":"b:/9sWqX98UpHwBHQEClCAEYgUoQEA","55":"b:/9sWqX98UpHwBHQEClCAEYgUoQEA","59":"b:/9sWqX98UpHwBHQEClCAEYgUoQEA","63":"b:/9sWqX98UpHwBHQEClCAEYgUoQEA","70":"b:/9sWqX98UpHwBHQEClCAEYgUoQEA","74":"b:/9sWqX98UpHwBHQEClCAEYgUoQEA","85":"b:/9sWqX98UpHwBHQEClCAEYgUoQEA","92":"b:/9sWqX98UpHwBHQEClCAEYgUoQEA","103":"b:/9sWqX98UpHwBHQEClCAEYgUoQEA","110":"b:/9sWqX98UpHwBHQEClCAEYgUoQEA","114":"b:/9sWqX98UpHwBHQEClCAEYgUoQEA","158":"b:/9sWqX98UpHwBHQEClCAEYgUoQEA","179":"b:/9sWqX98UpHwBHQEClCAEYgUoQEA","192":"b:/9sWqX98UpHwBHQEClCAEYgUoQEA","200":"b:/9sWqX98UpHwBHQEClCAEYgUoQEA","205":"b:/9sWqX98UpHwBHQEClCAEYgUoQEA","264":"b:/9sWqX98UpHwBHQEClCAEYgUoQEA","290":"b:/9sWqX98UpHwBHQEClCAEYgUoQEA","309":"b:/9sWqX98UpHwBHQEClCAEYgUoQEA","331":"b:/9sWqX98UpHwBHQEClCAEYgUoQEA","342":"b:/9sWqX98UpHwBHQEClCAEYgUoQEA"},"packages/@n8n/db/src/subscribers/user-subscriber.ts":{"12":"b:H4AQAAAAApAAIAAmAEAAgYDgEA8A","15":"b:H4AQAAAAApAAIAAmAEAAgYDgEA8A","19":"b:H4AQAAAAApAAIAAmAEAAgYDgEA8A","24":"b:H4AQAAAAApAAIAAmAEAAgYDgEA8A"},"packages/@n8n/decorators/src/redactable.ts":{"14":"b:A9smCX9YApAwBBQEAFAAAYD0HwAA","21":"b:A9smCX9YApAwBBQEAFAAAYD0HwAA","46":"b:A9smCX9YApAwBBQEAFAAAYD0HwAA","47":"b:A9smCX9YApAwBBQEAFAAAYD0HwAA","53":"b:A9smCX9YApAwBBQEAFAAAYD0HwAA","54":"b:A9smCX9YApAwBBQEAFAAAYD0HwAA"},"packages/@n8n/permissions/src/index.ts":{"20":"b:A9smi394ApGwBFQECFAAAYj0PwAA","21":"b:A9smi394ApGwBFQECFAAAYj0PwAA","24":"b:A9smi394ApGwBFQECFAAAYj0PwAA","26":"b:A9smi394ApGwBFQECFAAAYj0PwAA"},"packages/@n8n/permissions/src/public-api-permissions.ee.ts":{"183":[0,1,2,3,7,4,5,6],"190":[0,1,2,3,7,4,5,6],"197":[0,1,2,3,7,4,5,6],"200":[0,1,2,3,7,4,5,6]},"packages/@n8n/permissions/src/types.ee.ts":{"78":[0,1,2,3,4,5,6],"132":[0,1,2,3,4,5,6]},"packages/@n8n/permissions/src/utilities/combine-scopes.ee.ts":{"16":"b:+///////////////////////PgAA","18":"b:+///////////////////////PgAA","23":"b:A9smiX94ApGwBFQECFAAAYj0PgAA","26":"b:A9smiX94ApGwBFQECFAAAYj0PgAA"},"packages/@n8n/permissions/src/utilities/get-global-scopes.ee.ts":{"8":"b:A9smCX9YApAwBBQEAFAAAYD0HwAA","9":"b:A9smCX9YApAwBBQEAFAAAYD0HwAA"},"packages/@n8n/permissions/src/utilities/get-role-scopes.ee.ts":{"5":"b:+///////////////////////PgAA","16":"b:+///////////////////////PgAA","19":"b:A9smiX94ApGwBFQECFAAAYj0PgAA","30":"b:A9smiX94ApGwBFQECFAAAYj0PgAA","36":"b:A9smiX94ApGwBFQECFAAAYj0PgAA","38":"b:A9smiX94ApGwBFQECFAAAYj0PgAA"},"packages/@n8n/permissions/src/utilities/has-global-scope.ee.ts":{"10":"b:A9smCX94ApEwBBQEAFAAAYD0HgAA"},"packages/@n8n/permissions/src/utilities/has-scope.ee.ts":{"11":"b:+///////////////////////PgYA","20":"b:+/+///////////8/////////PgYA","21":"b:+///////////////////////PgYA"},"packages/cli/src/auth/auth-handler.registry.ts":{"7":"b:A9smCX9YApAwBBQEAFAAAYD0HwAA","20":"b:A9smCX9YApAwBBQEAFAAAYD0HwAA","30":"b:A9smCX9YApAwBBQEAFAAAYD0HwAA","82":"b:A9smCX9YApAwBBQEAFAAAYD0HwAA","94":"b:A9smCX9YApAwBBQEAFAAAYD0HwAA","112":"b:A9smCX9YApAwBBQEAFAAAYD0HwAA"},"packages/cli/src/auth/auth.service.ts":{"64":"b:A9smCX94ArXwDBQEAlQCEYD0HwAA","101":"b:A9smCX94ArXwDBQEAlQCEYD0HwAA","106":"b:A9smCX94ArXwDBQEAlQCEYD0HwAA","164":"b:A9smCX94ArXwDBQEAlQCEYD0HwAA","173":"b:A9smCX94ArXwDBQEAlQCEYD0HwAA","181":"b:A9smCX94ArXwDBQEAlQCEYD0HwAA","185":"b:A9smCX94ArXwDBQEAlQCEYD0HwAA","189":"b:A9smCX94ArXwDBQEAlQCEYD0HwAA","193":"b:A9smCX94ArXwDBQEAlQCEYD0HwAA","209":"b:A9smCX94ArXwDBQEAlQCEYD0HwAA","234":"b:A9smCX94ArXwDBQEAlQCEYD0HwAA","255":"b:A9smCX94ArXwDBQEAlQCEYD0HwAA","262":"b:A9smCX94ArXwDBQEAlQCEYD0HwAA","288":"b:A9smCX94ArXwDBQEAlQCEYD0HwAA","298":"b:A9smCX94ArXwDBQEAlQCEYD0HwAA","314":"b:A9smCX94ArXwDBQEAlQCEYD0HwAA","331":"b:A9smCX94ArXwDBQEAlQCEYD0HwAA","362":"b:A9smCX94ArXwDBQEAlQCEYD0HwAA","392":"b:A9smCX94ArXwDBQEAlQCEYD0HwAA","397":"b:A9smCX94ArXwDBQEAlQCEYD0HwAA","407":"b:A9smCX94ArXwDBQEAlQCEYD0HwAA","441":"b:A9smCX94ArXwDBQEAlQCEYD0HwAA","449":"b:A9smCX94ArXwDBQEAlQCEYD0HwAA","454":"b:A9smCX94ArXwDBQEAlQCEYD0HwAA","464":"b:A9smCX94ArXwDBQEAlQCEYD0HwAA"},"packages/cli/src/auth/handlers/email.auth-handler.ts":{"16":"b:A9smCX9YApAwBBQEAFAAAYD0HwAA","23":"b:A9smCX9YApAwBBQEAFAAAYD0HwAA","35":"b:A9smCX9YApAwBBQEAFAAAYD0HwAA"},"packages/cli/src/controller.registry.ts":{"35":"b:J/uGif94ApEwBHQFAFAAAYD0PDAA","44":"b:J/uGif94ApEwBHQFAFAAAYD0PDAA","50":"b:J/uGif94ApEwBHQFAFAAAYD0PDAA","62":"b:J/uGif94ApEwBHQFAFAAAYD0PDAA","88":"b:J/uGif94ApEwBHQFAFAAAYD0PDAA","114":"b:J/uGif94ApEwBHQFAFAAAYD0PDAA","119":"b:J/uGif94ApEwBHQFAFAAAYD0PDAA","142":"b:J/uGif94ApEwBHQFAFAAAYD0PDAA","222":"b:J/uGif94ApEwBHQFAFAAAYD0PDAA","223":"b:J/uGif94ApEwBHQFAFAAAYD0PDAA","232":"b:J/uGif94ApEwBHQFAFAAAYD0PDAA","233":"b:J/uGif94ApEwBHQFAFAAAYD0PDAA"},"packages/cli/src/controllers/api-keys.controller.ts":{"26":[0,1,2,3,4,5,6],"36":[0,1,2,3,4,5,6],"43":[0,1,2,3,4,5,6],"67":[0,1,2,3,4,5,6],"80":[0,1,2,3,4,5,6],"95":[0,1,2,3,4,5,6],"112":[0,1,2,3,4,5,6]},"packages/cli/src/controllers/auth.controller.ts":{"40":"b:A9s2K394ApFwBNQEAFAAAYj0HwAA","67":"b:A9s2K394ApFwBNQEAFAAAYj0HwAA","109":"b:A9s2K394ApFwBNQEAFAAAYj0HwAA","115":"b:A9s2K394ApFwBNQEAFAAAYj0HwAA","131":"b:A9s2K394ApFwBNQEAFAAAYj0HwAA","164":"b:A9s2K394ApFwBNQEAFAAAYj0HwAA","192":"b:A9s2K394ApFwBNQEAFAAAYj0HwAA","205":"b:A9s2K394ApFwBNQEAFAAAYj0HwAA","250":"b:A9s2K394ApFwBNQEAFAAAYj0HwAA","259":"b:A9s2K394ApFwBNQEAFAAAYj0HwAA","278":"b:A9s2K394ApFwBNQEAFAAAYj0HwAA"},"packages/cli/src/controllers/e2e.controller.ts":{"182":"b:A9s2K394ApEwBNQMAFAAAYj0H0IA","195":"b:A9s2K394ApEwBNQMAFAAAYj0H0IA","198":"b:A9s2K394ApEwBNQMAFAAAYj0H0IA","209":"b:A9s2K394ApEwBNQMAFAAAYj0H0IA","213":"b:A9s2K394ApEwBNQMAFAAAYj0H0IA","224":"b:A9s2K394ApEwBNQMAFAAAYj0H0IA","230":"b:A9s2K394ApEwBNQMAFAAAYj0H0IA","236":"b:A9s2K394ApEwBNQMAFAAAYj0H0IA","242":"b:A9s2K394ApEwBNQMAFAAAYj0H0IA","248":"b:A9s2K394ApEwBNQMAFAAAYj0H0IA","253":"b:A9s2K394ApEwBNQMAFAAAYj0H0IA","292":"b:A9s2K394ApEwBNQMAFAAAYj0H0IA","311":"b:A9s2K394ApEwBNQMAFAAAYj0H0IA","345":"b:A9s2K394ApEwBNQMAFAAAYj0H0IA","380":"b:A9s2K394ApEwBNQMAFAAAYj0H0IA","393":"b:A9s2K394ApEwBNQMAFAAAYj0H0IA","397":"b:A9s2K394ApEwBNQMAFAAAYj0H0IA","398":"b:A9s2K394ApEwBNQMAFAAAYj0H0IA","401":"b:A9s2K394ApEwBNQMAFAAAYj0H0IA","412":"b:A9s2K394ApEwBNQMAFAAAYj0H0IA","419":"b:A9s2K394ApEwBNQMAFAAAYj0H0IA","430":"b:A9s2K394ApEwBNQMAFAAAYj0H0IA","440":"b:A9s2K394ApEwBNQMAFAAAYj0H0IA","452":"b:A9s2K394ApEwBNQMAFAAAYj0H0IA","532":"b:A9s2K394ApEwBNQMAFAAAYj0H0IA","538":"b:A9s2K394ApEwBNQMAFAAAYj0H0IA","539":"b:A9s2K394ApEwBNQMAFAAAYj0H0IA","547":"b:A9s2K394ApEwBNQMAFAAAYj0H0IA","558":"b:A9s2K394ApEwBNQMAFAAAYj0H0IA","563":"b:A9s2K394ApEwBNQMAFAAAYj0H0IA","572":"b:A9s2K394ApEwBNQMAFAAAYj0H0IA","593":"b:A9s2K394ApEwBNQMAFAAAYj0H0IA","600":"b:A9s2K394ApEwBNQMAFAAAYj0H0IA","668":"b:A9s2K394ApEwBNQMAFAAAYj0H0IA"},"packages/cli/src/controllers/invitation.controller.ts":{"25":[0,1,2,3,7,4,5,6],"44":[0,1,2,3,7,4,5,6],"76":[0,1,2,3,7,4,5,6],"95":[0,1,2,3,7,4,5,6],"120":[0,1,2,3,7,4,5,6],"164":[0,1,2,3,7,4,5,6]},"packages/cli/src/eventbus/event-message-classes/abstract-event-message.ts":{"10":"b:A9smCX9YApAwBBQEAFAAAYD0HwAA","12":"b:A9smCX9YApAwBBQEAFAAAYD0HwAA","16":"b:A9smCX9YApAwBBQEAFAAAYD0HwAA","28":"b:A9smCX9YApAwBBQEAFAAAYD0HwAA","48":"b:A9smCX9YApAwBBQEAFAAAYD0HwAA","59":"b:A9smCX9YApAwBBQEAFAAAYD0HwAA","72":"b:A9smCX9YApAwBBQEAFAAAYD0HwAA","101":"b:A9smCX9YApAwBBQEAFAAAYD0HwAA","108":"b:A9smCX9YApAwBBQEAFAAAYD0HwAA","113":"b:A9smCX9YApAwBBQEAFAAAYD0HwAA","124":"b:A9smCX9YApAwBBQEAFAAAYD0HwAA","135":"b:A9smCX9YApAwBBQEAFAAAYD0HwAA","139":"b:A9smCX9YApAwBBQEAFAAAYD0HwAA"},"packages/cli/src/eventbus/event-message-classes/event-message-confirm.ts":{"19":"b:A9smCX9YApAwBBQEAFAAAYD0HwAA","25":"b:A9smCX9YApAwBBQEAFAAAYD0HwAA","36":"b:A9smCX9YApAwBBQEAFAAAYD0HwAA"},"packages/cli/src/eventbus/message-event-bus-writer/message-event-bus-log-writer.ts":{"67":"b:A9smCX9YApAwBBQEAFAAAYD0HwAA","72":"b:A9smCX9YApAwBBQEAFAAAYD0HwAA","82":"b:A9smCX9YApAwBBQEAFAAAYD0HwAA","110":"b:A9smCX9YApAwBBQEAFAAAYD0HwAA","116":"b:A9smCX9YApAwBBQEAFAAAYD0HwAA","122":"b:A9smCX9YApAwBBQEAFAAAYD0HwAA","126":"b:A9smCX9YApAwBBQEAFAAAYD0HwAA","132":"b:A9smCX9YApAwBBQEAFAAAYD0HwAA","142":"b:A9smCX9YApAwBBQEAFAAAYD0HwAA","153":"b:A9smCX9YApAwBBQEAFAAAYD0HwAA","162":"b:A9smCX9YApAwBBQEAFAAAYD0HwAA","169":"b:A9smCX9YApAwBBQEAFAAAYD0HwAA","175":"b:A9smCX9YApAwBBQEAFAAAYD0HwAA","184":"b:A9smCX9YApAwBBQEAFAAAYD0HwAA","205":"b:A9smCX9YApAwBBQEAFAAAYD0HwAA","213":"b:A9smCX9YApAwBBQEAFAAAYD0HwAA","241":"b:A9smCX9YApAwBBQEAFAAAYD0HwAA","291":"b:A9smCX9YApAwBBQEAFAAAYD0HwAA","326":"b:A9smCX9YApAwBBQEAFAAAYD0HwAA","333":"b:A9smCX9YApAwBBQEAFAAAYD0HwAA","341":"b:A9smCX9YApAwBBQEAFAAAYD0HwAA","345":"b:A9smCX9YApAwBBQEAFAAAYD0HwAA","353":"b:A9smCX9YApAwBBQEAFAAAYD0HwAA","366":"b:A9smCX9YApAwBBQEAFAAAYD0HwAA","369":"b:A9smCX9YApAwBBQEAFAAAYD0HwAA","380":"b:A9smCX9YApAwBBQEAFAAAYD0HwAA","406":"b:A9smCX9YApAwBBQEAFAAAYD0HwAA","410":"b:A9smCX9YApAwBBQEAFAAAYD0HwAA","414":"b:A9smCX9YApAwBBQEAFAAAYD0HwAA","418":"b:A9smCX9YApAwBBQEAFAAAYD0HwAA","422":"b:A9smCX9YApAwBBQEAFAAAYD0HwAA","433":"b:A9smCX9YApAwBBQEAFAAAYD0HwAA"},"packages/cli/src/events/relays/event-relay.ts":{"8":"b:A9smCX9YApAwBBQEAFAAAYD0HwAA","10":"b:A9smCX9YApAwBBQEAFAAAYD0HwAA","18":"b:A9smCX9YApAwBBQEAFAAAYD0HwAA"},"packages/cli/src/events/relays/log-streaming.event-relay.ts":{"15":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","19":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","34":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","42":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","44":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","45":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","46":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","47":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","48":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","49":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","50":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","51":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","52":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","53":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","54":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","55":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","56":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","57":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","58":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","59":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","60":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","61":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","62":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","63":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","64":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","65":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","66":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","67":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","68":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","69":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","70":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","71":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","72":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","73":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","74":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","75":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","76":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","77":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","78":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","79":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","80":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","81":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","83":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","84":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","86":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","88":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","90":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","91":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","93":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","94":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","95":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","96":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","97":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","98":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","99":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","100":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","101":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","102":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","103":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","104":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","105":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","106":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","107":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","108":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","109":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","110":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","111":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","112":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","113":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","114":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","115":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","116":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","117":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","118":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","119":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","120":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","121":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","122":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","123":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","124":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","125":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","126":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","127":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","128":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","129":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","130":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","131":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","132":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","133":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","134":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","135":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","136":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","143":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","155":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","163":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","171":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","179":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","192":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","210":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","223":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","244":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","280":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","344":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","363":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","380":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","392":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","412":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","437":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","445":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","453":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","461":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","469":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","477":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","489":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","497":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","504":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","519":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","527":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","535":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","549":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","557":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","569":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","581":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","589":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","597":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","608":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","616":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","623":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","637":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","645":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","653":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","664":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","673":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","682":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","691":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","700":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","709":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","718":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","732":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","743":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","751":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","762":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","769":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","778":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","796":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","811":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","821":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","839":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","854":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","881":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","890":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","897":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","904":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","911":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","918":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","925":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","932":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","939":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","946":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","953":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","960":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","967":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","974":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","985":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","992":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","1003":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","1010":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","1017":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","1029":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","1069":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","1084":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","1091":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","1098":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","1105":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","1112":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","1119":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","1126":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","1137":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","1155":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","1170":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","1184":"b://8+yX9/ErfwXHQWjlwCFbr2P68B","1197":"b://8+yX9/ErfwXHQWjlwCFbr2P68B"},"packages/cli/src/license.ts":{"43":"b:A9s2KX94EpGwBBQECFAAAYj0HwAA","53":"b:A9s2KX94EpGwBBQECFAAAYj0HwAA","72":"b:A9s2KX94EpGwBBQECFAAAYj0HwAA","73":"b:A9s2KX94EpGwBBQECFAAAYj0HwAA","75":"b:A9s2KX94EpGwBBQECFAAAYj0HwAA","76":"b:A9s2KX94EpGwBBQECFAAAYj0HwAA","78":"b:A9s2KX94EpGwBBQECFAAAYj0HwAA","79":"b:A9s2KX94EpGwBBQECFAAAYj0HwAA","81":"b:A9s2KX94EpGwBBQECFAAAYj0HwAA","82":"b:A9s2KX94EpGwBBQECFAAAYj0HwAA","84":"b:A9s2KX94EpGwBBQECFAAAYj0HwAA","85":"b:A9s2KX94EpGwBBQECFAAAYj0HwAA","86":"b:A9s2KX94EpGwBBQECFAAAYj0HwAA","110":"b:A9s2KX94EpGwBBQECFAAAYj0HwAA","112":"b:A9s2KX94EpGwBBQECFAAAYj0HwAA","131":"b:A9s2KX94EpGwBBQECFAAAYj0HwAA","146":"b:A9s2KX94EpGwBBQECFAAAYj0HwAA","151":"b:A9s2KX94EpGwBBQECFAAAYj0HwAA","156":"b:A9s2KX94EpGwBBQECFAAAYj0HwAA","158":"b:A9s2KX94EpGwBBQECFAAAYj0HwAA","163":"b:A9s2KX94EpGwBBQECFAAAYj0HwAA","180":"b:A9s2KX94EpGwBBQECFAAAYj0HwAA","182":"b:A9s2KX94EpGwBBQECFAAAYj0HwAA","190":"b:A9s2KX94EpGwBBQECFAAAYj0HwAA","203":"b:A9s2KX94EpGwBBQECFAAAYj0HwAA","213":"b:A9s2KX94EpGwBBQECFAAAYj0HwAA","222":"b:A9s2KX94EpGwBBQECFAAAYj0HwAA","231":"b:A9s2KX94EpGwBBQECFAAAYj0HwAA","241":"b:A9s2KX94EpGwBBQECFAAAYj0HwAA","254":"b:A9s2KX94EpGwBBQECFAAAYj0HwAA","258":"b:A9s2KX94EpGwBBQECFAAAYj0HwAA","262":"b:A9s2KX94EpGwBBQECFAAAYj0HwAA","267":"b:A9s2KX94EpGwBBQECFAAAYj0HwAA","272":"b:A9s2KX94EpGwBBQECFAAAYj0HwAA","277":"b:A9s2KX94EpGwBBQECFAAAYj0HwAA","282":"b:A9s2KX94EpGwBBQECFAAAYj0HwAA","287":"b:A9s2KX94EpGwBBQECFAAAYj0HwAA","292":"b:A9s2KX94EpGwBBQECFAAAYj0HwAA","297":"b:A9s2KX94EpGwBBQECFAAAYj0HwAA","302":"b:A9s2KX94EpGwBBQECFAAAYj0HwAA","307":"b:A9s2KX94EpGwBBQECFAAAYj0HwAA","312":"b:A9s2KX94EpGwBBQECFAAAYj0HwAA","317":"b:A9s2KX94EpGwBBQECFAAAYj0HwAA","322":"b:A9s2KX94EpGwBBQECFAAAYj0HwAA","327":"b:A9s2KX94EpGwBBQECFAAAYj0HwAA","332":"b:A9s2KX94EpGwBBQECFAAAYj0HwAA","337":"b:A9s2KX94EpGwBBQECFAAAYj0HwAA","342":"b:A9s2KX94EpGwBBQECFAAAYj0HwAA","347":"b:A9s2KX94EpGwBBQECFAAAYj0HwAA","352":"b:A9s2KX94EpGwBBQECFAAAYj0HwAA","357":"b:A9s2KX94EpGwBBQECFAAAYj0HwAA","362":"b:A9s2KX94EpGwBBQECFAAAYj0HwAA","367":"b:A9s2KX94EpGwBBQECFAAAYj0HwAA","372":"b:A9s2KX94EpGwBBQECFAAAYj0HwAA","377":"b:A9s2KX94EpGwBBQECFAAAYj0HwAA","381":"b:A9s2KX94EpGwBBQECFAAAYj0HwAA","385":"b:A9s2KX94EpGwBBQECFAAAYj0HwAA","389":"b:A9s2KX94EpGwBBQECFAAAYj0HwAA","399":"b:A9s2KX94EpGwBBQECFAAAYj0HwAA","409":"b:A9s2KX94EpGwBBQECFAAAYj0HwAA","412":"b:A9s2KX94EpGwBBQECFAAAYj0HwAA","416":"b:A9s2KX94EpGwBBQECFAAAYj0HwAA","423":"b:A9s2KX94EpGwBBQECFAAAYj0HwAA","428":"b:A9s2KX94EpGwBBQECFAAAYj0HwAA","433":"b:A9s2KX94EpGwBBQECFAAAYj0HwAA","438":"b:A9s2KX94EpGwBBQECFAAAYj0HwAA","443":"b:A9s2KX94EpGwBBQECFAAAYj0HwAA","451":"b:A9s2KX94EpGwBBQECFAAAYj0HwAA","455":"b:A9s2KX94EpGwBBQECFAAAYj0HwAA","459":"b:A9s2KX94EpGwBBQECFAAAYj0HwAA","467":"b:A9s2KX94EpGwBBQECFAAAYj0HwAA","475":"b:A9s2KX94EpGwBBQECFAAAYj0HwAA","490":"b:A9s2KX94EpGwBBQECFAAAYj0HwAA","505":"b:A9s2KX94EpGwBBQECFAAAYj0HwAA","514":"b:A9s2KX94EpGwBBQECFAAAYj0HwAA","519":"b:A9s2KX94EpGwBBQECFAAAYj0HwAA","524":"b:A9s2KX94EpGwBBQECFAAAYj0HwAA","528":"b:A9s2KX94EpGwBBQECFAAAYj0HwAA","534":"b:A9s2KX94EpGwBBQECFAAAYj0HwAA","537":"b:A9s2KX94EpGwBBQECFAAAYj0HwAA"},"packages/cli/src/permissions.ee/check-access.ts":{"27":"b:f9sGCX94ApEwBBSEAFAAAYj0PAAA","65":"b:f9sGCX94ApEwBBSEAFAAAYj0PAAA","85":"b:f9sGCX94ApEwBBSEAFAAAYj0PAAA","120":"b:f9sGCX94ApEwBBSEAFAAAYj0PAAA","130":"b:f9sGCX94ApEwBBSEAFAAAYj0PAAA"},"packages/cli/src/posthog/index.ts":{"28":"b:A9smCX9YApAwBBQEAFAAAYD0HwAA","33":"b:A9smCX9YApAwBBQEAFAAAYD0HwAA","39":"b:A9smCX9YApAwBBQEAFAAAYD0HwAA","45":"b:A9smCX9YApAwBBQEAFAAAYD0HwAA","51":"b:A9smCX9YApAwBBQEAFAAAYD0HwAA","65":"b:A9smCX9YApAwBBQEAFAAAYD0HwAA","91":"b:A9smCX9YApAwBBQEAFAAAYD0HwAA","103":"b:A9smCX9YApAwBBQEAFAAAYD0HwAA","117":"b:A9smCX9YApAwBBQEAFAAAYD0HwAA","145":"b:A9smCX9YApAwBBQEAFAAAYD0HwAA","165":"b:A9smCX9YApAwBBQEAFAAAYD0HwAA"},"packages/cli/src/public-api/index.ts":{"23":[0,145,1,2,3,4,5,6],"30":[0,145,1,2,3,4,5,6],"35":[0,145,1,2,3,4,5,6],"46":[0,145,1,2,3,4,5,6],"65":[0,145,1,2,3,4,5,6],"73":[0,145,1,2,3,4,5,6],"75":[0,145,1,2,3,4,5,6],"76":[0,145,1,2,3,4,5,6],"85":[0,145,1,2,3,4,5,6],"89":[0,145,1,2,3,4,5,6],"116":[0,145,1,2,3,4,5,6],"120":[0,145,1,2,3,4,5,6],"124":[0,145,1,2,3,4,5,6],"135":[0,145,1,2,3,4,5,6],"157":[0,145,1,2,3,4,5,6],"174":[0,145,1,2,3,4,5,6],"179":[0,145,1,2,3,4,5,6],"196":[0,145,1,2,3,4,5,6],"210":[0,145,1,2,3,4,5,6],"214":[0,145,1,2,3,4,5,6],"216":[0,145,1,2,3,4,5,6],"229":[0,145,1,2,3,4,5,6]},"packages/cli/src/public-api/v1/handlers/audit/audit.handler.ts":{"15":[0,145,1,2,3,4,5,6],"16":[0,145,1,2,3,4,5,6]},"packages/cli/src/public-api/v1/handlers/credentials/credentials.handler.ts":{"60":[0,145,1,2,3,4,5,6],"73":[0,145,1,2,3,4,5,6],"98":[0,145,1,2,3,4,5,6],"112":[0,145,1,2,3,4,5,6],"133":[0,145,1,2,3,4,5,6],"143":[0,145,1,2,3,4,5,6],"180":[0,145,1,2,3,4,5,6],"195":[0,145,1,2,3,4,5,6],"219":[0,145,1,2,3,4,5,6],"230":[0,145,1,2,3,4,5,6]},"packages/cli/src/public-api/v1/handlers/credentials/credentials.mapper.ts":{"8":[0,145,1,2,3,4,5,6]},"packages/cli/src/public-api/v1/handlers/credentials/credentials.middleware.ts":{"21":[0,145,1,2,3,4,5,6],"28":[0,145,1,2,3,4,5,6],"36":[0,145,1,2,3,4,5,6],"41":[0,145,1,2,3,4,5,6],"55":[0,145,1,2,3,4,5,6],"70":[0,145,1,2,3,4,5,6],"89":[0,145,1,2,3,4,5,6]},"packages/cli/src/public-api/v1/handlers/credentials/credentials.service.ts":{"30":[0,145,1,2,3,4,5,6],"34":[0,145,1,2,3,4,5,6],"55":[0,145,1,2,3,4,5,6],"60":[0,145,1,2,3,4,5,6],"61":[0,145,1,2,3,4,5,6],"70":[0,145,1,2,3,4,5,6],"77":[0,145,1,2,3,4,5,6],"81":[0,145,1,2,3,4,5,6],"98":[0,145,1,2,3,4,5,6],"137":[0,145,1,2,3,4,5,6],"178":[0,145,1,2,3,4,5,6],"243":[0,145,1,2,3,4,5,6],"256":[0,145,1,2,3,4,5,6],"271":[0,145,1,2,3,4,5,6],"277":[0,145,1,2,3,4,5,6],"292":[0,145,1,2,3,4,5,6],"307":[0,145,1,2,3,4,5,6],"308":[0,145,1,2,3,4,5,6],"311":[0,145,1,2,3,4,5,6],"325":[0,145,1,2,3,4,5,6],"336":[0,145,1,2,3,4,5,6],"462":[0,145,1,2,3,4,5,6],"470":[0,145,1,2,3,4,5,6]},"packages/cli/src/public-api/v1/handlers/data-tables/data-tables.columns.handler.ts":{"14":[0,145,1,2,3,4,5,6],"36":[0,145,1,2,3,4,5,6],"46":[0,145,1,2,3,4,5,6],"70":[0,145,1,2,3,4,5,6],"81":[0,145,1,2,3,4,5,6]},"packages/cli/src/public-api/v1/handlers/data-tables/data-tables.handler.ts":{"29":[0,145,1,2,3,4,5,6],"50":[0,145,1,2,3,4,5,6],"72":[0,145,1,2,3,4,5,6],"109":[0,145,1,2,3,4,5,6],"127":[0,145,1,2,3,4,5,6],"152":[0,145,1,2,3,4,5,6],"180":[0,145,1,2,3,4,5,6],"215":[0,145,1,2,3,4,5,6]},"packages/cli/src/public-api/v1/handlers/data-tables/data-tables.rows.handler.ts":{"25":[0,145,1,2,3,4,5,6],"40":[0,145,1,2,3,4,5,6],"63":[0,145,1,2,3,4,5,6],"106":[0,145,1,2,3,4,5,6],"135":[0,145,1,2,3,4,5,6],"166":[0,145,1,2,3,4,5,6],"197":[0,145,1,2,3,4,5,6]},"packages/cli/src/public-api/v1/handlers/data-tables/data-tables.service.ts":{"9":[0,145,1,2,3,4,5,6],"32":[0,145,1,2,3,4,5,6],"33":[0,145,1,2,3,4,5,6],"41":[0,145,1,2,3,4,5,6]},"packages/cli/src/public-api/v1/handlers/discover/discover.handler.ts":{"18":[0,145,1,2,3,4,5,6],"30":[0,145,1,2,3,4,5,6]},"packages/cli/src/public-api/v1/handlers/discover/discover.service.ts":{"51":[0,145,1,2,3,4,5,6],"55":[0,145,1,2,3,4,5,6],"63":[0,145,1,2,3,4,5,6],"76":[0,145,1,2,3,4,5,6],"88":[0,145,1,2,3,4,5,6],"95":[0,145,1,2,3,4,5,6],"156":[0,145,1,2,3,4,5,6],"164":[0,145,1,2,3,4,5,6],"206":[0,145,1,2,3,4,5,6],"211":[0,145,1,2,3,4,5,6],"215":[0,145,1,2,3,4,5,6],"223":[0,145,1,2,3,4,5,6],"247":[0,145,1,2,3,4,5,6]},"packages/cli/src/public-api/v1/handlers/executions/executions.handler.ts":{"30":[0,145,1,2,3,4,5,6],"41":[0,145,1,2,3,4,5,6],"61":[0,145,1,2,3,4,5,6],"105":[0,145,1,2,3,4,5,6],"151":[0,145,1,2,3,4,5,6],"172":[0,145,1,2,3,4,5,6],"232":[0,145,1,2,3,4,5,6],"260":[0,145,1,2,3,4,5,6],"283":[0,145,1,2,3,4,5,6],"285":[0,145,1,2,3,4,5,6],"314":[0,145,1,2,3,4,5,6],"336":[0,145,1,2,3,4,5,6],"338":[0,145,1,2,3,4,5,6]},"packages/cli/src/public-api/v1/handlers/executions/executions.service.ts":{"9":[0,145,1,2,3,4,5,6],"10":[0,145,1,2,3,4,5,6],"18":[0,145,1,2,3,4,5,6],"27":[0,145,1,2,3,4,5,6],"32":[0,145,1,2,3,4,5,6],"48":[0,145,1,2,3,4,5,6]},"packages/cli/src/public-api/v1/handlers/folders/folders.handler.ts":{"23":[0,145,1,2,3,4,5,6],"46":[0,145,1,2,3,4,5,6],"66":[0,145,1,2,3,4,5,6],"85":[0,145,1,2,3,4,5,6],"105":[0,145,1,2,3,4,5,6],"123":[0,145,1,2,3,4,5,6]},"packages/cli/src/public-api/v1/handlers/insights/insights.handler.ts":{"15":[0,145,1,2,3,4,5,6],"29":[0,145,1,2,3,4,5,6],"49":[0,145,1,2,3,4,5,6],"52":[0,145,1,2,3,4,5,6],"57":[0,145,1,2,3,4,5,6]},"packages/cli/src/public-api/v1/handlers/projects/projects.handler.ts":{"49":[0,145,1,2,3,4,5,6],"63":[0,145,1,2,3,4,5,6],"82":[0,145,1,2,3,4,5,6],"102":[0,145,1,2,3,4,5,6],"124":[0,145,1,2,3,4,5,6],"153":[0,145,1,2,3,4,5,6],"171":[0,145,1,2,3,4,5,6],"188":[0,145,1,2,3,4,5,6],"204":[0,145,1,2,3,4,5,6]},"packages/cli/src/public-api/v1/handlers/source-control/source-control.handler.ts":{"23":[0,145,1,2,3,4,5,6]},"packages/cli/src/public-api/v1/handlers/tags/tags.handler.ts":{"31":[0,145,1,2,3,4,5,6],"46":[0,145,1,2,3,4,5,6],"68":[0,145,1,2,3,4,5,6],"85":[0,145,1,2,3,4,5,6],"107":[0,145,1,2,3,4,5,6]},"packages/cli/src/public-api/v1/handlers/users/users.handler.ee.ts":{"39":[0,145,1,2,3,4,5,6],"61":[0,145,1,2,3,4,5,6],"94":[0,145,1,2,3,4,5,6],"110":[0,145,1,2,3,4,5,6],"119":[0,145,1,2,3,4,5,6]},"packages/cli/src/public-api/v1/handlers/users/users.service.ee.ts":{"9":[0,145,1,2,3,4,5,6],"21":[0,145,1,2,3,4,5,6],"30":[0,145,1,2,3,4,5,6],"45":[0,145,1,2,3,4,5,6],"51":[0,145,1,2,3,4,5,6],"66":[0,145,1,2,3,4,5,6],"73":[0,145,1,2,3,4,5,6],"78":[0,145,1,2,3,4,5,6]},"packages/cli/src/public-api/v1/handlers/variables/variables.handler.ts":{"29":[0,145,1,2,3,4,5,6],"42":[0,145,1,2,3,4,5,6],"55":[0,145,1,2,3,4,5,6],"65":[0,145,1,2,3,4,5,6]},"packages/cli/src/public-api/v1/handlers/workflows/workflows.handler.ts":{"29":[0,145,1,2,3,4,5,6],"58":[0,145,1,2,3,4,5,6],"66":[0,145,1,2,3,4,5,6],"83":[0,145,1,2,3,4,5,6],"99":[0,145,1,2,3,4,5,6],"135":[0,145,1,2,3,4,5,6],"162":[0,145,1,2,3,4,5,6],"228":[0,145,1,2,3,4,5,6],"276":[0,145,1,2,3,4,5,6],"299":[0,145,1,2,3,4,5,6],"327":[0,145,1,2,3,4,5,6],"348":[0,145,1,2,3,4,5,6],"365":[0,145,1,2,3,4,5,6],"392":[0,145,1,2,3,4,5,6],"394":[0,145,1,2,3,4,5,6],"431":[0,145,1,2,3,4,5,6],"447":[0,145,1,2,3,4,5,6]},"packages/cli/src/public-api/v1/handlers/workflows/workflows.service.ts":{"18":[0,145,1,2,3,4,5,6],"22":[0,145,1,2,3,4,5,6],"41":[0,145,1,2,3,4,5,6],"57":[0,145,1,2,3,4,5,6],"63":[0,145,1,2,3,4,5,6],"84":[0,145,1,2,3,4,5,6],"88":[0,145,1,2,3,4,5,6],"89":[0,145,1,2,3,4,5,6],"92":[0,145,1,2,3,4,5,6],"103":[0,145,1,2,3,4,5,6],"105":[0,145,1,2,3,4,5,6],"112":[0,145,1,2,3,4,5,6]},"packages/cli/src/public-api/v1/shared/middlewares/global.middleware.ts":{"21":[0,145,1,2,3,4,5,6],"26":[0,145,1,2,3,4,5,6],"57":[0,145,1,2,3,4,5,6],"60":[0,145,1,2,3,4,5,6],"63":[0,145,1,2,3,4,5,6],"97":[0,145,1,2,3,4,5,6],"99":[0,145,1,2,3,4,5,6],"105":[0,145,1,2,3,4,5,6],"106":[0,145,1,2,3,4,5,6],"128":[0,145,1,2,3,4,5,6],"131":[0,145,1,2,3,4,5,6],"138":[0,145,1,2,3,4,5,6],"153":[0,145,1,2,3,4,5,6],"154":[0,145,1,2,3,4,5,6]},"packages/cli/src/public-api/v1/shared/services/pagination.service.ts":{"10":[0,145,1,2,3,4,5,6],"14":[0,145,1,2,3,4,5,6],"26":[0,145,1,2,3,4,5,6],"38":[0,145,1,2,3,4,5,6],"47":[0,145,1,2,3,4,5,6]},"packages/cli/src/public-api/v1/shared/services/utils.service.ts":{"9":[0,145,1,2,3,4,5,6]},"packages/cli/src/services/api-key-auth.strategy.ts":{"17":[0,1,2,157,3,4,5,6],"23":[0,1,2,157,3,4,5,6],"66":[0,1,2,157,3,4,5,6],"72":[0,1,2,157,3,4,5,6],"79":[0,1,2,157,3,4,5,6],"84":[0,1,2,157,3,4,5,6]},"packages/cli/src/services/auth-strategy.registry.ts":{"24":[0,145,1,2,157,3,4,5,6],"27":[0,145,1,2,157,3,4,5,6],"31":[0,145,1,2,157,3,4,5,6],"49":[0,145,1,2,157,3,4,5,6]},"packages/cli/src/services/jwt.service.ts":{"12":"b:f9smCX94ApEwBBQEAFAAAYD0HzAA","33":"b:f9smCX94ApEwBBQEAFAAAYD0HzAA","60":"b:f9smCX94ApEwBBQEAFAAAYD0HzAA","64":"b:f9smCX94ApEwBBQEAFAAAYD0HzAA","68":"b:f9smCX94ApEwBBQEAFAAAYD0HzAA"},"packages/cli/src/services/last-active-at.service.ts":{"11":"b:A9smCX94ApEwBBQEAFAAAYD0HgAA","16":"b:A9smCX94ApEwBBQEAFAAAYD0HgAA","18":"b:A9smCX94ApEwBBQEAFAAAYD0HgAA","25":"b:A9smCX94ApEwBBQEAFAAAYD0HgAA"},"packages/cli/src/services/password.utility.ts":{"8":"b:A9smCX9YApAwBBQEAFAAAYD0HwAA","12":"b:A9smCX9YApAwBBQEAFAAAYD0HwAA"},"packages/cli/src/services/public-api-key.service.ts":{"33":[0,1,2,3,7,4,5,6],"37":[0,1,2,3,7,4,5,6],"42":[0,1,2,3,7,4,5,6],"60":[0,1,2,3,7,4,5,6],"75":[0,1,2,3,7,4,5,6],"109":[0,1,2,3,7,4,5,6],"117":[0,1,2,3,7,4,5,6],"145":[0,1,2,3,7,4,5,6],"173":[0,1,2,3,7,4,5,6],"188":[0,1,2,3,7,4,5,6],"189":[0,1,2,3,7,4,5,6],"195":[0,1,2,3,7,4,5,6],"200":[0,1,2,3,7,4,5,6],"208":[0,1,2,3,7,4,5,6],"232":[0,1,2,3,7,4,5,6],"241":[0,1,2,3,7,4,5,6],"250":[0,1,2,3,7,4,5,6],"255":[0,1,2,3,7,4,5,6],"257":[0,1,2,3,7,4,5,6],"260":[0,1,2,3,7,4,5,6],"270":[0,1,2,3,7,4,5,6],"279":[0,1,2,3,7,4,5,6],"280":[0,1,2,3,7,4,5,6],"285":[0,1,2,3,7,4,5,6],"287":[0,1,2,3,7,4,5,6]},"packages/cli/src/services/role.service.ts":{"45":"b://ue/398ApHyBNQFCFIAAZj0diEA","53":"b://ue/398ApHyBNQFCFIAAZj0diEA","56":"b://ue/398ApHyBNQFCFIAAZj0diEA","63":"b://ue/398ApHyBNQFCFIAAZj0diEA","67":"b://ue/398ApHyBNQFCFIAAZj0diEA","75":"b://ue/398ApHyBNQFCFIAAZj0diEA","82":"b://ue/398ApHyBNQFCFIAAZj0diEA","100":"b://ue/398ApHyBNQFCFIAAZj0diEA","113":"b://ue/398ApHyBNQFCFIAAZj0diEA","126":"b://ue/398ApHyBNQFCFIAAZj0diEA","149":"b://ue/398ApHyBNQFCFIAAZj0diEA","160":"b://ue/398ApHyBNQFCFIAAZj0diEA","167":"b://ue/398ApHyBNQFCFIAAZj0diEA","198":"b://ue/398ApHyBNQFCFIAAZj0diEA","226":"b://ue/398ApHyBNQFCFIAAZj0diEA","235":"b://ue/398ApHyBNQFCFIAAZj0diEA","262":"b://ue/398ApHyBNQFCFIAAZj0diEA","310":"b://ue/398ApHyBNQFCFIAAZj0diEA","320":"b://ue/398ApHyBNQFCFIAAZj0diEA","324":"b://ue/398ApHyBNQFCFIAAZj0diEA","334":"b://ue/398ApHyBNQFCFIAAZj0diEA","343":"b://ue/398ApHyBNQFCFIAAZj0diEA","355":"b://ue/398ApHyBNQFCFIAAZj0diEA","379":"b://ue/398ApHyBNQFCFIAAZj0diEA","390":"b://ue/398ApHyBNQFCFIAAZj0diEA","391":"b://ue/398ApHyBNQFCFIAAZj0diEA","401":"b://ue/398ApHyBNQFCFIAAZj0diEA","403":"b://ue/398ApHyBNQFCFIAAZj0diEA","408":"b://ue/398ApHyBNQFCFIAAZj0diEA","414":"b://ue/398ApHyBNQFCFIAAZj0diEA","418":"b://ue/398ApHyBNQFCFIAAZj0diEA","428":"b://ue/398ApHyBNQFCFIAAZj0diEA"},"packages/cli/src/services/user.service.ts":{"43":"b:/9s2K398ApFwJPQmAFCAgYj0Hw8B","58":"b:/9s2K398ApFwJPQmAFCAgYj0Hw8B","68":"b:/9s2K398ApFwJPQmAFCAgYj0Hw8B","72":"b:/9s2K398ApFwJPQmAFCAgYj0Hw8B","84":"b:/9s2K398ApFwJPQmAFCAgYj0Hw8B","96":"b:/9s2K398ApFwJPQmAFCAgYj0Hw8B","107":"b:/9s2K398ApFwJPQmAFCAgYj0Hw8B","113":"b:/9s2K398ApFwJPQmAFCAgYj0Hw8B","118":"b:/9s2K398ApFwJPQmAFCAgYj0Hw8B","161":"b:/9s2K398ApFwJPQmAFCAgYj0Hw8B","164":"b:/9s2K398ApFwJPQmAFCAgYj0Hw8B","165":"b:/9s2K398ApFwJPQmAFCAgYj0Hw8B","170":"b:/9s2K398ApFwJPQmAFCAgYj0Hw8B","178":"b:/9s2K398ApFwJPQmAFCAgYj0Hw8B","188":"b:/9s2K398ApFwJPQmAFCAgYj0Hw8B","260":"b:/9s2K398ApFwJPQmAFCAgYj0Hw8B","261":"b:/9s2K398ApFwJPQmAFCAgYj0Hw8B","265":"b:/9s2K398ApFwJPQmAFCAgYj0Hw8B","267":"b:/9s2K398ApFwJPQmAFCAgYj0Hw8B","269":"b:/9s2K398ApFwJPQmAFCAgYj0Hw8B","281":"b:/9s2K398ApFwJPQmAFCAgYj0Hw8B","287":"b:/9s2K398ApFwJPQmAFCAgYj0Hw8B","289":"b:/9s2K398ApFwJPQmAFCAgYj0Hw8B","309":"b:/9s2K398ApFwJPQmAFCAgYj0Hw8B","317":"b:/9s2K398ApFwJPQmAFCAgYj0Hw8B","320":"b:/9s2K398ApFwJPQmAFCAgYj0Hw8B","324":"b:/9s2K398ApFwJPQmAFCAgYj0Hw8B","327":"b:/9s2K398ApFwJPQmAFCAgYj0Hw8B","417":"b:/9s2K398ApFwJPQmAFCAgYj0Hw8B","443":"b:/9s2K398ApFwJPQmAFCAgYj0Hw8B"},"packages/cli/src/sso.ee/sso-helpers.ts":{"14":"b:/9smCX9YApAwBBQEAFAAAYD0HwAA","28":"b:/9smCX9YApAwBBQEAFAAAYD0HwAA","47":"b:/9smCX9YApAwBBQEAFAAAYD0HwAA","51":"b:/9smCX9YApAwBBQEAFAAAYD0HwAA","58":"b:/9smCX9YApAwBBQEAFAAAYD0HwAA","62":"b:/9smCX9YApAwBBQEAFAAAYD0HwAA","66":"b:/9smCX9YApAwBBQEAFAAAYD0HwAA","70":"b:/9smCX9YApAwBBQEAFAAAYD0HwAA","74":"b:/9smCX9YApAwBBQEAFAAAYD0HwAA","78":"b:/9smCX9YApAwBBQEAFAAAYD0HwAA","82":"b:/9smCX9YApAwBBQEAFAAAYD0HwAA","90":"b:/9smCX9YApAwBBQEAFAAAYD0HwAA","94":"b:/9smCX9YApAwBBQEAFAAAYD0HwAA","98":"b:/9smCX9YApAwBBQEAFAAAYD0HwAA"},"packages/cli/src/user-management/email/user-management-mailer.ts":{"42":"b:/wAAAAAEAAAgAAAQAAAAAAgAAQAA","59":"b:/wAAAAAEAAAgAAAQAAAAAAgAAQAA","70":"b:/wAAAAAEAAAgAAAQAAAAAAgAAQAA","81":"b:/wAAAAAEAAAgAAAQAAAAAAgAAQAA","107":"b:/wAAAAAEAAAgAAAQAAAAAAgAAQAA","128":"b:/wAAAAAEAAAgAAAQAAAAAAgAAQAA","138":"b:/wAAAAAEAAAgAAAQAAAAAAgAAQAA","155":"b:/wAAAAAEAAAgAAAQAAAAAAgAAQAA","169":"b:/wAAAAAEAAAgAAAQAAAAAAgAAQAA","183":"b:/wAAAAAEAAAgAAAQAAAAAAgAAQAA","187":"b:/wAAAAAEAAAgAAAQAAAAAAgAAQAA","192":"b:/wAAAAAEAAAgAAAQAAAAAAgAAQAA","208":"b:/wAAAAAEAAAgAAAQAAAAAAgAAQAA","212":"b:/wAAAAAEAAAgAAAQAAAAAAgAAQAA","217":"b:/wAAAAAEAAAgAAAQAAAAAAgAAQAA","233":"b:/wAAAAAEAAAgAAAQAAAAAAgAAQAA","237":"b:/wAAAAAEAAAgAAAQAAAAAAgAAQAA","242":"b:/wAAAAAEAAAgAAAQAAAAAAgAAQAA","251":"b:/wAAAAAEAAAgAAAQAAAAAAgAAQAA","256":"b:/wAAAAAEAAAgAAAQAAAAAAgAAQAA","257":"b:/wAAAAAEAAAgAAAQAAAAAAgAAQAA","270":"b:/wAAAAAEAAAgAAAQAAAAAAgAAQAA","275":"b:/wAAAAAEAAAgAAAQAAAAAAgAAQAA","280":"b:/wAAAAAEAAAgAAAQAAAAAAgAAQAA","296":"b:/wAAAAAEAAAgAAAQAAAAAAgAAQAA"},"packages/community-packages.handler.ts":{"32":[0,145,1,2,3,4,5,6],"47":[0,145,1,2,3,4,5,6],"56":[0,145,1,2,3,4,5,6],"74":[0,145,1,2,3,4,5,6]},"packages/community-packages.mapper.ts":{"4":[0,145,1,2,3,4,5,6],"8":[0,145,1,2,3,4,5,6],"12":[0,145,1,2,3,4,5,6],"17":[0,145,1,2,3,4,5,6],"22":[0,145,1,2,3,4,5,6],"36":[0,145,1,2,3,4,5,6]},"packages/engine/import-blocked.error.ts":{"6":[0,145,1,2,3,4,5,6],"13":[0,145,1,2,3,4,5,6]},"packages/engine/import-pipeline.ts":{"43":[0,145,1,2,3,4,5,6],"54":[0,145,1,2,3,4,5,6],"102":[0,145,1,2,3,4,5,6],"106":[0,145,1,2,3,4,5,6],"116":[0,145,1,2,3,4,5,6],"121":[0,145,1,2,3,4,5,6],"128":[0,145,1,2,3,4,5,6],"138":[0,145,1,2,3,4,5,6],"146":[0,145,1,2,3,4,5,6],"159":[0,145,1,2,3,4,5,6],"173":[0,145,1,2,3,4,5,6],"191":[0,145,1,2,3,4,5,6]},"packages/engine/n8n-package-parser.ts":{"24":[0,145,1,2,3,4,5,6],"26":[0,145,1,2,3,4,5,6],"37":[0,145,1,2,3,4,5,6],"47":[0,145,1,2,3,4,5,6]},"packages/entities/credential/credential-importer.ts":{"13":[0,145,1,2,3,4,5,6],"20":[0,145,1,2,3,4,5,6],"34":[0,145,1,2,3,4,5,6]},"packages/entities/credential/credential-matcher-factory.ts":{"13":[0,145,1,2,3,4,5,6],"21":[0,145,1,2,3,4,5,6]},"packages/entities/credential/credential-matcher.ts":{"20":[0,145,1,2,3,4,5,6],"26":[0,145,1,2,3,4,5,6],"35":[0,145,1,2,3,4,5,6],"36":[0,145,1,2,3,4,5,6],"47":[0,145,1,2,3,4,5,6]},"packages/entities/credential/credential-missing-mode.ts":{"13":[0,145,1,2,3,4,5,6],"17":[0,145,1,2,3,4,5,6]},"packages/entities/credential/credential-requirements.extractor.ts":{"11":[0,145,1,2,3,4,5,6]},"packages/entities/credential/credential.exporter.ts":{"32":[0,145,1,2,3,4,5,6],"37":[0,145,1,2,3,4,5,6],"74":[0,145,1,2,3,4,5,6]},"packages/entities/credential/credential.serializer.ts":{"11":[0,145,1,2,3,4,5,6]},"packages/entities/credential/credential.types.ts":{"38":[0,145,1,2,3,4,5,6]},"packages/entities/credential/id-based-credential-matcher.ts":{"15":[0,145,1,2,3,4,5,6],"24":[0,145,1,2,3,4,5,6],"29":[0,145,1,2,3,4,5,6],"36":[0,145,1,2,3,4,5,6],"38":[0,145,1,2,3,4,5,6],"42":[0,145,1,2,3,4,5,6],"58":[0,145,1,2,3,4,5,6]},"packages/entities/workflow/workflow-conflict-policy.ts":{"16":[0,145,1,2,3,4,5,6],"17":[0,145,1,2,3,4,5,6],"18":[0,145,1,2,3,4,5,6],"22":[0,145,1,2,3,4,5,6]},"packages/entities/workflow/workflow-import-match.service.ts":{"9":[0,145,1,2,3,4,5,6],"11":[0,145,1,2,3,4,5,6]},"packages/entities/workflow/workflow-importer.ts":{"32":[0,145,1,2,3,4,5,6],"38":[0,145,1,2,3,4,5,6],"46":[0,145,1,2,3,4,5,6],"70":[0,145,1,2,3,4,5,6],"88":[0,145,1,2,3,4,5,6],"130":[0,145,1,2,3,4,5,6]},"packages/entities/workflow/workflow.exporter.ts":{"31":[0,145,1,2,3,4,5,6],"37":[0,145,1,2,3,4,5,6],"70":[0,145,1,2,3,4,5,6],"74":[0,145,1,2,3,4,5,6],"75":[0,145,1,2,3,4,5,6]},"packages/entities/workflow/workflow.serializer.ts":{"18":[0,145,1,2,3,4,5,6],"41":[0,145,1,2,3,4,5,6]},"packages/io/slug.utils.ts":{"6":[0,145,1,2,3,4,5,6]},"packages/io/tar/tar-package-reader.ts":{"23":[0,145,1,2,3,4,5,6],"28":[0,145,1,2,3,4,5,6],"41":[0,145,1,2,3,4,5,6],"50":[0,145,1,2,3,4,5,6],"55":[0,145,1,2,3,4,5,6],"61":[0,145,1,2,3,4,5,6],"92":[0,145,1,2,3,4,5,6],"99":[0,145,1,2,3,4,5,6],"106":[0,145,1,2,3,4,5,6],"118":[0,145,1,2,3,4,5,6],"143":[0,145,1,2,3,4,5,6],"160":[0,145,1,2,3,4,5,6],"176":[0,145,1,2,3,4,5,6],"182":[0,145,1,2,3,4,5,6],"187":[0,145,1,2,3,4,5,6]},"packages/io/tar/tar-package-writer.ts":{"13":[0,145,1,2,3,4,5,6],"17":[0,145,1,2,3,4,5,6],"31":[0,145,1,2,3,4,5,6],"46":[0,145,1,2,3,4,5,6],"51":[0,145,1,2,3,4,5,6],"63":[0,145,1,2,3,4,5,6],"67":[0,145,1,2,3,4,5,6]},"packages/io/unique-filename-allocator.ts":{"6":[0,145,1,2,3,4,5,6],"11":[0,145,1,2,3,4,5,6]},"packages/n8n-packages.config.ts":{"6":[0,145,1,2,3,4,5,6]},"packages/n8n-packages.handler.ts":{"32":[0,145,1,2,3,4,5,6],"39":[0,145,1,2,3,4,5,6],"50":[0,145,1,2,3,4,5,6],"52":[0,145,1,2,3,4,5,6],"53":[0,145,1,2,3,4,5,6],"64":[0,145,1,2,3,4,5,6],"73":[0,145,1,2,3,4,5,6]},"packages/n8n-packages.service.ts":{"21":[0,145,1,2,3,4,5,6],"28":[0,145,1,2,3,4,5,6],"61":[0,145,1,2,3,4,5,6]},"packages/n8n-packages.types.ts":{"78":[0,145,1,2,3,4,5,6],"90":[0,145,1,2,3,4,5,6]},"packages/spec/manifest.schema.ts":{"22":[0,145,1,2,3,4,5,6]},"packages/spec/requirements.schema.ts":{"14":[0,145,1,2,3,4,5,6]},"packages/utils/import-package-upload.ts":{"23":[0,145,1,2,3,4,5,6],"36":[0,145,1,2,3,4,5,6],"44":[0,145,1,2,3,4,5,6],"48":[0,145,1,2,3,4,5,6],"51":[0,145,1,2,3,4,5,6]},"packages/@n8n/api-types/src/schemas/boolean-from-string.ts":{"3":"b:AtsWK394ApEwBNQEAFAAAYgEIAAA"},"packages/@n8n/backend-common/src/license-state.ts":{"9":"b:7vuW//98E5P2BPQECFIACZj0dqAA","15":"b:7vuW//98E5P2BPQECFIACZj0dqAA","18":"b:7vuW//98E5P2BPQECFIACZj0dqAA","22":"b:7vuW//98E5P2BPQECFIACZj0dqAA","33":"b:7vuW//98E5P2BPQECFIACZj0dqAA","47":"b:7vuW//98E5P2BPQECFIACZj0dqAA","57":"b:7vuW//98E5P2BPQECFIACZj0dqAA","61":"b:7vuW//98E5P2BPQECFIACZj0dqAA","65":"b:7vuW//98E5P2BPQECFIACZj0dqAA","69":"b:7vuW//98E5P2BPQECFIACZj0dqAA","73":"b:7vuW//98E5P2BPQECFIACZj0dqAA","77":"b:7vuW//98E5P2BPQECFIACZj0dqAA","81":"b:7vuW//98E5P2BPQECFIACZj0dqAA","85":"b:7vuW//98E5P2BPQECFIACZj0dqAA","89":"b:7vuW//98E5P2BPQECFIACZj0dqAA","93":"b:7vuW//98E5P2BPQECFIACZj0dqAA","97":"b:7vuW//98E5P2BPQECFIACZj0dqAA","101":"b:7vuW//98E5P2BPQECFIACZj0dqAA","105":"b:7vuW//98E5P2BPQECFIACZj0dqAA","109":"b:7vuW//98E5P2BPQECFIACZj0dqAA","113":"b:7vuW//98E5P2BPQECFIACZj0dqAA","117":"b:7vuW//98E5P2BPQECFIACZj0dqAA","121":"b:7vuW//98E5P2BPQECFIACZj0dqAA","125":"b:7vuW//98E5P2BPQECFIACZj0dqAA","129":"b:7vuW//98E5P2BPQECFIACZj0dqAA","133":"b:7vuW//98E5P2BPQECFIACZj0dqAA","137":"b:7vuW//98E5P2BPQECFIACZj0dqAA","141":"b:7vuW//98E5P2BPQECFIACZj0dqAA","145":"b:7vuW//98E5P2BPQECFIACZj0dqAA","149":"b:7vuW//98E5P2BPQECFIACZj0dqAA","153":"b:7vuW//98E5P2BPQECFIACZj0dqAA","157":"b:7vuW//98E5P2BPQECFIACZj0dqAA","161":"b:7vuW//98E5P2BPQECFIACZj0dqAA","165":"b:7vuW//98E5P2BPQECFIACZj0dqAA","169":"b:7vuW//98E5P2BPQECFIACZj0dqAA","173":"b:7vuW//98E5P2BPQECFIACZj0dqAA","177":"b:7vuW//98E5P2BPQECFIACZj0dqAA","181":"b:7vuW//98E5P2BPQECFIACZj0dqAA","185":"b:7vuW//98E5P2BPQECFIACZj0dqAA","189":"b:7vuW//98E5P2BPQECFIACZj0dqAA","193":"b:7vuW//98E5P2BPQECFIACZj0dqAA","197":"b:7vuW//98E5P2BPQECFIACZj0dqAA","205":"b:7vuW//98E5P2BPQECFIACZj0dqAA","209":"b:7vuW//98E5P2BPQECFIACZj0dqAA","213":"b:7vuW//98E5P2BPQECFIACZj0dqAA","217":"b:7vuW//98E5P2BPQECFIACZj0dqAA","221":"b:7vuW//98E5P2BPQECFIACZj0dqAA","225":"b:7vuW//98E5P2BPQECFIACZj0dqAA","229":"b:7vuW//98E5P2BPQECFIACZj0dqAA","233":"b:7vuW//98E5P2BPQECFIACZj0dqAA","237":"b:7vuW//98E5P2BPQECFIACZj0dqAA","241":"b:7vuW//98E5P2BPQECFIACZj0dqAA","246":"b:7vuW//98E5P2BPQECFIACZj0dqAA","259":"b:7vuW//98E5P2BPQECFIACZj0dqAA"},"packages/@n8n/db/src/repositories/project.repository.ts":{"9":"b:6tuWK399MpX4BNQECFAAAYj2NgAA","13":"b:6tuWK399MpX4BNQECFAAAYj2NgAA","25":"b:6tuWK399MpX4BNQECFAAAYj2NgAA","36":"b:6tuWK399MpX4BNQECFAAAYj2NgAA","46":"b:6tuWK399MpX4BNQECFAAAYj2NgAA","70":"b:6tuWK399MpX4BNQECFAAAYj2NgAA","85":"b:6tuWK399MpX4BNQECFAAAYj2NgAA","102":"b:6tuWK399MpX4BNQECFAAAYj2NgAA","112":"b:6tuWK399MpX4BNQECFAAAYj2NgAA","124":"b:6tuWK399MpX4BNQECFAAAYj2NgAA","140":"b:6tuWK399MpX4BNQECFAAAYj2NgAA","149":"b:6tuWK399MpX4BNQECFAAAYj2NgAA","165":"b:6tuWK399MpX4BNQECFAAAYj2NgAA","178":"b:6tuWK399MpX4BNQECFAAAYj2NgAA","192":"b:6tuWK399MpX4BNQECFAAAYj2NgAA","202":"b:6tuWK399MpX4BNQECFAAAYj2NgAA","209":"b:6tuWK399MpX4BNQECFAAAYj2NgAA"},"packages/@n8n/permissions/src/roles/all-roles.ts":{"58":"b:+v////////////////////8PAAAA","62":"b:+v////////////////////8PAAAA","83":"b:AtsWK394ApFwBNQEAFAAAYAEAAAA"},"packages/cli/src/controllers/module-settings.controller.ts":{"7":"b:AtsWK394ApFwBNQEAFAAAYgEAAAA","13":"b:AtsWK394ApFwBNQEAFAAAYgEAAAA"},"packages/cli/src/controllers/project.controller.ts":{"44":"b:/vuWq/99ApF4BNQUAFAAAYgGIAAA","53":"b:/vuWq/99ApF4BNQUAFAAAYgGIAAA","74":"b:/vuWq/99ApF4BNQUAFAAAYgGIAAA","85":"b:/vuWq/99ApF4BNQUAFAAAYgGIAAA","102":"b:/vuWq/99ApF4BNQUAFAAAYgGIAAA","123":"b:/vuWq/99ApF4BNQUAFAAAYgGIAAA","136":"b:/vuWq/99ApF4BNQUAFAAAYgGIAAA","144":"b:/vuWq/99ApF4BNQUAFAAAYgGIAAA","160":"b:/vuWq/99ApF4BNQUAFAAAYgGIAAA","198":"b:/vuWq/99ApF4BNQUAFAAAYgGIAAA","211":"b:/vuWq/99ApF4BNQUAFAAAYgGIAAA","222":"b:/vuWq/99ApF4BNQUAFAAAYgGIAAA","232":"b:/vuWq/99ApF4BNQUAFAAAYgGIAAA","241":"b:/vuWq/99ApF4BNQUAFAAAYgGIAAA","251":"b:/vuWq/99ApF4BNQUAFAAAYgGIAAA","259":"b:/vuWq/99ApF4BNQUAFAAAYgGIAAA","278":"b:/vuWq/99ApF4BNQUAFAAAYgGIAAA","300":"b:/vuWq/99ApF4BNQUAFAAAYgGIAAA","322":"b:/vuWq/99ApF4BNQUAFAAAYgGIAAA","341":"b:/vuWq/99ApF4BNQUAFAAAYgGIAAA","355":"b:/vuWq/99ApF4BNQUAFAAAYgGIAAA","366":"b:/vuWq/99ApF4BNQUAFAAAYgGIAAA","374":"b:/vuWq/99ApF4BNQUAFAAAYgGIAAA"},"packages/cli/src/controllers/role.controller.ts":{"31":"b:AtsWK394ApFwBNQEAFAAAYgEAAAA","37":"b:AtsWK394ApFwBNQEAFAAAYgEAAAA","44":"b:AtsWK394ApFwBNQEAFAAAYgEAAAA","45":"b:AtsWK394ApFwBNQEAFAAAYgEAAAA","46":"b:AtsWK394ApFwBNQEAFAAAYgEAAAA","47":"b:AtsWK394ApFwBNQEAFAAAYgEAAAA","53":"b:AtsWK394ApFwBNQEAFAAAYgEAAAA","65":"b:AtsWK394ApFwBNQEAFAAAYgEAAAA","75":"b:AtsWK394ApFwBNQEAFAAAYgEAAAA","87":"b:AtsWK394ApFwBNQEAFAAAYgEAAAA","105":"b:AtsWK394ApFwBNQEAFAAAYgEAAAA","121":"b:AtsWK394ApFwBNQEAFAAAYgEAAAA"},"packages/cli/src/controllers/tags.controller.ts":{"20":"b:AtsWK794ApFwBNUEAFAAQYwHAAAA","24":"b:AtsWK794ApFwBNUEAFAAQYwHAAAA","30":"b:AtsWK794ApFwBNUEAFAAQYwHAAAA","43":"b:AtsWK794ApFwBNUEAFAAQYwHAAAA","56":"b:AtsWK794ApFwBNUEAFAAQYwHAAAA"},"packages/cli/src/modules/data-table/data-table-aggregate.controller.ts":{"10":"b:AtsWK794A5FwBNQEAFAAAYgGAAAA","17":"b:AtsWK794A5FwBNQEAFAAAYgGAAAA","27":"b:AtsWK794A5FwBNQEAFAAAYgGAAAA"},"packages/cli/src/modules/data-table/data-table-size-validator.service.ts":{"16":"b:AtsWK7/4A5FwBNQEAFAAAYgEAAAA","21":"b:AtsWK7/4A5FwBNQEAFAAAYgEAAAA","33":"b:AtsWK7/4A5FwBNQEAFAAAYgEAAAA","56":"b:AtsWK7/4A5FwBNQEAFAAAYgEAAAA","73":"b:AtsWK7/4A5FwBNQEAFAAAYgEAAAA","86":"b:AtsWK7/4A5FwBNQEAFAAAYgEAAAA","91":"b:AtsWK7/4A5FwBNQEAFAAAYgEAAAA"},"packages/cli/src/modules/data-table/data-table.repository.ts":{"24":"b:AtsWK7/4A5FwBNQEAFAAAYgEAAAA","40":"b:AtsWK7/4A5FwBNQEAFAAAYgEAAAA","41":"b:AtsWK7/4A5FwBNQEAFAAAYgEAAAA","43":"b:AtsWK7/4A5FwBNQEAFAAAYgEAAAA","48":"b:AtsWK7/4A5FwBNQEAFAAAYgEAAAA","54":"b:AtsWK7/4A5FwBNQEAFAAAYgEAAAA","55":"b:AtsWK7/4A5FwBNQEAFAAAYgEAAAA","65":"b:AtsWK7/4A5FwBNQEAFAAAYgEAAAA","94":"b:AtsWK7/4A5FwBNQEAFAAAYgEAAAA","95":"b:AtsWK7/4A5FwBNQEAFAAAYgEAAAA","102":"b:AtsWK7/4A5FwBNQEAFAAAYgEAAAA","109":"b:AtsWK7/4A5FwBNQEAFAAAYgEAAAA","144":"b:AtsWK7/4A5FwBNQEAFAAAYgEAAAA","145":"b:AtsWK7/4A5FwBNQEAFAAAYgEAAAA","158":"b:AtsWK7/4A5FwBNQEAFAAAYgEAAAA","159":"b:AtsWK7/4A5FwBNQEAFAAAYgEAAAA","173":"b:AtsWK7/4A5FwBNQEAFAAAYgEAAAA","179":"b:AtsWK7/4A5FwBNQEAFAAAYgEAAAA","184":"b:AtsWK7/4A5FwBNQEAFAAAYgEAAAA","195":"b:AtsWK7/4A5FwBNQEAFAAAYgEAAAA","199":"b:AtsWK7/4A5FwBNQEAFAAAYgEAAAA","204":"b:AtsWK7/4A5FwBNQEAFAAAYgEAAAA","219":"b:AtsWK7/4A5FwBNQEAFAAAYgEAAAA","227":"b:AtsWK7/4A5FwBNQEAFAAAYgEAAAA","237":"b:AtsWK7/4A5FwBNQEAFAAAYgEAAAA","242":"b:AtsWK7/4A5FwBNQEAFAAAYgEAAAA","265":"b:AtsWK7/4A5FwBNQEAFAAAYgEAAAA","273":"b:AtsWK7/4A5FwBNQEAFAAAYgEAAAA","284":"b:AtsWK7/4A5FwBNQEAFAAAYgEAAAA","295":"b:AtsWK7/4A5FwBNQEAFAAAYgEAAAA","299":"b:AtsWK7/4A5FwBNQEAFAAAYgEAAAA","302":"b:AtsWK7/4A5FwBNQEAFAAAYgEAAAA","306":"b:AtsWK7/4A5FwBNQEAFAAAYgEAAAA","334":"b:AtsWK7/4A5FwBNQEAFAAAYgEAAAA","372":"b:AtsWK7/4A5FwBNQEAFAAAYgEAAAA"},"packages/cli/src/modules/data-table/data-table.service.ts":{"51":"b:EtsWK7/4A5FwBNQEAFAAAYgEAAAA","65":"b:EtsWK7/4A5FwBNQEAFAAAYgEAAAA","66":"b:EtsWK7/4A5FwBNQEAFAAAYgEAAAA","68":"b:EtsWK7/4A5FwBNQEAFAAAYgEAAAA","81":"b:EtsWK7/4A5FwBNQEAFAAAYgEAAAA","118":"b:EtsWK7/4A5FwBNQEAFAAAYgEAAAA","145":"b:EtsWK7/4A5FwBNQEAFAAAYgEAAAA","154":"b:EtsWK7/4A5FwBNQEAFAAAYgEAAAA","158":"b:EtsWK7/4A5FwBNQEAFAAAYgEAAAA","173":"b:EtsWK7/4A5FwBNQEAFAAAYgEAAAA","183":"b:EtsWK7/4A5FwBNQEAFAAAYgEAAAA","194":"b:EtsWK7/4A5FwBNQEAFAAAYgEAAAA","204":"b:EtsWK7/4A5FwBNQEAFAAAYgEAAAA","218":"b:EtsWK7/4A5FwBNQEAFAAAYgEAAAA","229":"b:EtsWK7/4A5FwBNQEAFAAAYgEAAAA","241":"b:EtsWK7/4A5FwBNQEAFAAAYgEAAAA","245":"b:EtsWK7/4A5FwBNQEAFAAAYgEAAAA","252":"b:EtsWK7/4A5FwBNQEAFAAAYgEAAAA","270":"b:EtsWK7/4A5FwBNQEAFAAAYgEAAAA","276":"b:EtsWK7/4A5FwBNQEAFAAAYgEAAAA","296":"b:EtsWK7/4A5FwBNQEAFAAAYgEAAAA","305":"b:EtsWK7/4A5FwBNQEAFAAAYgEAAAA","346":"b:EtsWK7/4A5FwBNQEAFAAAYgEAAAA","356":"b:EtsWK7/4A5FwBNQEAFAAAYgEAAAA","403":"b:EtsWK7/4A5FwBNQEAFAAAYgEAAAA","447":"b:EtsWK7/4A5FwBNQEAFAAAYgEAAAA","457":"b:EtsWK7/4A5FwBNQEAFAAAYgEAAAA","511":"b:EtsWK7/4A5FwBNQEAFAAAYgEAAAA","520":"b:EtsWK7/4A5FwBNQEAFAAAYgEAAAA","550":"b:EtsWK7/4A5FwBNQEAFAAAYgEAAAA","559":"b:EtsWK7/4A5FwBNQEAFAAAYgEAAAA","566":"b:EtsWK7/4A5FwBNQEAFAAAYgEAAAA","567":"b:EtsWK7/4A5FwBNQEAFAAAYgEAAAA","569":"b:EtsWK7/4A5FwBNQEAFAAAYgEAAAA","587":"b:EtsWK7/4A5FwBNQEAFAAAYgEAAAA","630":"b:EtsWK7/4A5FwBNQEAFAAAYgEAAAA","645":"b:EtsWK7/4A5FwBNQEAFAAAYgEAAAA","658":"b:EtsWK7/4A5FwBNQEAFAAAYgEAAAA","669":"b:EtsWK7/4A5FwBNQEAFAAAYgEAAAA","675":"b:EtsWK7/4A5FwBNQEAFAAAYgEAAAA","685":"b:EtsWK7/4A5FwBNQEAFAAAYgEAAAA","721":"b:EtsWK7/4A5FwBNQEAFAAAYgEAAAA","723":"b:EtsWK7/4A5FwBNQEAFAAAYgEAAAA","727":"b:EtsWK7/4A5FwBNQEAFAAAYgEAAAA","729":"b:EtsWK7/4A5FwBNQEAFAAAYgEAAAA","745":"b:EtsWK7/4A5FwBNQEAFAAAYgEAAAA","759":"b:EtsWK7/4A5FwBNQEAFAAAYgEAAAA","784":"b:EtsWK7/4A5FwBNQEAFAAAYgEAAAA","789":"b:EtsWK7/4A5FwBNQEAFAAAYgEAAAA","791":"b:EtsWK7/4A5FwBNQEAFAAAYgEAAAA","796":"b:EtsWK7/4A5FwBNQEAFAAAYgEAAAA","821":"b:EtsWK7/4A5FwBNQEAFAAAYgEAAAA","849":"b:EtsWK7/4A5FwBNQEAFAAAYgEAAAA","858":"b:EtsWK7/4A5FwBNQEAFAAAYgEAAAA"},"packages/cli/src/modules/data-table/utils/sql-utils.ts":{"25":"b:AtsWK7/4A5FwBNQEAFAAAYgEAAAA","26":"b:AtsWK7/4A5FwBNQEAFAAAYgEAAAA","44":"b:AtsWK7/4A5FwBNQEAFAAAYgEAAAA","72":"b:AtsWK7/4A5FwBNQEAFAAAYgEAAAA","79":"b:AtsWK7/4A5FwBNQEAFAAAYgEAAAA","83":"b:AtsWK7/4A5FwBNQEAFAAAYgEAAAA","87":"b:AtsWK7/4A5FwBNQEAFAAAYgEAAAA","102":"b:AtsWK7/4A5FwBNQEAFAAAYgEAAAA","111":"b:AtsWK7/4A5FwBNQEAFAAAYgEAAAA","128":"b:AtsWK7/4A5FwBNQEAFAAAYgEAAAA","137":"b:AtsWK7/4A5FwBNQEAFAAAYgEAAAA","140":"b:AtsWK7/4A5FwBNQEAFAAAYgEAAAA","144":"b:AtsWK7/4A5FwBNQEAFAAAYgEAAAA","148":"b:AtsWK7/4A5FwBNQEAFAAAYgEAAAA","161":"b:AtsWK7/4A5FwBNQEAFAAAYgEAAAA","165":"b:AtsWK7/4A5FwBNQEAFAAAYgEAAAA","175":"b:AtsWK7/4A5FwBNQEAFAAAYgEAAAA","183":"b:AtsWK7/4A5FwBNQEAFAAAYgEAAAA","196":"b:AtsWK7/4A5FwBNQEAFAAAYgEAAAA","203":"b:AtsWK7/4A5FwBNQEAFAAAYgEAAAA","221":"b:AtsWK7/4A5FwBNQEAFAAAYgEAAAA","242":"b:AtsWK7/4A5FwBNQEAFAAAYgEAAAA","247":"b:AtsWK7/4A5FwBNQEAFAAAYgEAAAA","251":"b:AtsWK7/4A5FwBNQEAFAAAYgEAAAA","280":"b:AtsWK7/4A5FwBNQEAFAAAYgEAAAA","313":"b:AtsWK7/4A5FwBNQEAFAAAYgEAAAA","331":"b:AtsWK7/4A5FwBNQEAFAAAYgEAAAA","354":"b:AtsWK7/4A5FwBNQEAFAAAYgEAAAA","371":"b:AtsWK7/4A5FwBNQEAFAAAYgEAAAA","377":"b:AtsWK7/4A5FwBNQEAFAAAYgEAAAA","382":"b:AtsWK7/4A5FwBNQEAFAAAYgEAAAA"},"packages/cli/src/modules/favorites/database/repositories/user-favorite.repository.ts":{"9":"b:AtsWK/94A5F4BNQEAFAAAZgGAAAA","13":"b:AtsWK/94A5F4BNQEAFAAAZgGAAAA","20":"b:AtsWK/94A5F4BNQEAFAAAZgGAAAA","24":"b:AtsWK/94A5F4BNQEAFAAAZgGAAAA"},"packages/cli/src/modules/favorites/favorites.controller.ts":{"10":"b:AtsWK394ApFwBNQEAFAAAYgEAAAA","16":"b:AtsWK394ApFwBNQEAFAAAYgEAAAA","19":"b:AtsWK394ApFwBNQEAFAAAYgEAAAA","24":"b:AtsWK394ApFwBNQEAFAAAYgEAAAA","29":"b:AtsWK394ApFwBNQEAFAAAYgEAAAA"},"packages/cli/src/modules/favorites/favorites.service.ts":{"25":"b:AtsWK/94A5F4BNQEAFAAAZgGAAAA","26":"b:AtsWK/94A5F4BNQEAFAAAZgGAAAA","28":"b:AtsWK/94A5F4BNQEAFAAAZgGAAAA","34":"b:AtsWK/94A5F4BNQEAFAAAZgGAAAA","45":"b:AtsWK/94A5F4BNQEAFAAAZgGAAAA","54":"b:AtsWK/94A5F4BNQEAFAAAZgGAAAA","66":"b:AtsWK/94A5F4BNQEAFAAAZgGAAAA","75":"b:AtsWK/94A5F4BNQEAFAAAZgGAAAA","91":"b:AtsWK/94A5F4BNQEAFAAAZgGAAAA","113":"b:AtsWK/94A5F4BNQEAFAAAZgGAAAA","114":"b:AtsWK/94A5F4BNQEAFAAAZgGAAAA","122":"b:AtsWK/94A5F4BNQEAFAAAZgGAAAA","127":"b:AtsWK/94A5F4BNQEAFAAAZgGAAAA","132":"b:AtsWK/94A5F4BNQEAFAAAZgGAAAA","145":"b:AtsWK/94A5F4BNQEAFAAAZgGAAAA","164":"b:AtsWK/94A5F4BNQEAFAAAZgGAAAA","187":"b:AtsWK/94A5F4BNQEAFAAAZgGAAAA","205":"b:AtsWK/94A5F4BNQEAFAAAZgGAAAA","231":"b:AtsWK/94A5F4BNQEAFAAAZgGAAAA","243":"b:AtsWK/94A5F4BNQEAFAAAZgGAAAA","247":"b:AtsWK/94A5F4BNQEAFAAAZgGAAAA"},"packages/cli/src/server.ts":{"85":"b:Avs2q394RpnwxdQ0APEEhYgEggAA","97":"b:Avs2q394RpnwxdQ0APEEhYgEggAA","99":"b:Avs2q394RpnwxdQ0APEEhYgEggAA","101":"b:Avs2q394RpnwxdQ0APEEhYgEggAA","102":"b:Avs2q394RpnwxdQ0APEEhYgEggAA","121":"b:Avs2q394RpnwxdQ0APEEhYgEggAA","123":"b:Avs2q394RpnwxdQ0APEEhYgEggAA","127":"b:Avs2q394RpnwxdQ0APEEhYgEggAA","132":"b:Avs2q394RpnwxdQ0APEEhYgEggAA","136":"b:Avs2q394RpnwxdQ0APEEhYgEggAA","140":"b:Avs2q394RpnwxdQ0APEEhYgEggAA","144":"b:Avs2q394RpnwxdQ0APEEhYgEggAA","145":"b:Avs2q394RpnwxdQ0APEEhYgEggAA","153":"b:Avs2q394RpnwxdQ0APEEhYgEggAA","159":"b:Avs2q394RpnwxdQ0APEEhYgEggAA","161":"b:Avs2q394RpnwxdQ0APEEhYgEggAA","195":"b:Avs2q394RpnwxdQ0APEEhYgEggAA","209":"b:Avs2q394RpnwxdQ0APEEhYgEggAA","220":"b:Avs2q394RpnwxdQ0APEEhYgEggAA","240":"b:Avs2q394RpnwxdQ0APEEhYgEggAA","270":"b:Avs2q394RpnwxdQ0APEEhYgEggAA","324":"b:Avs2q394RpnwxdQ0APEEhYgEggAA","328":"b:Avs2q394RpnwxdQ0APEEhYgEggAA","343":"b:Avs2q394RpnwxdQ0APEEhYgEggAA","358":"b:Avs2q394RpnwxdQ0APEEhYgEggAA","432":"b:Avs2q394RpnwxdQ0APEEhYgEggAA","434":"b:Avs2q394RpnwxdQ0APEEhYgEggAA","447":"b:Avs2q394RpnwxdQ0APEEhYgEggAA","454":"b:Avs2q394RpnwxdQ0APEEhYgEggAA","476":"b:Avs2q394RpnwxdQ0APEEhYgEggAA","485":"b:Avs2q394RpnwxdQ0APEEhYgEggAA","494":"b:Avs2q394RpnwxdQ0APEEhYgEggAA","495":"b:Avs2q394RpnwxdQ0APEEhYgEggAA","501":"b:Avs2q394RpnwxdQ0APEEhYgEggAA"},"packages/cli/src/services/frontend.service.ts":{"114":"b:AtsWP394ApFwBNQEAFAAAYgEAAAA","133":"b:AtsWP394ApFwBNQEAFAAAYgEAAAA","137":"b:AtsWP394ApFwBNQEAFAAAYgEAAAA","138":"b:AtsWP394ApFwBNQEAFAAAYgEAAAA","145":"b:AtsWP394ApFwBNQEAFAAAYgEAAAA","157":"b:AtsWP394ApFwBNQEAFAAAYgEAAAA","164":"b:AtsWP394ApFwBNQEAFAAAYgEAAAA","411":"b:AtsWP394ApFwBNQEAFAAAYgEAAAA","425":"b:AtsWP394ApFwBNQEAFAAAYgEAAAA","598":"b:AtsWP394ApFwBNQEAFAAAYgEAAAA","640":"b:AtsWP394ApFwBNQEAFAAAYgEAAAA","644":"b:AtsWP394ApFwBNQEAFAAAYgEAAAA","660":"b:AtsWP394ApFwBNQEAFAAAYgEAAAA","668":"b:AtsWP394ApFwBNQEAFAAAYgEAAAA","673":"b:AtsWP394ApFwBNQEAFAAAYgEAAAA","683":"b:AtsWP394ApFwBNQEAFAAAYgEAAAA","696":"b:AtsWP394ApFwBNQEAFAAAYgEAAAA","697":"b:AtsWP394ApFwBNQEAFAAAYgEAAAA","727":"b:AtsWP394ApFwBNQEAFAAAYgEAAAA"},"packages/cli/src/services/project.service.ee.ts":{"39":"b:/vu2q/99ApH4BPQUCFAAAYj2NgAA","47":"b:/vu2q/99ApH4BPQUCFAAAYj2NgAA","53":"b:/vu2q/99ApH4BPQUCFAAAYj2NgAA","57":"b:/vu2q/99ApH4BPQUCFAAAYj2NgAA","69":"b:/vu2q/99ApH4BPQUCFAAAYj2NgAA","80":"b:/vu2q/99ApH4BPQUCFAAAYj2NgAA","81":"b:/vu2q/99ApH4BPQUCFAAAYj2NgAA","86":"b:/vu2q/99ApH4BPQUCFAAAYj2NgAA","87":"b:/vu2q/99ApH4BPQUCFAAAYj2NgAA","92":"b:/vu2q/99ApH4BPQUCFAAAYj2NgAA","93":"b:/vu2q/99ApH4BPQUCFAAAYj2NgAA","98":"b:/vu2q/99ApH4BPQUCFAAAYj2NgAA","99":"b:/vu2q/99ApH4BPQUCFAAAYj2NgAA","104":"b:/vu2q/99ApH4BPQUCFAAAYj2NgAA","105":"b:/vu2q/99ApH4BPQUCFAAAYj2NgAA","106":"b:/vu2q/99ApH4BPQUCFAAAYj2NgAA","110":"b:/vu2q/99ApH4BPQUCFAAAYj2NgAA","111":"b:/vu2q/99ApH4BPQUCFAAAYj2NgAA","116":"b:/vu2q/99ApH4BPQUCFAAAYj2NgAA","117":"b:/vu2q/99ApH4BPQUCFAAAYj2NgAA","122":"b:/vu2q/99ApH4BPQUCFAAAYj2NgAA","123":"b:/vu2q/99ApH4BPQUCFAAAYj2NgAA","124":"b:/vu2q/99ApH4BPQUCFAAAYj2NgAA","128":"b:/vu2q/99ApH4BPQUCFAAAYj2NgAA","174":"b:/vu2q/99ApH4BPQUCFAAAYj2NgAA","191":"b:/vu2q/99ApH4BPQUCFAAAYj2NgAA","244":"b:/vu2q/99ApH4BPQUCFAAAYj2NgAA","263":"b:/vu2q/99ApH4BPQUCFAAAYj2NgAA","272":"b:/vu2q/99ApH4BPQUCFAAAYj2NgAA","281":"b:/vu2q/99ApH4BPQUCFAAAYj2NgAA","285":"b:/vu2q/99ApH4BPQUCFAAAYj2NgAA","288":"b:/vu2q/99ApH4BPQUCFAAAYj2NgAA","290":"b:/vu2q/99ApH4BPQUCFAAAYj2NgAA","305":"b:/vu2q/99ApH4BPQUCFAAAYj2NgAA","313":"b:/vu2q/99ApH4BPQUCFAAAYj2NgAA","327":"b:/vu2q/99ApH4BPQUCFAAAYj2NgAA","337":"b:/vu2q/99ApH4BPQUCFAAAYj2NgAA","341":"b:/vu2q/99ApH4BPQUCFAAAYj2NgAA","365":"b:/vu2q/99ApH4BPQUCFAAAYj2NgAA","368":"b:/vu2q/99ApH4BPQUCFAAAYj2NgAA","373":"b:/vu2q/99ApH4BPQUCFAAAYj2NgAA","378":"b:/vu2q/99ApH4BPQUCFAAAYj2NgAA","379":"b:/vu2q/99ApH4BPQUCFAAAYj2NgAA","393":"b:/vu2q/99ApH4BPQUCFAAAYj2NgAA","397":"b:/vu2q/99ApH4BPQUCFAAAYj2NgAA","404":"b:/vu2q/99ApH4BPQUCFAAAYj2NgAA","416":"b:/vu2q/99ApH4BPQUCFAAAYj2NgAA","420":"b:/vu2q/99ApH4BPQUCFAAAYj2NgAA","423":"b:/vu2q/99ApH4BPQUCFAAAYj2NgAA","424":"b:/vu2q/99ApH4BPQUCFAAAYj2NgAA","429":"b:/vu2q/99ApH4BPQUCFAAAYj2NgAA","433":"b:/vu2q/99ApH4BPQUCFAAAYj2NgAA","439":"b:/vu2q/99ApH4BPQUCFAAAYj2NgAA","449":"b:/vu2q/99ApH4BPQUCFAAAYj2NgAA","461":"b:/vu2q/99ApH4BPQUCFAAAYj2NgAA","470":"b:/vu2q/99ApH4BPQUCFAAAYj2NgAA","478":"b:/vu2q/99ApH4BPQUCFAAAYj2NgAA","483":"b:/vu2q/99ApH4BPQUCFAAAYj2NgAA","497":"b:/vu2q/99ApH4BPQUCFAAAYj2NgAA","514":"b:/vu2q/99ApH4BPQUCFAAAYj2NgAA","518":"b:/vu2q/99ApH4BPQUCFAAAYj2NgAA","536":"b:/vu2q/99ApH4BPQUCFAAAYj2NgAA","540":"b:/vu2q/99ApH4BPQUCFAAAYj2NgAA","552":"b:/vu2q/99ApH4BPQUCFAAAYj2NgAA","562":"b:/vu2q/99ApH4BPQUCFAAAYj2NgAA","567":"b:/vu2q/99ApH4BPQUCFAAAYj2NgAA","576":"b:/vu2q/99ApH4BPQUCFAAAYj2NgAA","578":"b:/vu2q/99ApH4BPQUCFAAAYj2NgAA","582":"b:/vu2q/99ApH4BPQUCFAAAYj2NgAA","592":"b:/vu2q/99ApH4BPQUCFAAAYj2NgAA","598":"b:/vu2q/99ApH4BPQUCFAAAYj2NgAA","610":"b:/vu2q/99ApH4BPQUCFAAAYj2NgAA","616":"b:/vu2q/99ApH4BPQUCFAAAYj2NgAA","624":"b:/vu2q/99ApH4BPQUCFAAAYj2NgAA","630":"b:/vu2q/99ApH4BPQUCFAAAYj2NgAA","634":"b:/vu2q/99ApH4BPQUCFAAAYj2NgAA","641":"b:/vu2q/99ApH4BPQUCFAAAYj2NgAA","651":"b:/vu2q/99ApH4BPQUCFAAAYj2NgAA","682":"b:/vu2q/99ApH4BPQUCFAAAYj2NgAA","704":"b:/vu2q/99ApH4BPQUCFAAAYj2NgAA","713":"b:/vu2q/99ApH4BPQUCFAAAYj2NgAA","726":"b:/vu2q/99ApH4BPQUCFAAAYj2NgAA","734":"b:/vu2q/99ApH4BPQUCFAAAYj2NgAA","741":"b:/vu2q/99ApH4BPQUCFAAAYj2NgAA","751":"b:/vu2q/99ApH4BPQUCFAAAYj2NgAA","762":"b:/vu2q/99ApH4BPQUCFAAAYj2NgAA"},"packages/cli/src/services/tag.service.ts":{"14":"b:AtsWq794EpNwBNUECFCAQczHEAAA","19":"b:AtsWq794EpNwBNUECFCAQczHEAAA","25":"b:AtsWq794EpNwBNUECFCAQczHEAAA","39":"b:AtsWq794EpNwBNUECFCAQczHEAAA","49":"b:AtsWq794EpNwBNUECFCAQczHEAAA","54":"b:AtsWq794EpNwBNUECFCAQczHEAAA","69":"b:AtsWq794EpNwBNUECFCAQczHEAAA","78":"b:AtsWq794EpNwBNUECFCAQczHEAAA","79":"b:AtsWq794EpNwBNUECFCAQczHEAAA","84":"b:AtsWq794EpNwBNUECFCAQczHEAAA"},"packages/@n8n/api-types/src/agent-builder-tool-node-types.ts":{"4":"b:+v////////////////////8PAAAA"},"packages/@n8n/api-types/src/agents/agent-integration.schema.ts":{"3":"b:+v////////////////////8PAAAA","16":"b:+v////////////////////8PAAAA","22":"b:+v////////////////////8PAAAA","35":"b:+v////////////////////8PAAAA"},"packages/@n8n/api-types/src/dto/data-table/list-data-table-query.dto.ts":{"32":"b:+v////////////////////8PAAAA","36":[47,48]},"packages/@n8n/api-types/src/dto/pagination/pagination.dto.ts":{"10":"b:ANsWKQ98ApHwBHQEAFAAAYgEAAAA","11":"b:ANsWKQ98ApHwBHQEAFAAAYgEAAAA","14":"b:ANsWKQ98ApHwBHQEAFAAAYgEAAAA","18":"b:+v////////////////////8PAAAA","22":"b:ANsWKQ98ApHwBHQEAFAAAYgEAAAA","23":"b:ANsWKQ98ApHwBHQEAFAAAYgEAAAA","27":"b:ANsWKQ98ApHwBHQEAFAAAYgEAAAA","35":"b:ANsWKQ98ApHwBHQEAFAAAYgEAAAA","47":"b:ANsWKQ98ApHwBHQEAFAAAYgEAAAA","48":"b:ANsWKQ98ApHwBHQEAFAAAYgEAAAA","51":"b:ANsWKQ98ApHwBHQEAFAAAYgEAAAA","55":"b:+v////////////////////8PAAAA","59":"b:ANsWKQ98ApHwBHQEAFAAAYgEAAAA","60":"b:ANsWKQ98ApHwBHQEAFAAAYgEAAAA","63":"b:ANsWKQ98ApHwBHQEAFAAAYgEAAAA","66":"b:ANsWKQ98ApHwBHQEAFAAAYgEAAAA"},"packages/@n8n/chat-hub/src/constants.ts":{"50":"b:+v////////////////////8PAAAA"},"packages/@n8n/chat/src/composables/useChat.ts":{"6":"b:+v////////////////////8PAAAA"},"packages/@n8n/chat/src/utils/event-bus.ts":{"11":"b:+v////////////////////8PAAAA","22":[14,15,16,17,77,95,110],"36":[14,15,16,17,77,95,110],"40":[14,15,16,17,77,95,110]},"packages/@n8n/codemirror-lang-sql/src/sql.ts":{"19":"b:+v////////////////////8PAAAA","26":[104],"61":"b:+v////////////////////8PAAAA","76":[104],"80":[104],"140":"b:+v////////////////////8PAAAA","157":"b:+v////////////////////8PAAAA","195":[104]},"packages/@n8n/codemirror-lang-sql/src/tokens.ts":{"33":"b:+v////////////////////8PAAAA","80":[104],"88":[104],"113":[104],"122":[104],"141":[104],"164":[104],"171":"b:+v////////////////////8PAAAA","221":"b:+v////////////////////8PAAAA","240":"b:+v////////////////////8PAAAA","241":[104]},"packages/@n8n/composables/src/useDeviceSupport.ts":{"3":"b:+v////////////////////8PAAAA","26":"b:AMACAAAAAAAAIAEAfkAABAEAAAAA","28":"b:KLYAoASQRCBM0mOQd2H9RfkPAAAA"},"packages/@n8n/composables/src/useDocumentTitle.ts":{"28":"b:+v////////////////////8PAAAA","37":"b:+v///f////////v///////8PAAAA","42":[132],"47":"b:cP9/4A84/v/n/wPg//////8PAAAA"},"packages/@n8n/design-system/src/components/AskAssistantChat/AskAssistantChat.vue":{"25":"b:+v///f////////v///////8PAAAA","62":[9],"77":"b:+v///f////////v///////8PAAAA","78":[9,10,11,12,13,18],"86":"b:+v///f////////v///////8PAAAA","87":[9,10,11,12,13,18],"99":"b:+v///f////////v///////8PAAAA","133":"b:+v///f////////v///////8PAAAA","272":"b:+v///f////////v///////8PAAAA","275":"b:+v///f////////v///////8PAAAA","287":[9,10,11,12,13,18],"303":"b:cP9/4A8w/v/h/4Mh//////sPAAAA","307":"b:+v///f////////v///////8PAAAA","311":"b:+v///f////////v///////8PAAAA","315":"b:+v///f////////v///////8PAAAA","321":[9,10,11,12,13,18],"327":"b:+v///f////////v///////8PAAAA","332":"b:+v///f////////v///////8PAAAA","345":[13],"360":"b:cP9/4A8w/v/h/4Mh//////sPAAAA","364":[18],"378":[9],"382":[9,12,13,18],"391":[13,18],"395":[13,18],"399":[9,10,12,13,18],"403":"b:+v///f////////v///////8PAAAA","405":"b:+v///f////////v///////8PAAAA","422":"b:+v///f////////v///////8PAAAA","439":[9,10,11,12],"443":[9,10,11,12,13,18],"456":[9,10,11,12,13,18],"464":[9,10,11,12,13,18],"469":"b:+v///f////////v///////8PAAAA","500":[9,10,11,12,13,18],"507":[9,10,11,12,13,18],"534":[10],"535":[10],"538":[13],"554":[9,10,12],"562":[9],"563":[9,10,12],"597":"b:+v///f////////v///////8PAAAA","602":[13,18],"614":"b:+v///f////////v///////8PAAAA"},"packages/@n8n/design-system/src/components/AskAssistantIcon/AssistantIcon.vue":{"4":"b:+v///f////////v///////8PAAAA","22":"b:+v///f////////v///////8PAAAA","30":"b:+v///f////////v///////8PAAAA"},"packages/@n8n/design-system/src/components/AskAssistantText/AssistantText.vue":{"9":"b:+v///f////////v///////8PAAAA"},"packages/@n8n/design-system/src/components/ConditionalRouterLink/CondtionalRouterLink.vue":{"16":"b:+P+f/Q/8/////3M0//////8PAAAA","27":"b:+P+f/Q/8/////3M0/////n8PAAAA","32":"b:+P+f/Q/8/////3M0//////8PAAAA"},"packages/@n8n/design-system/src/components/N8nActionBox/ActionBox.vue":{"33":"b:KAiAgAD9AQA+AOgZAAAAAAgCAAAA","46":"b:IAgAgAD5AQA+AOgZAAAAAAAAAAAA","51":"b:KAiAgAD9AQAwAGgZAAAAAAgCAAAA","59":"b:IAgAgAD4AQA+AOgZAAAAAAAAAAAA","67":[31,46,48,85,86,87,88]},"packages/@n8n/design-system/src/components/N8nActionToggle/ActionToggle.vue":{"31":"b:uL6b/S33187/+fs1z+///zsOAAAA","52":"b:uL6b/S33187/+fs1z+///zsOAAAA","53":"b:uL6b/S33187/+fs1z+///zsOAAAA","62":"b:gAAAAAABAQA+AEgBAAAAEAACAAAA","63":"b:gAAAAAABAQA+AEgBAAAAEAACAAAA","92":"b:uL6b/S33187/+fs1z+///zsOAAAA","99":"b:gAAAAAABAQA+AEgBAAAAEAACAAAA","117":"b:uL6b/S33187/+fs1z+///zsOAAAA","130":[66],"132":[66],"139":"b:gAAAAAABAQA+AEgBAAAAEAACAAAA"},"packages/@n8n/design-system/src/components/N8nBadge/Badge.vue":{"23":"b:eICAgAD1AwA0AGAwAAKAQFgKAAAA","25":"b:eICAgAD1AwA0AGAwAAKAQFgKAAAA"},"packages/@n8n/design-system/src/components/N8nButton/Button.vue":{"9":"b:+v///f////////v///////8PAAAA","25":"b:+v///f////////v///////8PAAAA","31":"b:+v///f////////v///////8PAAAA","37":"b:+v///f////////v///////8PAAAA","43":"b:+v///f////////v///////8PAAAA","48":"b:+v///f////////v///////8PAAAA","53":"b:+v///f////////v///////8PAAAA","55":"b:+v///f////////v///////8PAAAA","81":"b:+P+f8f//v///+/u3//////8PAAAA","84":"b:+v///f////////v///////8PAAAA","103":"b:+v///f////////v//////n8PAAAA","105":"b:+v///f////////v///////8PAAAA"},"packages/@n8n/design-system/src/components/N8nCallout/Callout.vue":{"9":"b:IIhBgCB7VoAgUXAwAQ3/PzIGAAAA","33":"b:IIhBgCB7VoAgUXAwAQ3/PzIGAAAA","42":"b:AIBBACAaEoAgUXAgAQ3fJzICAAAA","46":"b:AIBBACAaEoAgUXAgAQ3fJzICAAAA","55":"b:IIhBgCB7VoAgUXAwAQ3/PzIGAAAA","64":"b:IIhBgCB7VoAgUXAwAQ3/PzIGAAAA"},"packages/@n8n/design-system/src/components/N8nChatInput/ChatInput.vue":{"41":"b:+v///f////////v///////8PAAAA","77":"b:+v///f////////v///////8PAAAA","82":"b:+v///f////////v///////8PAAAA","96":"b:+v///f////////v///////8PAAAA","97":"b:+v///f////////v///////8PAAAA","107":"b:+v///f////////v///////8PAAAA","111":"b:+v///f////////v///////8PAAAA","120":"b:+v///f////////v///////8PAAAA","122":"b:+v///f////////v///////8PAAAA","131":"b:+v///f////////v///////8PAAAA","133":"b:ADYEAPAGAAAAAAAAAAAAAAAAAAAA","144":"b:+v///f////////v///////8PAAAA","153":"b:ADYEAPAGAAAAAAAAAAAAAAAAAAAA","160":"b:ADYEAPAGAAAAAAAAAAAAAAAAAAAA","164":[9,12,13,18],"170":[9,12,13,18,36,37,38,39,41,42],"177":[18],"184":[9,12,13,18],"229":"b:AD4EAPAGAAAAAAAAAAAAAAAAAAAA","234":"b:ADYEAPAGAAAAAAAAAAAAAAAAAAAA","239":[13],"244":[13],"249":"b:+v///f////////v///////8PAAAA","253":"b:+v///f////////v///////8PAAAA","255":"b:+v///f////////v///////8PAAAA","265":"b:+v///f////////v///////8PAAAA","269":"b:+v///f////////v//////n8PAAAA","290":[9,10,12,13,36,37,38,39,41,42],"304":[9,10,12,13,36,37,38,39,41,42],"314":[41],"326":[9,12,13,18,36,37,38,39,41,42]},"packages/@n8n/design-system/src/components/N8nCommandBar/CommandBar.vue":{"34":"b:+v+f//////////8///////8PAAAA","42":[137],"43":[137],"46":[137],"50":[137],"57":[137],"62":[137],"85":[137],"90":[137],"103":[137],"110":[137],"115":[137],"122":[137],"126":[137],"127":[137],"155":[137],"163":[137],"189":[137],"202":"b:KLYEoASQTCD80uMUd2H/Xf0PAAAA","252":"b:+P+f4f//////+/s3//////8PAAAA","260":[137],"265":"b:+v+f//////////8///////8PAAAA","270":[69,90,110,134,135],"274":"b:+v+f//////////8///////8PAAAA","279":"b:+v+f//////////8//////n8PAAAA","280":"b:+v+f//////////8//////n8PAAAA","293":[137],"313":[137],"325":[137],"327":[137],"340":[137]},"packages/@n8n/design-system/src/components/N8nDatatable/Datatable.vue":{"23":[85],"37":[85],"45":[85],"76":[85],"80":[85],"89":[85],"99":[85],"133":[85],"134":[85],"135":[85]},"packages/@n8n/design-system/src/components/N8nDropdownMenu/DropdownMenu.typeguards.ts":{"6":"b:+P+f/f////////u1//////8PAAAA","8":"b:+P+f/f////////u1//////8PAAAA"},"packages/@n8n/design-system/src/components/N8nDropdownMenu/DropdownMenu.vue":{"27":"b:+P+f/f////////u1//////8PAAAA","55":[37,38,39,65,66,67],"93":"b:+P+f/f////////u1//////8PAAAA","101":"b:+P+f/f////////u1//////8PAAAA","110":"b:0B4AAOWRASB/gksBQEBgVRADAAAA","121":[37,38,39],"147":[37,38,39,65,66,67],"176":"b:0B4AAOWRASB/gksBQEBgVRADAAAA","190":"b:+N6b+e2zV+p/+1s1z+//f/sPAAAA","197":"b:0J4ZYO2xE2p/y0shx8//dzkDAAAA","204":"b:0J4ZQO2xAyp/y0shx8//dzgDAAAA","218":"b:0B4AAOWRASB/gksBQEBgVRADAAAA","225":"b:+P+f/f////////u1//////8PAAAA","226":"b:+P+f/f////////u1//////8PAAAA","239":"b:+P+f/f////////u1//////8PAAAA","240":"b:8L6doP///+5/08Mw59/vff4PAAAA","246":"b:uNqb+amzV8o/+Vs1z+//f/sOAAAA","255":"b:0B4AAOWRASB/gksBQEBgVRADAAAA","285":"b:+P+f/f////////u1//////8PAAAA","289":"b:+P+f/f////////u1/////n8PAAAA","290":"b:+P+f/f////////u1//////8PAAAA","319":"b:+P+f/f////////u1//////8PAAAA","334":"b:0B4AAOWRASB/gksBQEBgVBADAAAA","375":"b:0B4AAOWRASB/gksBQEBgVRADAAAA","377":"b:0B4AAOWRASB/gksBQEBgVBADAAAA","384":[37,38,39,65,66,67],"387":"b:0BYAAOSAACBCggMAQEBgRRABAAAA","390":"b:0BYAAOSAACBOggMAQEBgRRABAAAA","393":"b:0BYAAOSBASB+gksBQEBgVRADAAAA"},"packages/@n8n/design-system/src/components/N8nDropdownMenu/composables/useMenuKeyboardNavigation.ts":{"23":"b:+P+f/f////////u1//////8PAAAA","110":"b:+P+f/f////////u1//////8PAAAA"},"packages/@n8n/design-system/src/components/N8nFormInput/FormInput.vue":{"56":"b:KgCAFAAEAQAgAHAGAAAAAAkCAAAA","82":"b:KgCAFAAEAQAgAHAGAAAAAAkCAAAA","122":"b:KACAEAAAAQAgADAGAAAAAAkCAAAA","128":"b:KACAEAAAAQAgADAGAAAAAAgCAAAA","133":"b:KACAFAAAAQAgADAGAAAAAAkCAAAA","137":[90],"143":"b:KgCAFAAEAQAgAHAGAAAAAAkCAAAA","161":"b:KgCAFAAEAQAgAHAGAAAAAAkCAAAA","167":"b:KgCAFAAEAQAgAHAGAAAAAAkCAAAA","173":[28,1,3,69,84,85,89,90],"176":"b:KgCAFAAEAQAgAHAGAAAAAAkCAAAA","214":"b:KgCAFAAEAQAgAHAGAAAAAAkCAAAA","215":[3,90],"232":[84],"234":[84]},"packages/@n8n/design-system/src/components/N8nFormInput/validators.ts":{"7":"b:KgCAFAAEAQAgAHAGAAAAAAgCAAAA","36":[85],"67":[28,1,69,89,90],"97":[84,85],"109":"b:+v////////////////////8PAAAA","139":"b:KgCAFAAEAQAgAHAGAAAAAAgCAAAA"},"packages/@n8n/design-system/src/components/N8nHeading/Heading.vue":{"27":"b:+v////////////////////8PAAAA","34":"b:+v////////////////////8PAAAA","50":"b:+v////////////////////8PAAAA","52":"b:+v////////////////////8PAAAA","56":"b:+v///////////////////n8PAAAA"},"packages/@n8n/design-system/src/components/N8nIcon/Icon.vue":{"21":"b:+v////////////////////8PAAAA","28":"b:+v////////////////////8PAAAA","38":"b:+v////////////////////8PAAAA","50":"b:+v////////////////////8PAAAA","77":"b:+v////////////////////8PAAAA","93":"b:+v////////////////////8PAAAA","95":"b:+v////////////////////8PAAAA","97":"b:cP974A8y/v/h+0Pg3/////sLAAAA","104":"b:+v////////////////////8PAAAA","110":"b:+v////////////////////8PAAAA"},"packages/@n8n/design-system/src/components/N8nIcon/custom/spinner.svg":{"9":"b:+v////////////////////8PAAAA"},"packages/@n8n/design-system/src/components/N8nIconButton/IconButton.vue":{"6":"b:+v///f////////v///////8PAAAA","7":"b:+v///f////////v//////n8PAAAA"},"packages/@n8n/design-system/src/components/N8nInfoTip/InfoTip.vue":{"14":"b:uI6L3STxgc6/EPIVgO9/3xkOAAAA","57":"b:uI6L3STxgc6/EPIVgO9/3xkOAAAA","63":"b:uI6L3STxgc6/EPIVgO9/3xkOAAAA"},"packages/@n8n/design-system/src/components/N8nInput/Input.vue":{"11":"b:uv7b/a33187/+fs37+///38PAAAA","40":"b:uv7b/a33187/+fs37+///3sPAAAA","49":"b:uv7b/a33187/+fs37+///38PAAAA","59":"b:uv7b/a33187/+fs37+///38PAAAA","78":"b:uv7b/a33187/+fs37+///38PAAAA","81":"b:uv7b/a33187/+fs37+///38PAAAA","83":"b:uv7b/a33187/+fs37+///38PAAAA","97":"b:uv7b/a33187/+fs37+///38PAAAA","111":"b:qJCZkKXwAQ4lEPgXgARyGQ4PAAAA","118":"b:qJCZkKXwAY4jEPg3yARyGT8HAAAA","124":"b:qJCZlKXwAY4nEPg3yARyGT8PAAAA","130":"b:CBAAAACQAAAEAKAEQAAyAQQCAAAA","135":"b:gAAYAAUAAAYkAAAAQAACGQICAAAA","146":"b:uv7b/a33187/+fs37+///38PAAAA","150":"b:uv7b/a33187/+fs37+///38PAAAA","156":"b:uNqb+am3V8q/+Xk1z+//fz8PAAAA","157":"b:uv7b/a33187/+fs37+///38PAAAA","162":"b:uv7b/a33187/+fs37+///38PAAAA","163":"b:qpLZ8KXxhY6nMfoXjOzyHw8PAAAA","172":"b:uv7b/a33187/+fs37+///38PAAAA","182":"b:qJCZlKXwAQ4nEOAVSARyGQsHAAAA","183":[117,123],"184":"b:KACAAACAAYAgAAAgAABQADkCAAAA","187":"b:uv7b/a33187/+fs37+///38PAAAA"},"packages/@n8n/design-system/src/components/N8nInputLabel/InputLabel.vue":{"31":"b:ur7b9K33187h+fs3z+3//zsGAAAA","33":"b:ur7b9K33187h+fs3z+3//zsGAAAA","65":"b:sr5b9K3z187h+es3z+3//zsGAAAA","69":"b:AogBAKDRAYAAEGAmAAAACDAGAAAA"},"packages/@n8n/design-system/src/components/N8nLink/Link.vue":{"31":"b:+v/f/S/5//////s///////8PAAAA","32":"b:+v/f/S/5//////s//////n8PAAAA","34":"b:+v/f/S/5//////s//////n8PAAAA"},"packages/@n8n/design-system/src/components/N8nLoading/Loading.vue":{"38":"b:+IqZ/Qnx/04/0Hg0xz/vfboOAAAA","47":"b:+IqZ/Qnx/04/0Hg0xz/vfboOAAAA","49":[40,47,48,138],"60":"b:+IqZ/Qnx/04/0Hg0xz/vfboOAAAA"},"packages/@n8n/design-system/src/components/N8nMenuItem/MenuItem.vue":{"15":"b:+v+f/f////////s///////8PAAAA","29":"b:+v+f/f////////s///////8PAAAA","45":"b:IAAAAYChAQAwAEAUQAIAQAgAAAAA","52":"b:+v+f/f////////s///////8PAAAA","64":"b:+v+f/f////////s///////8PAAAA","73":"b:+v+f/f////////s///////8PAAAA","89":"b:+v+f/f////////s///////8PAAAA","92":"b:+v+f/f////////s///////8PAAAA","99":"b:+v+f/f////////s///////8PAAAA","117":"b:+v+f/f////////s//////n8PAAAA","126":[24,69,102],"135":"b:oogBifB/gQAwENgfQAAACQgEAAAA"},"packages/@n8n/design-system/src/components/N8nNavigationDropdown/NavigationDropdown.vue":{"42":"b:+P+f/Q/8/////3M0//////8PAAAA","56":"b:+P+f/Q/8/////3M0//////8PAAAA","58":"b:+P+f/Q/8/////3M0//////8PAAAA","59":"b:+P+f/Q/8/////3M0//////8PAAAA","60":"b:+P+f/Q/8/////3M0//////8PAAAA","84":"b:eP+f4Q/8////+2M0//////8PAAAA","89":[23,48,3,69,5,126,131,137],"94":[23,48,3,69,5,131,137],"103":"b:+P+f/Q/8/////3M0//////8PAAAA","113":[23,48,3,69,5,126,131,137],"117":"b:+P+f/Q/8/////3M0//////8PAAAA","126":"b:+P+f/Q/8/////3M0//////8PAAAA","128":"b:+P+f/Q/8/////3M0//////8PAAAA","130":"b:+P+f/Q/8/////3M0/////n8PAAAA","141":"b:eCCAgALUeSR+yEMQ5aJPb8sKAAAA","143":"b:eCCAgALUeSR+yEMQ5aJPb8sKAAAA","161":"b:eCCAgALUeSR+yEMQ5aJPb8sKAAAA","163":"b:eCCAgALUeSR+yEMQ5aJPbksKAAAA","166":"b:eCCAgALUeSR+yEMQ5aJPbksKAAAA","170":[69,126,137],"171":"b:eCCAgALUeSR+yEMQ5aJPb8sKAAAA","172":"b:eCCAgALUeSR+yEMQ5aJPb8sKAAAA","184":[69],"208":"b:+P+f/Q/8/////3M0//////8PAAAA","212":"b:+P+f/Q/8/////3M0/////n8PAAAA"},"packages/@n8n/design-system/src/components/N8nOption/Option.vue":{"12":"b:+r7b/W33187/+fM3z+///38OAAAA","13":"b:+r7b/W33187/+fM3z+///n8OAAAA","16":"b:+r7b/W33187/+fM3z+///n8OAAAA"},"packages/@n8n/design-system/src/components/N8nPopover/Popover.vue":{"84":"b:+P+f/f/+/////3M0//////8PAAAA","105":"b:AAAAAQCAAAAgAEAkaAEvH1ICAAAA","111":"b:AAAAAACAAAAgAEAkSAEvGRICAAAA","125":"b:AAAAAACAAAAgAEAgSAEPHVICAAAA","133":"b:+P+f/f/+/////3M0//////8PAAAA","134":"b:AAAAAACAAAAgAEAgKAEvHxIAAAAA","143":"b:+P+f/f/+/////3M0//////8PAAAA","146":"b:AAAAAQCAAAAgAEAkSAEPHVICAAAA","147":"b:+P+f/f/+/////3M0//////8PAAAA","148":"b:+P+f/f/+/////3M0//////8PAAAA","151":"b:+P+f/f/+/////3M0//////8PAAAA","167":"b:AAAAAQCAAAAgAEAkaAEvHlICAAAA","174":"b:AAAAAQCAAAAgAAAkSAAAAFACAAAA"},"packages/@n8n/design-system/src/components/N8nPromptInputSuggestions/N8nPromptInputSuggestions.vue":{"10":"b:+v///f////////v///////8PAAAA","20":[18],"23":"b:+v///f////////v///////8PAAAA","41":"b:+v///f////////v///////8PAAAA","46":[18]},"packages/@n8n/design-system/src/components/N8nResizeWrapper/ResizeWrapper.vue":{"6":"b:+v///f////////v///////8PAAAA","72":"b:+v///f////////v///////8PAAAA","91":"b:+v///f////////v///////8PAAAA","141":"b:MJobYIgwVkol+QEkx///d/kOAAAA","167":"b:MJobYIgwVkol+QEkx///d/kOAAAA","195":"b:+v///f////////v///////8PAAAA","201":"b:+v///f////////v///////8PAAAA"},"packages/@n8n/design-system/src/components/N8nRoute/Route.vue":{"13":"b:+v/f/f////////s///////8PAAAA","15":"b:+v/f/f////////s///////8PAAAA","28":"b:+v/f/f////////s///////8PAAAA","29":"b:+v/f/f////////s///////8PAAAA","38":"b:+v+f/f////////s///////8PAAAA"},"packages/@n8n/design-system/src/components/N8nScrollArea/N8nScrollArea.vue":{"50":"b:+P+f/f/+/////3M0//////8PAAAA","68":"b:+P+f/f/+/////3M0//////8PAAAA","82":"b:+P+f/Q/8/////3M0//////8PAAAA","104":[13,18],"144":"b:+P+f/Q/8/////3M0//////8PAAAA","163":"b:+P+f/f/+/////3M0//////8PAAAA","172":"b:+P+f/f/+/////3M0/////n8PAAAA","174":"b:+P+f/f/+/////3M0//////8PAAAA","181":[36,37]},"packages/@n8n/design-system/src/components/N8nSelect/Select.vue":{"11":"b:+r7b/W33187/+fM3z+///38OAAAA","63":"b:+r7b/W33187/+fM3z+///38OAAAA","64":"b:+r7b/W33187/+fM3z+///38OAAAA","72":"b:+r7b/W33187/+fM3z+///38OAAAA","85":"b:+r7b/W33187/+fM3z+///38OAAAA","89":[11,31,44,45,46,69,86,92,5],"93":[15,16],"97":"b:AAAIAAEykAIBAAAAgAAAAQQAAAAA","113":"b:+r7b/W33187/+fM3z+///38OAAAA","134":"b:+r7b/W33187/+fM3z+///38OAAAA","136":"b:6AiBgAB1AQA4GGAQAEByA0gCAAAA","142":"b:MKABwEAzAAIhEAAAAEAACQAEAAAA","145":"b:MKABwEAzAAIhEAAAAEAACQAEAAAA"},"packages/@n8n/design-system/src/components/N8nSendStopButton/N8nSendStopButton.vue":{"5":"b:+v///f////////v///////8PAAAA","30":[9,12,13,36,37,38,39,41,42],"34":[18],"36":"b:+v///f////////v///////8PAAAA","62":"b:+v///f////////v//////n8PAAAA"},"packages/@n8n/design-system/src/components/N8nSpinner/Spinner.vue":{"20":"b:+v////////////////////8PAAAA"},"packages/@n8n/design-system/src/components/N8nTabs/Tabs.vue":{"25":"b:uJ7b/Q32187/+XM0z+///zsKAAAA","30":"b:uJ7b/Q32187/+XM0z+///zsKAAAA","40":"b:uJ7b/Q32187/+XM0z+///zsKAAAA","53":"b:OJqbeQiyV0o1+REkz+//dzkCAAAA","63":[69,117,121],"73":"b:uJ7b/Q32187/+XM0z+///zsKAAAA","92":"b:uJ7b/Q32187/+XM0z+///jsKAAAA","101":"b:uJ7b/Q32187/+XM0z+///zsKAAAA","125":"b:uAiA3QD0AQA+AHAUAAIAQBgKAAAA","142":[69,117,121]},"packages/@n8n/design-system/src/components/N8nText/Text.vue":{"18":"b:+v/f/f////////v///////8PAAAA","26":"b:+v/f/f////////v///////8PAAAA","46":"b:+v/f/f////////v///////8PAAAA","48":"b:+v/f/f////////v///////8PAAAA","52":"b:+v/f/f////////v//////n8PAAAA"},"packages/@n8n/design-system/src/components/N8nTooltip/Tooltip.vue":{"21":"b:+v///f////////v///////8PAAAA","37":"b:+v///f////////v///////8PAAAA","45":"b:+v///f////////v///////8PAAAA","46":"b:+v///f////////v///////8PAAAA","48":"b:+v///f////////v///////8PAAAA","57":"b:+v///f////////v///////8PAAAA","62":"b:+v///f////////v///////8PAAAA","63":"b:+v///f////////v///////8PAAAA","73":"b:+v///f////////v///////8PAAAA","75":"b:cNsb4S++//9x+Quk/////+sDAAAA","77":"b:+v///f////////v///////8PAAAA","88":"b:+v///f////////v//////n8PAAAA","98":"b:+v///f////////v///////8PAAAA","101":"b:+v///f////////v///////8PAAAA","109":"b:AMATAAIAAAIBIAAAgEgABAAAAAAA"},"packages/@n8n/design-system/src/components/TableBase/TableBase.vue":{"4":[85]},"packages/@n8n/design-system/src/composables/useAutosizeTextarea.ts":{"41":"b:+v///f////////v///////8PAAAA","57":"b:+v///f////////v///////8PAAAA","70":"b:+v///f////////v///////8PAAAA","116":"b:+v///f////////v///////8PAAAA","127":"b:+v///f////////v///////8PAAAA","136":"b:+v///f////////v///////8PAAAA","144":"b:+P//+a+3//////s1//////8PAAAA","154":"b:+v///f////////v///////8PAAAA","160":"b:+v///f////////v///////8PAAAA"},"packages/@n8n/design-system/src/composables/useCharacterLimit.ts":{"15":"b:+v///f////////v///////8PAAAA","19":"b:+v///f////////v///////8PAAAA","23":[9,10,12,13,18],"25":"b:+v///f////////v///////8PAAAA"},"packages/@n8n/design-system/src/composables/useI18n.ts":{"4":"b:+v///f////////v///////8PAAAA","6":"b:+v///f////////v///////8PAAAA"},"packages/@n8n/design-system/src/composables/useTooltipAppendTo.ts":{"7":"b:cP8f4A84/v/n/wOg//////8PAAAA","11":"b:+v///f////////v///////8PAAAA","14":"b:+v///f////////v///////8PAAAA"},"packages/@n8n/design-system/src/directives/n8n-html.ts":{"19":"b:MP7f4C37187x/esxz+3//ysOAAAA","31":"b:MP7f4C37187x/esxz+3//ysOAAAA"},"packages/@n8n/design-system/src/directives/n8n-truncate.ts":{"19":"b:KACAgADwAQA0AGAQAAIAQBgKAAAA"},"packages/@n8n/design-system/src/locale/format.ts":{"8":"b:+v////////////////////8PAAAA","12":"b:+v///f////////v///////8PAAAA"},"packages/@n8n/design-system/src/locale/index.ts":{"16":"b:+v///f////////v///////8PAAAA","36":"b:+v////////////////////8PAAAA","38":"b:+v////////////////////8PAAAA"},"packages/@n8n/design-system/src/plugin.ts":{"8":"b:+v////////////////////8PAAAA"},"packages/@n8n/design-system/src/utils/cn.ts":{"4":"b:+v///f////////v///////8PAAAA"},"packages/@n8n/design-system/src/utils/typeguards.ts":{"1":"b:+r7b/W33187/+fM3z+///38OAAAA"},"packages/@n8n/design-system/src/utils/uid.ts":{"6":"b:+v////////////////////8PAAAA"},"packages/@n8n/design-system/src/v2/components/Select/Select.vue":{"45":"b:+v///f////////v///////8PAAAA","63":"b:+uP//f////////v///////8PAAAA","69":"b:+v///f////////v///////8PAAAA","84":"b:+v///f////////v///////8PAAAA","91":"b:+v///f////////v///////8PAAAA","99":"b:+v///f////////v///////8PAAAA","106":[42,3],"108":"b:+uP//f////////v///////8PAAAA","110":"b:+uP//f////////v///////8PAAAA","126":"b:+v///f////////v///////8PAAAA","137":"b:+v///f////////v//////n8PAAAA","144":"b:+v///f////////v///////8PAAAA","147":"b:+v///f////////v///////8PAAAA","158":"b:+uP//f////////v///////8PAAAA","166":"b:+uP//f////////v///////8PAAAA","167":"b:+uP//f////////v//////n8PAAAA","169":[42,3],"181":"b:+uP//f////////v///////8PAAAA","182":"b:+uP//f////////v///////8PAAAA","185":"b:+uP//f////////v///////8PAAAA","188":"b:+uP//f////////v///////8PAAAA"},"packages/@n8n/design-system/src/v2/components/Select/SelectItem.vue":{"10":"b:+uP//f////////v///////8PAAAA","13":"b:+uP//f////////v///////8PAAAA","17":"b:+uP//f////////v///////8PAAAA","21":"b:+uP//f////////v///////8PAAAA","25":"b:+uP//f////////v///////8PAAAA","32":[42],"33":"b:+uP//f////////v///////8PAAAA","35":"b:+uP//f////////v///////8PAAAA","39":"b:+uP//f////////v///////8PAAAA","46":"b:+uP//f////////v///////8PAAAA"},"packages/@n8n/design-system/src/v2/utils/index.ts":{"6":"b:+uP//f////////v///////8PAAAA","12":"b:+uP//f////////v///////8PAAAA"},"packages/@n8n/i18n/src/index.ts":{"36":"b:+v////////////////////8PAAAA","48":"b:cP9b4A8y/v/h+YOhz/3//+sCAAAA","63":"b:+v////////////////////8PAAAA","93":"b:+v////////////////////8PAAAA","101":"b:cP9b4C9z/v/h+cOxz/3//+sGAAAA","105":"b:AMADAAAAAAAAIACABFwAAMAAAAAA","138":"b:cIoZoAkw/k4h0AAgxy3vfaoCAAAA","145":"b:IIgBgCBxgAAgEEAQAAAACQAEAAAA","153":"b:IIgBgCBxgAAgEEAQAAAACQAEAAAA","170":"b:IIgBgCBxgAAgEEAQAAAACQAEAAAA","180":"b:IIgBgCBxgAAgEEAQAAAACQAEAAAA","190":"b:IIgBgCBxgAAgEEAQAAAACQAEAAAA","203":"b:IIgBgCBxgAAgEEAQAAAACQAEAAAA","216":"b:IIgBgCBxgAAgEEAQAAAACQAEAAAA","229":"b:MP9b4C9z1v/h+cOxz/3//+sGAAAA","238":"b:ML5b4C1z1s7h+cMxz+3//ysGAAAA","250":"b:ML5b4A0y1s7h+YMhz+3//ysCAAAA","262":"b:ML5b4A0y1s7h+YMhz+3//ysCAAAA","277":"b:ML5b4A0y1s7h+YMhz+3//ysCAAAA","295":"b:ML5b4A0y1s7h+YMhz+3//ysCAAAA","317":"b:MJ5b4A0y1s7h+QMgz+3//ysCAAAA","340":[113,117,118,121],"373":[20,57],"380":"b:ANcbAA4gAP/BaAKAh/xilsAAAAAA","389":"b:cL4ZoA0w/m5h1gMg523vfasPAAAA","407":"b:+v////////////////////8PAAAA"},"packages/@n8n/permissions/src/scope-information.ts":{"4":"b:+v////////////////////8PAAAA","5":"b:+v////////////////////8PAAAA","6":"b:+v////////////////////8PAAAA","14":"b:+v////////////////////8PAAAA","15":"b:+v////////////////////8PAAAA","16":"b:+v////////////////////8PAAAA"},"packages/@n8n/permissions/src/utilities/get-resource-permissions.ee.ts":{"14":"b:+v+f//////////+///////8PAAAA","15":"b:+v+f//////////+///////8PAAAA","18":"b:+v+f//////////8///////8PAAAA"},"packages/@n8n/stores/src/metaTagConfig.ts":{"1":"b:+v////////////////////8PAAAA","8":"b:+v////////////////////8PAAAA","34":"b:+v////////////////////8PAAAA"},"packages/@n8n/stores/src/useAgentRequestStore.ts":{"18":"b:+v////////////////////8PAAAA","64":[8,17,75,77,96,107,111,112,114],"78":"b:AAcDAAQAAESBKAAAgchvFgAAAAAA"},"packages/@n8n/stores/src/useRootStore.ts":{"38":"b:+v////////////////////8PAAAA","69":"b:+v////////////////////8PAAAA","71":"b:AABQIAEQBAIBAAAAAIggDAACAAAA","73":"b:AABQIAEQBAIBAAAAAIggDAACAAAA","75":[110],"79":"b:AABQIAEQBAIBAAAAAIggDAACAAAA","81":"b:AMBTIAEQBAIBIACAAMggDAACAAAA","89":"b:AABQIAEQBAIBAAAAAIggDAACAAAA","91":"b:AABQIAEQBAIBAAAAAIggDAACAAAA","93":"b:+v////////////////////8PAAAA","95":"b:ANcbAA4gAP/BaAKAh/x/l8EIAAAA","97":"b:+v////////////////////8PAAAA","99":[9,10,15,16,106,110,117],"103":"b:+v+f/f////////s///////8PAAAA","105":"b:+v///f////////v///////8PAAAA","107":[11,44,46,123,138],"111":"b:+v////////////////////8PAAAA","113":[93],"115":[93],"117":[93],"119":"b:+v////////////////////8PAAAA","130":"b:+v////////////////////8PAAAA","135":"b:+v////////////////////8PAAAA","140":"b:+v////////////////////8PAAAA","144":"b:+v////////////////////8PAAAA","148":"b:+v////////////////////8PAAAA","152":"b:+v////////////////////8PAAAA","156":"b:+v////////////////////8PAAAA","160":"b:+v////////////////////8PAAAA","164":"b:+v////////////////////8PAAAA","168":"b:+v////////////////////8PAAAA","172":"b:+v////////////////////8PAAAA","177":"b:+v////////////////////8PAAAA","181":"b:+v////////////////////8PAAAA","185":"b:+v////////////////////8PAAAA","189":"b:+v////////////////////8PAAAA","193":"b:+v////////////////////8PAAAA","201":"b:+v////////////////////8PAAAA","205":"b:+v////////////////////8PAAAA","209":"b:+v////////////////////8PAAAA","213":[110,134,135]},"packages/@n8n/tournament/src/index.ts":{"16":"b:+v/////////////////////vECQA","17":"b:AMMSAHIAAIBAAAIAAEACgIHiECQA","25":"b:+v/////////////////////vECQA","29":"b:MP9T4HcwVp7h/0KgX+///6vnECQA","33":"b:MP9T4HcwVp7h/0KgX+///6vnECQA"},"packages/@n8n/utils/src/event-bus.ts":{"43":"b:+v////////////////////8PAAAA","50":"b:+v////////////////////8PAAAA","60":[90,137],"61":[90,137],"68":"b:+P//8G/7/////+u1//////8PAAAA","75":"b:8P9/8G95/v///+v3//////8PAAAA","78":"b:8P9/8A95/v///8v3//////8PAAAA"},"packages/@n8n/utils/src/sort/sortByProperty.ts":{"1":"b:+P+f/Q/8/////3M0//////8PAAAA","6":"b:eCAAgACQKQR+yAMQpaILb8sKAAAA"},"packages/@n8n/utils/src/string/truncate.ts":{"1":"b:KACAgPD2AQA0CGAQAEJyQhgKAAAA","11":"b:ACAAAPAGAIAAAAAAQIgABAAAAAAA"},"packages/frontend/editor-ui/src/Interface.ts":{"391":"b:+v////////////////////8PAAAA"},"packages/frontend/editor-ui/src/app/App.vue":{"32":"b:+v////////////////////8PAAAA","52":"b:+v////////////////////8PAAAA","61":"b:AI4LAAEwAAIhQAAAhgX/HwIAAAAA","63":"b:+v////////////////////8PAAAA","69":"b:+v////////////////////8PAAAA","75":"b:+v///f////////v///////8PAAAA","76":"b:+v///f////////v///////8PAAAA","83":"b:+v////////////////////8PAAAA","95":"b:+v///f////////v///////8PAAAA","102":"b:+v////////////////////8PAAAA","107":"b:+v////////////////////8PAAAA","115":"b:+v////////////////////8PAAAA","118":"b:+v////////////////////8PAAAA"},"packages/frontend/editor-ui/src/app/api/favorites.ts":{"16":"b:+v+f/f////////s///////8PAAAA"},"packages/frontend/editor-ui/src/app/components/BottomMenu.vue":{"23":"b:+P+f/f/+/////3M0//////8PAAAA","33":[24,102],"36":[24,102],"78":[24,69,90,102],"82":[69,90],"84":"b:+P+f/f/+/////3M0//////8PAAAA","104":[24,102],"106":[24,102],"118":[24,102],"129":"b:+P+f/Q/8/////3M0//////8PAAAA","134":[24,102],"146":[69,90],"148":[69,90],"168":"b:+P+f/f/+/////3M0//////8PAAAA","173":[69,90]},"packages/frontend/editor-ui/src/app/components/DynamicModalLoader.vue":{"9":"b:+v////////////////////8PAAAA","17":"b:+v+f/f////////s///////8PAAAA","23":"b:+v////////////////////8PAAAA","29":"b:+v+f/f////////s///////8PAAAA","44":"b:+v////////////////////8PAAAA","46":"b:+v+f/f////////s///////8PAAAA","54":"b:+v////////////////////8PAAAA","58":"b:+v+f/f////////s//////n8PAAAA","60":[38,39,40,41,47,48]},"packages/frontend/editor-ui/src/app/components/KeyboardShortcutTooltip.vue":{"21":"b:+P///f/+/////3P0//////8PAAAA"},"packages/frontend/editor-ui/src/app/components/MainSidebar.vue":{"32":"b:+P+f/Q/8/////3M0//////8PAAAA","79":"b:+P+f/Q/8/////3M0//////8PAAAA","82":"b:+P8f/A/8/////3M0//////8PAAAA","87":"b:+P+f/Q/8/////3M0//////8PAAAA","89":"b:+P+f/Q/8/////3M0//////8PAAAA","212":"b:+P+f/Q/8/////3M0//////8PAAAA","213":"b:+P+f/Q/8/////3M0//////8PAAAA","216":"b:+P+f/Q/8/////3M0//////8PAAAA","228":[24,43,48,68,69,90,131],"229":[24,43,48,68,69,90,131],"234":"b:+P+f/Q/8/////3M0//////8PAAAA","238":"b:+P+f/Q/8/////3M0//////8PAAAA","243":"b:+P+f/Q/8/////3M0//////8PAAAA","254":"b:MAAAAAAAAAAkAAAEAAIAQBgOAAAA","263":[102],"270":[137],"273":[137],"285":[24,69,90,102],"328":[69,90],"336":"b:+P+f/Q/8/////3M0//////8PAAAA","369":"b:+P+f/Q/8/////3M0//////8PAAAA"},"packages/frontend/editor-ui/src/app/components/MainSidebarHeader.vue":{"37":"b:eP+f4Q/8////+2M0//////8PAAAA","41":[24,43,48,68,69,90,131],"45":[137],"69":"b:AAAACfAOAQAwAAAEAAAAAAgAAAAA","114":"b:+P+f/Q/8/////3M0//////8PAAAA","123":"b:+P+f/Q/8/////3M0//////8PAAAA","132":"b:+P+f/Q/8/////3M0//////8PAAAA","137":[84],"144":[27,45,69,7,131],"168":"b:+P+f/f/+/////3M0//////8PAAAA"},"packages/frontend/editor-ui/src/app/components/MainSidebarSourceControl.vue":{"27":[84],"37":[84],"41":"b:+P+f/Q/8/////3M0//////8PAAAA","47":[84],"53":[84],"62":[84],"84":"b:+P+f/Q/8/////3M0//////8PAAAA","111":[84],"144":[84],"170":[84]},"packages/frontend/editor-ui/src/app/components/Modal.vue":{"59":"b:8IoBgODzgYA6FOg1QAAACTUHAAAA","81":"b:8IoBgODzgYA4FOg1QAAACTUHAAAA","90":"b:4IoBgODzAYA4EGg1QAAACTUHAAAA","97":[31,44,47,86,92,5],"102":"b:4IoBgODzAYA4FOg1QAAACTUHAAAA","109":[31,44,47,86,92,5,102],"113":"b:4IgBgGBzAIAqEGg1QAAACTUHAAAA","125":"b:IAAAgGAzAAAgAGARAAAACBAFAAAA","129":"b:8IoBgODzgYA6FOg1QAAACTUHAAAA","162":"b:8IoBgODzgYA6FOg1QAAACTUHAAAA","164":"b:IIoBgODzgYAwFMAxAAAACTAGAAAA","178":[68,69,102]},"packages/frontend/editor-ui/src/app/components/ModalDrawer.vue":{"7":"b:+v////////////////////8PAAAA","40":"b:KBYAoASQACBMgmOQd0D0RRkPAAAA","61":"b:+v////////////////////8PAAAA","75":"b:+v////////////////////8PAAAA","89":"b:+v////////////////////8PAAAA","91":[23]},"packages/frontend/editor-ui/src/app/components/ModalRoot.vue":{"20":"b:+v////////////////////8PAAAA","21":"b:+v///////////////////n8PAAAA"},"packages/frontend/editor-ui/src/app/components/Modals.vue":{"144":"b:+v////////////////////8PAAAA","146":"b:IIgBgCBxgAAgEEAQAAAACQAEAAAA","166":[102],"174":[11,31,44,45,46,69,86,92,5],"178":[65],"184":[102,136],"192":[130],"200":"b:+v////////////////////8PAAAA","204":"b:+v////////////////////8PAAAA","210":[93],"228":[7],"234":[63,93,132,133,137],"238":[90],"242":[90],"246":[4,6,137],"252":[83],"260":[83],"271":[87,88],"325":[86],"331":[86],"357":[137],"386":[74,138],"395":[68],"404":[9],"416":[67],"422":[67,68,69],"446":[128],"470":[85],"488":[63,93,132,133,137]},"packages/frontend/editor-ui/src/app/components/NpsSurvey.vue":{"14":"b:+v////////////////////8PAAAA","40":"b:+v////////////////////8PAAAA","117":"b:+v////////////////////8PAAAA","127":"b:+v////////////////////8PAAAA","144":"b:+v////////////////////8PAAAA","146":"b:+v///////////////////n8PAAAA"},"packages/frontend/editor-ui/src/app/components/UpdatesPanel.vue":{"11":"b:+v////////////////////8PAAAA","15":"b:+v///////////////////n8PAAAA","24":"b:+v////////////////////8PAAAA","29":[23],"61":[23],"70":[23]},"packages/frontend/editor-ui/src/app/components/app/AppBanners.vue":{"7":"b:+v////////////////////8PAAAA","9":"b:+v////////////////////8PAAAA","10":"b:+v////////////////////8PAAAA"},"packages/frontend/editor-ui/src/app/components/app/AppChatPanel.vue":{"8":"b:+v///f////////v///////8PAAAA","16":"b:+v///f////////v///////8PAAAA","18":"b:+v///f////////v///////8PAAAA","26":"b:+v///f////////v///////8PAAAA","41":"b:+v///f////////v///////8PAAAA"},"packages/frontend/editor-ui/src/app/components/app/AppCommandBar.vue":{"11":"b:+v////////////////////8PAAAA","24":"b:+v+f//////////8///////8PAAAA","26":"b:+v////////////////////8PAAAA","28":"b:+v+f//////////8///////8PAAAA","34":[137],"37":"b:+v////////////////////8PAAAA"},"packages/frontend/editor-ui/src/app/components/app/AppLayout.vue":{"5":"b:+v////////////////////8PAAAA","6":"b:uAiA3QL0AQA+AHAUAAIAQBgOAAAA","9":"b:ggAAAAAJAAAAANgPAAAAAAAAAAAA","12":"b:cP8f4A84/v/n/wMg//////8PAAAA","14":[26,28,69,90],"15":[21,22,94,95,110,134,135],"16":[36,37,38,39,41,42],"30":"b:+v///f////////v///////8PAAAA","35":"b:+v///f////////v///////8PAAAA","37":"b:+v////////////////////8PAAAA"},"packages/frontend/editor-ui/src/app/components/app/AppModals.vue":{"7":"b:+v////////////////////8PAAAA"},"packages/frontend/editor-ui/src/app/components/forms/ResourceFiltersDropdown.vue":{"51":[137],"63":"b:uACA3QDwAQA+AHAUAAIAQBgKAAAA","66":"b:uACA3QDwAQA+AHAUAAIAQBgKAAAA","89":"b:uACA3QDwAQA+AHAUAAIAQBgKAAAA","91":[137],"115":"b:uACA3QDwAQA+AHAUAAIAQBgKAAAA","119":[137],"126":"b:uACA3QDwAQA+AHAUAAIAQBgKAAAA","130":"b:uACA3QDwAQA+AHAUAAIAQBgKAAAA","142":"b:uACA3QDwAQA+AHAUAAIAQBgKAAAA","148":[137],"164":[137],"182":[137]},"packages/frontend/editor-ui/src/app/components/layouts/PageViewLayoutList.vue":{"10":"b:uACA3QDwAQA+AHAUAAIAQBgKAAAA"},"packages/frontend/editor-ui/src/app/components/layouts/ResourcesListLayout.vue":{"150":"b:uAiA3QDwAQA+AHAUAAIAQBgKAAAA","151":[137],"154":"b:uAiA3QDwAQA+AHAUAAIAQBgKAAAA","165":"b:uAiA3QDwAQA+AHAUAAIAQBgKAAAA","169":"b:KAiAgADwAQA+AGAQAAIAQBgKAAAA","173":[31,44,45,46,68,69,85,86,92,5],"198":[44,68,85,5],"242":"b:uAiA3QDwAQA+AHAUAAIAQBgKAAAA","243":[137],"252":"b:uAiA3QDwAQA+AHAUAAIAQBgKAAAA","259":"b:uAiA3QDwAQA+AHAUAAIAQBgKAAAA","260":[47,65,66,67,68,69,131,137],"266":"b:uAiA3QDwAQA+AHAUAAIAQBgKAAAA","273":"b:uAiA3QDwAQA+AHAUAAIAQBgKAAAA","274":[66,85,137],"278":"b:uAiA3QDwAQA+AHAUAAIAQBgKAAAA","279":[11,31,45,92,5],"285":"b:uAiA3QDwAQA+AHAUAAIAQBgKAAAA","292":"b:uAiA3QDwAQA+AHAUAAIAQBgKAAAA","299":"b:uAiA3QDwAQA+AHAUAAIAQBgKAAAA","311":"b:OACAGQCAAQA0ABAEAAIAQBgCAAAA","316":[31,44,66,67,85,86,92,5,137],"330":"b:uAiA3QDwAQA+AHAUAAIAQBgKAAAA","344":"b:uACA3QDwAQA+AHAUAAIAQBgKAAAA","349":[137],"354":"b:OAiAiQDwAQA+AHAUAAIAQAgKAAAA","358":[48],"366":[44],"377":"b:IAgAgACgAQA+AAAQAAAAAAgAAAAA","387":"b:IAgAgACgAQA+AAAQAAAAAAgCAAAA","395":[45,47,68,69,92,5,131],"402":"b:IAgAgACgAQA+AAAQAAAAAAgCAAAA","417":[85],"421":[137],"425":"b:IAgAgACgAQA+AAAQAAAAAAgAAAAA","426":"b:IAgAgACgAQA+AAAQAAAAAAgAAAAA","439":[31,44,45,46,68,69,86,92,5],"446":[85],"453":[44],"459":[137],"463":[66,85,137],"477":[44,48],"526":"b:uAiA3QDwAQA+AHAUAAIAQBgKAAAA","576":"b:uACAXQCAAQA+ABAEAAIAQBgKAAAA","592":"b:uAiA3QDwAQA+AHAUAAIAQBgKAAAA","624":"b:uACA3QDwAQA+AHAUAAIAQBgKAAAA","639":"b:uACA3QDwAQA+AHAUAAIAQBgKAAAA","649":[44],"650":"b:uACA3QDwAQA+AHAUAAIAQBgKAAAA","652":"b:uACA3QDwAQA+AHAUAAIAQBgKAAAA","670":[137],"688":"b:uACA3QDwAQA+AHAUAAIAQBgKAAAA","694":"b:uACA3QDwAQA+AHAUAAIAQBgKAAAA","721":[31,44,45,46,68,69,86,92,5],"732":"b:CACAAACAAQA+AAAAAAIAQBgKAAAA","764":[85],"768":[85],"779":[85,137]},"packages/frontend/editor-ui/src/app/composables/useAiGateway.ts":{"13":"b:+v+f/f////////s///////8PAAAA","17":"b:+v+f/Q////////s///////8PAAAA","30":"b:cP8f4A86/v/n/wMg//////8PAAAA"},"packages/frontend/editor-ui/src/app/composables/useBackendStatus.ts":{"10":"b:+v////////////////////8PAAAA","19":"b:+v////////////////////8PAAAA","49":"b:+v////////////////////8PAAAA","67":"b:IIECACAGAQIjAAAABAYAAMIAAAAA","72":"b:+v////////////////////8PAAAA"},"packages/frontend/editor-ui/src/app/composables/useBeforeUnload.ts":{"15":"b:+v////////////////////8PAAAA","22":"b:AAAAQAAAAAAkAAAAFiAAQAkCAAAA","27":"b:AAAAQAAAAAAkAAAAFiAAQAkCAAAA","32":"b:AAAAQAAAAAAgAAAAFiAAQAkCAAAA","43":"b:+v////////////////////8PAAAA","47":"b:cP9/4A84/v/l/wOg//////8PAAAA","51":"b:MIAAAAAAAAAkAAAgBF4AQNgOAAAA"},"packages/frontend/editor-ui/src/app/composables/useBrowserNotifications.ts":{"57":"b:+v///f////////v///////8PAAAA","66":[13,18],"80":[13,18]},"packages/frontend/editor-ui/src/app/composables/useBugReporting.ts":{"30":"b:+P+f/Q/8/////3M0//////8PAAAA"},"packages/frontend/editor-ui/src/app/composables/useClipboard.ts":{"24":[90,107],"44":[98,102,104,131,132],"55":[98,102,104,131],"73":"b:8P9/4P/+///n/zOk//////8PAAAA","86":"b:MJ4bYKgwV0ol+SEkz///f/kOAAAA"},"packages/frontend/editor-ui/src/app/composables/useDebounce.ts":{"19":"b:+v////////////////////8PAAAA","30":"b:cL5b4C3w1+7n+cMxx/3//+sOAAAA","43":"b:cIoZoAkw/04l0CAgx73vfaoKAAAA"},"packages/frontend/editor-ui/src/app/composables/useDebugInfo.ts":{"72":"b:+v////////////////////8PAAAA","78":"b:+P+f/Q/8/////3M0//////8PAAAA","115":"b:+P+f/Q/8/////3M0//////8PAAAA","126":"b:+P+f/Q/8/////3M0//////8PAAAA","136":"b:+P+f/Q/8/////3M0//////8PAAAA","147":"b:+P+f/Q/8/////3M0//////8PAAAA","154":"b:+P+f/Q/8/////3M0//////8PAAAA","158":[102],"166":[102],"169":[102],"174":[102],"184":"b:+P+f/Q/8/////3M0//////8PAAAA","201":"b:+P+f/Q/8/////3M0//////8PAAAA","219":[102],"233":"b:+P+f/Q/8/////3M0//////8PAAAA","237":"b:+P+f/Q/8/////3M0//////8PAAAA"},"packages/frontend/editor-ui/src/app/composables/useDocumentVisibility.ts":{"12":"b:+v///f////////v///////8PAAAA","17":"b:KgCAQDAEAQA+AFAFFiAAQBkKAAAA","28":"b:+v///f////////v///////8PAAAA","36":"b:+v///f////////v///////8PAAAA","40":[9,10,11,12,124,128,129]},"packages/frontend/editor-ui/src/app/composables/useEditorContext.ts":{"26":"b:AD4EIAgAAAAAAAEAxwAgAAAAAAAA","29":"b:cP8f4A84/v/n/wMg//////8PAAAA","40":"b:+v////////////////////8PAAAA","41":"b:cP8f4A84/v/n/wMg//////8PAAAA","47":"b:cP8f4A84/v/n/wMg//////8PAAAA","48":"b:cP8fwA8wAP/naQKgn///1/8OAAAA","51":"b:cP8fwA8wAP/naQKgn///1/8OAAAA"},"packages/frontend/editor-ui/src/app/composables/useErrorHandler.ts":{"26":"b:+v///f////////v///////8PAAAA"},"packages/frontend/editor-ui/src/app/composables/useExecutingNode.ts":{"15":"b:+v////////////////////8PgAAA","19":"b:ANcbAA4gAP/BaAKAh/x/l8EAgAAA","24":"b:ANcbAA4gAP/BaAKAh/x/l8EAgAAA","33":"b:cP9/4A84/v/n/wPg//////8PgAAA","38":"b:cP8b4A8w/v/h/wPg//////sPgAAA"},"packages/frontend/editor-ui/src/app/composables/useExposeCssVar.ts":{"7":"b:+v////////////////////8PAAAA","11":"b:+v////////////////////8PAAAA","12":"b:+v////////////////////8PAAAA"},"packages/frontend/editor-ui/src/app/composables/useExternalHooks.ts":{"10":"b:+v///f////////v///////8PAAAA"},"packages/frontend/editor-ui/src/app/composables/useFloatingUiOffsets.ts":{"9":"b:+v////////////////////8PAAAA","15":"b:MJ5b4A0w1s7h+YMhx+3//ysCAAAA","16":"b:+v////////////////////8PAAAA","19":"b:+v////////////////////8PAAAA","20":"b:+v////////////////////8PAAAA","29":"b:+v////////////////////8PAAAA"},"packages/frontend/editor-ui/src/app/composables/useGlobalEntityCreation.ts":{"22":"b:eCCAgALUeSR+yEMQ5aJPb8sKAAAA","25":"b:eCCAgALUeSR+yEMQ5aJPb8sKAAAA","65":"b:+P+f/Q/8/////3M0//////8PAAAA","68":"b:+P+f/Q/8/////3M0//////8PAAAA","72":"b:+P+f/Q/8/////3M0//////8PAAAA","76":"b:+P+f/Q/8/////3M0//////8PAAAA","83":"b:+P+f/Q/8/////3M0//////8PAAAA","85":"b:+P+f/Q/8/////3M0//////8PAAAA","92":"b:+P+f/Q/8/////3M0//////8PAAAA","102":"b:+P+f/Q/8/////3M0//////8PAAAA","226":"b:eCCAgALUeSR+yEMQ5aJPb8sKAAAA","260":"b:eCCAgALUeSR+yEMQ5aJPb8sKAAAA","320":[23,48,3,69,5,131,137],"343":[23,48,3,69,5,126,131,137],"354":[27,45,69,7,131],"379":"b:+P+f/Q/8/////3M0//////8PAAAA","380":"b:+P+f/Q/8/////3M0//////8PAAAA","381":"b:+P+f/Q/8/////3M0//////8PAAAA"},"packages/frontend/editor-ui/src/app/composables/useHistoryHelper.ts":{"17":"b:+v////////////////////8PAAAA","26":[102,128],"54":[102],"82":[102,128],"88":[102,128],"93":[102],"104":"b:CLYAIASQRCBM0iOAd2D0RfkPAAAA","111":"b:KLYAoASQRCBM0mOQd2D0RfkPAAAA","141":"b:+v////////////////////8PAAAA"},"packages/frontend/editor-ui/src/app/composables/useKeybindings.ts":{"60":"b:+P///f/+/////3P0//////8PAAAA","81":"b:AKAAIACARAAA0AAAdyCAQPkOAAAA","83":"b:KLYAoASQRCBM0mOQd2D0RfkPAAAA","87":"b:AKAAIACARAAA0AAAdyCAQPkOAAAA","89":"b:AKAAIACARAAA0AAAdyCAQPkOAAAA","91":"b:AKAAIACARAAA0AAAdyCAQPkOAAAA","96":"b:AKAAIACARAAA0AAAdyCAQPkOAAAA","98":"b:AKAAIACARAAA0AAAdyCAQPkOAAAA","99":"b:AKAAIACARAAA0AAAdyCAQPkOAAAA","103":"b:AKAAIACARAAA0AAAdyCAQPkOAAAA","109":"b:AKAAIACARAAA0AAAdyCAQPkOAAAA","127":"b:AKAAIACARAAA0AAAdyCAQPkOAAAA","145":"b:AKAAIACARAAA0AAAdyCAQPkOAAAA","199":"b:KLYAoASQRCBM0mOQd2D0RfkPAAAA"},"packages/frontend/editor-ui/src/app/composables/useMessage.ts":{"14":[88,106,123,126,138],"48":"b:AAAAAICQAQAAADAhAAwASBAGAAAA","63":"b:AAAAAICQAQAAADAhAAwASBAGAAAA","110":[66,67,98]},"packages/frontend/editor-ui/src/app/composables/useN8nLocalStorage.ts":{"26":"b:uAiA3QDwAQA+AHAUAAIAQBgKAAAA","29":"b:uACAXQCAAQA+ABAEAAIAQBgKAAAA","33":[48],"58":"b:uACAXQCAAQA+ABAEAAIAQBgKAAAA"},"packages/frontend/editor-ui/src/app/composables/useNodeDirtiness.ts":{"27":[78,97,98,110,128,134,135],"35":[78,97,98,110,128,134,135],"58":[110,128],"66":[78,97,98,110,128,134,135],"67":[78,97,98,110,128,134,135],"77":[134,135],"89":"b:AAQAAAAAAACBQAAAgMQAFQEAAAAA","138":"b:+v////////////////////8PAAAA","142":"b:ANcbAA4gAP/BaAKAh/x/l8EAAAAA","146":"b:ANcbAA4gAP/BaAKAh/x/l8EAAAAA","150":[78,134,135],"154":"b:ANcbAA4gAP/BaAKAh/x/l8EAAAAA","156":"b:ANcbAAwgAL/BaAKAhvx/l8EAAAAA","157":[8,15,16,17,110],"160":"b:ANcbAA4gAP/BaAKAh/x/l8EAAAAA","177":"b:ANcbAA4gAP/BaAKAh/x/l8EAAAAA","213":[78],"216":[78],"256":"b:cP974A8w/v/h/wPg3/////sPAAAA","260":"b:AAQAAAAAAACBQAAAgMQAFQEAAAAA","269":[78],"306":"b:ANcbAAwgAL/BaAKAhvx/l8EAAAAA","307":"b:ANcbAAwgAL/BaAKAhvx/l8EAAAAA"},"packages/frontend/editor-ui/src/app/composables/useResourcesListI18n.ts":{"8":"b:uAiA3QDwAQA+AHAUAAIAQBgKAAAA","15":"b:uACA3QDwAQA+AHAUAAIAQBgKAAAA"},"packages/frontend/editor-ui/src/app/composables/useSelectionValidation.ts":{"25":"b:+v////////////////////8PAAAA","37":[100],"54":[100,128],"61":[100],"68":[100],"78":[100,128],"84":[100,128],"86":[100,128],"93":[100,128],"95":[100,128]},"packages/frontend/editor-ui/src/app/composables/useSettingsItems.ts":{"23":"b:+v+f/f////////s///////8PAAAA","192":"b:+v+f/f////////s///////8PAAAA","195":"b:+v+f/f////////s///////8PAAAA"},"packages/frontend/editor-ui/src/app/composables/useSidebarLayout.ts":{"9":"b:+P+f/f/+/////3M0//////8PAAAA","12":[24,43,48,68,69,90,131]},"packages/frontend/editor-ui/src/app/composables/useStorage.ts":{"4":"b:+v////////////////////8PAAAA"},"packages/frontend/editor-ui/src/app/composables/useStyles.ts":{"26":"b:+v////////////////////8PAAAA","27":"b:+v////////////////////8PAAAA","34":"b:+v////////////////////8PAAAA"},"packages/frontend/editor-ui/src/app/composables/useTelemetry.ts":{"4":"b:+v////////////////////8PAAAA"},"packages/frontend/editor-ui/src/app/composables/useTelemetryInitializer.ts":{"13":"b:+v////////////////////8PAAAA","27":"b:+v////////////////////8PAAAA","32":"b:+v////////////////////8PAAAA","36":"b:+v////////////////////8PAAAA","40":"b:+v////////////////////8PAAAA","59":"b:+v////////////////////8PAAAA","69":"b:+v////////////////////8PAAAA"},"packages/frontend/editor-ui/src/app/composables/useToast.ts":{"23":"b:6NeLgK53Af//eHqWl/x/390GAAAA","93":"b:gACAAAAAAAA+AAAGEAQAQBACAAAA","107":[23],"149":[41,42,44,48,89,122,138],"186":"b:AIYBAAA2AQAAAAAChEwgBMgEAAAA","192":"b:MNcbEA4gAP/laAKkh/9/19kOAAAA","193":[9,10,106,134,135,138],"203":"b:cP9/4A84/v/n/wOg//////8PAAAA","205":"b:cP9/4A84/v/n/wOg//////8PAAAA"},"packages/frontend/editor-ui/src/app/composables/useUniqueNodeName.ts":{"4":"b:+v////////////////////8PAAAA","11":"b:AIAAAAAAAAAAAAAA5gEANAgAAAAA","12":"b:AIAAAAAAAAAAAAAA5gEANAgAAAAA","27":"b:cL4ZoA0w/m5h1gMg523vfasPAAAA","34":"b:AIAAAAAAAAAAAAAA5gEANAgAAAAA"},"packages/frontend/editor-ui/src/app/composables/useUserHelpers.ts":{"5":"b:+v+f/f////////s///////8PAAAA","6":"b:+v+f/f////////s///////8PAAAA","12":"b:+v+f/f////////s///////8PAAAA"},"packages/frontend/editor-ui/src/app/composables/useWorkflowDiffRouting.ts":{"18":"b:+v////////////////////8PAAAA","27":"b:+v////////////////////8PAAAA","50":"b:+v////////////////////8PAAAA","73":"b:+v////////////////////8PAAAA","111":"b:+v////////////////////8PAAAA","133":"b:+v////////////////////8PAAAA"},"packages/frontend/editor-ui/src/app/composables/useWorkflowHelpers.ts":{"71":"b:AIJRIAESBophOUIAA8mvHwMCgAAA","172":"b:AAIAAAAAAIBACAIAAEgHFwEAgAAA","275":"b:AAAAIAAAAAAgAAAAAAAgGQMAgAAA","285":"b:AAAAIAAAAAAgAAAAAAAgGQMAgAAA","310":"b:AJYZAA4gALtBwgMARvxwx8kJgAAA","316":"b:AIJRIAEQBophOQIAA8mvHwMCgAAA","347":"b:AAIAAAAAAIAACAIAAEkPFwEAgAAA","363":[9,151,62,64,96,107,122],"389":"b:AIJRIAEQBsphOQIAA8mvHwMCgAAA","478":"b:+v////////////////////8PgAAA","491":"b:ABYAAAQAACBAggMAREBgRQgBgAAA","517":"b:cJ4JoA0w/ixg0gMAx03iXaoAgAAA","531":"b:AABRIAEQBAIBAAAAAIggDAACgAAA","552":"b:AABQIAEQBAIBAAAAAIggDAACgAAA","593":[9,10,151],"596":[9,10,151],"627":"b:AIJRIAESBoJBOUIAAcmvHwACgAAA","657":[151],"704":"b:ABYAAAQAACBAggMAREBgRQgBgAAA","735":[151,65,96,98,102,122,131,138],"739":[151,96,98,102,122,131,138],"744":[151,138],"746":[151,138],"760":[151,65],"768":[151],"778":"b:cMdzQA4gALvjaQKAnvrzw9kOgAAA","816":"b:cMdzQA4gALvjaQCAnvrzw9kOgAAA","847":[151],"857":[151],"870":[151],"881":[151]},"packages/frontend/editor-ui/src/app/composables/useWorkflowId.ts":{"6":"b:+v////////////////////8PAAAA","12":"b:+v///f////////v///////8PAAAA"},"packages/frontend/editor-ui/src/app/composables/useWorkflowSaving.ts":{"44":"b:+v////////////////////8PAAAA","71":[69,105,126,132],"75":[126],"147":"b:QL4dwA0wAGblYAIgl83vV+8OAAAA","154":"b:QL4dwA0wAGblYAIgl83vV+8OAAAA","184":"b:QL4dwA0wAGblYAIgl83vV+8OAAAA","359":"b:QL4dgA0wAGZnQAIgh03tVa4OAAAA","555":"b:QL4RwA0wACJlQAIgl03nQ+8GAAAA","569":"b:QL4RwA0wACJlQAIgl03nQ+8GAAAA","588":"b:cL4Z4A0w/m7l9gMg9+3vf+8PAAAA","614":[137],"622":"b:+v////////////////////8PAAAA"},"packages/frontend/editor-ui/src/app/composables/useWorkflowUpdate.ts":{"44":"b:+v///f////////v///////8PAAAA","64":[13],"66":[13],"69":[13],"76":[13],"99":[13],"112":[13],"189":[13],"198":[13],"202":[13],"217":[13],"242":[13],"254":[13],"255":[13],"259":[13],"261":[13],"285":[13],"319":[13],"334":[13],"349":[13],"370":[13]},"packages/frontend/editor-ui/src/app/constants/actions.ts":{"1":"b:+v////////////////////8PAAAA"},"packages/frontend/editor-ui/src/app/constants/durations.ts":{"33":"b:+v////////////////////8PAAAA"},"packages/frontend/editor-ui/src/app/constants/experiments.ts":{"6":"b:+v////////////////////8PAAAA"},"packages/frontend/editor-ui/src/app/constants/navigation.ts":{"1":"b:+v////////////////////8PAAAA","79":"b:+v////////////////////8PAAAA"},"packages/frontend/editor-ui/src/app/constants/nodeTypes.ts":{"136":"b:+v////////////////////8PAAAA"},"packages/frontend/editor-ui/src/app/constants/workflows.ts":{"16":"b:+v////////////////////8PAAAA"},"packages/frontend/editor-ui/src/app/dev/render-tracker.ts":{"38":"b:+v////////////////////8PAAAA","67":"b:+v////////////////////8PAAAA"},"packages/frontend/editor-ui/src/app/init.ts":{"45":"b:+v////////////////////8PAAAA","99":"b:+v///f////////v///////8PAAAA","163":[43],"185":"b:+v+f/b////////s///////8PAAAA","230":"b:+v////////////////////8PAAAA","243":"b:+v+f//////////8///////8PAAAA","279":[69,90]},"packages/frontend/editor-ui/src/app/layouts/BaseLayout.vue":{"10":"b:+v////////////////////8PAAAA"},"packages/frontend/editor-ui/src/app/layouts/DefaultLayout.vue":{"8":"b:uAiA3QD0AQA+AHAUAAIAQBgOAAAA","10":"b:uAiA3QD0AQA+AHAUAAIAQBgOAAAA"},"packages/frontend/editor-ui/src/app/models/history.ts":{"8":"b:+v////////////////////8PAAAA","35":"b:cL4ZoA0w/m5h8gMg923vfesDAAAA","44":[128],"52":"b:cL4doA0w/m5h8gMg923vfesDAAAA","57":"b:AJYZAAwgAGZBYAIAh0xtFcEAAAAA","58":"b:AJYZAAwgAGZBYAIAh0xtFcEAAAAA","69":[13,77,78,79,96,97,100,102,131],"81":[102],"85":[13,78,79,96],"96":[102],"97":[102],"110":"b:cL4ZoA0w/m5h0gMg523vfasDAAAA","115":[102,128],"119":"b:ML4ZoA0w1i5h0gMgx2XvfSsBAAAA","123":[102,128],"124":[102,128],"134":[73,96,97,100,102,110,128],"139":[102,128],"143":[97,102,128],"147":[102,128],"148":[102,128],"158":"b:ML4ZoA0w1i5h0gMg12XvfSsBAAAA","163":[102,128],"167":"b:ACYBAAAAECBAwgIAU0BgBQEBAAAA","177":[102,128],"178":[102,128],"188":"b:ACAAAAAAAAAAwgAAU0AAAAEAAAAA","193":[102,128],"197":"b:ACAAAAAAAAAAwgAAU0AAAAEAAAAA","207":[102,128],"208":[102,128],"209":[102,128],"224":"b:AIAAAAAAAAAAAAAgRUAAAOAAAAAA","231":[102],"235":[98,102],"241":[102],"242":[102],"257":[98],"287":[79,128],"296":[128],"305":[79],"314":[128],"315":[128]},"packages/frontend/editor-ui/src/app/moduleInitializer/modalRegistry.ts":{"6":"b:+v////////////////////8PAAAA","10":"b:+v+f/f////////s///////8PAAAA","11":"b:+v+f/f////////s///////8PAAAA","14":"b:+v+f/f////////s///////8PAAAA","42":"b:+v////////////////////8PAAAA"},"packages/frontend/editor-ui/src/app/moduleInitializer/moduleInitializer.ts":{"31":"b:+v+f/f////////s///////8PAAAA","32":"b:+v+f/f////////s///////8PAAAA","33":"b:+v+f/f////////s///////8PAAAA","42":"b:+v+f/f////////s///////8PAAAA","44":"b:+v+f/f////////s///////8PAAAA","62":"b:+v+f/f////////s///////8PAAAA","64":"b:+v+f/f////////s///////8PAAAA","75":[47,48],"101":"b:+v+f/f////////s///////8PAAAA","102":"b:+v+f/f////////s///////8PAAAA","103":"b:+v+f/f////////s///////8PAAAA","114":"b:+v////////////////////8PAAAA","115":"b:+v////////////////////8PAAAA","116":"b:+v////////////////////8PAAAA"},"packages/frontend/editor-ui/src/app/moduleInitializer/resourceRegistry.ts":{"25":"b:+v+f/f////////s///////8PAAAA"},"packages/frontend/editor-ui/src/app/plugins/chartjs.ts":{"15":"b:+v////////////////////8PAAAA"},"packages/frontend/editor-ui/src/app/plugins/components.ts":{"10":"b:+v////////////////////8PAAAA"},"packages/frontend/editor-ui/src/app/plugins/directives.ts":{"5":"b:+v////////////////////8PAAAA"},"packages/frontend/editor-ui/src/app/plugins/sentry.ts":{"26":[82],"29":[82],"53":"b:+v////////////////////8PAAAA"},"packages/frontend/editor-ui/src/app/plugins/telemetry/index.ts":{"33":"b:+v///f////////v///////8PAAAA","37":"b:+v////////////////////8PAAAA","72":"b:+v+f/f////////s///////8PAAAA","104":"b:eP8f8f///////+u/7/////8PAAAA","127":"b:+v///f////////v///////8PAAAA","157":[69,90],"169":[103],"199":"b:MJQZoA0wgA6hAAEAx4WvHQMAAAAA","274":"b:+v////////////////////8PAAAA"},"packages/frontend/editor-ui/src/app/push-connection/useEventSourceClient.ts":{"13":"b:+v////////////////////8PAAAA"},"packages/frontend/editor-ui/src/app/push-connection/useHeartbeat.ts":{"12":"b:+v////////////////////8PAAAA","17":"b:+v////////////////////8PAAAA","21":[39,105]},"packages/frontend/editor-ui/src/app/push-connection/useReconnectTimer.ts":{"14":"b:+v////////////////////8PAAAA","33":[39,105],"40":"b:cP8f4P8+/v/l/wuo//////8PAAAA"},"packages/frontend/editor-ui/src/app/push-connection/useWebSocketClient.ts":{"24":"b:+v////////////////////8PAAAA","35":[8,41,69],"40":"b:cP8f4P8+/v/l/wuo//////8PAAAA","53":"b:cP8fwP82AP/laQKgn///1/8OAAAA","61":"b:cP8f4P8+/v/n/wuo//////8PAAAA","75":"b:cP8f4P8+/v/l/wuo//////8PAAAA","94":"b:cP8fwA8wAP/naQIgn///1/8OAAAA"},"packages/frontend/editor-ui/src/app/router.ts":{"40":"b:cP9/4A84/v/n/wOg//////8PAAAA","41":[15,98,106,107,108,110,134,135],"42":[15,98,106,107,108,110,134],"43":[15,98,106,107,108,110,134,135],"44":[15,98,106,107,108,110,134],"47":[98,106,107,108,110,134,135],"48":[98,106,107,108,110,134],"51":[1,89,90],"52":[1,89,90],"53":[7],"54":[7],"56":[83],"57":[83],"58":[43],"59":[43],"60":[87,88],"61":[87,88],"63":[26,28,69,90],"65":[138],"66":[138],"67":[139],"68":[139],"69":[138],"70":[138],"71":[139],"72":[139],"78":[69,90],"80":[84],"81":[84],"82":[86],"87":[86],"96":[91],"97":[91],"98":[105],"99":[105],"100":[139],"101":[93],"102":[93],"105":[93],"106":[93],"174":"b:CACATUKAAQAwAAAAAAAAQAACAAAA","253":[74,138],"282":[139],"287":[139],"446":"b:cL4doA84/m5l1gMg503vfb4PAAAA","466":[21,22,95,110,134,135],"477":[94],"483":[94],"591":[25],"610":"b:+v+f/f////////s///////8PAAAA","732":[9,10,11,12,13,18],"786":"b:+v+f9b////////s///////8PAAAA","1009":"b:+v+f9b////////s///////8PAAAA","1085":"b:+v////////////////////8PAAAA","1100":"b:+v///f////////v///////8PAAAA","1110":"b:+v////////////////////8PAAAA","1142":[26,28,7],"1174":"b:+v///f////////v///////8PAAAA"},"packages/frontend/editor-ui/src/app/stores/aiGateway.store.ts":{"13":[151],"17":"b:+v/f/f////////s///////8PgAAA","27":[151],"37":[151],"48":[151],"59":[151],"70":[151],"74":[151],"78":[151]},"packages/frontend/editor-ui/src/app/stores/backendConnection.store.ts":{"7":"b:+v////////////////////8PAAAA","10":"b:+v////////////////////8PAAAA"},"packages/frontend/editor-ui/src/app/stores/canvas.store.ts":{"6":"b:+v////////////////////8PAAAA","13":"b:AEECIAAAAAABIAAAP0BgAAEAAAAA","20":"b:cP8f4A84/v/l/wOg//////8PAAAA"},"packages/frontend/editor-ui/src/app/stores/cloudPlan.store.ts":{"25":"b:+v////////////////////8PAAAA","34":[69,90],"40":[24,27,43,69,84,90,131],"42":[43],"45":[43],"48":[43],"58":[43],"65":[43],"71":[43],"73":[43],"83":[43],"85":[43],"87":"b:+P+f/Q/8/////3M0//////8PAAAA","89":[43],"91":"b:uACAXQCAAQA+ABAEAAIAQBgKAAAA","111":[43],"122":[1,43,89,90],"127":[43],"142":[43],"158":[43],"183":[43],"204":[43],"217":[43],"228":[43],"236":[43]},"packages/frontend/editor-ui/src/app/stores/favorites.store.ts":{"9":"b:+v////////////////////8PAAAA","32":"b:+v+f/f////////s///////8PAAAA","42":"b:eP+f4A/8/////0Mg//////8PAAAA","48":[23,47,48,67,3,69,5,131,137],"82":[132,137],"88":[69,90]},"packages/frontend/editor-ui/src/app/stores/focusPanel.store.ts":{"47":"b:+v////////////////////8PAAAA","54":"b:+v////////////////////8PAAAA","64":"b:+v////////////////////8PAAAA","72":"b:cP9/4A84/v/l/wOg//////8PAAAA","73":[80,99],"74":"b:+v////////////////////8PAAAA","77":"b:+v////////////////////8PAAAA","99":"b:+v////////////////////8PAAAA","105":[65,80,99],"140":"b:QL4dgA0wAGZnQAIgh03tVa4OAAAA","176":[80,99],"194":[80,99],"205":"b:+v////////////////////8PAAAA","206":[80,99],"218":"b:+v////////////////////8PAAAA"},"packages/frontend/editor-ui/src/app/stores/history.store.ts":{"10":"b:+v////////////////////8PAAAA","17":[102,128],"24":"b:cL4ZoA0w/m5h8gMg923vfesDAAAA","28":"b:ML4ZoA0w1i5h0gMg12XvfSsBAAAA","41":[102],"48":"b:cL4ZoA0w/m5h8gMg923vfesDAAAA","53":[102,128],"58":"b:cP9/4A84/v/l+wPg//////8PAAAA","61":"b:cP9/4A84/v/l+wPg//////8PAAAA","64":"b:cP9/4A84/v/l+wPg//////8PAAAA","68":[102],"74":[102,128],"78":"b:cL4doA0w/m5h8gMg923vfesDAAAA","81":"b:cL4doA0w/m5h8gMg923vfesDAAAA"},"packages/frontend/editor-ui/src/app/stores/logs.store.ts":{"19":"b:+v////////////////////8PAAAA","22":"b:cP8f4A84/v/n/wOg//////8PAAAA","50":"b:cP8f4A84/v/l/wOg//////8PAAAA","54":"b:+v////////////////////8PAAAA","58":[14,15,17,69,95],"62":[14,15,17,69,95],"66":[14,15,16,17,77,95,110],"74":[14,15,16,17,77,110],"78":[110],"124":[14,15,16,17,77,95,110],"130":"b:cP8f4A84/v/l/wOg//////8PAAAA","131":[14,15,16,17,77,110],"134":"b:+v////////////////////8PAAAA","135":"b:cP8f4A84/v/l/wOg//////8PAAAA","136":"b:AMADAAAQAgAAMACAAECAAAAAAAAA","137":[14,15,16,17,77,95,110]},"packages/frontend/editor-ui/src/app/stores/nodeTypes.store.ts":{"42":"b:+v////////////////////8PgAAA","57":"b:cIoZoAkw/k4h0AAgxy3vfaoCgAAA","58":"b:cIoZoAkw/k4h0AAgxy3vfCoCgAAA","76":"b:cP8f4A86/v/n/wsg//////8PgAAA","78":"b:cL8f4A84/P9n/wsg97////8PgAAA","79":"b:cL8f4A84/P9n/wsg97////8PgAAA","82":"b:cIoZoAkw/k4h0AAgxy3vfaoCgAAA","84":"b:cIoJoAkQ/E4h0AAgxy3vfaoCgAAA","85":"b:cIoJoAkQ/E4h0AAgxy3vfaoCgAAA","88":"b:cIoZoAkw/k4h0AAgxy3vfaoCgAAA","92":"b:cP9/4A84/v/n/wPg//////8PgAAA","93":"b:cP8f4A84/v/n/wMg//////8PgAAA","94":"b:cP8f4A84/v/n/wMg//////8PgAAA","98":"b:cP8f4A86/v/n/wsg//////8PgAAA","100":"b:cP8f4A86/v/n/wsg//////8PgAAA","108":"b:cP8f4A86/v/n/wsg//////8PgAAA","109":"b:cP8f4A86/v/n/wsg//////8PgAAA","125":"b:cP9/4C87/v/n/8Px//////8PgAAA","126":"b:cP974C8z/v/h/8Px/////nsPgAAA","141":"b:MJ5b4A0w1s7h+QMgz+3//ysCgAAA","142":"b:MJ5b4A0w1s7h+QMgz+3//isCgAAA","147":[151,58],"148":[151,58],"159":"b:cP974A8w/v/h/wPg3/////sPgAAA","160":"b:cP974A8w/v/h/wPg3////nsPgAAA","172":"b:cP974A8w/v/h/wPg3/////sPgAAA","177":"b:cP974A8w/v/h/wPg//////sPgAAA","178":"b:cP974A8w/v/h/wPg/////nsPgAAA","184":"b:ML9b4A0w1s7h+QMgz+3//ysCgAAA","185":"b:ML9b4A0w1s7h+QMgz+3//isCgAAA","188":"b:ML8b4A0w1s7h+QMgz+3//ysAgAAA","200":"b:MJ5b4A0w1s7h8QMgz+3//ysCgAAA","201":"b:MJ5b4A0w1s7h8QMgz+3//isCgAAA","204":"b:MJ4b4A0w1s7h8QMgz+3//ysAgAAA","216":[151],"217":[151],"222":"b:cP8f4A86/v/n/wsg//////8PgAAA","226":"b:cP8f4A86/v/n/wsg//////8PgAAA","229":[151],"230":[151],"236":[15,16,151,41,49,119,120],"237":[15,16,151,41,49,119,120],"241":[15,16,151,41,49,119,120],"262":[15,16,151,41,49,119,120],"278":[151],"279":[151],"283":[151],"302":"b:cP974A8w/v/h/wPg3/////sPgAAA","303":"b:cP974A8w/v/h/wPg3////nsPgAAA","317":"b:MP974A8w1r/h/wPg3////+sNgAAA","328":"b:+v///f////////v///////8PgAAA","336":[151],"337":[151],"343":[151],"352":[151],"364":[151],"375":"b:+v////////////////////8PgAAA","382":"b:+v+f//////////9///////8PgAAA","388":[151],"396":[151,29,117,120],"400":[151,123],"404":[151,123,124],"412":[151,69,128,129],"420":[151],"424":"b:cP9/4A84/v/n/wvg//////8PgAAA","434":"b:cL9/4A84/P9n/wvg97////8PgAAA","441":[151,55,83],"456":"b:cP974A8w/v/h/wOg//////sPgAAA","457":"b:cP974A8w/v/h/wOg/////nsPgAAA","466":"b:+v////////////////////8PgAAA","469":[151],"470":"b:APdbIA8wBv/h+wPAx/3/38sLgAAA"},"packages/frontend/editor-ui/src/app/stores/npsSurvey.store.ts":{"18":"b:+v////////////////////8PAAAA","27":"b:+v+f/f////////s///////8PAAAA","35":"b:oIARIAAABCgEEIghMk2xgOUBAAAA","75":[69,90],"79":"b:QL4RwA0wACJlQAIgl0XnQ68GAAAA"},"packages/frontend/editor-ui/src/app/stores/posthog.store.ts":{"21":"b:+v////////////////////8PAAAA","36":[69,90],"51":[69,90],"59":"b:+v///f////////v///////8PAAAA","63":"b:+v///f////////v///////8PAAAA","70":"b:+v///f////////v///////8PAAAA","162":"b:+v+f/f////////s///////8PAAAA"},"packages/frontend/editor-ui/src/app/stores/pushConnection.store.ts":{"17":"b:+v////////////////////8PAAAA","35":"b:cP9/4P8+/v/l/wvo//////8PAAAA","38":[39,69,105,126,132],"46":"b:+v////////////////////8PAAAA","48":"b:+v////////////////////8PAAAA","66":"b:cP8fwP82AP/naQKgn///1/8OAAAA","80":"b:cP8fwP82AP/naQKgn///1/8OAAAA","85":"b:+v////////////////////8PAAAA","87":"b:+v////////////////////8PAAAA","93":"b:cP8fwA8wAP/naQIgn///1/8OAAAA","105":"b:cP8f4P8+/v/l/wuo//////8PAAAA","125":"b:cP8f4P8+/v/n/wuo//////8PAAAA","132":"b:cP8f4P8+/v/n/wug//////8PAAAA","148":[39,105,126,132],"160":[39],"173":"b:+v////////////////////8PAAAA","174":"b:cP8f4P8+/v/n/wuo//////8PAAAA","195":[69,105,126,132],"199":"b:cP8f4P8+/v/l/wOo//////8PAAAA"},"packages/frontend/editor-ui/src/app/stores/rbac.store.ts":{"8":"b:+v////////////////////8PAAAA","77":"b:+v+f/f////////s///////8PAAAA","113":"b:+v////////////////////8PAAAA"},"packages/frontend/editor-ui/src/app/stores/roles.store.ts":{"19":"b:+v+f/f////////s///////8PAAAA","36":[23,42,48,3,69,86,5,131,137],"37":[23,42,48,3,69,86,5,131,137],"40":[23,42,48,3,69,86,5,131,137],"42":[23,42,48,3,69,86,5,131,137],"43":[23,42,48,3,69,86,5,131,137],"46":[23,42,48,3,69,86,5,131,137],"53":[40,45,92,5],"54":[40,45,92,5],"57":[4,6,137],"58":[4,6,137],"61":"b:+v+f/f////////s///////8PAAAA"},"packages/frontend/editor-ui/src/app/stores/settings.store.ts":{"22":"b:+v////////////////////8PAAAA","51":"b:+P+f/Q/8/////3M0//////8PAAAA","53":"b:+P+f/Q/8/////3M0//////8PAAAA","55":"b:+P+f/Q/8/////3M0//////8PAAAA","59":"b:+P+f/Q/8/////3M0//////8PAAAA","61":"b:+P+f/Q/8/////3M0//////8PAAAA","63":"b:+P+f/Q/8/////3M0//////8PAAAA","68":"b:+v////////////////////8PAAAA","70":"b:+P+f/Q/8/////3M0//////8PAAAA","72":"b:+P+f/Q/8/////3M0//////8PAAAA","74":"b:+v////////////////////8PAAAA","76":"b:+v////////////////////8PAAAA","78":"b:+v+f/f////////s///////8PAAAA","80":[43],"82":"b:+v////////////////////8PAAAA","84":"b:cP8f4A84/v/l/wMg//////8PAAAA","86":[43],"88":[43],"90":"b:+v////////////////////8PAAAA","94":"b:cI4ZoAkw/k4h0AEgxy3vfSoCAAAA","96":"b:+v///f////////v///////8PAAAA","100":[9,10,11,12,13,18],"104":"b:+v///f////////v///////8PAAAA","106":"b:+P+f/Q/8/////3M0//////8PAAAA","108":"b:+v+f/f////////s///////8PAAAA","110":"b:+v////////////////////8PAAAA","112":"b:+v////////////////////8PAAAA","131":"b:uJ7b/f33187/+XM0z+///zsOAAAA","135":[36,37,38,39,41,42],"141":"b:+v+f/f////////s///////8PAAAA","147":"b:+P///Q+4/////xOk//////8PAAAA","151":"b:+v////////////////////8PAAAA","155":"b:oIARIAAABCgEEIghMk2xgOUBAAAA","163":[1,89,90],"165":"b:uAiA3QDwAQA+AHAUAAIAQBgKAAAA","167":"b:+v+f/f////////s///////8PAAAA","169":"b:+v////////////+///////8PAAAA","173":"b:OJ7b4A02187h+UMgz+3//ysCAAAA","192":[16],"196":[42,3],"200":"b:eP+f4A+4/////wMg//////8PAAAA","204":"b:cP8f4A84/v/n/wMg//////8PAAAA","210":"b:+v////////////////////8PAAAA","212":"b:+P+f/Q/8/////3M0//////8PAAAA","214":[139],"216":"b:+P+f/Q/8/////3M0//////8PAAAA","218":"b:+v////////////////////8PAAAA","220":"b:+v//9b////////v///////8PAAAA","222":[83],"228":"b:+v+f/f////////s///////8PAAAA","229":"b:cP8f4A84/v/l/wMg//////8PAAAA","231":[91,127,133],"233":[93],"237":[43],"239":"b:+P+f/Q/8/////3M0//////8PAAAA","243":"b:+v////////////////////8PAAAA","245":"b:+v////////////////////8PAAAA","277":"b:+v////////////////////8PAAAA","281":"b:+v////////////////////8PAAAA","285":"b:+v////////////////////8PAAAA","289":"b:+v////////////////////8PAAAA","293":"b:+v////////////////////8PAAAA","297":"b:+v////////////////////8PAAAA","347":"b:+v////////////////////8PAAAA","371":[139],"372":[139],"377":[93],"386":"b:+v+f/f////////s///////8PAAAA"},"packages/frontend/editor-ui/src/app/stores/ui.store.ts":{"118":"b:+v////////////////////8PAAAA","177":"b:+v////////////////////8PAAAA","285":"b:KACASAAAAQA+AFAEFnwAQNkKAAAA","286":"b:+v////////////////////8PAAAA","347":"b:cP974P93/v/x/0Pw3/////sPAAAA","351":"b:cP974P93/v/x/0Pw3/////sPAAAA","355":[85,6,137],"413":"b:+v////////////////////8PAAAA","414":"b:+v////////////////////8PAAAA","420":"b:cP9/4A84/v/n/wOg//////8PAAAA","422":"b:+v+f/f////////s///////8PAAAA","424":"b:+v+f/f////////s///////8PAAAA","426":"b:+v+f/f////////s///////8PAAAA","432":"b:MMECQAIAAJuiKQGAfvryx9kOAAAA","440":"b:cP9f4A84/v/n/wMg//////8PAAAA","441":"b:QL4dwA0wAGbnYAIgl83vV+8OAAAA","447":"b:cIoZoAkw/k4h0AAgxy3vfaoCAAAA","452":"b:KLYAoASQRKBM0mOwd2D0RfkPAAAA","469":"b:IIgBgCBxgAAgEEgQAAAACQAEAAAA","476":"b:IIgBgCBxgAAoEEgQAAAACQAEAAAA","483":"b:IIgBgCBwgAAgEEAQAAAACQAEAAAA","490":"b:0AIAAMADAIA6AOAhAAAAADECAAAA","497":"b:8IqBgODzgYA6FOg1QAAACTUHAAAA","505":"b:0AIAAMADAIA6AOAhAAAAADECAAAA","510":"b:8KoFgODzAYA+EGg1RF4ASf0PAAAA","515":"b:4IoBgODzAYA6EGg1QAAACTUHAAAA","523":[40,44,45],"536":"b:IIgBgCBwgAAgEEAQAAAACQAEAAAA","562":[83],"568":[83],"578":[67],"587":[67,68,69],"604":"b:QL4dwA0wAGbnYAIgl83vV+8OAAAA","610":"b:QL4dwA0wAGbnYAIgl83vV+8OAAAA","617":[24,43,48,68,69,90,131],"628":[21,22,95],"633":"b:cP9/4A84/v/n/wPg//////8PAAAA","640":"b:+v+f/f////////s///////8PAAAA","651":"b:+v+f/f////////s///////8PAAAA","659":"b:ANcLAA4gAP/BaAKAh/x/l8EAAAAA","663":"b:cL4Z4A0w/m7l9oMh9+3vf+8PAAAA","671":"b:cP9/4A84/v/n/4Ph//////8PAAAA","679":"b:+v+f/f////////s///////8PAAAA","701":"b:+v+f/f////////s///////8PAAAA","702":"b:+v+f/f////////s///////8PAAAA","708":"b:+v+f/f////////s///////8PAAAA","710":"b:+v+f/f////////s///////8PAAAA","734":"b:cP9/4A84/v/n/wOg//////8PAAAA","735":"b:+v////////////////////8PAAAA","736":[33,63,93,132,133,137],"749":[1,89,90],"792":"b:IAgAgEBxAAAwBEAQAAAAAAAEAAAA","800":"b:IAgAgEBxAAAwAEAQAAAAAAAEAAAA","802":"b:IAgAgEBxAAAwAEAQAAAAAAAEAAAA"},"packages/frontend/editor-ui/src/app/stores/ui.utils.ts":{"4":[22,94],"12":"b:+v////////////////////8PAAAA","17":"b:+v////////////////////8PAAAA","23":"b:+v////////////////////8PAAAA"},"packages/frontend/editor-ui/src/app/stores/versions.store.ts":{"32":"b:+v////////////////////8PAAAA","64":"b:+P+f/Q/8/////3M0//////8PAAAA","95":"b:+v+f/f////////s///////8PAAAA","99":[23],"103":"b:+P8f/Q/8/////3M0//////8PAAAA","109":"b:+v8f/f////////s///////8PAAAA","115":"b:+v+f/f////////s///////8PAAAA","125":"b:+v+f/f////////s///////8PAAAA","140":"b:+v+f/f////////s///////8PAAAA","141":"b:+v+f/f////////s///////8PAAAA","142":"b:+v+f/f////////s///////8PAAAA","145":"b:+v8f/f////////s///////8PAAAA","158":"b:+P8f/Q/8/////3M0//////8PAAAA","173":"b:+v8f/f////////s///////8PAAAA","178":"b:+v8f/f////////s///////8PAAAA","185":"b:+v8f/f////////s///////8PAAAA","192":"b:+v+f/f////////s///////8PAAAA","233":"b:+v+f/f////////s///////8PAAAA","237":"b:+v+f/f////////s///////8PAAAA","260":[23]},"packages/frontend/editor-ui/src/app/stores/workflowDocument/useWorkflowDocumentActive.ts":{"14":"b:+v////////////////////8PgAAA","17":"b:QP8f4A8wAP/laAKg3/3/9/8PgAAA","21":"b:cP9/wA8wAP/naQLgn///1/8OgAAA","30":"b:cP9/wA8wAP/naQLgn///1/8OgAAA","34":"b:cMcTQA4gALvjaQKAnvrzw9kOgAAA"},"packages/frontend/editor-ui/src/app/stores/workflowDocument/useWorkflowDocumentChecksum.ts":{"12":"b:+v////////////////////8PgAAA","17":"b:cP9/wA8wAP/naQLgn///1/8OgAAA","22":"b:cP9/wA8wAP/naQLgn///1/8OgAAA"},"packages/frontend/editor-ui/src/app/stores/workflowDocument/useWorkflowDocumentConnections.ts":{"33":"b:+v////////////////////8PgAAA","44":"b:cOdzQA4gALvjbQDAnvrzw9sOgAAA","49":"b:ML4ZoA0w1i5h0gMg12XvfSsBgAAA","110":"b:ACAAAAAAAAAAwgAAU0AAAAEAgAAA","140":[151,73,96,97,100,102,110,128],"182":[151,88],"191":"b:cP9/4A86/v/n/0Pg//////8PgAAA","193":"b:YP8b4A8wBv/hfwKg3/////sPgAAA","197":"b:cP9b4A8w1v/h/wMg3/////sPgAAA","204":"b:YP8b4A8wBv/hfwKg3/////sPgAAA","215":"b:cOdzQA4gALvjbQDAnvrzw9sOgAAA","219":"b:ML4ZoA0w1i5h0gMg12XvfSsBgAAA","223":"b:ACAAAAAAAAAAwgAAU0AAAAEAgAAA","227":[151,73,96,97,100,102,110,128],"234":[151],"240":[151,88]},"packages/frontend/editor-ui/src/app/stores/workflowDocument/useWorkflowDocumentDescription.ts":{"12":"b:+v////////////////////8PgAAA","17":"b:cMdzQA4gALvjaQDAnvrzw9kOgAAA","25":"b:cMdzQA4gALvjaQDAnvrzw9kOgAAA"},"packages/frontend/editor-ui/src/app/stores/workflowDocument/useWorkflowDocumentExpression.ts":{"6":"b:+v////////////////////8PgAAA","11":"b:cP974A8y/v/h/0Pg//////sPgAAA"},"packages/frontend/editor-ui/src/app/stores/workflowDocument/useWorkflowDocumentGraph.ts":{"15":"b:+v////////////////////8PgAAA","20":"b:ML9b4A0w1s7h+QMg3+3//ysCgAAA","28":"b:MJ9b4A0w1s7h+QMgz+3//ysCgAAA","36":"b:cL5b4A0w/u7h/wMg7+3//6sPgAAA","40":[151,128],"47":[151,78,79,96],"73":[151],"77":[16,17,151,77],"81":"b:AIJRIAEQBophOQIAA8mvHwMCgAAA","85":"b:AIJRIAEQBophOQIAA8mvHwMCgAAA","93":"b:MJ4b4A0w1g7h+QEgz+Xv/yoAgAAA","108":"b:AAcDAAQAAESBKAAAgchvFgAAgAAA","111":"b:AAcDAAQAAASAKAAAgMhvFgAAgAAA","117":"b:AAcCAAQAAESBCAAAgchvFgAAgAAA","119":[151]},"packages/frontend/editor-ui/src/app/stores/workflowDocument/useWorkflowDocumentHomeProject.ts":{"9":"b:+v////////////////////8PgAAA","14":"b:cP9/4A84/v/n+wPg//////8PgAAA","22":"b:cP9/4A84/v/n+wPg//////8PgAAA"},"packages/frontend/editor-ui/src/app/stores/workflowDocument/useWorkflowDocumentIsArchived.ts":{"12":"b:+v////////////////////8PgAAA","17":"b:cMdzQA4gALvjaQDAnvrzw9kOgAAA","22":"b:cMdzQA4gALvjaQDAnvrzw9kOgAAA"},"packages/frontend/editor-ui/src/app/stores/workflowDocument/useWorkflowDocumentMeta.ts":{"13":"b:+v////////////////////8PgAAA","18":"b:cMdzwA4wALvjfQDAnvrzy9kOgAAA","26":"b:cMdzQA4gALvjaQDAnvrzw9kOgAAA","30":"b:MIABgAAQAAAhFAAAAEAACQAMgAAA"},"packages/frontend/editor-ui/src/app/stores/workflowDocument/useWorkflowDocumentName.ts":{"16":"b:+v////////////////////8PgAAA","21":"b:cP9/4A84/v/n/wPg//////8PgAAA","27":"b:cP9/4A84/v/n/wPg//////8PgAAA"},"packages/frontend/editor-ui/src/app/stores/workflowDocument/useWorkflowDocumentNodeGroups.ts":{"30":"b:+v////////////////////8PgAAA","37":"b:cP9/4A84/v/n/wOg//////8PgAAA","39":[151,77,96,97,100,102,128,131],"49":"b:cMdzQA4gALvjaQDAnvrzw9kOgAAA","50":[151,100],"57":[151,100],"69":[151,100],"78":"b:cMdzQA4gALvjaQDAnvrzw9kOgAAA","82":[151,100],"96":[151,100],"97":[151],"115":[151,100],"119":[151,100],"125":[151,100],"130":[151,100],"135":[151,100],"141":[151],"150":[151],"157":[151],"161":[151,100,128],"166":"b:AAAAAAAAAAAAAoABU0AAAAEAgAAA","169":[151,100],"178":"b:AABgAAAAAAAgAACBAEIAQNAAgAAA"},"packages/frontend/editor-ui/src/app/stores/workflowDocument/useWorkflowDocumentNodeMetadata.ts":{"20":"b:+v////////////////////8PgAAA","29":"b:cOdzQA4iALvjaQDBnvrzw9sOgAAA","34":"b:cP974A8y/v/h/4Ph//////sPgAAA","42":"b:cL5b4A0w/u7h/wMg7+3//6sPgAAA","52":[151,106],"65":"b:AAAAAAAAAAAAAoABU0AAAAEAgAAA","75":[151,98,120,129],"89":"b:cOdzQA4iALvjaQDBnvrzw9sOgAAA","94":"b:cL4ZoA0w/m5h1oMh523vfasPgAAA","100":"b:YOdzQA4iALvhaQDAnvrzw9sOgAAA","105":"b:AAAAAAAAAAAAAoABU0AAAAEAgAAA","109":[151,98,120,129],"113":"b:cL5b4A0w/u7h/wMg7+3//6sPgAAA","117":"b:ALQZIA0wlA6hgAEAx4UvHQMAgAAA","124":[151],"131":[151],"138":[151,106],"142":"b:ANcbAA4gAP/BaAKAh/x/l8EAgAAA","146":"b:ANcbAAwgAL/BaAKAhvx/l8EAgAAA","150":"b:ANcbAA4gAP/BaAKAh/x/l8EAgAAA","154":"b:MJ5b4A0w1s7h+QMgz+3//ysCgAAA"},"packages/frontend/editor-ui/src/app/stores/workflowDocument/useWorkflowDocumentNodes.ts":{"75":"b:+v////////////////////8PgAAA","91":"b:ML4Z4A0w1g7h/YEh182vP+sNgAAA","115":"b:cOdzQA4iALvjaQDAnvrzw9sOgAAA","139":"b:YOdzQA4iALvhaQDAnvrzw9sOgAAA","143":"b:cL4ZoA0w/m5h1oMh523vfasPgAAA","163":[151,87,88],"164":[151,87,88],"178":[151,73,96,97,100,102,110,128],"179":[151,73,96,97,100,102,110,128],"180":[151,73,96,97,100,102,110,128],"199":"b:+v////////////////////8PgAAA","223":"b:cP974A8w/v/h/wPg//////sPgAAA","238":"b:cP974A8w/v/h/wPg//////sPgAAA","252":"b:cP974A8w/v/h/wPg//////sPgAAA","266":"b:cP974A8y/v/h/4Ph//////sPgAAA","269":"b:cP974A8y/v/h/4Ph//////sPgAAA","272":"b:cP974A8w/v/h/wPg//////sPgAAA","276":"b:cP974A8w/v/h/wPg//////sPgAAA","279":"b:AAAgAAAAAAAAAoABU0AAAAEAgAAA","282":"b:AAAgAAAAAAAAAoABU0AAAAEAgAAA","289":"b:+v////////////////////8PgAAA","297":"b:+v////////////////////8PgAAA","298":"b:YOdzQA4iALvhaQDAnvrzw9sOgAAA","299":"b:YOdzQA4iALvhaQDAnvrzw9sOgAAA","305":"b:cP974A8y/v/j/4Ph//////sPgAAA","339":"b:cP974A8y/v/j/4Ph//////sPgAAA","365":[151],"367":"b:cL4ZoA0w/m5h1gMg523vfasPgAAA","369":"b:cP9/4A84/v/n/wPg//////8PgAAA","370":"b:cP874A8w/v/h/wMg//////sPgAAA","376":"b:cIoZoAkw/k4h0AAg5y3vfaoCgAAA","377":"b:MIoZoAgwugYh0AAgxyXvfSIAgAAA","384":"b:cP9b4A8w/v/h+wOg//3///sPgAAA","388":"b:+v////////////////////8PgAAA","392":"b:MJ4b4A0w1s7h+QMgx+3//ysCgAAA","393":"b:MJ4b4A0w1s7h+QMgx+3//ysCgAAA","396":"b:AIAAAAAAAAAAAAAgRUAABOgEgAAA","404":"b:cOdzQA4iALvjaQDAnvrzw9sOgAAA","408":"b:cL4ZoA0w/m5h1oMh523vfasPgAAA","412":[151,87,88],"416":[151,73,96,97,100,102,110,128],"420":"b:MJwZoA0w1A6hgAEgx4WvPSMAgAAA","421":"b:MJwZoA0w1A6hgAEgx4WvPSMAgAAA","446":"b:MAgRoAgQVAIhAAAgxwElPSIAgAAA","447":"b:MAgRoAgQVAIhAAAgxwElPSIAgAAA","465":"b:ACAAAAAAAAAA4AAAUwAAAAgAgAAA","466":"b:ACAAAAAAAAAA4AAAUwAAAAgAgAAA","489":"b:ACAAAAAAAAAA4AAAUwAAAAgAgAAA","490":"b:ACAAAAAAAAAA4AAAUwAAAAgAgAAA","496":[151],"497":[151],"502":"b:MIABwAAwAAAhEIAhRUAACeAEgAAA","503":"b:MIABwAAwAAAhEIAhRUAACeAEgAAA","519":"b:cP9b4A8w/v/h/wOg//////sPgAAA","520":"b:cP9b4A8w/v/h/wOg//////sPgAAA","547":[151,88],"557":[151,106],"558":[151,106],"565":[151],"570":[151],"600":"b:AIABwAAyAAAgEAAAAAAACQAAgAAA","607":"b:AIABwAAyAAAgEAAAAAAACQAAgAAA","626":[15,16,151,44,76]},"packages/frontend/editor-ui/src/app/stores/workflowDocument/useWorkflowDocumentNodesIssues.ts":{"23":"b:+v////////////////////8PgAAA","24":"b:cP8fwA8wBv/neQIgn///9/8PgAAA","25":"b:YP8bwA8wBv/heQIgn///9/sPgAAA","35":[151],"37":[151],"41":"b:AOoTIAMQBsIBNQAgSsivbTAPgAAA","42":"b:AOoTIAMQBsIBNQAgSsivbTAPgAAA","54":[13,151,18],"57":[151],"60":[13,151],"69":[13,151],"73":[13,151],"95":[151],"108":"b:cP974A8w/v/h/wPg//////sPgAAA","114":"b:cP974A8y/v/h/4Ph//////sPgAAA","117":"b:cP974A8y/v/h/4Ph//////sPgAAA","120":"b:cP974A8w/v/h/wPg//////sPgAAA","123":"b:AAAgAAAAAAAAAoABU0AAAAEAgAAA","126":"b:AAAgAAAAAAAAAoABU0AAAAEAgAAA","132":"b:+v////////////////////8PgAAA","140":"b:cP974A8y/v/j/4Ph//////sPgAAA"},"packages/frontend/editor-ui/src/app/stores/workflowDocument/useWorkflowDocumentParentFolder.ts":{"9":"b:+v////////////////////8PgAAA","14":"b:cP9/4A84/v/n+wPg//////8PgAAA","22":"b:cP9/4A84/v/n+wPg//////8PgAAA"},"packages/frontend/editor-ui/src/app/stores/workflowDocument/useWorkflowDocumentPinData.ts":{"38":"b:AAAAAAAAAABAAAAAQAVvBwABgAAA","43":"b:AAAAAAAAAABAAAAAQAVvBwABgAAA","56":"b:cMdzQA4gALvjaQDBnvrzw9kOgAAA","57":"b:AABAAAAAAABAAAAACIhzAwEIgAAA","58":"b:AABAAAAAAABAAAAACIhzAwEIgAAA","68":"b:MN5b4A0w1s7h+QMgz+3//ysHgAAA","72":"b:AABAAAAAAABAAAAASIV/BwEBgAAA","76":"b:AAAAAAAAAABAAAAAQAVvBwABgAAA","79":"b:AAAAAAAAAABAAAAAQAVvBwABgAAA","89":"b:+v////////////////////8PgAAA","94":"b:cMdzQA4gALvjaQDBnvrzw9kOgAAA","99":"b:AAAAAAAAAABAAAAAQAVvBwABgAAA","107":"b:AAAAAAAAAAAAAoABU0QAAAEAgAAA","116":[151,98,120,129],"122":[151],"123":[151],"129":[151],"140":"b:cMdzQA4gALvjaQDBnvrzw9kOgAAA","144":"b:AAAAAAAAAABAAAAAQAVvBwABgAAA","148":[151,106],"152":[151,98,120,129],"156":"b:cP9/4A8y/v/l/0Pg//////8PgAAA","160":"b:ML5b4A0w1s7h+QMg3+3//ysCgAAA","179":"b:cP974A8w/v/h/wPg//////sPgAAA","185":"b:cP974A8y/v/h/4Ph//////sPgAAA","188":"b:cP974A8y/v/h/4Ph//////sPgAAA","191":"b:cP974A8w/v/h/wPg//////sPgAAA","194":"b:AAAgAAAAAAAAAoABU0AAAAEAgAAA","197":"b:AAAgAAAAAAAAAoABU0AAAAEAgAAA","203":"b:+v////////////////////8PgAAA","211":"b:cP974A8y/v/j/4Ph//////sPgAAA"},"packages/frontend/editor-ui/src/app/stores/workflowDocument/useWorkflowDocumentScopes.ts":{"13":"b:+v////////////////////8PgAAA","18":"b:cP9/4A84/v/n+wPg//////8PgAAA","23":"b:cP9/4A84/v/n+wPg//////8PgAAA"},"packages/frontend/editor-ui/src/app/stores/workflowDocument/useWorkflowDocumentSettings.ts":{"19":"b:+v////////////////////8PgAAA","24":"b:cMdzQA4gALvjaQDAnvrzw9kOgAAA","33":"b:cMdzQA4gALvjaQDAnvrzw9kOgAAA","37":[151],"41":"b:QP8fwA8wAP/laAKg3/3/9+8PgAAA"},"packages/frontend/editor-ui/src/app/stores/workflowDocument/useWorkflowDocumentSharedWithProjects.ts":{"13":"b:+v////////////////////8PgAAA","18":"b:cMdzQA4gALvjaQDAnvrzw9kOgAAA","29":"b:cMdzQA4gALvjaQDAnvrzw9kOgAAA"},"packages/frontend/editor-ui/src/app/stores/workflowDocument/useWorkflowDocumentTags.ts":{"15":"b:cMdzQA4gALvj6QHAnvrzx90PgAAA","16":[151,80,126,130,136],"19":"b:+v////////////////////8PgAAA","24":"b:cMdzQA4gALvj6QHAnvrzx90PgAAA","29":[151,130],"30":[151],"37":"b:cMdzQA4gALvjaQDAnvrzw90OgAAA","41":"b:AAAAAAAAACAAgAEAAABARQABgAAA","46":[151,130]},"packages/frontend/editor-ui/src/app/stores/workflowDocument/useWorkflowDocumentTimestamps.ts":{"19":"b:+v////////////////////8PgAAA","26":"b:cMdzQA4gALvjaQDAnvrzw9kOgAAA","31":"b:cP9/wA8wAP/naQLgn///1/8OgAAA","36":"b:cMdzQA4gALvjaQDAnvrzw9kOgAAA","40":"b:cP9/wA8wAP/naQLgn///1/8OgAAA"},"packages/frontend/editor-ui/src/app/stores/workflowDocument/useWorkflowDocumentUsedCredentials.ts":{"13":"b:+v////////////////////8PgAAA","18":"b:cMdzQA4gALvjaQDAnvrzw9kOgAAA","26":"b:cMdzQA4gALvjaQDAnvrzw9kOgAAA","27":"b:AIABQAAgAJMgAAAAAEAAAAAEgAAA"},"packages/frontend/editor-ui/src/app/stores/workflowDocument/useWorkflowDocumentVersionData.ts":{"14":"b:+v////////////////////8PgAAA","20":"b:cP9/wA8wAP/naQLgn///1/8OgAAA","32":"b:cP9/wA8wAP/naQLgn///1/8OgAAA"},"packages/frontend/editor-ui/src/app/stores/workflowDocument/useWorkflowDocumentViewport.ts":{"13":"b:+v////////////////////8PgAAA","18":"b:MIBgAAAAAAAkAACgBF4AQNgOgAAA","26":"b:MIBgAAAAAAAkAACgBF4AQNgOgAAA"},"packages/frontend/editor-ui/src/app/stores/workflowDocument/useWorkflowDocumentWorkflowObject.ts":{"12":"b:+v////////////////////8PgAAA","26":"b:AABgAAAAAAAgAADAAEIAQNAAgAAA","46":"b:cP974A8y/v/j/4Ph//////sPgAAA","50":"b:cP974A8w1r/j/wPh3/////sPgAAA","54":"b:cP9/4A84/v/n/wPg//////8PgAAA","58":"b:cMdzQA4gALvjaQDAnvrzw9kOgAAA","62":"b:ADYAAAQAACBAggMAREBgRQoBgAAA","81":[13,151,98,120,129],"87":[13,151,98,120,129]},"packages/frontend/editor-ui/src/app/stores/workflowDocument.store.ts":{"114":"b:+v////////////////////8PgAAA","124":"b:+v////////////////////8PgAAA","138":"b:+v////////////////////8PgAAA","139":"b:+v////////////////////8PgAAA","148":"b:cP9/4A84/v/n/wPg//////8PgAAA","161":"b:cMdzQA4gALvjaQDAnvrzw9kOgAAA","170":"b:MAgRoAgQVAIhAAAgxwElPSIAgAAA","173":"b:cP974A8y/v/j/4Ph//////sPgAAA","184":[151],"185":"b:cP974A8w1r/j/wPh3/////sPgAAA","211":"b:cL4Z4A0w/m7h9oMh9+3vfesPgAAA","212":"b:ML4ZoA0w1i5h0gMg12XvfSsBgAAA","213":[151,100],"215":"b:cP974A8y/v/j/4Ph//////sPgAAA","221":[151,88],"228":"b:QP8fwA8wAP/laAKgl/3/1+8OgAAA","229":"b:QP8bwA8wAP/haAKgl/3/1+sOgAAA","249":[151,100],"262":[151,94],"314":"b:AABgAAAAAAAgAACAAEIAQNAAgAAA","354":"b:cP974A8y/v/h/0Pg//////sPgAAA","369":"b:APcPAA4gAP/BaAIAx/1/l8EBgAAA","448":[151,69,105,126,132],"464":"b:+v////////////////////8PgAAA","466":"b:+v////////////////////8PgAAA","475":"b:+v////////////////////8PgAAA"},"packages/frontend/editor-ui/src/app/stores/workflowExecutionState.store.ts":{"73":"b:+v////////////////////8PgAAA","89":"b:+v////////////////////8PgAAA","90":"b:+v////////////////////8PgAAA","137":"b:cP9/4A84/v/n/wPg//////8PgAAA","150":"b:ANd7AA4gAP/BaALAh/x/l8EIgAAA","170":"b:cP9/4C97/v/n/8Px//////8PgAAA","191":"b:+v////////////////////8PgAAA","198":[151],"208":[151],"214":"b:cP8f4A84/v/n/wOg//////8PgAAA","220":[151,113,116,118,121],"226":"b:+v////////////////////8PgAAA","233":[151],"248":"b:cP974A8w/v/h/wPg//////sPgAAA","267":"b:cP9/4A84/v/n/wPg//////8PgAAA","273":"b:cP9/4A84/v/n/wPg//////8PgAAA","279":"b:cP9/4A84/v/n/wPg//////8PgAAA","286":"b:cP9/4A84/v/n/wPg//////8PgAAA","292":"b:MN5b4A0w1s7h+QMgz+3//ysCgAAA","298":"b:cP9/4A84/v/n/wPg//////8PgAAA","328":"b:cP8b4A8w/v/h/wPg//////sPgAAA","336":"b:cP8b4A8w/v/h/wPg//////sPgAAA","346":"b:cP974A8w/v/h/4Ph//////sPgAAA","349":"b:cP974A8w/v/h/4Ph//////sPgAAA","352":"b:cP8b4A8w/v/h/wPg//////sPgAAA","356":"b:cP8b4A8w/v/h/wPg//////sPgAAA","359":"b:AAAgAAAAAAAgAoABU0IAQBEAgAAA","362":"b:AAAAAAAAAAAAAoABU0AAAAEAgAAA","369":"b:+v////////////////////8PgAAA","383":"b:cP974A8w/v/j/4Oh//////sPgAAA","419":"b:cP9/4A84/v/n/wPg//////8PgAAA","430":[151],"433":[151],"438":[151],"439":[151],"444":[151],"448":"b:ANd7AA4gAP/BaALAh/x/l8EIgAAA","470":[151,106,110,134,135],"479":"b:cP8f4A84/v/n/wOg//////8PgAAA","485":[151],"496":[151],"515":"b:ANcbAA4gAP/BaAKAh/x/l8EAgAAA","532":"b:cP8f4A84/v/n/wOg//////8PgAAA","555":"b:AIAAAAAAAAAAAgAgV0AAAOEAgAAA","562":"b:AMATAAIAAAIBIACAAEgABAAAgAAA","567":[151,106],"572":"b:cP8f4A84/v/n/wOg//////8PgAAA","585":"b:cP9/4A84/v/n/wPg//////8PgAAA","607":[151],"616":"b:cP8f4A84/v/n/wOg//////8PgAAA","621":[151],"626":"b:cP9/4A84/v/n/wPg//////8PgAAA","631":"b:cP9/4A84/v/n/wPg//////8PgAAA","635":[151],"637":[151],"643":[151],"645":[151],"646":[151],"655":[151],"660":[151],"665":"b:cP9/4A84/v/n/wOg//////8PgAAA","678":[151,98,120,129],"691":[151],"697":[151],"703":[151],"716":[151,98,120,129],"741":"b:cP9/4A84/v/n/wPg//////8PgAAA","774":[151,110],"888":"b:cP9/4A84/v/n/wPg//////8PgAAA"},"packages/frontend/editor-ui/src/app/stores/workflowSave.store.ts":{"15":"b:+v////////////////////8PAAAA","26":"b:cL4Z4A0w/m7l9gMg9+3vf+8PAAAA","30":"b:QL4dwA0wAGblYAIgl83vV+8OAAAA","55":"b:QLYRQAwgACLhYAIAls3nV+ECAAAA"},"packages/frontend/editor-ui/src/app/stores/workflows.store.ts":{"53":"b:+v////////////////////8PgAAA","82":"b:+v////////////////////8PgAAA","87":"b:AIAAAAAAAAAAAAAABFwAAMAAgAAA","88":[151],"91":"b:cP9/4C97/v/n/8Px//////8PgAAA","98":"b:MN5b4A0w1s7h+QMgz+3//ysCgAAA","101":"b:cP8f4A84/v/n/wOg//////8PgAAA","107":"b:+v////////////////////8PgAAA","110":[151,113,116,118,121],"122":"b:cP8f4A86/v/n/wOg//////8PgAAA","132":"b:cP8f4A84/v/n/wOg//////8PgAAA","133":"b:cP8fwA8wAP/naQKgn///1/8OgAAA","142":"b:cP974C9z/v/h/8Px3/////sPgAAA","150":"b:ML4b4A0w1s7h+QMgz+3//ysCgAAA","152":[151],"153":[151],"158":"b:MP9b4C9z1v/h+cOx3/3//+sGgAAA","160":"b:+v+f//////////8///////8PgAAA","164":[151],"175":"b:MJ4b4A0w1s7h+QMgx+3//ysCgAAA","179":"b:MJ4b4A0w1s7h+QMgx+3//ysCgAAA","189":[151],"190":[151],"193":[151,74,138,139],"194":[151],"214":[151,136],"221":"b:cP8f4A84/v/n/wOg//////8PgAAA","249":[151],"257":"b:cP9/4A84/v/n/wPg//////8PgAAA","261":"b:cP9/4A84/v/n/wPg//////8PgAAA","270":"b:cMcTQA4gALvjaQKAnvrzw9kOgAAA","277":[151,132,137],"293":[151,132,137],"308":[151,63,93,132,133,137],"320":[151,132,137],"324":[151,65],"342":[151],"346":[151],"350":"b:cP9/4A84/v/n/wPg//////8PgAAA","354":"b:cP9/4A84/v/n/wPg//////8PgAAA","358":[151],"362":[151,98,120,129],"366":[151],"370":"b:AIAAAAAAAAAAAgAgV0AAAOEAgAAA","375":[151],"393":[151,106,110,134,135],"407":"b:QL4dwA0wAGbvYAIgl83vV+8OgAAA","408":"b:QL4ZwA0wAGbhYAIgl83vV+sOgAAA","416":"b:QL4dgA0wAGZnQAIgh03tVa8OgAAA","450":"b:QLYRQAwgACLrYAIAls3nV+ECgAAA","493":[151,63,93,128,132,133,137],"507":[151,137],"534":[151],"586":"b:ANcbAA4gAP/BaAKAh/x/l8EIgAAA","605":[151],"613":"b:ANcLAA4gAP/BaAKAh/x/l8EAgAAA","625":[151],"629":[151],"633":[151]},"packages/frontend/editor-ui/src/app/stores/workflowsList.store.ts":{"13":"b:+v////////////////////8PAAAA","22":[128,129],"23":[128,129],"27":"b:cP8f4A84/v/l/wOg//////8PAAAA","41":"b:eP//wA+wAf//aQKgn///1/8OAAAA","51":[132,137],"56":"b:cP9/4A84/v/l+wPg//////8PAAAA","66":[63,93,132,133,137],"79":[132,137],"93":"b:uACAXQCAAQA+ABAEAAIAQBsKAAAA","129":"b:CACAAACAAQA+AAAAAAIAQBsKAAAA","130":"b:CACAAACAAQA+AAAAAAIAQBsKAAAA","141":"b:uACAXQCAAQA+ABAEAAIAQBsKAAAA","170":[93,137],"197":[93,137],"216":"b:cMcTQA4gALv9aQIgnvrzw9sOAAAA","222":[83],"226":"b:+P+f/Q+4/////xMk//////8PAAAA","232":"b:cL4doA84/m5l0gMg503vfb4DAAAA","238":[132,137],"244":[132,137],"265":[132,137]},"packages/frontend/editor-ui/src/app/utils/htmlUtils.ts":{"8":"b:6NeLgK73Bf//eXq31/3/3/0GgAAA","10":"b:AACAAAAAAAA+AQAAAAAiABECgAAA","31":"b:gACAAAAWAQA+AQACAAAqBBEGgAAA","44":"b:AAAAAICQAQAMADAhBAwASBAGgAAA","51":[151],"55":"b:+v////////////////////8PgAAA","56":"b:+v////////////////////8PgAAA","57":"b:+v////////////////////8PgAAA","63":[151,96,131,138],"80":"b:cP8f4A84/v/n/wOg//////8PgAAA","101":"b:AIYBIAgQAgAAMUEAz0mvGwAAgAAA"},"packages/frontend/editor-ui/src/app/utils/injectStrict.ts":{"4":"b:+v///f////////v///////8PgAAA"},"packages/frontend/editor-ui/src/app/utils/modules/tabUtils.ts":{"22":"b:uAiA3QD0AQA+AHAUAAIAQBgKAAAA","45":"b:uAiA3QD0AQA+AHAUAAIAQBgKAAAA","49":"b:uAiA3QD0AQA+AHAUAAIAQBgKAAAA"},"packages/frontend/editor-ui/src/app/utils/nodeTypes/nodeTypeTransforms.ts":{"8":"b:+v///f////////v///////8PgAAA","29":"b:+v///f////////v///////8PgAAA","32":"b:+v///f////////v///////8PgAAA"},"packages/frontend/editor-ui/src/app/utils/nodeViewUtils.ts":{"60":[151,21,22,74,95,138,139],"61":[151,21,22,74,95,138,139],"70":"b:ABYAAAQAACBAggMAREBgRQgBgAAA","71":"b:ABYAAAQAACBAggMAREBgRQgBgAAA","80":"b:ABYAAAQAACBAggMAREBgRQgBgAAA","81":"b:ABYAAAQAACBAggMAREBgRQgBgAAA","90":"b:ABYAAAQAACBAggMAREBgRQgBgAAA","91":"b:ABYAAAQAACBAggMAREBgRQgBgAAA","100":"b:ABYAAAQAACBAggMAREBgRQgBgAAA","101":"b:ABYAAAQAACBAggMAREBgRQgBgAAA","110":"b:ABYAAAQAACBAggMAREBgRQgBgAAA","127":"b:MIgZoAgwkgYh0AAgxyWvfSoAgAAA","144":[151,78,79,96],"159":"b:cP974A8y/v/h/wPg//////sPgAAA","178":"b:cP974A8y/v/h/wPg//////sPgAAA","188":"b:cL4ZoA0w/m5h1gMg523vfasPgAAA","253":"b:ANdbYAQAOorhKQMA/+33l/kEgAAA","263":[151,101],"275":[151,101],"294":[151,101],"303":[151,21,22,74,95,138,139],"314":[151,21,22,74,95,138,139],"384":"b:MN5b4A0w1s7h+QMgz+3//ysCgAAA","526":[151,97],"552":"b:KLYAoASQRCBs0mOwd370RfkPgAAA","569":"b:cN4ZoA0w/m5h0gMg523vfaoDgAAA","581":[14,151,110],"590":[14,151,110],"596":[14,151,110],"632":"b:cP974A8w/v/h/wPg3/////sPgAAA"},"packages/frontend/editor-ui/src/app/utils/rbac/checks/hasRole.ts":{"5":"b:+v+f//////////8///////8PAAAA"},"packages/frontend/editor-ui/src/app/utils/rbac/checks/hasScope.ts":{"4":"b:+v////////////////////8PAAAA"},"packages/frontend/editor-ui/src/app/utils/rbac/checks/isAuthenticated.ts":{"5":"b:+v////////////////////8PAAAA","14":"b:+v///f////////v///////8PAAAA"},"packages/frontend/editor-ui/src/app/utils/rbac/checks/isValid.ts":{"3":"b:+v+f/f////////s///////8PAAAA"},"packages/frontend/editor-ui/src/app/utils/rbac/middleware/authenticated.ts":{"6":"b:+v///f////////v///////8PAAAA"},"packages/frontend/editor-ui/src/app/utils/rbac/middleware/custom.ts":{"4":"b:uAiA3UL0AQA+AHgUAAIAQBgKAAAA"},"packages/frontend/editor-ui/src/app/utils/rbac/permissions.ts":{"28":"b:+v////////////////////8PAAAA"},"packages/frontend/editor-ui/src/app/utils/typeGuards.ts":{"31":[151],"35":[151,113,121],"39":[151,46,123,138],"43":"b:ACYKAAQAAIzASAIAiu1/twEAgAAA","46":[151],"49":"b:MCgQoAAS1AJhCQAgBElnvyMAgAAA","57":"b:IIgBgCBxgAAgEEAQAAAACQAEgAAA","61":[151,124],"65":[151,86],"71":"b:cP974A8w/v/h/wPg//////sPgAAA","77":"b:cP974A8w/v/h/wPg/////+sPgAAA","81":"b:AIABIAAAOgAAwAAAAyCAEQAAgAAA","90":"b:AAAQIAEAAAIBAAAAAIggBAACgAAA","96":[151,106,124],"102":[151],"109":"b:AAAAAAAAAAAAAEAABFwAAMAAgAAA","113":[151,44,68,85,5],"117":[151,44,68,85,5],"121":[151,85],"125":"b:IAAAgABwAAAwAGAQAAAAAAAAgAAA","129":[151],"135":[151,44,68,85,5],"142":"b:uACA3QDwAQA+AHAUAAIAQBgKgAAA","155":[151,23,42,48,3,69,86,5,131,137],"164":[151],"167":[151,137]},"packages/frontend/editor-ui/src/experiments/readyToRunWorkflowsV2/stores/readyToRunWorkflowsV2.store.ts":{"12":"b:+P+f/Q/8/////3O0//////8PAAAA"},"packages/frontend/editor-ui/src/experiments/resourceCenter/stores/resourceCenter.store.ts":{"19":"b:+P+f/Q/8/////3M0//////8PAAAA","32":"b:+P+f/Q/8/////3M0//////8PAAAA","114":"b:+P+f/Q/8/////3M0//////8PAAAA"},"packages/frontend/editor-ui/src/experiments/sidebarExpanded/useSidebarExpandedExperiment.ts":{"6":"b:+P+f/Q/8/////3M0//////8PAAAA","10":"b:+P+f/Q/8/////3M0//////8PAAAA"},"packages/frontend/editor-ui/src/experiments/utils.ts":{"32":"b:cL4doA84/m5n1gMg503vfb4PAAAA","39":"b:+v////////////////////8PAAAA","46":"b:+P+f/Q/8/////3M0//////8PAAAA"},"packages/frontend/editor-ui/src/features/agents/composables/useAgentPermissions.ts":{"34":"b:uAiA3QD0AQA+AHAUAAIAQBgKAAAA"},"packages/frontend/editor-ui/src/features/ai/assistant/assistant.store.ts":{"37":"b:+v////////////////////8PAAAA","45":"b:cP8f4A84/v/l/wMg//////8PAAAA","55":[10],"56":[10],"76":[9,10,11,12,13,18],"77":[9,10,12],"79":[9,10,11,12],"81":[9,10,11,12,13,18],"91":"b:+v////////////////////8PAAAA","93":"b:+v////////////////////8PAAAA","97":[9,10,11],"99":[9,11],"104":"b:+v////////////////////8PAAAA","112":"b:+v///f////////v///////8PAAAA","116":[9,10,11,12],"120":[9,10,11,12],"133":[9,10,11,12],"135":[9,10,11,12],"139":[9,10,11,12],"196":[9,10],"207":[11],"213":[9,10,11,12],"217":[9,10,11,12],"240":[9,10,11,12],"244":[9,11,12],"270":[9,10,11,12],"290":[9,10,11,12],"294":[9,10,11,12],"298":[9,10,11,12],"309":[11],"328":[9,12],"410":[9,11,12],"470":[9,11,12],"471":[9,11,12],"483":[9,10],"544":[9,10],"545":[9,10],"552":[10],"580":[10],"581":[10],"588":"b:ANcbAA4gAP/BaAKAh/x/l8EAAAAA","619":[9,12],"669":[9,12],"670":[9,12],"682":[9,12],"696":[9,10,11,12,13,18],"736":"b:+v////////////////////8PAAAA","737":"b:cL4Z4A0w/m7l9oMh9+3vf+8PAAAA","743":"b:+v////////////////////8PAAAA","744":"b:+v////////////////////8PAAAA"},"packages/frontend/editor-ui/src/features/ai/assistant/builder.store.ts":{"164":"b:+v////////////////////8PAAAA","186":"b:+v///f////////v///////8PAAAA","228":"b:eP//8P++/////wP0//////8PAAAA","255":"b:+v////////////////////8PAAAA","258":[13,18],"297":[13,18],"300":"b:+v///f////////v///////8PAAAA","316":"b:+v///f////////v///////8PAAAA","320":[13,18],"322":"b:+v///f////////v///////8PAAAA","328":"b:+v///f////////v///////8PAAAA","348":"b:+v///f////////v///////8PAAAA","360":"b:+v///f////////v///////8PAAAA","364":"b:+v///f////////v///////8PAAAA","367":"b:+v///f////////v///////8PAAAA","369":"b:+v///f////////v///////8PAAAA","381":"b:+v///f////////v///////8PAAAA","403":[13,18],"413":"b:+v///f////////v///////8PAAAA","425":"b:eP//8P++/////wP0//////8PAAAA","455":"b:ANcLAA4gAP/BaAKAh/x/l8EAAAAA","462":"b:cP9/4A84/v/n/wPg//////8PAAAA","470":[13,18],"474":[13,18],"496":[13,18],"523":[13,18],"524":[13,18],"573":[13,18],"645":[18],"656":[18],"665":[18],"696":[13,18],"727":[13,18],"740":[13,18],"817":[13,18],"833":[13,18],"865":[13],"889":[13,18],"1025":[13],"1028":[13],"1050":[13],"1057":[18],"1128":[13,18],"1397":[13],"1402":[13],"1429":[13,18],"1440":"b:QLYRQAwgACLhYAIAls3nV+ECAAAA","1448":"b:QLYRQAwgACLhYAIAls3nV+ECAAAA","1456":[13],"1460":[13,18],"1465":[13,18],"1479":"b:+v////////////////////8PAAAA","1480":"b:cP9/4A84/v/n/wPg//////8PAAAA","1513":"b:+v////////////////////8PAAAA","1525":[13],"1546":[13],"1677":"b:+v///f////////v///////8PAAAA"},"packages/frontend/editor-ui/src/features/ai/assistant/chatPanel.store.ts":{"32":[9,10,11,12,13,18],"39":"b:+v////////////////////8PAAAA","50":[9,10,11,12],"58":[9,10,11,12,13,18],"64":"b:+v///f////////v///////8PAAAA","66":"b:cP8f4A84/v/l/wMg//////8PAAAA","69":[9,10,11,12,13,18],"103":[9,11],"110":[9,10,11,12,13,18],"119":[9],"127":[9],"142":[9,12,13,18],"150":[9,10,11,12,13,18],"182":[11],"200":[9,10],"216":"b:+v////////////////////8PAAAA","217":"b:+v///f////////v///////8PAAAA","254":"b:+v////////////////////8PAAAA","255":"b:+v///f////////v///////8PAAAA"},"packages/frontend/editor-ui/src/features/ai/assistant/chatPanelState.store.ts":{"14":"b:+v////////////////////8PAAAA"},"packages/frontend/editor-ui/src/features/ai/assistant/components/Agent/AskAssistantBuild.vue":{"76":"b:+v///f////////v///////8PAAAA","90":"b:+v///f////////v///////8PAAAA","120":[13],"127":"b:+v///f////////v///////8PAAAA","128":[13],"134":"b:+v///f////////v///////8PAAAA","138":"b:+v///f////////v///////8PAAAA","143":"b:+v///f////////v///////8PAAAA","153":"b:+v///f////////v///////8PAAAA","158":"b:+v///f////////v///////8PAAAA","169":"b:+v///f////////v///////8PAAAA","170":[13,18],"172":[13,18],"180":[13,18],"181":[13,18],"184":[13,18],"200":"b:+v///f////////v///////8PAAAA","201":"b:+v///f////////v///////8PAAAA","202":"b:+v///f////////v///////8PAAAA","205":"b:+v///f////////v///////8PAAAA","211":"b:+v///f////////v///////8PAAAA","218":"b:+v///f////////v///////8PAAAA","225":"b:+v///f////////v///////8PAAAA","229":"b:+v///f////////v///////8PAAAA","247":[13],"281":"b:+v///f////////v///////8PAAAA","313":"b:+v///f////////v///////8PAAAA","345":"b:cOF/4A8w/v/h/4Mh//////sPAAAA","347":[13,18],"394":[13,18],"410":[13],"419":"b:OICAkPCmAQA+BAA0BF4AQNgOAAAA","543":[13],"557":"b:+v///f////////v///////8PAAAA","559":"b:eOP/8P++/////wP0//////8PAAAA","594":"b:+v///f////////v///////8PAAAA","595":[13,18],"607":"b:+v///f////////v///////8PAAAA","609":[13,18],"684":"b:OICAkPCmAQA+BAA0BF4AQNgOAAAA","691":"b:+v///f////////v///////8PAAAA","703":[13,18],"709":"b:+v///f////////v///////8PAAAA","712":[13,18],"743":[13,18],"749":[13],"756":"b:+v///f////////v///////8PAAAA","773":"b:+v///f////////v///////8PAAAA","778":[13,18],"785":"b:cMF74A8w/v/h/4Mh//////sPAAAA","788":[13],"840":"b:+v///f////////v///////8PAAAA","870":"b:+v///f////////v///////8PAAAA","872":"b:+v///f////////v///////8PAAAA","880":"b:cOF/4A8w/v/h/4Mh//////sPAAAA","910":"b:cOF/4A8w/v/h/4Mh//////sPAAAA"},"packages/frontend/editor-ui/src/features/ai/assistant/components/Agent/PlanModeSelector.vue":{"17":"b:+v///f////////v///////8PAAAA","27":"b:+v///f////////v///////8PAAAA","46":"b:+v///f////////v///////8PAAAA","47":"b:+v///f////////v///////8PAAAA","53":"b:+v///f////////v///////8PAAAA","71":"b:+v///f////////v///////8PAAAA","74":"b:+uP//f////////v///////8PAAAA"},"packages/frontend/editor-ui/src/features/ai/assistant/components/AssistantsHub.vue":{"19":"b:+v///f////////v///////8PAAAA","39":"b:+v///f////////v///////8PAAAA","40":[9,10,11,12,13,18],"51":"b:+v///f////////v///////8PAAAA","85":[9],"89":[9,10,11,12,13,18],"98":"b:AP8fAA4gAP/BaAKAh/x/l8EAAAAA","106":"b:+v///f////////v///////8PAAAA","112":"b:eL6f8P321+7//WM0x/////8OAAAA","124":"b:+v///f////////v///////8PAAAA","141":"b:+v///f////////v///////8PAAAA","150":"b:+v///f////////v//////n8PAAAA","164":"b:+v///f////////v///////8PAAAA","169":[13,18]},"packages/frontend/editor-ui/src/features/ai/assistant/components/FocusedNodes/ChatInputWithMention.vue":{"24":"b:+v///f////////v///////8PAAAA","45":"b:+v///f////////v///////8PAAAA","66":"b:+v///f////////v///////8PAAAA","67":[13,18],"73":[13,18],"103":[13],"114":[13,18],"121":[13,18],"127":[18],"159":[13,18],"174":"b:+v///f////////v///////8PAAAA","283":"b:+v///f////////v///////8PAAAA"},"packages/frontend/editor-ui/src/features/ai/assistant/composables/useAIAssistantHelpers.ts":{"43":"b:+v////////////////////8PgAAA","59":[9,10,11,151],"71":[151],"78":[9,10,11,151],"97":[151],"98":[151],"110":[151],"119":[151],"128":[151],"134":[151],"160":[151],"177":[151],"204":[9,10,151],"211":[9,10,151],"224":[9,10,11,12,151],"248":[11,151],"273":[9,10,151],"295":[9,10,11,151],"298":[9,10,11,151],"306":[9,10,11,13,151],"332":[9,12,151],"354":[12,151],"376":[12,151],"417":[9,12,13,151,18],"425":[151],"444":[151],"462":[151],"506":[151],"579":[151],"593":[151],"629":[151]},"packages/frontend/editor-ui/src/features/ai/assistant/composables/useAskModeCoachmark.ts":{"14":[13,18],"17":"b:+v///f////////v///////8PAAAA","25":"b:+v///f////////v///////8PAAAA","27":"b:+v///f////////v///////8PAAAA","35":"b:+v///f////////v///////8PAAAA"},"packages/frontend/editor-ui/src/features/ai/assistant/composables/useBuilderMessages.ts":{"82":"b:+v////////////////////8PAAAA","88":[13,18],"89":[13,18],"208":[13],"326":"b:+v///f////////v///////8PAAAA","327":[13,18],"330":"b:+v///f////////v///////8PAAAA","342":[13],"395":[13],"419":[13],"436":[13],"460":[13],"462":[13],"471":[13,18],"517":[18],"556":"b:eP//8P++/////wP0//////8PAAAA"},"packages/frontend/editor-ui/src/features/ai/assistant/composables/useBuilderTodos.ts":{"37":"b:+v////////////////////8PAAAA","47":[13],"89":[13],"129":[13,18],"138":[13],"151":[13,18],"206":[13,18],"212":[13],"246":[13,18],"247":[13],"254":[13]},"packages/frontend/editor-ui/src/features/ai/assistant/composables/useFocusedNodesChipUI.ts":{"14":"b:+v///f////////v///////8PAAAA"},"packages/frontend/editor-ui/src/features/ai/assistant/composables/useNodeMention.ts":{"32":"b:+v///f////////v///////8PAAAA","61":"b:+v///f////////v///////8PAAAA","62":"b:MKAZoAgwkgYh0gCg92evffsAAAAA","155":[13,18]},"packages/frontend/editor-ui/src/features/ai/assistant/composables/useReviewChanges.ts":{"34":"b:+v///f////////v///////8PAAAA","71":"b:+v///f////////v///////8PAAAA","100":[13],"107":[13],"128":[13],"145":[13],"252":[9,10,11,12],"278":[13,18],"288":[13],"299":[13,18],"309":[9,10,11,12],"311":"b:+v///f////////v///////8PAAAA"},"packages/frontend/editor-ui/src/features/ai/assistant/focusedNodes.store.ts":{"25":"b:+v////////////////////8PAAAA","27":"b:+v////////////////////8PAAAA","33":"b:+v////////////////////8PAAAA","35":"b:+v///f////////v///////8PAAAA","45":"b:cP9/4A84/v/n/wPg//////8PAAAA","240":[13,18],"266":"b:+v////////////////////8PAAAA","267":"b:cP9/4A84/v/n/wPg//////8PAAAA","282":"b:+v////////////////////8PAAAA","283":"b:cP9/4A84/v/n/4Ph//////8PAAAA","285":"b:cP974A8w/v/h/4Oh//////sPAAAA","311":"b:+v////////////////////8PAAAA","312":"b:cP9/4A84/v/n/4Ph//////8PAAAA","324":"b:+v////////////////////8PAAAA","325":"b:MJ5b4A0w1s7h+YMhx+3//ysCAAAA","334":[13,18]},"packages/frontend/editor-ui/src/features/ai/chatHub/chat.store.ts":{"107":"b:+v////////////////////8PAAAA","136":[36,37,38,39,41,42],"139":[36,37,38,39,41,42],"146":[36,37,38,39,41,42],"162":[36,37,38,39,41,42],"172":[36,37,38,39,41,42],"176":[36,37,38,39,41,42],"213":[36,37,38,39,41,42],"236":[37],"278":[36,37,38,39,41,42],"304":[36,37,38,39],"314":[36,37,38,39,41,42],"333":[36,37,38,39,41,42],"340":[41],"367":[36,37,38,39,41,42],"370":[36,37,38,39,41,42],"376":[36,37,38,39,41,42],"381":[36,37,38,39,41,42],"410":[36,37,38,39,41,42],"440":[36,37],"446":[36,37],"457":[36,37,38,39,41,42],"466":[36,37,38,39,41,42],"483":[41,42],"594":[36,37,38,39,41,42],"609":[36],"656":[41],"693":[37],"796":[37],"948":[37],"960":[39],"984":[39],"995":[39],"1030":[39],"1055":[39],"1075":[39],"1080":[39],"1090":[36,37,38,39,41,42],"1094":[36,37,38,39,41,42],"1105":[40],"1116":[40],"1126":[40],"1143":[36,37,38,39,41,42],"1189":[36,37,38,39],"1207":[36,37,38,39,41,42],"1223":[41,42],"1245":[36,37,38,39,41,42],"1287":[36,37,38,39,41,42],"1328":[36,37,38,39,41,42],"1355":[36,37,38,39,41,42],"1385":[36],"1406":[37],"1524":[36,37,38,39,41,42],"1525":[36,37,38,39,41,42],"1550":[36,37,38,39,41,42],"1551":[36,37,38,39,41,42]},"packages/frontend/editor-ui/src/features/ai/chatHub/chatHubPanel.store.ts":{"19":"b:+v///f////////v///////8PAAAA","29":"b:cP9/4A84/v/l/wOg//////8PAAAA","66":"b:+v///f////////v///////8PAAAA","67":"b:OIiAkPCmAQA+BAA0BF4AQNgOAAAA"},"packages/frontend/editor-ui/src/features/ai/chatHub/module.descriptor.ts":{"18":[36,37,38,39,41,42],"19":[42],"20":[42],"21":[39],"22":[39],"23":[40],"24":[40],"46":[41],"57":[39],"69":[38],"93":[40],"203":"b:+v+f/f////////s///////8PAAAA"},"packages/frontend/editor-ui/src/features/ai/instanceAi/instanceAi.store.ts":{"20":"b:+v////////////////////8PAAAA"},"packages/frontend/editor-ui/src/features/ai/instanceAi/instanceAiSettings.store.ts":{"30":"b:+v////////////////////8PAAAA"},"packages/frontend/editor-ui/src/features/ai/mcpAccess/module.descriptor.ts":{"41":"b:+v+f/f////////s///////8PAAAA"},"packages/frontend/editor-ui/src/features/collaboration/collaboration/collaboration.store.ts":{"32":"b:+v////////////////////8PAAAA","70":"b:cP9/4A84/v/n/wOg//////8PAAAA","78":"b:cP9/4A84/v/l/wOg//////8PAAAA","79":"b:cP8fwA8wAP/naQIgn///1/8OAAAA","82":"b:+v///f////////v///////8PAAAA","86":"b:+v///f////////v///////8PAAAA","90":"b:cP8fwA8wAP/naQIgn///1/8OAAAA","108":"b:cP8fwA8wAP/naQIgn///1/8OAAAA","113":"b:AAAAQAAAAAAgAAAAFiIAQBkCAAAA","117":"b:AAAAQAAAAAAgAAAAFiIAQBECAAAA","122":"b:cP8fwA8wAP/naQIgn///1/8OAAAA","129":"b:cP8fwA8wAP/laQIgn///1/8OAAAA","134":"b:ILwAwAkQAIKhYAAgl+eGV/kGAAAA","153":"b:ILwAwAkQAIKhYAAgl+WGV/kGAAAA","161":"b:ILwAwAkQAIKhYAAgl+eGV/kGAAAA","195":"b:AAAAQAAAAAAgAAAAFiAAQAkCAAAA","204":"b:ILwAwAkQAIKhYAAgl+WGV/kGAAAA","208":"b:cL4d4A0w/u7l9gMg9+3vf/8PAAAA","247":[69,126,132],"266":"b:AIECAAAAAAAjAAAABFwAAsEAAAAA","281":"b:cP8fwA8wAP/naQIgn///1/8OAAAA","288":"b:cP8fwA8wAP/laQIgn///1/8OAAAA","293":"b:cP9/4A84/v/l/wOg//////8PAAAA","297":"b:QL4ZwA0wAGblYIIhl8/vV/8OAAAA","302":[15],"318":"b:QLYRQAwgAKLhYAIgls3nV/ECAAAA","345":"b:+v////////////////////8PAAAA","346":"b:cL4Z4A0w/m7l9oMh9+3vf+8PAAAA","355":"b:cP8fwA8wAP/naQIgn///1/8OAAAA","367":"b:cP8fwA8wAP/naQIgn///1/8OAAAA","389":"b:cP8fwA8wAP/naQIgn///1/8OAAAA","445":[69,105,126,132]},"packages/frontend/editor-ui/src/features/collaboration/projects/components/ProjectCardBadge.vue":{"23":"b:+v////////////////////8PAAAA","37":"b:KACAgADwAQA0AEAQAAIAQBgKAAAA","46":"b:KACAgADwAQA0AEAQAAIAQBgKAAAA","50":"b:KACAgADwAQA0AEAQAAIAQBgKAAAA","73":"b:KACAgADwAQA0AEAQAAIAQBgKAAAA","77":"b:KACAgADwAQA0AEAQAAIAQBgKAAAA","89":"b:KACAgADwAQA0AEAQAAIAQBgKAAAA","105":"b:KACAgADwAQA0AEAQAAIAQBgKAAAA","148":"b:KACAgADwAQA0AEAQAAIAQBgKAAAA","175":"b:KACAgADwAQA0AEAQAAIAQBgKAAAA","178":"b:CACAAACAAQA0AAAAAAIAQBgKAAAA"},"packages/frontend/editor-ui/src/features/collaboration/projects/components/ProjectCreateResource.vue":{"14":"b:uAiA3QDwAQA+AHAUAAIAQBgKAAAA","23":"b:uAiA3QDwAQA+AHAUAAIAQBgKAAAA","34":[48,66,67],"35":"b:uAiA3QDwAQA+AHAUAAIAQBgKAAAA"},"packages/frontend/editor-ui/src/features/collaboration/projects/components/ProjectHeader.vue":{"46":"b:OACAgABUAQA+AEAAAAAAAAgCAAAA","48":"b:uAiA3QD0AQA+AHAUAAIAQBgKAAAA","50":"b:OACAgABUAQA+AEAAAAAAAAgCAAAA","70":"b:OACAgABUAQA+AEAAAAAAAAgCAAAA","82":"b:uAiA3QD0AQA+AHAUAAIAQBgKAAAA","86":"b:OAiAgAD0AQA+AEAQAAAAAAgCAAAA","90":"b:uAiA3QD0AQA+AHAUAAIAQBgKAAAA","107":"b:OAiAgAD0AQA+AEAQAAAAAAgCAAAA","110":[85],"113":[85],"117":"b:KAiAgACgAQAwAAAQAAAAAAgCAAAA","121":"b:uAiA3QD0AQA+AHAUAAIAQBgKAAAA","128":"b:uAiA3QDwAQA+AHAUAAIAQBgKAAAA","135":"b:uAiA3QD0AQA+AHAUAAIAQBgKAAAA","149":"b:uAiA3QD0AQA+AHAUAAIAQBgKAAAA","162":"b:uACAXQCAAQA+ABAEAAIAQBgKAAAA","172":[11,31,44,45,46,68,69,86,92,5],"182":[47,48],"192":[85],"209":"b:uAiA3QDwAQA+AHAUAAIAQBgKAAAA","216":"b:uAiA3QDwAQA+AHAUAAIAQBgKAAAA","232":"b:uAiA3QDwAQA+AHAUAAIAQBgKAAAA","308":"b:uAiA3QD0AQA+AHAUAAIAQBgKAAAA","314":[11,31,44,45,66,4,92,5,131,137],"324":[66,4,5,131,137],"335":[11,31,44,45,66,4,92,5,131,137],"348":[66,4,5,131,137],"358":[11,31,44,45,92,5],"370":[66,67],"373":[47,48],"379":[85],"389":"b:uAiA3QD0AQA+AHAUAAIAQBgKAAAA","399":"b:uAiA3QD0AQA+AHAUAAIAQBgKAAAA","419":"b:OACAgABUAQA+AEAAAAAAAAgCAAAA","427":"b:OACAgABUAQA+AEAAAAAAAAgCAAAA","437":"b:uAiA3QD0AQA+AHAUAAIAQBgKAAAA","451":[3],"462":"b:MAgAgACwAQAMACAQAAAAAAgCAAAA","479":"b:uAiA3QD0AQA+AHAUAAIAQBgKAAAA","482":"b:qAiA3QCgAQAwAHAUAAIAQBgKAAAA","487":[3],"514":"b:uAiA3QDwAQA+AHAUAAIAQBgKAAAA","521":[48,66,67],"522":"b:uAiA3QDwAQA+AHAUAAIAQBgKAAAA","527":"b:MAgAgACwAQAEACAQAAAAAAgCAAAA"},"packages/frontend/editor-ui/src/features/collaboration/projects/components/ProjectNavigation.vue":{"22":"b:+P+f/Q/8/////3M0//////8PAAAA","46":"b:+P+f/Q/8/////3M0//////8PAAAA","48":"b:+P+f/Q/8/////3M0//////8PAAAA","53":"b:+P+f/Q/8/////3M0//////8PAAAA","58":"b:+P+f/Q/8/////3M0//////8PAAAA","59":"b:+P+f/Q/8/////3M0//////8PAAAA","62":"b:+P+f/Q/8/////3M0//////8PAAAA","74":"b:+P+f/Q/8/////3M0//////8PAAAA","83":"b:eP+f7Q/8/////3M0//////8PAAAA","92":"b:eCCAgALUeSR+yEMQ5aJPb8sKAAAA","104":"b:+P+f/Q/8/////3M0//////8PAAAA","116":"b:+P+f/Q/8/////3M0//////8PAAAA","126":"b:+P+f/Q/8/////3M0//////8PAAAA","140":"b:+P+f/Q/8/////3M0//////8PAAAA","145":"b:MAAAAAAAAAAkAAAEAAIAQBgOAAAA","148":"b:+P+f/Q/8/////3M0//////8PAAAA","246":[48,68,69,131],"263":"b:eCCAgALUeSR+yEMQ5aJPb8sKAAAA"},"packages/frontend/editor-ui/src/features/collaboration/projects/components/ProjectTabs.vue":{"22":"b:uAiA3QD0AQA+AHAUAAIAQBgKAAAA","36":"b:uAiA3QD0AQA+AHAUAAIAQBgKAAAA","38":"b:uAiA3QD0AQA+AHAUAAIAQBgKAAAA","44":"b:OAiAgAD0AQA+AEAQAAAAAAgCAAAA","46":"b:uAiA3QD0AQA+AHAUAAIAQBgKAAAA","89":"b:uAiA3QD0AQA+AHAUAAIAQBgKAAAA","102":"b:uAiA3QD0AQA+AHAUAAIAQBgKAAAA","141":"b:uAiA3QD0AQA+AHAUAAIAQBgKAAAA","142":"b:uAiA3QD0AQA+AHAUAAIAQBgKAAAA","158":"b:uAiA3QD0AQA+AHAUAAIAQBgKAAAA"},"packages/frontend/editor-ui/src/features/collaboration/projects/composables/useFavoriteNavItems.ts":{"22":"b:+P+f/Q/8/////3M0//////8PAAAA","128":"b:+P+f/Q/8/////3M0//////8PAAAA"},"packages/frontend/editor-ui/src/features/collaboration/projects/composables/useProjectPages.ts":{"7":"b:+P+f/Q/8/////3O0//////8PAAAA","11":"b:OAiAgAB0AQA+AEAQAAAAAAgCAAAA","14":"b:uAiA3QD0AQA+AHAUAAIAQBgKAAAA","17":"b:uAiA3QD0AQA+AHAUAAIAQBgKAAAA"},"packages/frontend/editor-ui/src/features/collaboration/projects/projects.api.ts":{"7":[151,23,42,48,3,69,86,5,131,137],"11":[151,67,68,69,137],"27":[151,40,45,7,4,92,5,6,137],"45":"b:+v+f/f////////s///////8PgAAA","49":"b:+v+f/f////////s///////8PgAAA","53":"b:OCiAgAL0AQA+AEAQAAAAQMoCgAAA","57":[151,23,48,3,69,5,131,137],"64":[151,23,48,3,69,5,131,137],"72":[151],"85":"b:+v+f/f////////s///////8PgAAA","89":[151,42,3],"97":[151,42],"106":[151]},"packages/frontend/editor-ui/src/features/collaboration/projects/projects.routes.ts":{"10":"b:uACAXQKAAQA+ABAEAAIAQBgKAAAA","11":[11,31,44,45,46,68,69,86,92,5],"12":[11,31,44,45,46,68,69,86,92,5],"13":[23,42,48,3,69,86,5,131,137],"16":[85],"18":"b:uAiA3ULwAQA+AHAUAAIAQBgKAAAA","22":"b:MAiAgADwAQA+AEAQAAAAAAgCAAAA","33":"b:uACAXUKAAQA+ABAEAAIAQBgKAAAA","44":[11,31,44,45,46,68,69,86,92,5],"64":[65,66,67],"74":[85],"134":"b:+v////////////////////8PAAAA","146":[23,42,48,3,69,86,5,131,137],"147":[23,42,48,3,69,86,5,131,137],"169":"b:qAiA3UKgAQAwAHAUAAIAQBgKAAAA","184":"b:+v////////////////////8PAAAA"},"packages/frontend/editor-ui/src/features/collaboration/projects/projects.store.ts":{"32":"b:+v////////////////////8PgAAA","51":"b:+v+f//////////8///////8PgAAA","54":"b:+v+f//////////8///////8PgAAA","58":"b:+v////////////////////8PgAAA","64":[151,137],"65":[151],"66":[151],"68":[151,40,45,86,92,5],"69":"b:+v+f/b////////s///////8PgAAA","70":"b:+P+f/Q/8/////3M0//////8PgAAA","71":"b:+v+f/b////////s///////8PgAAA","72":[151],"75":"b:+v+f/b////////s///////8PgAAA","81":"b:+v////////////////////8PgAAA","84":"b:+v+f//////////8///////8PgAAA","89":"b:+P+f/Q/8/////3M0//////8PgAAA","90":"b:+v////////////////////8PgAAA","95":"b:qCiA3fK2AQAwAHAUAAIAQNoKgAAA","99":[151,23,42,48,3,69,86,5,131,137],"103":"b:+v+f/f////////s///////8PgAAA","107":"b:+v+f/f////////s///////8PgAAA","111":[151],"119":[151,67,68,69,137],"129":[151,40,45,7,4,92,5,6,137],"139":"b:OCiAgAL0AQA+AEAQAAAAQMoCgAAA","142":"b:OAiAgAD0AQA+AEAQAAAAAAgCgAAA","146":"b:ACAAgAIQAAAgAAAAAAAAQMICgAAA","153":"b:+v///f////////v///////8PgAAA","159":[151,23,48,3,69,5,131,137],"166":[151,23,48,3,69,5,131,137],"174":[151,23,48,3,69,5,131,137],"192":[151,42,3],"200":[151,42],"209":[151],"214":[151],"217":[151],"220":"b:+v+f/f////////s///////8PgAAA","224":"b:MMECQAIAAJuiKQAAHvryw9kOgAAA","232":[151,5],"262":[151,68,69],"285":[151],"299":[151,23,42,48,3,69,86,5,131,137],"310":"b:+v////////////////////8PgAAA"},"packages/frontend/editor-ui/src/features/collaboration/projects/projects.utils.ts":{"16":[151,40,45,7,4,92,5,6,137],"18":[151,40,45,7,4,92,5,6,137],"31":"b:uACA3QDwAQA+AHAUAAIAQBgKgAAA","33":[151,67,68,69,137],"42":[151],"50":"b:8IgBgCDxgQA8EEAwAAAASQgOgAAA","64":[151,68,69],"69":"b:+v////////////////////8PgAAA"},"packages/frontend/editor-ui/src/features/collaboration/projects/views/ProjectVariables.vue":{"68":[85],"78":[85],"82":[85],"87":[85],"91":[85],"93":[85],"94":[85],"109":[85],"114":[85],"150":[85],"184":[85],"193":[85],"197":[85],"216":[85],"222":[85],"269":[85],"281":[85],"290":[85],"314":[85],"400":[85],"434":[85],"435":[85],"451":[85],"452":[85],"463":[85]},"packages/frontend/editor-ui/src/features/core/dataTable/dataTable.api.ts":{"13":[151,47,48,137],"40":[151,47,48],"61":[151,48],"77":[151,47],"93":[151,47],"109":[151,47],"122":[151,47],"139":[151],"156":[151,47,48],"176":[151,47],"193":[151,47],"214":[151,47],"220":[151,47],"238":"b:+v+f/b////////s///////8PgAAA","246":[151],"269":[151],"283":[151]},"packages/frontend/editor-ui/src/features/core/dataTable/dataTable.store.ts":{"37":"b:+v////////////////////8PAAAA","50":[47,48],"56":"b:+v+f/b////////s///////8PAAAA","64":[47,48],"72":"b:+v+f//////////8///////8PAAAA","76":[47,48,137],"101":[47,48],"176":[48],"179":[48],"185":[47],"197":[47],"199":[47],"207":[47],"215":[47],"236":[47,48],"237":[47,48],"244":[47],"256":[47],"264":[47],"278":[47],"279":[47],"313":[47,48],"331":[47],"341":[47],"356":[47],"360":"b:+v+f/b////////s///////8PAAAA"},"packages/frontend/editor-ui/src/features/core/folders/folders.constants.ts":{"16":"b:+v////////////////////8PAAAA"},"packages/frontend/editor-ui/src/features/core/folders/folders.store.ts":{"23":"b:+v////////////////////8PAAAA","40":"b:OACACQCAAQA+ABAEAAIAQBgKAAAA","41":[65,66,67],"52":[66,67],"56":[66,67],"64":[65,66,67],"75":[65,66,67],"81":[65,66,67],"99":"b:uACAXQCAAQA+ABAEAAIAQBgKAAAA","115":[67],"116":[67],"121":[67],"125":[67],"134":[67,68,69],"174":[67],"183":[67],"190":[67],"206":[67],"219":[65,67],"249":[67],"262":[66],"273":[66],"342":[66]},"packages/frontend/editor-ui/src/features/credentials/credentials.api.ts":{"15":"b:+v+f/f////////s///////8PgAAA","33":"b:+v+f/f////////s///////8PgAAA","37":"b:IIgBgCBwgAAgEEAQAAAACQAEgAAA","60":"b:IAgAgABxAAA4AMARAAAAAAAGgAAA","76":"b:cP8f4P8+/v/n/wMg//////8PgAAA","85":"b:IIABgCBwAAAgEEAQAAAACQAEgAAA","92":[151,44],"96":[151],"100":[151,40,44,45,92,5],"113":[13,151,38,40,44,45,138],"123":[151,138],"134":[151,46,123],"144":"b:IKABgCARAAAgEAAQAAAAAQAEgAAA"},"packages/frontend/editor-ui/src/features/credentials/credentials.store.ts":{"41":"b:+v////////////////////8PgAAA","49":[13,151],"53":[13,151],"63":[151],"67":"b:+v+f/f////////s///////8PgAAA","68":"b:cP8f4P9//v/3/8sx//////8PgAAA","73":"b:MKgB4PF31pdzFUAwRUGgLygGgAAA","74":"b:IIABQCAWQAJRAAAARQEgKQAGgAAA","77":"b:MKABwPA3AJMhFAAAAEAACQAEgAAA","80":"b:MKABwPA3AJMhFAAAAEAACQAEgAAA","82":"b:MKABwPA3AJMhEAAAAEAACQAEgAAA","91":"b:MKgB4AEy1gZhEQAgBEGgLyAAgAAA","95":"b:MKgB4AEy1gZhEQAgBEGgLyAAgAAA","97":"b:MKABwAAyQAZhEAAABEEgKQAAgAAA","107":[15,16,151,31,44,69,76,120,123],"108":[15,16,151,31,44,69,76,123],"112":[15,16,151,31,44,69,76,120,123],"116":[15,16,151],"124":"b:ML5b4P131t/x/UMwz+3//ysPgAAA","125":"b:ML5b4P131t/x/UMwz+3//ysPgAAA","128":"b:MKgBwPB3gAAhEEAQBEAACQAFgAAA","129":"b:MKgBwPB3gAAhEEAQBEAACQAFgAAA","132":"b:AIABgAAyAAAgEAAAAAAACQAAgAAA","133":"b:AIABgAAyAAAgEAAAAAAACAAAgAAA","139":"b:MKABwPA3AJMhFAAAAEAACQAEgAAA","140":"b:MKABwPA3AJMhFAAAAEAACAAEgAAA","145":[151],"146":[151],"151":"b:IIABgCAxAAAgEAAQAAAAAQAEgAAA","152":"b:IIABgCAxAAAgEAAQAAAAAAAEgAAA","160":"b:IIABgCAxAAAgEAAQAAAAAQAEgAAA","165":[151,30,44],"166":[151,30,44],"172":[151,30,44],"196":"b:IIgBgCBxgAAgEEAQAAAACQAEgAAA","197":"b:IIgBgCBxgAAgEEAQAAAACAAEgAAA","214":"b:IIgBgCBxgAAgEEAQAAAACQAEgAAA","215":"b:IIgBgCBxgAAgEEAQAAAACAAEgAAA","222":"b:cP8f4A84/v/n/wMg//////8PgAAA","223":"b:cP8f4A84/v/n/wMg//////8PgAAA","234":"b:+v+f/f////////s3//////8PgAAA","235":"b:+v+f/f////////s3//////8PgAAA","245":[151],"246":[151],"253":"b:cP8f4P9//v///8Mx//////8PgAAA","254":"b:MKABwPB3SJd5IkARd+91acQOgAAA","265":"b:IIABgCBxAAAgEEAQAAAACQAEgAAA","277":"b:+v+f/f////////s///////8PgAAA","285":"b:IAgAgABxAAA4AMARAAAAAAAGgAAA","317":"b:cP8f4P8+/v/n/wMg//////8PgAAA","328":[13,151,38,40,44,45,138],"336":"b:ML5b4A0y1s7h+QMgz+3//ysCgAAA","349":"b:IIABgCBwAAAgEEAQAAAACQAEgAAA","386":[151,40,44,45,92,5],"399":[151,44],"408":[151],"419":[151,46,123],"423":[151,138],"427":"b:IKABgCARAAAgEAAQAAAAAQAEgAAA","442":"b:IIgBgCBwgAAgEEAQAAAACQAEgAAA","459":[151,92,5],"469":[151,92,5],"481":[151],"487":[151],"544":[13,151,38,40,74,138],"553":[13,151,38,40,138],"555":[13,151,38,40,138]},"packages/frontend/editor-ui/src/features/execution/executions/executions.store.ts":{"31":"b:+v////////////////////8PAAAA","42":[15,98,106,107,108,110,134,135],"63":[15,98,106,107,108,110,134,135],"66":[106,108,134,135],"73":[15,98,106,107,108,110,134,135],"74":[98,106,107,108,110,134,135],"103":[15,98,106,107,108,110,134,135],"111":[15,98,106,107,108,110,134,135],"112":[135],"123":[15,98,106,107,108,110,134,135],"133":[135],"140":[107],"145":[134],"149":[15,98,106,107,108,110,134,135],"157":[15,98,106,107,108,110,134,135],"177":[15,98,106,107,108,110,134,135],"194":[98,106,107,108,110,134,135],"208":[15,98,106,107,108,110,134,135],"214":[106,107,134,135],"222":[15,98,106,107,108,110,134,135],"227":[15,98,106,107,108,110,134,135],"286":[110],"308":[107],"330":[15,98,106,134,135],"338":[15,98,106,134,135]},"packages/frontend/editor-ui/src/features/execution/executions/executions.utils.ts":{"48":"b:+v////////////////////8PgAAA","62":"b:AIAAAAAAAAAAAAAABFwAAMAAgAAA","124":[151,19,20,57],"137":"b:ANcbAA4gAP/BaAKAh/x/l8EAgAAA","139":"b:ANcbAA4gAP/BaAKAh/x/l8EAgAAA","190":[151,110],"247":"b:AMYbAAQAAM7BaAIAgsx/lwEAgAAA","248":"b:AMYbAAQAAM7BaAIAgsx/lwEAgAAA","256":"b:AMYbAAQAAM7BaAIAgsx/lwEAgAAA","265":"b:AMYbAAQAAM7BaAIAgsx/lwEAgAAA","266":"b:AMYbAAQAAM7BaAIAgsx/lwEAgAAA","269":[151],"324":"b:ANcLAA4gAP/BaAIAh/x/l8EAgAAA","362":"b:AIYBAAAgAAAAAAAAAEwgAMAAgAAA","411":"b:ANcLAA4gAP/BaAIAh/x/l8EAgAAA","428":"b:cP9/4A84/v/n/wOg//////8PgAAA","442":[13,151],"449":[13,151,63,107,111,122],"455":"b:cL964A8w/P/hzwMg3/////sPgAAA","461":[151],"497":[151],"519":[151]},"packages/frontend/editor-ui/src/features/execution/insights/components/InsightsSummary.vue":{"33":"b:KAiA1QCgAQAwAHAUAAIAQBgKAAAA","46":"b:KAiA1QCgAQAwAHAUAAIAQBgKAAAA","54":"b:KAiA1QCgAQAwAHAUAAIAQBgKAAAA","56":"b:KAiA1QCgAQAwAHAUAAIAQBgKAAAA","59":"b:KAiA1QCgAQAwAHAUAAIAQBgKAAAA","60":"b:KAiA1QCgAQAwAHAUAAIAQBgKAAAA","118":"b:KAiA1QCgAQAwAHAUAAIAQBgKAAAA","133":"b:KAiA1QCgAQAwAHAUAAIAQBgKAAAA"},"packages/frontend/editor-ui/src/features/execution/insights/insights.api.ts":{"16":"b:KAiA1QKgAQAwAHAUAAIAQBgKAAAA","34":"b:KAiA1QKgAQAwAHAUAAIAQBgKAAAA"},"packages/frontend/editor-ui/src/features/execution/insights/insights.constants.ts":{"21":"b:KAiA1QKgAQAwAHAUAAIAQBgKAAAA","22":"b:KAiA1QKgAQAwAHAUAAIAQBgKAAAA","23":"b:KAiA1QKgAQAwAHAUAAIAQBgKAAAA","24":"b:KAiA1QKgAQAwAHAUAAIAQBgKAAAA","25":"b:KAiA1QKgAQAwAHAUAAIAQBgKAAAA"},"packages/frontend/editor-ui/src/features/execution/insights/insights.store.ts":{"12":"b:uAiA3QLwAQA+AHAUAAIAQBgKAAAA","17":"b:qAiA3QKgAQAwAHAUAAIAQBgKAAAA","21":"b:KAiA1QKgAQAwAHAUAAIAQBgKAAAA","25":"b:qAiA3QKgAQAwAHAUAAIAQBgKAAAA","30":"b:KAiA1QKgAQAwAHAUAAIAQBgKAAAA"},"packages/frontend/editor-ui/src/features/execution/insights/insights.utils.ts":{"17":"b:KAiA1QKgAQAwAHAUAAIAQBgKAAAA","19":"b:KAiA1QKgAQAwAHAUAAIAQBgKAAAA","20":"b:KAiA1QKgAQAwAHAUAAIAQBgKAAAA","23":"b:KAiA1QKgAQAwAHAUAAIAQBgKAAAA","24":"b:KAiA1QKgAQAwAHAUAAIAQBgKAAAA","52":"b:KAiA1QKgAQAwAHAUAAIAQBgKAAAA","54":"b:KAiA1QKgAQAwAHAUAAIAQBgKAAAA","79":"b:KAiA1QCgAQAwAHAUAAIAQBgKAAAA","96":"b:KAiA1QCgAQAwAHAUAAIAQBgKAAAA","117":"b:KAiA1QCgAQAwAHAUAAIAQBgKAAAA"},"packages/frontend/editor-ui/src/features/instanceRegistry/stores/instanceRegistry.store.ts":{"7":"b:+v////////////////////8PAAAA","14":[102]},"packages/frontend/editor-ui/src/features/integrations/sourceControl.ee/sourceControl.api.ts":{"22":"b:+v////////////////////8PgAAA","24":[151,84],"30":[151],"37":[151],"44":[151,84],"53":[151,84],"61":[151],"65":[151],"76":[151],"87":[151,84],"96":[151]},"packages/frontend/editor-ui/src/features/integrations/sourceControl.ee/sourceControl.store.ts":{"14":"b:+v////////////////////8PgAAA","18":"b:+v+f/f////////s///////8PgAAA","24":"b:+v////////////////////8PgAAA","45":[151],"58":[151],"62":[151,84],"66":"b:+v////////////////////8PgAAA","68":[151,84],"73":[151,84],"78":[151,84],"87":[151,84],"102":[151],"112":[151],"116":[151],"124":[151]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/FilterConditions/constants.ts":{"299":"b:+v////////////////////8PAAAA","305":"b:+v////////////////////8PAAAA","311":"b:+v////////////////////8PAAAA","317":"b:+v////////////////////8PAAAA","323":"b:+v////////////////////8PAAAA","329":"b:+v////////////////////8PAAAA"},"packages/frontend/editor-ui/src/features/ndv/shared/ndv.store.ts":{"41":"b:+v////////////////////8PgAAA","45":"b:+v////////////////////8PgAAA","46":"b:+v////////////////////8PgAAA","109":"b:+v////////////////////8PgAAA","113":"b:MJ5b4C1w1s7h+UMwz+3//ysGgAAA","135":"b:ML5b4C1z1s7h+cMxz+3//ysGgAAA","139":"b:MJ5b4C1w1s7h+UMwz+3//ysGgAAA","146":"b:IJAZgCVwAA6hEEAQCAUvHwAEgAAA","150":"b:ML4b4A0y1s7h+cMgz+3//ysCgAAA","152":[151,113],"154":[151,113],"156":"b:AMZaAAQAAM7BaAIAiu1/twEAgAAA","158":"b:MP5b4A0w1s7h+QMgz+3//zsCgAAA","160":"b:AMZaAAQAAM7BaAIAiu1/twEAgAAA","162":"b:AAYIAAQAAIzASAIAiu1/twEAgAAA","182":"b:AIYAAAAAAIBAAQIAgEmvHwAAgAAA","184":"b:AIIAAAAAAIBAAQIAAEmvHwAAgAAA","186":"b:AAAAAAAAAACAAEAAAAUPHwAAgAAA","188":[151],"190":"b:ML5b4C1z1s7h+cMxz+3//ysGgAAA","203":"b:ML5b4C1z1s7h+cMxz+3//ysGgAAA","211":"b:ML5b4C1z1s7h+cMxz+3//ysGgAAA","228":"b:+v////////////////////8PgAAA","230":"b:ALofYAgw3koh+QEhx+3/d7kCgAAA","235":"b:MJ5b4A0w1s7h+YMhx+3//ysCgAAA","244":"b:MJ4b4A0w1o7h+QMgx+3//ysAgAAA","248":[17,151,118,121],"252":"b:MJ5b4A0w1s7h+QMgx+3//ysCgAAA","256":[151],"266":"b:MJ5b4A0w1s7h+QMgx+3//ysCgAAA","270":"b:ALoZYAgwVkoh2QEgx+3/djkCgAAA","274":"b:AAAAAAAAAAAACAAAAElyAgAAgAAA","285":"b:AAAAAAAAAAAAAAAAACEPBgAAgAAA","289":"b:AAAAAAAAAAAAAAAAACEPBgAAgAAA","293":"b:ABAYAAUwAA6hAAAACAQvHwIAgAAA","297":[151,113],"315":[151,113],"325":[151,113],"329":[151,113],"333":[151,113],"337":[151,113,116,118,121],"342":"b:MN5b4A0w1s7h+QMgz+3//ysCgAAA","350":"b:MN5b4A0w1s7h+QMgz+3//ysCgAAA","358":[151,113],"363":[151,113,116,118,121],"368":[151],"373":"b:ABAYAAUgAA4BAEAAAAUPHwAAgAAA","377":[151],"390":"b:ABAYAAUykA6hAIABiAQvHwIAgAAA","467":"b:+v////////////////////8PgAAA","471":[151,69,105,126,132],"489":"b:+v////////////////////8PgAAA","491":"b:+v////////////////////8PgAAA","494":"b:+v////////////////////8PgAAA"},"packages/frontend/editor-ui/src/features/resolvers/composables/useDynamicCredentials.ts":{"9":"b:+v//9b////////v///////8PAAAA"},"packages/frontend/editor-ui/src/features/settings/environments.ee/components/VariableModal.vue":{"57":[85],"80":[85],"84":[85],"103":[85],"118":[85],"119":[85],"122":[85],"128":[85],"168":[85],"169":[85],"173":[85],"178":[85],"182":[85],"218":[85],"222":[85],"239":[85],"252":[85],"265":[85],"272":[85],"295":[85],"300":[85],"306":[85],"313":[85],"315":[85],"320":[85],"334":[85]},"packages/frontend/editor-ui/src/features/settings/environments.ee/environments.api.ts":{"10":[151,85,99,124,132],"21":[151,85],"28":[151,85],"40":[151,85]},"packages/frontend/editor-ui/src/features/settings/environments.ee/environments.store.ts":{"13":"b:cP9/4C97/v/n/+Px//////8PgAAA","18":[151],"21":[151,85],"22":[151,85],"29":"b:ML5b4C1z1s7h+cMxz+3//ysGgAAA","30":[151,99,124],"35":[151,85,99,124,132],"43":[151,85],"46":[151],"56":[151,85],"59":[151],"64":[151,85],"69":[151,85],"74":[151,85],"79":"b:ML5b4C1z1s7h+cMxz+3//ysGgAAA","80":[151,99,124],"89":[151]},"packages/frontend/editor-ui/src/features/settings/sso/sso.store.ts":{"19":"b:+v////////////////////8PAAAA","26":[26,28,69,90],"39":"b:+v////////////////////8PAAAA","91":[26,28,1,69,89,90,7],"154":[26,28,69,90,7],"175":[26,28,69,90]},"packages/frontend/editor-ui/src/features/settings/users/users.store.ts":{"36":"b:+v+f//////////8///////8PAAAA","37":"b:+v////////////////////8PAAAA","38":"b:+v+f//////////8///////8PAAAA","40":[45,69,131],"45":"b:+v////////////////////8PAAAA","62":"b:+P+f/Q/8/////3M0//////8PAAAA","64":"b:+v////////////////////8PAAAA","68":"b:MAgQoAgQZAIhAAAgxwFlPSIAAAAA","72":"b:+v///f////////v///////8PAAAA","74":[45,69,131],"76":"b:eIoZoAk0/04h0Eggxy3vfaoCAAAA","78":[1,89,90],"80":[1,89,90],"84":[15,16,77,93,110,119,120],"88":[24],"92":[15,77,93,110,119,120],"98":[15,16,44,49,76,96,107,119,120],"124":[7],"130":"b:+v+f//////////8///////8PAAAA","131":"b:+v+f//////////8///////8PAAAA","153":"b:+v+f//////////8///////8PAAAA","166":"b:+v+f//////////8///////8PAAAA","175":"b:+v+f//////////8///////8PAAAA","186":[69,90],"190":[7],"209":[28,69,90],"218":"b:+v////////////////////8PAAAA","222":"b:+v////////////////////8PAAAA","226":[69,90],"283":[89,90],"319":[7],"324":"b:+P+f/Q/8/////3M0//////8PAAAA","374":"b:+P///Q+4/////xOk//////8PAAAA","381":[90],"385":[90],"393":[90],"400":[90],"417":[7],"435":[7],"444":"b:+v+f/f////////s///////8PAAAA"},"packages/frontend/editor-ui/src/features/setupPanel/setupPanel.store.ts":{"10":"b:+v////////////////////8PAAAA","14":"b:cP8f4A84/v/l/wMg//////8PAAAA","20":"b:cP9/4A84/v/l/wPg//////8PAAAA","22":[13],"29":[13],"34":[13]},"packages/frontend/editor-ui/src/features/shared/banners/banners.store.ts":{"14":"b:+v////////////////////8PAAAA","32":"b:+v+f/f////////s///////8PAAAA","93":"b:+v////////////////////8PAAAA","97":[43],"102":[69,90],"110":"b:+v+f/f////////s///////8PAAAA"},"packages/frontend/editor-ui/src/features/shared/banners/components/BannerStack.vue":{"38":"b:+v////////////////////8PAAAA","46":"b:+v////////////////////8PAAAA","51":[43],"55":[43],"56":[43],"59":"b:+v////////////////////8PAAAA","65":[43],"86":"b:+v////////////////////8PAAAA","89":"b:+v////////////////////8PAAAA"},"packages/frontend/editor-ui/src/features/shared/commandBar/composables/useChatHubCommands.ts":{"28":"b:+v////////////////////8PAAAA","40":[36,37,38,39,41,42],"47":[36,37,38,39,41,42],"81":[36,37,38,39,41,42],"87":[36,37,38,39,41,42],"98":[36,37,38,39,41,42],"101":[36,37,38,39,41,42],"128":[36,37,38,39,41,42],"150":[36,37,38,39,41,42],"151":[36,37,38,39,41,42],"154":[36,37,38,39,41,42],"175":[36,37,38,39,41,42],"176":[36,37,38,39,41,42],"179":[36,37,38,39,41,42],"199":[36,37,38,39,41,42],"200":[36,37,38,39,41,42],"203":[36,37,38,39,41,42]},"packages/frontend/editor-ui/src/features/shared/commandBar/composables/useCommandBar.ts":{"31":"b:+v////////////////////8PAAAA","45":"b:+v+f//////////8///////8PAAAA","52":"b:+v+f/f////////s///////8PAAAA","188":"b:+v+f//////////8///////8PAAAA","222":"b:+v+f//////////8///////8PAAAA","244":[137],"253":"b:+v+f//////////8///////8PAAAA","259":[137],"266":"b:cP8f4P8+/v/n/wMg//////8PAAAA","284":"b:+v+f//////////8///////8PAAAA","285":"b:+v+f//////////8///////8PAAAA","289":"b:+v+f//////////8///////8PAAAA","290":"b:+v+f//////////8///////8PAAAA","293":[137],"311":"b:+v+f//////////8///////8PAAAA","314":"b:+v+f/f////////s///////8PAAAA"},"packages/frontend/editor-ui/src/features/shared/commandBar/composables/useCredentialNavigationCommands.ts":{"22":"b:+v////////////////////8PAAAA","40":[137],"41":[137],"44":"b:+v+f//////////8///////8PAAAA","46":[137],"56":[137],"62":[137],"119":"b:+v+f//////////8///////8PAAAA","123":"b:+v+f//////////8///////8PAAAA","130":"b:+v+f//////////8///////8PAAAA","192":[137],"215":"b:ugiA3fD/AQA+BPgfAEAAQMgOAAAA"},"packages/frontend/editor-ui/src/features/shared/commandBar/composables/useDataTableNavigationCommands.ts":{"20":"b:+v////////////////////8PAAAA","44":"b:+v+f//////////8///////8PAAAA","50":[137],"58":[137],"69":[137],"124":"b:+v+f/b////////s///////8PAAAA","128":"b:+v+f//////////8///////8PAAAA","135":"b:+v+f//////////8///////8PAAAA","186":[137]},"packages/frontend/editor-ui/src/features/shared/commandBar/composables/useExecutionCommands.ts":{"27":"b:+v////////////////////8PAAAA","38":[98,106,107,108,110,134,135],"40":[98,106,107,108,110,134,135],"46":[98,106,107,108,110,134,135],"51":[98,106,107,108,110,134,135],"73":[98,106,107,108,110,134,135],"79":[98,106,107,108,110,134,135],"209":[98,106,107,108,110,134,135]},"packages/frontend/editor-ui/src/features/shared/commandBar/composables/useExecutionNavigationCommands.ts":{"10":"b:+v////////////////////8PAAAA","28":"b:+v+f//////////8///////8PAAAA"},"packages/frontend/editor-ui/src/features/shared/commandBar/composables/useGenericCommands.ts":{"31":"b:+v////////////////////8PAAAA","40":"b:+v+f//////////8///////8PAAAA"},"packages/frontend/editor-ui/src/features/shared/commandBar/composables/useInstanceAiCommands.ts":{"20":"b:+v////////////////////8PAAAA","27":"b:+v+f//////////8///////8PAAAA","54":"b:+v+f//////////8///////8PAAAA","101":"b:+v+f/f////////s///////8PAAAA"},"packages/frontend/editor-ui/src/features/shared/commandBar/composables/useNodeCommands.ts":{"26":"b:+v////////////////////8PAAAA","43":"b:cP8f4A84/v/n+wMg//////8PAAAA","46":"b:cP8f4A84/v/n+wMg//////8PAAAA","48":"b:cP8f4A84/v/n/wMg//////8PAAAA","52":"b:cP8f4A84/v/n/wMg//////8PAAAA","56":"b:cP8f4A84/v/n/wMg//////8PAAAA","62":"b:cP8f4A84/v/n/wMg//////8PAAAA","91":"b:cP8f4A84/v/n/wMg//////8PAAAA","96":"b:cP8f4A84/v/n/wMg//////8PAAAA","99":"b:cP8f4A84/v/n/wMg//////8PAAAA","107":"b:cP8b4A8w/v/h/wMg//////sPAAAA","136":"b:cP8f4A84/v/n/wMg//////8PAAAA","137":"b:cP8b4A8w/v/h/wMg//////sPAAAA","140":"b:cP8f4A84/v/n/wMg//////8PAAAA","148":"b:cP8f4A84/v/n/wMg//////8PAAAA"},"packages/frontend/editor-ui/src/features/shared/commandBar/composables/useProjectNavigationCommands.ts":{"16":"b:+v////////////////////8PAAAA","27":[137],"72":"b:qACADCAkAQAgAEAAAAAAAAgCAAAA","78":"b:+v+f//////////8///////8PAAAA","84":"b:+v+f//////////8///////8PAAAA","125":[137]},"packages/frontend/editor-ui/src/features/shared/commandBar/composables/useRecentResources.ts":{"32":"b:+v////////////////////8PAAAA","43":"b:+v///f////////v///////8PAAAA","58":"b:cP8fwA8wAP/naQIgn///1/8OAAAA","59":"b:IJoawAwQAMrgaQIAF+/3x5kGAAAA","70":"b:IJ4awA0QAM7haQIAh+3/1wMCAAAA","73":"b:AIIAwAAQAAggCQAABezyRwAAAAAA","89":"b:+v+f//////////8///////8PAAAA","177":"b:+v+f/f////////s///////8PAAAA","181":"b:MMECQAIAAJumKQAAHvryw9kCAAAA"},"packages/frontend/editor-ui/src/features/shared/commandBar/composables/useWorkflowCommands.ts":{"51":"b:+v////////////////////8PAAAA","68":"b:cP8f4A84/v/n+wMg//////8PAAAA","71":"b:cP8f4A84/v/n/wMg//////8PAAAA","73":"b:cP8f4A84/v/n/wMg//////8PAAAA","77":"b:cP8f4A84/v/n/wMg//////8PAAAA","81":"b:cP8f4A84/v/n/wMg//////8PAAAA","84":"b:cP8b4A8w/v/h/wMg//////sPAAAA","85":"b:MKABwAAwAJMhEAAAAEAACQAEAAAA","97":"b:MKABwAAwAJMhEAAAAEAACQAEAAAA","117":"b:cP8f4A84/v/n/wMg//////8PAAAA","300":"b:cP8f4A84/v/n/wMg//////8PAAAA","302":"b:cP8b4A8w/v/h/wMg//////sPAAAA","303":[69,127,128,129],"304":[69,127,128,129],"310":[69,128,129],"320":[69,128,129],"342":"b:cP8f4A84/v/n/wMg//////8PAAAA","383":"b:cP8f4A84/v/n/wMg//////8PAAAA","420":"b:cP8f4A84/v/n/wMg//////8PAAAA","474":"b:cP8f4A84/v/n/wMg//////8PAAAA","484":"b:cP8f4A84/v/n/wMg//////8PAAAA"},"packages/frontend/editor-ui/src/features/shared/commandBar/composables/useWorkflowNavigationCommands.ts":{"29":"b:+v////////////////////8PAAAA","55":"b:+v+f//////////8///////8PAAAA","57":[137],"65":[137],"74":[137],"161":[137],"162":[137],"167":[137],"168":[137],"206":[137],"220":[137],"242":[137],"302":[137],"312":"b:+v+f/7////////8///////8PAAAA","313":[137],"316":"b:+v+f//////////8///////8PAAAA","320":[137],"323":"b:+v+f//////////8///////8PAAAA","377":[137],"402":"b:+v+f/f////////s///////8PAAAA"},"packages/frontend/editor-ui/src/features/shared/editors/components/CodeNodeEditor/completions/js.snippets.ts":{"8":"b:+v////////////////////8PAAAA"},"packages/frontend/editor-ui/src/features/shared/editors/plugins/codemirror/completions/constants.ts":{"467":"b:+v////////////////////8PAAAA","471":"b:+v////////////////////8PAAAA"},"packages/frontend/editor-ui/src/features/shared/editors/plugins/codemirror/completions/datatype.completions.ts":{"75":"b:AAAAAAAAAAAAAEAAAAEPHwAAAAAA","163":[112,113,120,122],"179":[112,113,115,120,122],"181":[112,113,115,120,122],"187":[112,113,115,120],"188":[112,113,115,120],"205":[112,113,115,120,122],"208":[112,113,115,120,122],"210":[112,113,115,120,122],"211":[112,113,115,120,122],"215":[115],"240":[112,113,115,120,122],"261":[112,113,115,120,122],"285":[112,113,115,120],"292":[112,113,115,120],"315":[112,113,115,120],"324":[112,113,115,120],"330":[112,113,115,120],"342":[112,113,120],"348":[112,113,120],"353":[112,113,120],"362":[112,113,120],"368":[112,113,115,120],"380":[112,113,115,120],"381":[112,113,115,120],"382":[112,113,115,120],"392":[112,113,115,120,122],"414":[112,113,115,120],"422":[112,113,120,122],"453":[112,113,120,122],"472":[122],"476":[112,113,120],"477":[112,113,120],"527":[112,113,115,120,122],"545":[112,113,115,120,122],"553":[112,113,115,120,122],"561":[112,113,115,120,122],"562":[112,113,115,120,122],"573":[115],"574":[115],"578":[115],"583":[115],"633":[115],"700":[115],"731":[115],"763":[115],"776":[115],"784":[112,113,120],"985":[122],"1077":[122],"1078":[122],"1560":"b:+v////////////////////8PAAAA"},"packages/frontend/editor-ui/src/features/shared/editors/plugins/codemirror/completions/infoBoxRenderer.ts":{"6":[115],"18":[115],"31":[115],"64":[122],"76":[115,122],"117":[115],"166":[115],"170":[115],"177":[115],"189":[115],"217":[115],"238":"b:+v////////////////////8PAAAA","239":[115,122]},"packages/frontend/editor-ui/src/features/shared/editors/plugins/codemirror/completions/utils.ts":{"27":[104,112,113,114,115,120,122],"83":[112,113,115,120,122],"119":[112,113,120,122],"122":[112,113,120,122],"131":"b:AAAAAAAAAAAAAEAAAAEPFQAAAAAA","134":[112,113,120],"143":[112,113,120],"169":"b:AAAAAAAAAAAAAAAAAAEPFQAAAAAA","183":[122],"207":"b:AAAAAAAAAAAAAEAAAAEPFQAAAAAA","232":"b:AIIBAAAQAoBAMEIAAUmPHwAAAAAA","234":"b:AAAAAAAAAAAAAEAAAAEPFQAAAAAA","252":"b:AAAAAAAAAAAAAAAAAAEPFQAAAAAA","269":[112,113,120,122],"271":[112,113,120,122],"274":"b:AAQAIAgAAAAAAAEAxwEvFQAAAAAA","298":"b:AAQAIAgAAAAAAAEAxwEvFQAAAAAA","302":"b:AAQAIAgAAAAAAAEAxwEvFQAAAAAA","303":"b:AAQAIAgAAAAAAAEAxwEvFQAAAAAA","310":"b:AAAAAAAAAAAAAEAAAAEPFQAAAAAA","314":"b:AAAAAAAAAAAAAEAAAAEPFQAAAAAA","315":"b:AAAAAAAAAAAAAEAAAAEPFQAAAAAA","319":"b:AAAAAAAAAAAAAEAAAAEPFQAAAAAA","328":"b:AAAAAAAAAAAAAEAAAAEPFQAAAAAA","353":[112,113,115,120,122],"356":[112,113,115,120,122],"357":[112,113,115,120,122],"358":[112,113,115,120,122],"376":"b:AAAAAAAAAAAAAAAAAAEPFQAAAAAA","432":[112,113,115,120,122],"434":[112,113,115,120,122],"438":[112,113,115,120],"439":[112,113,115,120],"442":[112,113,120,122],"453":"b:+v////////////////////8PAAAA","464":[112,113,120],"481":[112,113,115,120,122]},"packages/frontend/editor-ui/src/features/shared/editors/plugins/codemirror/format.ts":{"10":"b:+v////////////////////8PAAAA"},"packages/frontend/editor-ui/src/features/shared/editors/plugins/codemirror/keymap.ts":{"83":"b:+v////////////////////8PAAAA","100":[113],"261":"b:AAAAAAAAAAAAAAAAAAEvHQAAAAAA"},"packages/frontend/editor-ui/src/features/shared/editors/plugins/codemirror/multiCursor.ts":{"4":"b:+v////////////////////8PAAAA"},"packages/frontend/editor-ui/src/features/shared/editors/plugins/codemirror/resolvableHighlighter.ts":{"61":"b:+v////////////////////8PAAAA","62":"b:AIIAAAAAAIBAAUIAAEmPHwAAAAAA","65":"b:AIIAAAAAAIBAAUIAAEmPHwAAAAAA","75":[104,113,115],"81":[113,120,121,124],"101":"b:AIIAAAAAAIBAAUIAAEmPHwAAAAAA","102":"b:AIIAAAAAAIBAAEIAAEmPHwAAAAAA","115":"b:AIIAAAAAAIBAAUIAAEmPHwAAAAAA","116":[72,104,107,113,114,115,120]},"packages/frontend/editor-ui/src/features/shared/editors/plugins/codemirror/tooltips/InfoBoxTooltip.ts":{"27":"b:+v////////////////////8PAAAA","28":"b:AIIBAAAQAoBAMQIAAUivHgAAAAAA","44":[112,114,115,122,124],"55":[115],"74":[112,114,115,122,124],"96":"b:AIIBAAAQAoBAMUIAAUivHwAAAAAA","100":"b:AIIBAAAQAoBAMQIAAUivHwAAAAAA","104":"b:AIIBAAAQAoBAMUIAAUivHwIAAAAA","119":[112,114,115,122,124],"120":[112,114,115,122,124],"143":[112,114,115,122,124],"165":[115],"179":"b:AIIBAAAQAoBAMUIAAUivHwIAAAAA","227":[112,114,115,122,124],"233":[115],"245":"b:AIIBAAAQAoBAMUIAAUivHwIAAAAA","253":"b:AIIBAAAQAoBAMUIAAUivHwIAAAAA","262":"b:AIIBAAAQAoBAMUIAAUivHwIAAAAA","286":"b:+v////////////////////8PAAAA","290":"b:AIIBAAAQAoBAMUIAAUivHwIAAAAA","293":"b:AIIBAAAQAoBAMUIAAUivHwIAAAAA","323":"b:AIIBAAAQAoBAMUIAAUivHwIAAAAA","331":[115,122],"349":[115],"352":[115],"394":"b:AIYBIAgQAgAAEEEAxwGvGwAAAAAA","406":"b:AIIBAAAQAoBAMUIAAUivHwIAAAAA","414":"b:AIIBAAAQAgAAMUAAAUiFAgAAAAAA","420":"b:AIIBAAAQAoBAMUIAAUivHwIAAAAA"},"packages/frontend/editor-ui/src/features/shared/editors/plugins/codemirror/typescript/client/facet.ts":{"9":"b:+v////////////////////8PAAAA"},"packages/frontend/editor-ui/src/features/shared/envFeatureFlag/useEnvFeatureFlag.ts":{"5":"b:+v////////////////////8PAAAA","8":"b:+v///f////////v///////8PAAAA"},"packages/frontend/editor-ui/src/features/shared/nodeCreator/composables/useActionsGeneration.ts":{"31":"b:cP8f4A84/v/n/wMg//////8PgAAA","37":"b:cP8f4A84/v/n/wMg//////8PgAAA","45":"b:cP8f4A84/v/n/wMg//////8PgAAA","48":"b:cP8f4A84/v/n/wMg//////8PgAAA","61":"b:cP8f4A84/v/n/wMg//////8PgAAA","67":"b:cP8f4A84/v/n/wMg//////8PgAAA","82":"b:cP8f4A84/v/n/wMg//////8PgAAA","102":"b:cP8f4A84/v/n/wMg//////8PgAAA","103":"b:cP8f4A84/v/n/wMg//////8PgAAA","106":"b:cP8f4A84/v/n/wMg//////8PgAAA","120":"b:cP8f4A84/v/n/wMg//////8PgAAA","126":"b:cP8f4A84/v/n/wMg//////8PgAAA","130":"b:cP8f4A84/v/n/wMg//////8PgAAA","148":"b:cP8f4A84/v/n/wMg//////8PgAAA","153":"b:cP8f4A84/v/n/wMg//////8PgAAA","161":"b:cP8f4A84/v/n/wMg//////8PgAAA","179":"b:cP8f4A84/v/n/wMg//////8PgAAA","182":"b:cP8f4A84/v/n/wMg//////8PgAAA","203":"b:cP8f4A84/v/n/wMg//////8PgAAA","214":"b:cP8f4A84/v/n/wMg//////8PgAAA","233":"b:cP8f4A84/v/n/wMg//////8PgAAA","235":"b:cP8f4A84/v/n/wMg//////8PgAAA","239":"b:cP8f4A84/v/n/wMg//////8PgAAA","241":"b:cP8f4A84/v/n/wMg//////8PgAAA","242":"b:cP8f4A84/v/n/wMg//////8PgAAA","246":"b:cP8f4A84/v/n/wMg//////8PgAAA","261":"b:cP8f4A84/v/n/wMg//////8PgAAA","271":"b:cP8f4A84/v/n/wMg//////8PgAAA","309":"b:+v////////////////////8PgAAA","310":"b:cP8f4A84/v/n/wMg//////8PgAAA","328":"b:cP8f4A84/v/n/wMg//////8PgAAA","331":"b:cP8f4A84/v/n/wMg//////8PgAAA","342":"b:cP8f4A84/v/n/wMg//////8PgAAA","372":"b:cP8f4A84/v/n/wMg//////8PgAAA","379":"b:cP8f4A84/v/n/wMg//////8PgAAA","401":"b:cP8f4A84/v/n/wMg//////8PgAAA","402":"b:cP8f4A84/v/n/wMg//////8PgAAA","407":"b:cP8f4A84/v/n/wMg//////8PgAAA","413":"b:cP8f4A84/v/n/wMg//////8PgAAA","424":"b:cP8f4A84/v/n/wMg//////8PgAAA","425":"b:cP8f4A84/v/n/wMg//////8PgAAA","429":"b:cP8f4A84/v/n/wMg//////8PgAAA"},"packages/frontend/editor-ui/src/features/shared/nodeCreator/composables/useGetNodeCreatorFilter.ts":{"9":"b:+v////////////////////8PAAAA","13":[15,16,49,119,120],"30":[15,16,49,119,120],"49":[15,49,119]},"packages/frontend/editor-ui/src/features/shared/nodeCreator/composables/useViewStacks.ts":{"106":"b:+v////////////////////8PAAAA","113":"b:cP8f4A84/v/l/wMg//////8PAAAA","122":"b:cIoZoAkw/k4h0AAgxy3vfaoCAAAA","154":"b:cIoZoAkw/k4h0AAgxy3vfSoCAAAA","161":"b:cIoZoAkw/k4h0AAgxy3vfaoCAAAA","174":"b:cIoZoAkw/k4h0AAgxy3vfaoCAAAA","178":"b:cIoZoAkw/k4h0AAgxy3vfSoCAAAA","182":"b:cIoZoAkw/k4h0AAgxy3vfSoCAAAA","185":"b:cIoZoAkw/k4h0AAgxy3vfaoCAAAA","189":"b:cIoZoAkw/k4h0AAgxy3vfaoCAAAA","193":"b:cIoZoAkw/k4h0AAgxy3vfaoCAAAA","197":"b:cIoZoAkw/k4h0AAgxy3vfSoCAAAA","198":"b:cIoZoAkw/k4h0AAgxy3vfSoCAAAA","204":"b:cIoZoAkw/k4h0AAgxy3vfaoCAAAA","222":"b:cIoZoAkw/k4h0AAgxy3vfSoCAAAA","223":"b:cIoZoAkw/k4h0AAgxy3vfSoCAAAA","236":[11,35,51],"251":[51,52],"253":"b:cIoZoAkw/k4h0AAgxy3vfSoCAAAA","257":[15,16,44,49,76,119,120],"258":[15,16,44,49,76,119,120],"269":[15,16,49,119,120],"270":[15,16,49,119],"284":[15,49,119],"292":[15,49,119],"293":[15,49,119],"296":[15,49,119],"310":"b:cIoZoAkw/k4h0AAgxy3vfaoCAAAA","315":"b:cIoZoAkw/k4h0AAgxy3vfaoCAAAA","327":[15,16,44,49,119,120],"368":[15,49,119],"400":[15,49,119],"415":"b:cIoZoAkw/k4h0AAgxy3vfSoCAAAA","416":"b:cIoZoAkw/k4h0AAgxy3vfSoCAAAA","432":[15,16,49,119,120],"451":[15,16,49,119,120],"481":[15,16,49,119,120],"497":[15,49,119],"504":[15,16,49,119,120],"518":"b:cIoZoAkw/k4h0AAgxy3vfaoCAAAA","547":[51],"548":[51],"569":"b:cIoZoAkw/k4h0AAgxy3vfaoCAAAA","591":[51,53],"598":"b:cIoZoAkw/k4h0AAgxy3vfaoCAAAA","600":"b:cIoZoAkw/k4h0AAgxy3vfaoCAAAA","604":"b:cIoZoAkw/k4h0AAgxy3vfaoCAAAA","613":"b:cIoZoAkw/k4h0AAgxy3vfaoCAAAA"},"packages/frontend/editor-ui/src/features/shared/nodeCreator/nodeCreator.store.ts":{"49":"b:+v////////////////////8PAAAA","51":"b:AAoAIAAAyAAgAAAARAmEAYACAAAA","71":[15,16,49,119,120],"72":[15,16,49,119,120],"75":"b:cP8f4A84/v/l/wMg//////8PAAAA","83":"b:cP8f4A84/v/l/wMg//////8PAAAA","87":"b:cP9/4A84/v/l/wPg//////8PAAAA","91":"b:cIoZoAkw/k4h0AAgxy3vfaoCAAAA","95":[119,120],"116":[119,120],"141":"b:cP9/4A84/v/n/wPg//////8PAAAA","180":"b:AIABIAAAOgAAwAAAAyCAEQAAAAAA","269":"b:AAoAIAAAyAAgAAAARAkEAIACAAAA","329":"b:cIoZoAkw/k4h0AAgxy3vfaoCAAAA","335":"b:cIoZoAkw/k4h0AAgxy3vfaoCAAAA","339":"b:cIoZoAkw/k4h0AAgxy3vfaoCAAAA","346":"b:cIoZoAkw/k4h0AAgxy3vfaoCAAAA","366":"b:QIgZgAkwEAYhQAAgxw2vPSIAAAAA","382":"b:QIgZgAkwEAYhQAAgxw2vPSIAAAAA","422":[54],"426":"b:MAgRoAgQZAIhAAAgxwFlPSIAAAAA","439":[15,49,51,52],"446":"b:cIoZoAkw/k4h0AAgxy2vfaoCAAAA","462":"b:cP9/4A84/v/n/wPg//////8PAAAA"},"packages/frontend/editor-ui/src/features/shared/tags/tags.api.ts":{"8":"b:+v////////////////////8PgAAA","10":"b:+v+f/b////////s///////8PgAAA","13":[151,80,126,130,136],"19":[151],"26":[151,130]},"packages/frontend/editor-ui/src/features/shared/tags/tags.store.ts":{"15":"b:+v////////////////////8PgAAA","19":"b:+v////////////////////8PgAAA","31":[151,65,130,137],"32":[151,130,137],"35":[151,65,130,137],"37":[151],"41":"b:+v+f/b////////s///////8PgAAA","42":"b:AAAAAAAAAAAAAAAAAAAKQAQLgAAA","50":"b:cMdzQA4gALvjaQGAnvrzw90PgAAA","51":[151,80,126,130,136],"72":[151,130],"77":"b:+v+f/f////////s///////8PgAAA","96":[151,80,126,130,136],"104":[151],"115":[151],"121":[151,130]},"packages/frontend/editor-ui/src/features/workflows/canvas/canvas.types.ts":{"24":"b:+v////////////////////8PgAAA","51":"b:+v////////////////////8PgAAA","154":"b:cP9/4A84/v/n/wPg//////8PgAAA"},"packages/frontend/editor-ui/src/features/workflows/canvas/canvas.utils.ts":{"37":"b:cP974A8w/v/h/wOg3/////sPgAAA","46":"b:MP974A8w1r/h/wOg3////+sNgAAA","47":"b:cP974A8w/v/h/wOg3/////sPgAAA","49":"b:MP974A8w1r/h/wOg3////+sNgAAA","50":"b:cP974A8w/v/h/wOg3/////sPgAAA","66":"b:cP9/4A84/v/n/wPg//////8PgAAA","83":"b:cP9/4A84/v/n/wPg//////8PgAAA","106":[151],"114":"b:cP9/4A84/v/n/wPg//////8PgAAA","119":"b:cP9/4A84/v/n/wPg//////8PgAAA","121":"b:MP974A8w1r/h/wPg3////+sNgAAA","127":"b:MP974A8w1r/h/wPg3////+sNgAAA","129":"b:MP974A8w1r/h/wPg3////+sNgAAA","130":"b:MP974A8w1r/h/wPg3////+sNgAAA","187":[151,102,128],"219":"b:cP974A8w/v/h/wPg/////+sPgAAA","239":"b:cP974A8w/v/h/wPg//////sPgAAA","254":"b:MP974A8w1r/h/wPg3////+sNgAAA","261":"b:ML4ZoA0w1i5h0gMg92XvfSsBgAAA","295":"b:cP974A8w/v/h/wPg//////sPgAAA","304":"b:cP974A8w/v/h/wPg3/////sPgAAA","312":"b:cP974A8w/v/h/wPg3/////sPgAAA","329":[151,79,101,127],"347":"b:cP9/4A84/v/n/wPg//////8PgAAA","364":"b:cP8b4A8w/v/h/wNg3/////sPgAAA","374":"b:cP8b4A8w/v/h/wNg3/////sPgAAA","378":"b:cP8b4A8w/v/h/wNg3/////sPgAAA","392":"b:KLYAoASQRCBM0mOQd2D0RfkPgAAA"},"packages/frontend/editor-ui/src/features/workflows/canvas/composables/useCanvasNodeGroupOperationGuards.ts":{"54":"b:+v////////////////////8PAAAA","57":[100],"60":"b:ML4ZoA0w1i5h0gMg12XvfSsBAAAA","68":[100],"105":[100],"127":[100],"139":[100],"142":[100],"226":[100],"236":[100],"252":[100],"270":[100],"293":"b:ML4ZoA0w1i5h0gMg12XvfSsBAAAA","338":"b:ML4ZoA0w1i5h0gMg12XvfSsBAAAA"},"packages/frontend/editor-ui/src/features/workflows/canvas/experimental/experimentalNdv.store.ts":{"17":"b:+v////////////////////8PAAAA","19":"b:cP9/4A84/v/l/wPg//////8PAAAA","24":"b:cP9/4A84/v/l/4Oh//////8PAAAA","54":"b:cP9/4A84/v/n/wPg//////8PAAAA","62":[13,80,99],"140":"b:cP9/4A84/v/l/wPg//////8PAAAA","141":"b:cP9/4A84/v/l/wOg//////8PAAAA"},"packages/frontend/editor-ui/src/features/workflows/readyToRun/components/ReadyToRunButton.vue":{"13":"b:uAiA3QDwAQA+AHAUAAIAQBgKAAAA","25":"b:uAiA3QDwAQA+AHAUAAIAQBgKAAAA","31":"b:uAiA3QDwAQA+AHAUAAIAQBgKAAAA","53":"b:uAiA3QDwAQA+AHAUAAIAQBgKAAAA"},"packages/frontend/editor-ui/src/features/workflows/readyToRun/composables/useEmptyStateDetection.ts":{"9":"b:+P+f/Q/8/////3O0//////8PAAAA","22":"b:uACAXQCAAQA+ABAEAAIAQBgKAAAA"},"packages/frontend/editor-ui/src/features/workflows/readyToRun/stores/readyToRun.store.ts":{"22":"b:+P+f/Q/8/////3O0//////8PAAAA","59":"b:+P+f/Q/8/////3O0//////8PAAAA","66":"b:+P+f/Q/8/////3O0//////8PAAAA","74":"b:+P+f/Q/8/////3O0//////8PAAAA","90":"b:+P+f/Q/8/////3O0//////8PAAAA","91":"b:+P+f/Q/8/////3O0//////8PAAAA","110":"b:uAiA3QDwAQA+AHAUAAIAQBgKAAAA","208":"b:uAiA3QDwAQA+AHAUAAIAQBgKAAAA","220":"b:uACAXQCAAQA+ABAEAAIAQBgKAAAA","224":"b:cP8f4A84/v/n/wMg//////8PAAAA"},"packages/frontend/editor-ui/src/features/workflows/templates/templates.store.ts":{"48":[139],"54":"b:+v////////////////////8PAAAA","89":[139],"90":[139],"95":[138],"96":[138],"99":[138,139],"100":[138,139],"106":[138],"108":[139],"109":[139],"112":[139],"113":[139],"120":[139],"124":[139],"125":[139],"132":[139],"136":[139],"137":[139],"165":"b:+P+f/Q/8/////3M0//////8PAAAA","169":"b:+P+f/Q/8/////3M0//////8PAAAA","178":"b:+P+f/Q/8/////3M0//////8PAAAA","193":"b:+P+f/Q/8/////3M0//////8PAAAA","198":[120],"205":[139],"209":[138,139],"212":[138,139],"213":[138,139],"224":[138,139],"225":[138,139],"231":[139],"235":[139],"243":[139],"248":[139],"293":"b:+v///f////////v///////8PAAAA","298":[74,138,139],"304":[138,139],"320":[138],"338":[139],"354":[139],"369":[139],"374":[139],"420":[74,138,139],"428":[74,138,139],"436":[74,138,139]},"packages/frontend/editor-ui/src/features/workflows/templates/utils/typeGuards.ts":{"8":[151,138],"14":[151,138],"20":"b:+v////////////////////8PgAAA"},"packages/frontend/editor-ui/src/features/workflows/templates/utils/workflowSamples.ts":{"14":"b:+v////////////////////8PgAAA","22":"b:+v////////////////////8PgAAA","26":"b:+v////////////////////8PgAAA","43":[151],"54":[151],"94":[151],"100":[151],"103":[151]},"packages/frontend/editor-ui/src/features/workflows/workflowHistory/workflowHistory.store.ts":{"22":"b:+v////////////////////8PAAAA","28":[105],"30":[105],"34":[105],"38":[105],"44":"b:ACAAAAAAAAAAAAAABF4AAMAAAAAA"},"packages/localhost-44589/assets/_plugin-vue_export-helper-Da88TEg1.js":{"2":[25,85,99,124,132]},"packages/localhost-44589/assets/chunk-CC9Q-vWm.js":{"8":[25,85,99,124,132],"9":[25,85,99,124,132],"10":[25,85,99,124,132],"19":[25,85,99,124,132],"23":[25,85,99,124,132],"29":[25,85,99,124,132],"33":[25,85,99,124,132],"34":[25,85,99,124,132]},"packages/vite/source-map-js-shim.ts":{"1":"b:+v////////////////////8PAAAA"},"packages/@n8n/chat-hub/src/artifact.ts":{"3":[36,37,38,39,41,42],"19":[36,37,38]},"packages/@n8n/chat-hub/src/parser.ts":{"12":[36,37,38,39,41,42],"117":[36,37,38,39,41,42],"134":[36,37,38,39,41,42],"159":[36,37,38],"187":[36,37,38],"217":[36,37,38],"250":[36,37,38,39,41,42],"275":[36,37,38]},"packages/@n8n/design-system/src/components/N8nActionDropdown/ActionDropdown.vue":{"14":"b:8P8f4P++///n/wOg//////8PAAAA","49":"b:8P8f4P++///n/wOg//////8PAAAA","54":"b:8P8f4P++///n/wOg//////8PAAAA","59":"b:8P8f4P++///n/wOg//////8PAAAA","67":"b:8P8f4P++///n/wOg//////8PAAAA","68":"b:8P8f4P++///n/wOg//////8PAAAA","86":"b:0BYAAISAACBCggMAQEBgRRABAAAA","87":"b:0BYAAISAACBCggMAQEBgRRABAAAA","97":"b:8P8f4P++///n/wOg//////8PAAAA","104":"b:8P8f4P++///n/wOg//////8PAAAA","128":"b:8P8f4P++///n/wOg//////8PAAAA","141":"b:0BYAAISAACBCggMAQEBgRRABAAAA","149":"b:0BYAAISAACBCggMAQEBgRRABAAAA","151":"b:UBYAAISAACBCggMAQEBgRBABAAAA","156":"b:0BYAAISAACBCggMAQEBgRRABAAAA"},"packages/@n8n/design-system/src/components/N8nCard/Card.vue":{"9":"b:OACAibDwAQA+ANAVAAIAQBgKAAAA","14":"b:OACAibDwAQA+ANAVAAIAQBgKAAAA","19":"b:OACAibDwAQA+ANAVAAIAQBgKAAAA"},"packages/@n8n/design-system/src/components/N8nDropdownMenu/DropdownMenuItem.vue":{"25":"b:0B4AAOWRASB/gksBQEBgVRADAAAA","81":"b:0B4AAOWRASB/gksBQEBgVRADAAAA","82":"b:0B4AAOWRASB/gksBQEBgVRADAAAA","84":[37,38,39,65,66,67],"110":"b:0B4AAOWRASB/gksBQEBgVRADAAAA","114":"b:0B4AAOWRASB/gksBQEBgVRADAAAA","118":"b:0B4AAOWRASB/gksBQEBgVRADAAAA","122":"b:gAgAAAERAQA/AEgBAAAAEAACAAAA","124":[37,38,39],"128":"b:0B4AAOWRASB/gksBQEBgVRADAAAA","135":"b:0B4AAOWRASB/gksBQEBgVRADAAAA","143":"b:0B4AAOWRASB/gksBQEBgVRADAAAA","144":"b:0B4AAOWRASB/gksBQEBgVRADAAAA","152":"b:0B4AAOWRASB/gksBQEBgVRADAAAA","162":[37,38,39,65,66,67],"167":[37,38,39,65,66,67],"175":[65,66,67],"205":[37,38,39,65,66,67],"212":[37,38,39],"238":[37,38,39],"240":[37,38,39],"248":[37,38,39],"251":[37,38,39],"254":[37,38,39],"280":"b:0B4AAOWRASB/gksBQEBgVRADAAAA","282":"b:0B4AAIURASB/gksBQEBgVRADAAAA","294":"b:gAgAAAERAQA/AEgBAAAAEAACAAAA","299":"b:gAgAAAERAQA/AEgBAAAAEAACAAAA"},"packages/@n8n/design-system/src/components/N8nDropdownMenu/DropdownMenuSearch.vue":{"17":[37,38,39],"71":[37,38,39],"76":[37,38,39]},"packages/@n8n/design-system/src/components/N8nIcon/custom/filled-square.svg":{"10":"b:AD4EAPAGAAAAAAAAAAAAAAAAAAAA"},"packages/@n8n/design-system/src/components/N8nIconPicker/IconPicker.vue":{"26":[23,39,42,48,3,69,86,5,131,137],"59":[69],"61":[69],"118":[23,39,42,48,3,69,5,131,137],"122":[69],"135":[69],"142":[69],"148":[69],"155":[69],"158":[69],"167":[23,39,42,48,3,69,86,5,131,137],"189":[23,39,42,48,3,69,86,5,131,137],"212":[69],"228":[69],"233":[69],"263":[69],"274":[69],"278":[69]},"packages/@n8n/design-system/src/components/N8nLogo/Logo.vue":{"8":"b:AAAAHfAOAQAwAAAEAAAAAAgAAAAA","24":"b:AAAAHfAOAQAwAAAEAAAAAAgAAAAA","30":"b:AAAAHfAOAQAwAAAEAAAAAAgAAAAA","42":"b:AAAAHfAOAQAwAAAEAAAAAAgAAAAA","57":"b:AAAAHfAOAQAwAAAEAAAAAAgAAAAA"},"packages/@n8n/design-system/src/components/N8nLogo/logo-icon.svg":{"11":"b:AAAAHfAOAQAwAAAEAAAAAAgAAAAA"},"packages/@n8n/design-system/src/components/N8nLogo/logo-text.svg":{"11":"b:AAAAHfAOAQAwAAAEAAAAAAgAAAAA"},"packages/@n8n/design-system/src/components/N8nNodeIcon/IconContent.vue":{"20":"b:cP974P93/v/x/0Pw3/////sPAAAA","34":"b:cP974A8y/v/h+0Pg3/////sPAAAA","53":"b:cP974A8y/v/h+0Pg3/////sPAAAA","56":"b:cP974P93/v/x/0Pw3/////sPAAAA"},"packages/@n8n/design-system/src/components/N8nNodeIcon/NodeIcon.vue":{"24":"b:cP974P93/v/x/0Pw3/////sPAAAA","28":"b:cP974P93/v/x/0Pw3/////sPAAAA","43":"b:cP974P93/v/x/0Pw3/////sPAAAA","59":"b:MJ5b4A0w1s7h+QMgx+3//ysOAAAA"},"packages/@n8n/utils/src/assert.ts":{"4":"b:IJYFgKBxAAAgEMARAAAACQAMAAAA"},"packages/@n8n/utils/src/retry.ts":{"46":[36,37,38,39,41,42]},"packages/frontend/editor-ui/src/app/composables/useFreeAiCredits.ts":{"24":"b:MJ5b4P131s7h+UMwz+3//ysGAAAA","26":[36,37,38,39,41,42],"38":"b:MJ5b4P131s7h+UMwz+3//ysGAAAA"},"packages/frontend/editor-ui/src/app/composables/useResizablePanel.ts":{"51":[65],"61":[65],"62":[65],"63":"b:cP8f4P8+/v/n/wOg//////8PAAAA","92":[65],"96":"b:cP8f4P8+/v/n/wOg//////8PAAAA","100":[65],"104":"b:cP8f4P8+/v/n/wOg//////8PAAAA","108":[65],"125":[65],"138":"b:cP8f4P8+/v/n/wOg//////8PAAAA","139":"b:cP8f4P8+/v/n/wOg//////8PAAAA","145":"b:cP8f4P8+/v/n/wOg//////8PAAAA","153":"b:AMACAIAAAAAAIAAgBF4AQNAAAAAA","159":"b:cP8f4P8+/v/n/wOg//////8PAAAA","160":[14,15,16,17,65,77,95,110],"161":[14,15,16,17,65,77,110]},"packages/frontend/editor-ui/src/app/constants/localStorage.ts":{"22":[36,37,38,39,41,42],"24":[36,37,38,39,41,42],"30":[36,37,38,39,41,42]},"packages/frontend/editor-ui/src/app/layouts/ChatLayout.vue":{"8":[36,37,38,39,41,42],"10":[36,37,38,39,41,42]},"packages/frontend/editor-ui/src/app/utils/nodeTypesUtils.ts":{"43":"b:IIgBgCBxggAgEEAQAAAACQAEgAAA","46":"b:IIgBgCBxggAgEEAQAAAACQAEgAAA","54":"b:MPgb4Acy1pfhvQAgRe2gryAPgAAA","58":[151,74,120,123,138],"61":[151,74,120,123,138],"65":"b:AAAAIAEAAAABAAAAAIAgBAAKgAAA","77":"b:cP974A8w/v/h/wPg//////sPgAAA","111":[151,20,50,56,57,61,64,117],"122":[151,20,50,56,57,61,64,117],"134":"b:cP8f4A84/v/n/wMg//////8PgAAA","135":"b:cP8b4A8w/v/h/wMg3/////sPgAAA","140":[151,138,139],"141":[151,138,139],"142":[151,138,139],"146":[151,138,139],"149":"b:AAAAAAAAAAAAAEAAAAAPHQIAgAAA","150":"b:AAAAAAAAAAAAAEAAAAAPHQAAgAAA","153":"b:ML5b4C1z1s7h+cMxz+3//ysGgAAA","173":"b:MP5b4A0w1s7h+QMgz+3//ysCgAAA","174":"b:AMZaAAQAAM7BaAIAiu1/lwEAgAAA","182":"b:MIgBgAAQFAAgEAAgAECgCSMAgAAA","194":"b:MKgB4AEy1gZhEQAgBEGgLyAAgAAA","214":"b:MK4ToAkS1s7h+YMhz+n//ysCgAAA","221":"b:MCgAoAEQFAIhAQAAAAAgLyAAgAAA","224":"b:MCgAoAEQEAIhAQAAAAAgLyAAgAAA","241":"b:AK4TIAkS1s7heYMhz+n//ysAgAAA","246":"b:AKgBIAECxgZBEAAgBEGAAQAAgAAA","250":[151,29,32,50,57,64],"255":[151,29,32,50,57,64],"257":[151,29,32,50,57,64],"274":"b:MK4BgCBxgAAgEEAQAAAACQAEgAAA","288":[11,13,151,31,44,69,4,5,120,123],"292":[11,13,151,31,44,69,4,5,120,123],"295":[11,13,151,31,44,69,4,5,120,123],"322":[11,13,151,31,44,69,4,5,120,123],"331":[13,151],"337":[13,151],"346":[11,13,151,31,44,69,4,5,120,123],"353":[11,13,151,31,44,69,4,5,120,123],"359":"b:MKgBgAAQgAAgEAAAAAAACQAAgAAA","368":[11,13,151,31,44,69,4,5,120,123],"376":"b:MCgAoAAQFAAgAQAAAAAgLyAAgAAA","381":"b:MCgAoAAQFAAgAQAAAAAgLyAAgAAA","393":"b:MK4ToAkS1s7heYMhz+n//ysAgAAA","399":"b:MKgBoAES1gZhEQAgBEGgLyAAgAAA","401":"b:MCgAoAEQFAIhAQAAAAAgLyAAgAAA","402":"b:MCgAoAEQFAIhAQAAAAAgLyAAgAAA","404":"b:MCgAoAEQFAIhAQAAAAAgLyAAgAAA","420":"b:MCgAoAEQFAIhAQAAAAAgLyAAgAAA","443":[151,31,44,69,4,5,120,123],"469":"b:MCgAoAAQFAAgAQAAAAAgLyAAgAAA","478":[151],"479":[151],"491":"b:ML5b4C1z1s7h+cMxz+3//ysGgAAA","498":[151,124],"511":[151,124],"520":[151,124],"547":[151,124],"559":"b:cP974P93/v/x/0Pw3/////sPgAAA"},"packages/frontend/editor-ui/src/features/ai/chatHub/ChatPersonalAgentsView.vue":{"38":[39],"39":[39],"40":[39],"42":[39],"51":[39],"66":[39],"78":[39],"79":[39],"87":[39],"110":[39],"129":[39],"133":[39],"140":[39],"145":[39],"158":[39],"159":[39]},"packages/frontend/editor-ui/src/features/ai/chatHub/ChatView.vue":{"76":[36,37,38,39,41,42],"84":[36,37,38,39,41,42],"91":[36,37,38,39,41,42],"94":[36,37,38,39,41,42],"96":[36,37,38,39,41,42],"99":[36,37,38,39,41,42],"101":[36,37,38,39,41,42],"106":[36,37,38,39,41,42],"108":[36,37,38,39,41,42],"134":[36,37],"141":[36,37,38,39,41,42],"146":[36,37,38,39,41,42],"150":[36,37,38,39,41,42],"182":[36,37,38,39,41,42],"214":[36,37,38,39,41,42],"218":[36,37,38,39,41,42],"225":[36,37,38,39,41],"236":[41],"245":[36,37,38,39,41,42],"253":[36,37,38,39,41,42],"258":[36,37,38,39,41,42],"267":[36,37,38,39,41,42],"293":[36,37,38,39,41,42],"308":[36,37,38,39,41,42],"323":[36,37,38,39,41,42],"335":[36,37,38,39,41,42],"363":[36,37,38,39,41,42],"364":[36,37,38,39,41,42],"382":[36,37,38,39,41,42],"400":[36,37,38,39,41,42],"408":[36,37,38,39,41,42],"417":[36,37,38,39,41,42],"428":[36,37,38,39,41,42],"448":[36,37,38,39,41,42],"464":[36,37,38,39,41,42],"472":[36,37,38,39,41,42],"483":[36,37,38,39,41,42],"517":[37],"525":[37],"553":[37],"576":[36,37,38,39,41],"600":[36,37,38,39,41],"604":[37],"628":[39],"707":[36,37,38,39,41,42],"736":[36,37,38,39,41,42],"748":[36,37,38,39,41,42],"769":[37]},"packages/frontend/editor-ui/src/features/ai/chatHub/chat.api.ts":{"32":[36,37,38,39,40,41,42],"44":[36,37,38,39,41,42],"79":[37],"120":[37],"160":[36,37,38,39,41,42],"183":[36,37,38,39,41,42],"232":[36,37,38,39,41,42],"240":[39],"248":[39],"256":[39],"265":[39],"299":[40],"309":[40],"322":[40],"340":[36],"395":[36,37,38,39,41,42],"399":[41]},"packages/frontend/editor-ui/src/features/ai/chatHub/chat.utils.ts":{"25":[36,37,38,39,41,42],"46":[36,37,38,39,41,42],"64":[36,37,38,39,41,42],"71":[36,37,39,41,42],"82":[39,42],"110":[36,37,38,39,41,42],"122":[36,37,38,39,41,42],"158":[39,42],"196":[36,37,38,39,41,42],"200":[37,38,39],"215":[36,37,38,39,41,42],"227":[36,37,38,39,41,42],"280":[36,37,38,39,41,42],"331":[36,37,38,39,41,42],"335":[36,37,38,39,41,42],"341":[36,37,38,39,41,42],"352":[36,37,38,39,41],"361":[36,37,38,39,41],"381":[36,37,38,39,41,42],"412":[36,37,38,39,41,42],"442":[36,37,38,39,41,42],"459":[36],"467":[36],"487":[36,37,38,39,41,42],"491":[36,37,38,39,41,42],"505":[36,37,38,39,41,42],"515":[36,37,38,39,41,42],"608":[36,37,38,39,41,42]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/AgentEditorModal.vue":{"116":[39],"119":[39],"125":[39],"126":[39],"127":[39],"132":[39],"138":[39],"145":[39],"152":[39],"156":[39],"162":[39],"172":[39],"195":[39],"197":[39],"210":[39],"238":[39],"243":[39],"426":[39],"435":[39],"449":[39],"471":[39],"485":[39],"520":[39],"540":[39],"555":[39],"571":[39],"581":[39],"600":[39],"687":[39],"690":[39]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/ChatAgentAvatar.vue":{"22":[36,37,38,39,41,42]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/ChatAgentCard.vue":{"24":[39,42],"30":[39,42],"36":[39],"43":[39,42],"53":[39,42],"56":[39,42],"74":[39],"76":[39]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/ChatAgentSearchSort.vue":{"8":[39,42],"18":[39,42],"27":[39,42],"45":[39,42],"57":[39,42]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/ChatConversationHeader.vue":{"47":[36,37,38,39,41,42],"65":[36,37,38,39,41,42],"67":[36,37,38,39,41,42],"85":[36,37,38,39,41,42]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/ChatGreetings.vue":{"22":[36,37,38,39,41,42],"38":[39,42]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/ChatMessage.vue":{"68":[36,37,38,39,41,42],"96":[36,37,38,39,41,42],"116":[36,37,38,39,41,42],"117":[36,37,38,39,41,42],"144":[36,37,38,39,41,42],"149":[36,37,38,39,41,42],"150":[36,37,38,39,41,42],"159":[36,37,38,39,41,42],"169":[36,37,38,39,41,42],"170":[36],"181":[37],"188":[36,37,38,39,41,42],"190":[36,37,38,39,41,42],"198":[36,37,38,39,41,42],"200":[37],"208":[37],"276":[37],"290":[37],"295":[36,37,38,39,41,42],"296":[36,37,38,39,41,42],"307":[36,37,38,39,41,42],"309":[37],"317":[36,37,38,39,41,42],"320":[36,37,38,39,41,42],"389":[37],"397":[37],"407":[36],"419":[36,37,38,39,41,42]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/ChatMessageActions.vue":{"13":[36,37,38,39,41,42],"31":[37],"32":[37],"35":[36,37,38,39,41,42],"37":[36,37,38,39,41,42],"52":[36,37,38,39,41,42],"53":[36,37,38,39,41,42],"55":[37],"59":[37],"65":[36,37,38,39,41,42],"126":[37],"129":[37]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/ChatPrompt.vue":{"18":[36,37,38,39,41,42],"59":[36,37,38,39,41,42],"71":[36,37,38,39,41,42],"75":[36,37,38,39,41,42],"79":[36,37,38,39,41,42],"81":[36,37,38,39,41,42],"82":[36,37,38,39,41,42],"104":[36],"150":[36,37,38,39,41,42],"208":[36,37,38,39,41,42],"209":[36,37,38,39,41,42],"225":[36,37,38,39,41,42],"286":[36,37,38,39,41,42]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/ChatPromptCallouts.vue":{"19":[36,37,38,39,41,42],"35":[37],"45":[37],"62":[41],"72":[41],"81":[41]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/ChatPromptFull.vue":{"10":[36,37,38,39,41,42],"55":[36],"71":[36,37,38,39,41,42],"75":[36,37,38,39,41,42],"87":[36,37,38,39,41,42],"103":[36,37,38,39,41,42],"112":[36,37,38,39,41,42],"125":[36,37,38,39,41,42]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/ChatProviderAvatar.vue":{"13":[37,38,39],"23":[37,38,39]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/ChatSessionMenuItem.vue":{"20":[36,37,38,39,41,42],"34":[36,37,38,39,41,42],"44":[36,37,38,39,41,42],"87":[36,37,38,39,41,42],"89":[36,37,38,39,41,42],"101":[36,37,38,39,41,42],"122":[36,37,38,39,41,42]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/ChatSidebar.vue":{"15":[36,37,38,39,41,42],"45":[36,37,38,39,41,42],"55":[36,37,38,39,41,42],"56":[36,37,38,39,41,42],"65":[36,37,38,39,41,42]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/ChatSidebarContent.vue":{"25":[36,37,38,39,41,42],"32":[36,37,38,39,41,42],"39":[36,37,38,39,41,42],"43":[36,37,38,39,41,42],"45":[36,37,38,39,41,42],"57":[36,37,38,39,41,42],"69":[36,37,38,39,41,42],"80":[36,37,38,39,41,42],"138":[36,37,38,39,41,42],"141":[36,37,38,39,41,42],"156":[36,37,38,39,41,42],"176":[36,37,38,39,41,42],"181":[36,37,38,39,41,42],"184":[36,37,38,39,41,42],"195":[36,37,38,39,41,42],"199":[36,37,38,39,41,42]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/ChatSidebarLink.vue":{"26":[36,37,38,39,41,42],"45":[36,37,38,39,41,42],"62":[36,37,38,39,41,42]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/ChatStarter.vue":{"36":[36,37,38,39,41,42],"38":[36,37,39],"42":[36,37,39],"46":[36,37,39],"47":[36,37,39],"49":[36,37,39],"59":[36,37,38,39,41,42],"67":[36,37,39],"80":[36,37,39],"97":[36,37,39],"111":[36,37,39],"133":[36,37,39],"148":[36,37,39],"159":[36,37,39]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/ChatTypingIndicator.vue":{"2":[36,37,38,39,41,42]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/CopyButton.vue":{"12":[36,37,38,39,41,42]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/ModelSelector.vue":{"58":[36,37,38,39,41,42],"82":[36,37,38,39,41,42],"88":[36,37,38,39,41,42],"89":[36,37,38,39,41,42],"97":[36,37,38,39,41,42],"107":[36,37,38,39,41,42],"109":[36,37,38,39,41,42],"113":[37],"117":[37,38],"148":[37,38,39],"179":[37,38,39],"188":[36,37,38,39,41,42],"207":[36,37,38,39,41,42],"215":[37,38,39]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/SkeletonMenuItem.vue":{"2":[36,37,38,39,41,42]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/SuggestedPromptsEditor.vue":{"9":[39],"51":[39],"92":[39]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/ToolsSelector.vue":{"32":[41],"34":[36,37,38,39,41,42],"36":[41],"39":[41],"41":[41],"45":[41],"50":[36,37,38,39,41,42],"53":[41],"62":[41],"104":[41],"108":[41],"116":[41],"153":[36,37,38,39,41,42],"166":[36,37,38,39,41,42],"175":[36,37,38,39,41,42],"197":[41],"204":[41],"207":[41]},"packages/frontend/editor-ui/src/features/ai/chatHub/composables/useChatArtifacts.ts":{"6":[36,37,38,39,41,42],"12":[36,37,38,39,41,42],"13":[36,37,38,39,41,42],"21":[36,37,38,39,41,42],"24":[36,37,38,39,41,42],"31":[36,37,38,39,41,42],"81":[36,37,38,39,41,42],"82":[36,37,38,39,41,42]},"packages/frontend/editor-ui/src/features/ai/chatHub/composables/useChatCredentials.ts":{"18":[36,37,38,39,41,42],"38":[36,37,38,39,41,42],"43":[36,37,38,39,41,42],"47":[36,37,38,39,41,42],"49":[36,37,38,39,41,42],"72":[37,42],"81":[36,37,38,39,41,42],"83":[36,37,38,39,41,42],"100":[36,37,38,39,41,42],"102":[36,37,38,39,41,42]},"packages/frontend/editor-ui/src/features/ai/chatHub/composables/useChatHubMarkdownOptions.ts":{"25":[65],"40":[36,37,38,39,41,42,65],"56":[36,37,38,39,41,42,65],"75":[36,37,38,39,41,42,65],"85":[36,65],"104":[65],"116":[65],"117":[65],"138":[36,37,38,39,41,42,65],"139":[36,37,38,39,41,42,65],"141":[65],"144":[65],"156":[36,37,38,39,41,42,65],"161":[36,65],"179":[36,37,38,39,41,42,65],"183":[65],"190":[65],"199":[36,37,38,39,41,42,65],"206":[36,37,38,39,41,42,65],"215":[65],"226":[65],"227":[65],"228":[65],"229":[65],"230":[65]},"packages/frontend/editor-ui/src/features/ai/chatHub/composables/useChatInputFocus.ts":{"13":[36,37,38,39,41,42]},"packages/frontend/editor-ui/src/features/ai/chatHub/composables/useChatPushHandler.ts":{"31":[36,37,38,39,41,42],"42":[36,37,38,39,41,42],"50":[36,37,38,39,41,42],"62":[36,37,38,39,41,42],"93":[36,37,38,39],"118":[36,37,38,39,41,42],"133":[41,42],"148":[36,37,38,39,41,42],"155":[37],"162":[36,37,38,39,41,42],"179":[36,37,38,39,41,42],"211":[36,37,38,39,41,42],"220":[36,37,38,39,41,42],"222":[36,37,38,39,41,42],"233":[39],"268":[36,37,39,41]},"packages/frontend/editor-ui/src/features/ai/chatHub/composables/useChatSession.ts":{"29":[36,37,38,39,41,42],"37":[36,37,38,39,41,42],"41":[39],"46":[36,37,38,39,41,42],"47":[36,37,38,39,41,42],"51":[36,37,38,39,41,42],"71":[36,37,38,39,41,42],"78":[36,37],"85":[36,37,38,39,41,42],"95":[36,37,38,39,41,42],"111":[36,37,38,39,41,42],"112":[36,37,38,39,41,42]},"packages/frontend/editor-ui/src/features/ai/chatHub/composables/useCustomAgent.ts":{"7":[36,37,38,39,41,42],"8":[36,37,38,39,41],"18":[36,37,38,39,41,42]},"packages/frontend/editor-ui/src/features/ai/chatHub/composables/useDynamicCredentialsStatus.ts":{"29":[36,37,38,39,41,42],"35":[36,37,38,39,41,42],"36":[36,37,38,39,41,42],"170":[36,37,38,39,41,42]},"packages/frontend/editor-ui/src/features/ai/chatHub/composables/useFileDrop.ts":{"3":[36,37,38,39,41,42]},"packages/frontend/editor-ui/src/features/ai/chatHub/model-selector.utils.ts":{"115":[36,37,38,39,41,42],"129":[36,37,38,39,41,42],"139":[39],"167":[42],"179":[42],"196":[36,37,38,39,41,42],"220":[36,37,38,39,41,42],"264":[36,37,38,39,41,42],"271":[36,37,38,39,41,42],"281":[36,37,38,39,41,42],"331":[36,37,38,39,41,42],"373":[36,37,38,39,41,42],"390":[36,37,38,39,41,42]},"packages/frontend/editor-ui/src/features/ai/modelSelector/AiModelSelectorDropdown.vue":{"56":[36,37,38,39,41,42],"60":[37,38,39],"66":[37,38,39],"90":[36,37,38,39,41,42],"109":[36,37,38,39,41],"129":[37,38,39],"143":[37,38,39],"160":[37,38,39]},"packages/frontend/editor-ui/src/features/credentials/components/CredentialIcon.vue":{"24":"b:IKgBgPB3ggAwEEAQAAAACQAEAAAA","26":"b:IKgBgPB3ggAwEEAQAAAACQAEAAAA","30":"b:IKgBgPB3ggAwEEAQAAAACQAEAAAA","38":"b:IKgBgPB3ggAwEEAQAAAACQAEAAAA","49":"b:IKgBgPB3ggAwEEAQAAAACQAEAAAA","55":"b:IKgBgPB3ggAwEEAQAAAACQAEAAAA","65":"b:IKgBgPB3ggAwEEAQAAAACQAEAAAA","75":"b:IKgBgPB3ggAwEEAQAAAACQAEAAAA"},"packages/localhost-33345/assets/_plugin-vue_export-helper-Da88TEg1.js":{"2":[38,39,40]},"packages/localhost-33345/assets/chunk-CC9Q-vWm.js":{"8":[38,39,40],"9":[38,39,40],"10":[38,39,40],"19":[38,39,40],"23":[38,39,40],"29":[38,39,40],"33":[38,39,40],"34":[38,39,40]},"packages/@n8n/api-types/src/dto/project/list-projects-query.dto.ts":{"13":"b:6ACAAAAlAAA4AEAAAAAAAAgCAAAA","14":"b:6ACAAAAlAAA4AEAAAAAAAAgCAAAA","17":"b:6ACAAAAlAAA4AEAAAAAAAAgCAAAA","26":"b:6ACAAAAlAAA4AEAAAAAAAAgCAAAA","34":"b:6ACAAAAlAAA4AEAAAAAAAAgCAAAA","35":"b:6ACAAAAlAAA4AEAAAAAAAAgCAAAA","38":"b:6ACAAAAlAAA4AEAAAAAAAAgCAAAA","41":"b:6ACAAAAlAAA4AEAAAAAAAAgCAAAA"},"packages/@n8n/backend-common/src/logging/logger.ts":{"20":"b:AABgAAAVAQAAAFAMAAAACABsAoAB","30":"b:AABgAAAVAQAAAFAMAAAACABsAoAB","41":"b:AABgAAAVAQAAAFAMAAAACABsAoAB","71":"b:AABgAAAVAQAAAFAMAAAACABsAoAB","76":"b:AABgAAAVAQAAAFAMAAAACABsAoAB","88":"b:AABgAAAVAQAAAFAMAAAACABsAoAB","109":"b:AABgAAAVAQAAAFAMAAAACABsAoAB","130":"b:AABgAAAVAQAAAFAMAAAACABsAoAB","142":"b:AABgAAAVAQAAAFAMAAAACABsAoAB","151":"b:AABgAAAVAQAAAFAMAAAACABsAoAB","159":"b:AABgAAAVAQAAAFAMAAAACABsAoAB","163":"b:AABgAAAVAQAAAFAMAAAACABsAoAB","169":"b:AABgAAAVAQAAAFAMAAAACABsAoAB","170":"b:AABgAAAVAQAAAFAMAAAACABsAoAB","176":"b:AABgAAAVAQAAAFAMAAAACABsAoAB","182":"b:AABgAAAVAQAAAFAMAAAACABsAoAB","192":"b:AABgAAAVAQAAAFAMAAAACABsAoAB","195":"b:AABgAAAVAQAAAFAMAAAACABsAoAB","198":"b:AABgAAAVAQAAAFAMAAAACABsAoAB","208":"b:AABgAAAVAQAAAFAMAAAACABsAoAB","214":"b:AABgAAAVAQAAAFAMAAAACABsAoAB","221":"b:AABgAAAVAQAAAFAMAAAACABsAoAB","223":"b:AABgAAAVAQAAAFAMAAAACABsAoAB","231":"b:AABgAAAVAQAAAFAMAAAACABsAoAB","245":"b:AABgAAAVAQAAAFAMAAAACABsAoAB","264":"b:AABgAAAVAQAAAFAMAAAACABsAoAB","268":"b:AABgAAAVAQAAAFAMAAAACABsAoAB","272":"b:AABgAAAVAQAAAFAMAAAACABsAoAB","276":"b:AABgAAAVAQAAAFAMAAAACABsAoAB","284":"b:AABgAAAVAQAAAFAMAAAACABsAoAB"},"packages/@n8n/backend-common/src/modules/module-registry.ts":{"26":[40,156,157],"65":[40,156,157],"68":[40,156,157],"74":[40,156,157],"85":[40,156,157],"143":[40,156,157],"181":[40,156,157],"200":[40,156,157],"216":[40,156,157],"220":[40,156,157]},"packages/@n8n/db/src/repositories/credential-dependency.repository.ts":{"25":"b:MKAAwHBxAJMwEEAQAEAAAAAEJIAA","62":"b:MKAAwHBxAJMwEEAQAEAAAAAEJIAA","66":"b:MKAAwHBxAJMwEEAQAEAAAAAEJIAA","75":"b:MKAAwHBxAJMwEEAQAEAAAAAEJIAA","78":"b:MKAAwHBxAJMwEEAQAEAAAAAEJIAA","93":"b:MKAAwHBxAJMwEEAQAEAAAAAEJIAA","103":"b:MKAAwHBxAJMwEEAQAEAAAAAEJIAA","116":"b:MKAAwHBxAJMwEEAQAEAAAAAEJIAA","117":"b:MKAAwHBxAJMwEEAQAEAAAAAEJIAA","118":"b:MKAAwHBxAJMwEEAQAEAAAAAEJIAA","138":"b:MKAAwHBxAJMwEEAQAEAAAAAEJIAA","149":"b:MKAAwHBxAJMwEEAQAEAAAAAEJIAA"},"packages/@n8n/db/src/repositories/credentials.repository.ts":{"16":"b:MPsGoP99urX2HEAQGlAAAYgUMAAA","20":"b:MPsGoP99urX2HEAQGlAAAYgUMAAA","27":"b:MPsGoP99urX2HEAQGlAAAYgUMAAA","45":"b:MPsGoP99urX2HEAQGlAAAYgUMAAA","63":"b:MPsGoP99urX2HEAQGlAAAYgUMAAA","134":"b:MPsGoP99urX2HEAQGlAAAYgUMAAA","174":"b:MPsGoP99urX2HEAQGlAAAYgUMAAA","191":"b:MPsGoP99urX2HEAQGlAAAYgUMAAA","220":"b:MPsGoP99urX2HEAQGlAAAYgUMAAA","245":"b:MPsGoP99urX2HEAQGlAAAYgUMAAA","261":"b:MPsGoP99urX2HEAQGlAAAYgUMAAA","272":"b:MPsGoP99urX2HEAQGlAAAYgUMAAA","284":"b:MPsGoP99urX2HEAQGlAAAYgUMAAA","292":"b:MPsGoP99urX2HEAQGlAAAYgUMAAA","304":"b:MPsGoP99urX2HEAQGlAAAYgUMAAA","344":"b:MPsGoP99urX2HEAQGlAAAYgUMAAA","422":"b:MPsGoP99urX2HEAQGlAAAYgUMAAA","424":"b:MPsGoP99urX2HEAQGlAAAYgUMAAA","428":"b:MPsGoP99urX2HEAQGlAAAYgUMAAA","446":"b:MPsGoP99urX2HEAQGlAAAYgUMAAA"},"packages/@n8n/db/src/repositories/project-relation.repository.ts":{"9":"b:/tMKDH4hAJXgCAAABFwCEYjwEC8A","13":"b:/tMKDH4hAJXgCAAABFwCEYjwEC8A","27":"b:/tMKDH4hAJXgCAAABFwCEYjwEC8A","35":"b:/tMKDH4hAJXgCAAABFwCEYjwEC8A","38":"b:/tMKDH4hAJXgCAAABFwCEYjwEC8A","43":"b:/tMKDH4hAJXgCAAABFwCEYjwEC8A","49":"b:/tMKDH4hAJXgCAAABFwCEYjwEC8A","56":"b:/tMKDH4hAJXgCAAABFwCEYjwEC8A","62":"b:/tMKDH4hAJXgCAAABFwCEYjwEC8A","70":"b:/tMKDH4hAJXgCAAABFwCEYjwEC8A","76":"b:/tMKDH4hAJXgCAAABFwCEYjwEC8A","79":"b:/tMKDH4hAJXgCAAABFwCEYjwEC8A"},"packages/@n8n/db/src/repositories/secrets-provider-connection.repository.ee.ts":{"8":"b:OKiAwHB1gJMwEEAQAEAAAQgGJIAA","12":"b:OKiAwHB1gJMwEEAQAEAAAQgGJIAA","16":"b:OKiAwHB1gJMwEEAQAEAAAQgGJIAA","25":"b:OKiAwHB1gJMwEEAQAEAAAQgGJIAA","33":"b:OKiAwHB1gJMwEEAQAEAAAQgGJIAA","36":"b:OKiAwHB1gJMwEEAQAEAAAQgGJIAA","55":"b:OKiAwHB1gJMwEEAQAEAAAQgGJIAA","89":"b:OKiAwHB1gJMwEEAQAEAAAQgGJIAA","119":"b:OKiAwHB1gJMwEEAQAEAAAQgGJIAA","125":"b:OKiAwHB1gJMwEEAQAEAAAQgGJIAA","140":"b:OKiAwHB1gJMwEEAQAEAAAQgGJIAA","164":"b:OKiAwHB1gJMwEEAQAEAAAQgGJIAA","182":"b:OKiAwHB1gJMwEEAQAEAAAQgGJIAA","190":"b:OKiAwHB1gJMwEEAQAEAAAQgGJIAA","200":"b:OKiAwHB1gJMwEEAQAEAAAQgGJIAA","210":"b:OKiAwHB1gJMwEEAQAEAAAQgGJIAA","222":"b:OKiAwHB1gJMwEEAQAEAAAQgGJIAA"},"packages/@n8n/decorators/src/module/module-metadata.ts":{"17":[40,156,157],"20":[40,156,157],"24":[40,156,157],"28":[40,156,157],"32":[40,156,157],"33":[40,156,157]},"packages/cli/src/credentials/credential-dependency.service.ts":{"19":"b:MKAAwHBxAJMwEEAQAEAAAAAEJIAA","24":"b:MKAAwHBxAJMwEEAQAEAAAAAEJIAA","39":"b:MKAAwHBxAJMwEEAQAEAAAAAEJIAA","46":"b:MKAAwHBxAJMwEEAQAEAAAAAEJIAA","64":"b:MKAAwHBxAJMwEEAQAEAAAAAEJIAA","82":"b:MKAAwHBxAJMwEEAQAEAAAAAEJIAA","98":"b:MKAAwHBxAJMwEEAQAEAAAAAEJIAA"},"packages/cli/src/credentials/credentials.controller.ts":{"54":"b:MPsW4H99kpOwFMARCFAAAYgEJIAA","70":"b:MPsW4H99kpOwFMARCFAAAYgEJIAA","85":"b:MPsW4H99kpOwFMARCFAAAYgEJIAA","95":"b:MPsW4H99kpOwFMARCFAAAYgEJIAA","103":"b:MPsW4H99kpOwFMARCFAAAYgEJIAA","117":"b:MPsW4H99kpOwFMARCFAAAYgEJIAA","144":"b:MPsW4H99kpOwFMARCFAAAYgEJIAA","157":"b:MPsW4H99kpOwFMARCFAAAYgEJIAA","199":"b:MPsW4H99kpOwFMARCFAAAYgEJIAA","242":"b:MPsW4H99kpOwFMARCFAAAYgEJIAA","338":"b:MPsW4H99kpOwFMARCFAAAYgEJIAA","378":"b:MPsW4H99kpOwFMARCFAAAYgEJIAA","384":"b:MPsW4H99kpOwFMARCFAAAYgEJIAA","400":"b:MPsW4H99kpOwFMARCFAAAYgEJIAA","401":"b:MPsW4H99kpOwFMARCFAAAYgEJIAA","404":"b:MPsW4H99kpOwFMARCFAAAYgEJIAA","405":"b:MPsW4H99kpOwFMARCFAAAYgEJIAA","435":"b:MPsW4H99kpOwFMARCFAAAYgEJIAA","441":"b:MPsW4H99kpOwFMARCFAAAYgEJIAA","477":"b:MPsW4H99kpOwFMARCFAAAYgEJIAA","484":"b:MPsW4H99kpOwFMARCFAAAYgEJIAA"},"packages/cli/src/credentials/credentials.service.ts":{"124":"b:sPsW4P99UpfxFMCRGnGAEYgUtIEA","153":"b:sPsW4P99UpfxFMCRGnGAEYgUtIEA","157":"b:sPsW4P99UpfxFMCRGnGAEYgUtIEA","161":"b:sPsW4P99UpfxFMCRGnGAEYgUtIEA","166":"b:sPsW4P99UpfxFMCRGnGAEYgUtIEA","174":"b:sPsW4P99UpfxFMCRGnGAEYgUtIEA","187":"b:sPsW4P99UpfxFMCRGnGAEYgUtIEA","188":"b:sPsW4P99UpfxFMCRGnGAEYgUtIEA","197":"b:sPsW4P99UpfxFMCRGnGAEYgUtIEA","228":"b:sPsW4P99UpfxFMCRGnGAEYgUtIEA","297":"b:sPsW4P99UpfxFMCRGnGAEYgUtIEA","358":"b:sPsW4P99UpfxFMCRGnGAEYgUtIEA","441":"b:sPsW4P99UpfxFMCRGnGAEYgUtIEA","482":"b:sPsW4P99UpfxFMCRGnGAEYgUtIEA","518":"b:sPsW4P99UpfxFMCRGnGAEYgUtIEA","532":"b:sPsW4P99UpfxFMCRGnGAEYgUtIEA","534":"b:sPsW4P99UpfxFMCRGnGAEYgUtIEA","535":"b:sPsW4P99UpfxFMCRGnGAEYgUtIEA","539":"b:sPsW4P99UpfxFMCRGnGAEYgUtIEA","542":"b:sPsW4P99UpfxFMCRGnGAEYgUtIEA","547":"b:sPsW4P99UpfxFMCRGnGAEYgUtIEA","550":"b:sPsW4P99UpfxFMCRGnGAEYgUtIEA","554":"b:sPsW4P99UpfxFMCRGnGAEYgUtIEA","579":"b:sPsW4P99UpfxFMCRGnGAEYgUtIEA","594":"b:sPsW4P99UpfxFMCRGnGAEYgUtIEA","595":"b:sPsW4P99UpfxFMCRGnGAEYgUtIEA","600":"b:sPsW4P99UpfxFMCRGnGAEYgUtIEA","605":"b:sPsW4P99UpfxFMCRGnGAEYgUtIEA","607":"b:sPsW4P99UpfxFMCRGnGAEYgUtIEA","608":"b:sPsW4P99UpfxFMCRGnGAEYgUtIEA","613":"b:sPsW4P99UpfxFMCRGnGAEYgUtIEA","614":"b:sPsW4P99UpfxFMCRGnGAEYgUtIEA","618":"b:sPsW4P99UpfxFMCRGnGAEYgUtIEA","637":"b:sPsW4P99UpfxFMCRGnGAEYgUtIEA","644":"b:sPsW4P99UpfxFMCRGnGAEYgUtIEA","657":"b:sPsW4P99UpfxFMCRGnGAEYgUtIEA","674":"b:sPsW4P99UpfxFMCRGnGAEYgUtIEA","701":"b:sPsW4P99UpfxFMCRGnGAEYgUtIEA","711":"b:sPsW4P99UpfxFMCRGnGAEYgUtIEA","760":"b:sPsW4P99UpfxFMCRGnGAEYgUtIEA","786":"b:sPsW4P99UpfxFMCRGnGAEYgUtIEA","807":"b:sPsW4P99UpfxFMCRGnGAEYgUtIEA","815":"b:sPsW4P99UpfxFMCRGnGAEYgUtIEA","837":"b:sPsW4P99UpfxFMCRGnGAEYgUtIEA","854":"b:sPsW4P99UpfxFMCRGnGAEYgUtIEA","868":"b:sPsW4P99UpfxFMCRGnGAEYgUtIEA","922":"b:sPsW4P99UpfxFMCRGnGAEYgUtIEA","938":"b:sPsW4P99UpfxFMCRGnGAEYgUtIEA","942":"b:sPsW4P99UpfxFMCRGnGAEYgUtIEA","953":"b:sPsW4P99UpfxFMCRGnGAEYgUtIEA","975":"b:sPsW4P99UpfxFMCRGnGAEYgUtIEA","989":"b:sPsW4P99UpfxFMCRGnGAEYgUtIEA","1003":"b:sPsW4P99UpfxFMCRGnGAEYgUtIEA","1018":"b:sPsW4P99UpfxFMCRGnGAEYgUtIEA","1062":"b:sPsW4P99UpfxFMCRGnGAEYgUtIEA","1077":"b:sPsW4P99UpfxFMCRGnGAEYgUtIEA","1078":"b:sPsW4P99UpfxFMCRGnGAEYgUtIEA","1081":"b:sPsW4P99UpfxFMCRGnGAEYgUtIEA","1090":"b:sPsW4P99UpfxFMCRGnGAEYgUtIEA","1093":"b:sPsW4P99UpfxFMCRGnGAEYgUtIEA","1106":"b:sPsW4P99UpfxFMCRGnGAEYgUtIEA","1115":"b:sPsW4P99UpfxFMCRGnGAEYgUtIEA","1136":"b:sPsW4P99UpfxFMCRGnGAEYgUtIEA","1146":"b:sPsW4P99UpfxFMCRGnGAEYgUtIEA","1171":"b:sPsW4P99UpfxFMCRGnGAEYgUtIEA","1231":"b:sPsW4P99UpfxFMCRGnGAEYgUtIEA","1233":"b:sPsW4P99UpfxFMCRGnGAEYgUtIEA","1252":"b:sPsW4P99UpfxFMCRGnGAEYgUtIEA","1261":"b:sPsW4P99UpfxFMCRGnGAEYgUtIEA","1269":"b:sPsW4P99UpfxFMCRGnGAEYgUtIEA","1270":"b:sPsW4P99UpfxFMCRGnGAEYgUtIEA","1281":"b:sPsW4P99UpfxFMCRGnGAEYgUtIEA","1282":"b:sPsW4P99UpfxFMCRGnGAEYgUtIEA","1287":"b:sPsW4P99UpfxFMCRGnGAEYgUtIEA","1294":"b:sPsW4P99UpfxFMCRGnGAEYgUtIEA","1302":"b:sPsW4P99UpfxFMCRGnGAEYgUtIEA","1323":"b:sPsW4P99UpfxFMCRGnGAEYgUtIEA","1332":"b:sPsW4P99UpfxFMCRGnGAEYgUtIEA","1370":"b:sPsW4P99UpfxFMCRGnGAEYgUtIEA","1398":"b:sPsW4P99UpfxFMCRGnGAEYgUtIEA","1402":"b:sPsW4P99UpfxFMCRGnGAEYgUtIEA","1465":"b:sPsW4P99UpfxFMCRGnGAEYgUtIEA"},"packages/cli/src/credentials/validation.ts":{"19":"b:MKAAwHBxAJMwEEAQAEAAAAAEJIAA","26":"b:MKAAwHBxAJMwEEAQAEAAAAAEJIAA","54":"b:MKAAwHBxAJMwEEAQAEAAAAAEJIAA","90":"b:MKAAwHBxAJMwEEAQAEAAAAAEJIAA","133":"b:MKAAwHBxAJMwEEAQAEAAAAAEJIAA","151":"b:MKAAwHBxAJMwEEAQAEAAAAAEJIAA","152":"b:MKAAwHBxAJMwEEAQAEAAAAAEJIAA","164":"b:MKAAwHBxAJMwEEAQAEAAAAAEJIAA"},"packages/cli/src/credentials-helper.ts":{"69":"b:MKAA4HBxAJMwEEARAEAgCQAMJIQA","72":"b:MKAA4HBxAJMwEEARAEAgCQAMJIQA","75":"b:MKAA4HBxAJMwEEARAEAgCQAMJIQA","87":"b:MKAA4HBxAJMwEEARAEAgCQAMJIQA","103":"b:MKAA4HBxAJMwEEARAEAgCQAMJIQA","134":"b:MKAA4HBxAJMwEEARAEAgCQAMJIQA","135":"b:MKAA4HBxAJMwEEARAEAgCQAMJIQA","161":"b:MKAA4HBxAJMwEEARAEAgCQAMJIQA","171":"b:MKAA4HBxAJMwEEARAEAgCQAMJIQA","222":"b:MKAA4HBxAJMwEEARAEAgCQAMJIQA","238":"b:MKAA4HBxAJMwEEARAEAgCQAMJIQA","267":"b:MKAA4HBxAJMwEEARAEAgCQAMJIQA","274":"b:MKAA4HBxAJMwEEARAEAgCQAMJIQA","290":"b:MKAA4HBxAJMwEEARAEAgCQAMJIQA","316":"b:MKAA4HBxAJMwEEARAEAgCQAMJIQA","335":"b:MKAA4HBxAJMwEEARAEAgCQAMJIQA","376":"b:MKAA4HBxAJMwEEARAEAgCQAMJIQA","475":"b:MKAA4HBxAJMwEEARAEAgCQAMJIQA","584":"b:MKAA4HBxAJMwEEARAEAgCQAMJIQA","609":"b:MKAA4HBxAJMwEEARAEAgCQAMJIQA","663":"b:MKAA4HBxAJMwEEARAEAgCQAMJIQA"},"packages/cli/src/errors/http-error-classifier.ts":{"6":"b:AABgAAARAQAAABAMAAAACABsAoAD","41":"b:AABgAAARAQAAABAMAAAACABsAoAD","58":"b:AABgAAARAQAAABAMAAAACABsAoAD"},"packages/cli/src/errors/http-error-serializers.ts":{"13":"b:AABgAAARAQAAABAMAAAACABsAoAD","51":"b:AABgAAARAQAAABAMAAAACABsAoAD"},"packages/cli/src/errors/response-errors/abstract/response.error.ts":{"19":"b:AABgAAARAAAAABAEAAAAAAAgApAD"},"packages/cli/src/errors/response-errors/not-found.error.ts":{"4":"b:AABgAAAFAAAwAAAAAAAAAAAgIIAC","14":"b:AABgAAAFAAAwAAAAAAAAAAAgIIAC"},"packages/cli/src/generic-helpers.ts":{"13":"b:ANsGgA81EpGwBAAACFAAAYj0NgAA","25":"b:ANsGgA81EpGwBAAACFAAAYj0NgAA"},"packages/cli/src/middlewares/list-query/filter.ts":{"11":"b:YAgAXQJxAAAwANQFAAAAABgEYAAA"},"packages/cli/src/middlewares/list-query/pagination.ts":{"10":"b:YAgAXQJxAAAwANQFAAAAABgEYAAA"},"packages/cli/src/middlewares/list-query/select.ts":{"11":"b:YAgAXQJxAAAwANQFAAAAABgEYAAA"},"packages/cli/src/middlewares/list-query/sort-by.ts":{"12":"b:YAgAXQJxAAAwANQFAAAAABgEYAAA"},"packages/cli/src/modules/chat-hub/chat-hub.settings.controller.ts":{"16":[40],"26":[40],"33":[40],"48":[40],"68":[40]},"packages/cli/src/modules/chat-hub/chat-hub.settings.service.ts":{"19":[36,37,38,39,40,7],"24":[36,37,38,39,40,7],"35":[36,37,38,39,40,7],"37":[36,37,38,39,40,7],"44":[36,37,38,39,40,7],"51":[36,37,38,39,40,7],"64":[36,37,38,39,40,7],"72":[36,37,38,39,40,7],"89":[36,37,38,39,40,7],"111":[36,37,38,39,40,7],"121":[36,37,38,39,40,7],"137":[36,37,38,39,40,7],"148":[36,37,38,39,40,7]},"packages/cli/src/modules/data-table/data-table-file-cleanup.service.ts":{"13":"b:KKKA4AEHgCAgATBMAEAAAIgEAAAA","20":"b:KKKA4AEHgCAgATBMAEAAAIgEAAAA","29":"b:KKKA4AEHgCAgATBMAEAAAIgEAAAA","33":"b:KKKA4AEHgCAgATBMAEAAAIgEAAAA","38":"b:KKKA4AEHgCAgATBMAEAAAIgEAAAA","49":"b:KKKA4AEHgCAgATBMAEAAAIgEAAAA","82":"b:KKKA4AEHgCAgATBMAEAAAIgEAAAA"},"packages/cli/src/modules/external-secrets.ee/provider-registry.service.ts":{"10":"b:IIkCgABxgAAgEEAQAAAAAQAECAAA","13":"b:IIkCgABxgAAgEEAQAAAAAQAECAAA","17":"b:IIkCgABxgAAgEEAQAAAAAQAECAAA","21":"b:IIkCgABxgAAgEEAQAAAAAQAECAAA","25":"b:IIkCgABxgAAgEEAQAAAAAQAECAAA","29":"b:IIkCgABxgAAgEEAQAAAAAQAECAAA","33":"b:IIkCgABxgAAgEEAQAAAAAQAECAAA","43":"b:IIkCgABxgAAgEEAQAAAAAQAECAAA","47":"b:IIkCgABxgAAgEEAQAAAAAQAECAAA","51":"b:IIkCgABxgAAgEEAQAAAAAQAECAAA","55":"b:IIkCgABxgAAgEEAQAAAAAQAECAAA","57":"b:IIkCgABxgAAgEEAQAAAAAQAECAAA","58":"b:IIkCgABxgAAgEEAQAAAAAQAECAAA"},"packages/cli/src/modules/external-secrets.ee/secrets-providers-completions.controller.ee.ts":{"15":"b:IIgAgABxgAAgEEAQAAAAAQAEAAAA","24":"b:IIgAgABxgAAgEEAQAAAAAQAEAAAA","55":"b:IIgAgABxgAAgEEAQAAAAAQAEAAAA","72":"b:IIgAgABxgAAgEEAQAAAAAQAEAAAA","84":"b:IIgAgABxgAAgEEAQAAAAAQAEAAAA"},"packages/cli/src/modules/external-secrets.ee/secrets-providers-connections.service.ee.ts":{"39":"b:KIiAgLB1gAAgEEAQAAAAAQgGAAAA","53":"b:KIiAgLB1gAAgEEAQAAAAAQgGAAAA","79":"b:KIiAgLB1gAAgEEAQAAAAAQgGAAAA","107":"b:KIiAgLB1gAAgEEAQAAAAAQgGAAAA","124":"b:KIiAgLB1gAAgEEAQAAAAAQgGAAAA","141":"b:KIiAgLB1gAAgEEAQAAAAAQgGAAAA","146":"b:KIiAgLB1gAAgEEAQAAAAAQgGAAAA","147":"b:KIiAgLB1gAAgEEAQAAAAAQgGAAAA","152":"b:KIiAgLB1gAAgEEAQAAAAAQgGAAAA","153":"b:KIiAgLB1gAAgEEAQAAAAAQgGAAAA","168":"b:KIiAgLB1gAAgEEAQAAAAAQgGAAAA","190":"b:KIiAgLB1gAAgEEAQAAAAAQgGAAAA","212":"b:KIiAgLB1gAAgEEAQAAAAAQgGAAAA","221":"b:KIiAgLB1gAAgEEAQAAAAAQgGAAAA","244":"b:KIiAgLB1gAAgEEAQAAAAAQgGAAAA","252":"b:KIiAgLB1gAAgEEAQAAAAAQgGAAAA","262":"b:KIiAgLB1gAAgEEAQAAAAAQgGAAAA","266":"b:KIiAgLB1gAAgEEAQAAAAAQgGAAAA","274":"b:KIiAgLB1gAAgEEAQAAAAAQgGAAAA","282":"b:KIiAgLB1gAAgEEAQAAAAAQgGAAAA","286":"b:KIiAgLB1gAAgEEAQAAAAAQgGAAAA","288":"b:KIiAgLB1gAAgEEAQAAAAAQgGAAAA","295":"b:KIiAgLB1gAAgEEAQAAAAAQgGAAAA","310":"b:KIiAgLB1gAAgEEAQAAAAAQgGAAAA","320":"b:KIiAgLB1gAAgEEAQAAAAAQgGAAAA","338":"b:KIiAgLB1gAAgEEAQAAAAAQgGAAAA","339":"b:KIiAgLB1gAAgEEAQAAAAAQgGAAAA","350":"b:KIiAgLB1gAAgEEAQAAAAAQgGAAAA","376":"b:KIiAgLB1gAAgEEAQAAAAAQgGAAAA","403":"b:KIiAgLB1gAAgEEAQAAAAAQgGAAAA","407":"b:KIiAgLB1gAAgEEAQAAAAAQgGAAAA","420":"b:KIiAgLB1gAAgEEAQAAAAAQgGAAAA","437":"b:KIiAgLB1gAAgEEAQAAAAAQgGAAAA","441":"b:KIiAgLB1gAAgEEAQAAAAAQgGAAAA","468":"b:KIiAgLB1gAAgEEAQAAAAAQgGAAAA","472":"b:KIiAgLB1gAAgEEAQAAAAAQgGAAAA","485":"b:KIiAgLB1gAAgEEAQAAAAAQgGAAAA","501":"b:KIiAgLB1gAAgEEAQAAAAAQgGAAAA","523":"b:KIiAgLB1gAAgEEAQAAAAAQgGAAAA"},"packages/cli/src/push/abstract.push.ts":{"34":"b:KPuW5H8/ErXgDTBMClQCEYgEAAAA","40":"b:KPuW5H8/ErXgDTBMClQCEYgEAAAA","43":"b:KPuW5H8/ErXgDTBMClQCEYgEAAAA","58":"b:KPuW5H8/ErXgDTBMClQCEYgEAAAA","66":"b:KPuW5H8/ErXgDTBMClQCEYgEAAAA","70":"b:KPuW5H8/ErXgDTBMClQCEYgEAAAA","79":"b:KPuW5H8/ErXgDTBMClQCEYgEAAAA","96":"b:KPuW5H8/ErXgDTBMClQCEYgEAAAA","102":"b:KPuW5H8/ErXgDTBMClQCEYgEAAAA","106":"b:KPuW5H8/ErXgDTBMClQCEYgEAAAA","115":"b:KPuW5H8/ErXgDTBMClQCEYgEAAAA","117":"b:KPuW5H8/ErXgDTBMClQCEYgEAAAA","124":"b:KPuW5H8/ErXgDTBMClQCEYgEAAAA","134":"b:KPuW5H8/ErXgDTBMClQCEYgEAAAA"},"packages/cli/src/response-helper.ts":{"15":"b:AABgIAARAQAAABAMAAAgCABsAoAD","48":"b:AABgIAARAQAAABAMAAAgCABsAoAD","95":"b:AABgIAARAQAAABAMAAAgCABsAoAD","117":"b:AABgIAARAQAAABAMAAAgCABsAoAD","131":"b:AABgIAARAQAAABAMAAAgCABsAoAD","135":"b:AABgIAARAQAAABAMAAAgCABsAoAD"},"packages/cli/src/wait-tracker.ts":{"35":"b:KKKAxAEXACAgATBMAEAAAIgEAAgA","50":"b:KKKAxAEXACAgATBMAEAAAIgEAAgA","62":"b:KKKAxAEXACAgATBMAEAAAIgEAAgA","66":"b:KKKAxAEXACAgATBMAEAAAIgEAAgA","71":"b:KKKAxAEXACAgATBMAEAAAIgEAAgA","73":"b:KKKAxAEXACAgATBMAEAAAIgEAAgA","82":"b:KKKAxAEXACAgATBMAEAAAIgEAAgA","91":"b:KKKAxAEXACAgATBMAEAAAIgEAAgA","104":"b:KKKAxAEXACAgATBMAEAAAIgEAAgA","112":"b:KKKAxAEXACAgATBMAEAAAIgEAAgA","120":"b:KKKAxAEXACAgATBMAEAAAIgEAAgA","190":"b:KKKAxAEXACAgATBMAEAAAIgEAAgA","200":"b:KKKAxAEXACAgATBMAEAAAIgEAAgA","211":"b:KKKAxAEXACAgATBMAEAAAIgEAAgA","232":"b:KKKAxAEXACAgATBMAEAAAIgEAAgA","235":"b:KKKAxAEXACAgATBMAEAAAIgEAAgA","249":"b:KKKAxAEXACAgATBMAEAAAIgEAAgA","253":"b:KKKAxAEXACAgATBMAEAAAIgEAAgA"},"packages/workflow/src/errors/base/base.error.ts":{"32":"b:AANiAAgXACAAABAEBFgAAIBwAiIC"},"packages/workflow/src/errors/ensure-error.ts":{"2":"b:AABgAAARAQAAABAEAAAACABsAjAD"},"packages/workflow/src/errors/index.ts":{"5":"b:AIJgAAA3AQAAABAMAEAgCQBsArAD","14":"b:AIJgAAA3AQAAABAMAEAgCQBsArAD","17":"b:AIJgAAA3AQAAABAMAEAgCQBsArAD","23":"b:AIJgAAA3AQAAABAMAEAgCQBsArAD","27":"b:AIJgAAA3AQAAABAMAEAgCQBsArAD","29":"b:AIJgAAA3AQAAABAMAEAgCQBsArAD","30":"b:AIJgAAA3AQAAABAMAEAgCQBsArAD","33":"b:AIJgAAA3AQAAABAMAEAgCQBsArAD","36":"b:AIJgAAA3AQAAABAMAEAgCQBsArAD"},"packages/workflow/src/node-helpers.ts":{"251":"b:MPs+oH9/EtfxDEIRj9zjl7n+Nq8B","259":"b:MPs+oH9/EtfxDEIRj9zjl7n+Nq8B","269":"b:MPs+oH9/EtfxDEIRj9zjl7n+Nq8B","279":"b:MPs+oH9/EtfxDEIRj9zjl7n+Nq8B","294":"b:MPs+oH9/EtfxDEIRj9zjl7n+Nq8B","316":"b:MPs+oH9/EtfxDEIRj9zjl7n+Nq8B","317":"b:MPs+oH9/EtfxDEIRj9zjl7n+Nq8B","334":"b:MPs+oH9/EtfxDEIRj9zjl7n+Nq8B","338":"b:MPs+oH9/EtfxDEIRj9zjl7n+Nq8B","353":"b:MPs+oH9/EtfxDEIRj9zjl7n+Nq8B","412":"b:MPs+oH9/EtfxDEIRj9zjl7n+Nq8B","439":"b:MPs+oH9/EtfxDEIRj9zjl7n+Nq8B","478":"b:MPs+oH9/EtfxDEIRj9zjl7n+Nq8B","514":"b:MPs+oH9/EtfxDEIRj9zjl7n+Nq8B","551":"b:MPs+oH9/EtfxDEIRj9zjl7n+Nq8B","586":"b:MPs+oH9/EtfxDEIRj9zjl7n+Nq8B","591":"b:MPs+oH9/EtfxDEIRj9zjl7n+Nq8B","667":"b:MPs+oH9/EtfxDEIRj9zjl7n+Nq8B","934":"b:MPs+oH9/EtfxDEIRj9zjl7n+Nq8B","973":"b:MPs+oH9/EtfxDEIRj9zjl7n+Nq8B","1005":"b:MPs+oH9/EtfxDEIRj9zjl7n+Nq8B","1006":"b:MPs+oH9/EtfxDEIRj9zjl7n+Nq8B","1054":"b:MPs+oH9/EtfxDEIRj9zjl7n+Nq8B","1084":"b:MPs+oH9/EtfxDEIRj9zjl7n+Nq8B","1114":"b:MPs+oH9/EtfxDEIRj9zjl7n+Nq8B","1135":"b:MPs+oH9/EtfxDEIRj9zjl7n+Nq8B","1144":"b:MPs+oH9/EtfxDEIRj9zjl7n+Nq8B","1148":"b:MPs+oH9/EtfxDEIRj9zjl7n+Nq8B","1154":"b:MPs+oH9/EtfxDEIRj9zjl7n+Nq8B","1157":"b:MPs+oH9/EtfxDEIRj9zjl7n+Nq8B","1180":"b:MPs+oH9/EtfxDEIRj9zjl7n+Nq8B","1242":"b:MPs+oH9/EtfxDEIRj9zjl7n+Nq8B","1278":"b:MPs+oH9/EtfxDEIRj9zjl7n+Nq8B","1304":"b:MPs+oH9/EtfxDEIRj9zjl7n+Nq8B","1334":"b:MPs+oH9/EtfxDEIRj9zjl7n+Nq8B","1348":"b:MPs+oH9/EtfxDEIRj9zjl7n+Nq8B","1373":"b:MPs+oH9/EtfxDEIRj9zjl7n+Nq8B","1401":"b:MPs+oH9/EtfxDEIRj9zjl7n+Nq8B","1436":"b:MPs+oH9/EtfxDEIRj9zjl7n+Nq8B","1444":"b:MPs+oH9/EtfxDEIRj9zjl7n+Nq8B","1456":"b:MPs+oH9/EtfxDEIRj9zjl7n+Nq8B","1499":"b:MPs+oH9/EtfxDEIRj9zjl7n+Nq8B","1502":"b:MPs+oH9/EtfxDEIRj9zjl7n+Nq8B","1667":"b:MPs+oH9/EtfxDEIRj9zjl7n+Nq8B","1708":"b:MPs+oH9/EtfxDEIRj9zjl7n+Nq8B","1716":"b:MPs+oH9/EtfxDEIRj9zjl7n+Nq8B","1728":"b:MPs+oH9/EtfxDEIRj9zjl7n+Nq8B","1738":"b:MPs+oH9/EtfxDEIRj9zjl7n+Nq8B","1742":"b:MPs+oH9/EtfxDEIRj9zjl7n+Nq8B","1759":"b:MPs+oH9/EtfxDEIRj9zjl7n+Nq8B","1768":"b:MPs+oH9/EtfxDEIRj9zjl7n+Nq8B","1774":"b:MPs+oH9/EtfxDEIRj9zjl7n+Nq8B","1776":"b:MPs+oH9/EtfxDEIRj9zjl7n+Nq8B","1784":"b:MPs+oH9/EtfxDEIRj9zjl7n+Nq8B","1788":"b:MPs+oH9/EtfxDEIRj9zjl7n+Nq8B","1812":"b:MPs+oH9/EtfxDEIRj9zjl7n+Nq8B","1847":"b:MPs+oH9/EtfxDEIRj9zjl7n+Nq8B","1854":"b:MPs+oH9/EtfxDEIRj9zjl7n+Nq8B","1870":"b:MPs+oH9/EtfxDEIRj9zjl7n+Nq8B","1875":"b:MPs+oH9/EtfxDEIRj9zjl7n+Nq8B","1909":"b:MPs+oH9/EtfxDEIRj9zjl7n+Nq8B","1942":"b:MPs+oH9/EtfxDEIRj9zjl7n+Nq8B","1957":"b:MPs+oH9/EtfxDEIRj9zjl7n+Nq8B","1983":"b:MPs+oH9/EtfxDEIRj9zjl7n+Nq8B","2001":"b:MPs+oH9/EtfxDEIRj9zjl7n+Nq8B","2014":"b:MPs+oH9/EtfxDEIRj9zjl7n+Nq8B","2028":"b:MPs+oH9/EtfxDEIRj9zjl7n+Nq8B","2042":"b:MPs+oH9/EtfxDEIRj9zjl7n+Nq8B","2053":"b:MPs+oH9/EtfxDEIRj9zjl7n+Nq8B"},"packages/@n8n/design-system/src/components/N8nAvatar/Avatar.vue":{"15":"b:+gCAAAAlAQA4AEAWAAAAAAgCAAAA","28":"b:+gCAAAAlAQA4AEAWAAAAAAgCAAAA","29":"b:+gCAAAAlAQA4AEAWAAAAAAgCAAAA","31":"b:+gCAAAAlAQA4AEAWAAAAAAgCAAAA","33":"b:+gCAAAAlAQA4AEAWAAAAAAgCAAAA","43":"b:+gCAAAAlAQA4AEAWAAAAAAgCAAAA","44":"b:+gCAAAAlAQA4AEAWAAAAAAgCAAAA"},"packages/@n8n/design-system/src/components/N8nDataTableServer/N8nDataTableServer.vue":{"52":"b:qACAAAAFAQAgAEAAAAAAAAgCAAAA","95":"b:qACAAAAFAQAgAEAAAAAAAAgCAAAA","96":[40,42,48,3,69,86,7,5],"104":"b:qACAAAAFAQAgAEAAAAAAAAgCAAAA","111":"b:qACAAAAFAQAgAEAAAAAAAAgCAAAA","115":"b:qACAAAAFAQAgAEAAAAAAAAgCAAAA","121":"b:qACAAAAFAQAgAEAAAAAAAAgCAAAA","133":"b:qACAAAAFAQAgAEAAAAAAAAgCAAAA","137":"b:qACAAAAFAQAgAEAAAAAAAAgCAAAA","146":"b:qACAAAAFAQAgAEAAAAAAAAgCAAAA","151":"b:qACAAAAFAQAgAEAAAAAAAAgCAAAA","180":"b:qACAAAAFAQAgAEAAAAAAAAgCAAAA","181":"b:qACAAAAFAQAgAEAAAAAAAAgCAAAA","192":[23,42,48,3,69,86,7,5,131,137],"218":"b:qACAAAAFAQAgAEAAAAAAAAgCAAAA","226":[42,3],"229":[42,3],"241":"b:qACAAAAFAQAgAEAAAAAAAAgCAAAA","290":"b:qACAAAAFAQAgAEAAAAAAAAgCAAAA","322":[42,3],"340":"b:qACAAAAFAQAgAEAAAAAAAAgCAAAA","344":[7],"356":[42,3],"389":"b:qACAAAAFAQAgAEAAAAAAAAgCAAAA","406":"b:qACAAAAFAQAgAEAAAAAAAAgCAAAA","407":"b:qACAAAAFAQAgAEAAAAAAAAgCAAAA","466":"b:qACAAAAFAQAgAEAAAAAAAAgCAAAA","467":"b:qACAAAAFAQAgAEAAAAAAAAgCAAAA","470":[42,7],"472":"b:qACAAAAFAQAgAEAAAAAAAAgCAAAA","511":[40],"513":[40]},"packages/@n8n/design-system/src/components/N8nIcon/custom/mcp.svg":{"13":"b:ioCAAACJAwA+ANgPAAKAQBgKAAAA"},"packages/@n8n/design-system/src/components/N8nIconPicker/types.ts":{"13":"b:OCCAgAL1AQA+AEAQAAAAAAoCAAAA"},"packages/@n8n/design-system/src/components/N8nInlineTextEdit/InlineTextEdit.vue":{"16":"b:cP9f4C/7///v/8Mx//////8PAAAA","35":"b:cP9f4C/7///v/8Mx//////8PAAAA","38":"b:cP9f4C/7///v/8Mx//////8PAAAA","44":"b:cP9f4C/7///v/8Mx//////8PAAAA","47":"b:cP9f4C/7///v/8Mx//////8PAAAA","57":"b:cP9f4C/7///v/8Mx//////8PAAAA","68":"b:YBYAgASwACBMgsMREEBgRQAHAAAA","74":"b:QBYAAAQgACBkggMAAEBgRRQDAAAA","81":"b:YBYAgASwACBMgsMREEBgRQAHAAAA","92":"b:YBYAgASwACBMgsMREEBgRQAHAAAA","96":"b:YBYAgASwACBsgsMREEBgRRQHAAAA","103":"b:cP9f4C/7///v/8Mx//////8PAAAA","122":"b:cP9f4C/7///v/8Mx/////n8PAAAA","127":"b:cP9f4C/7///v/8Mx/////n8PAAAA","143":"b:YBYAgASwACBMgsMREEBgRQAHAAAA"},"packages/@n8n/design-system/src/components/N8nInputNumber/InputNumber.vue":{"15":"b:AIpKAAEBFECBQcAgQunvfyAEAAAA","31":"b:AIpKAAEBFECBQcAgQunvfyAEAAAA","32":"b:AIpKAAEBFECBQcAgQunvfyAEAAAA"},"packages/@n8n/design-system/src/components/N8nPagination/Pagination.vue":{"10":[40]},"packages/@n8n/design-system/src/components/N8nRadioButtons/RadioButton.vue":{"22":"b:cP9f4C95/v/n/8Pw//////8PAAAA"},"packages/@n8n/design-system/src/components/N8nRadioButtons/RadioButtons.vue":{"20":"b:cP9f4C95/v/n/8Pw//////8PAAAA","33":"b:AIAAAAAAAAAACEAABFx/H8IAAAAA","41":"b:cP9f4C95/v/n/8Pw//////8PAAAA","50":"b:cP9f4C95/v/n/8Pw/////n8PAAAA","58":"b:AIAAAAAAAAAACEAABFx/H8IAAAAA","59":"b:cP9f4C95/v/n/8Pw//////8PAAAA"},"packages/@n8n/design-system/src/components/N8nSwitch/Switch.vue":{"10":[40],"14":[40],"21":[40],"22":[40],"23":[40],"30":[40],"40":[40]},"packages/@n8n/design-system/src/components/N8nTag/Tag.vue":{"15":"b:8v8fwA8ZAP/nadsvn///1/8PAAAA"},"packages/@n8n/design-system/src/components/PreviewTag/PreviewTag.vue":{"11":"b:ggAACQAJAQAwANgPAAAAAAgAAAAA","12":"b:ggAACQAJAQAwANgPAAAAAAgAAAAA"},"packages/@n8n/design-system/src/utils/labelUtil.ts":{"1":"b:+gCAAAAlAQA4AEAWAAAAAAgCAAAA","4":"b:+gCAAAAlAQA4AEAWAAAAAAgCAAAA","6":"b:+gCAAAAlAQA4AEAWAAAAAAgCAAAA","11":"b:+gCAAAAlAQA4AEAWAAAAAAgCAAAA"},"packages/@n8n/i18n/src/utils.ts":{"9":"b:ML5b4C1z1s7h+cMxz+3//ysGAAAA","29":"b:ML5b4C1z1s7h+cMxz+3//ysGAAAA","31":"b:ML5b4C1z1s7h+cMxz+3//ysGAAAA","34":"b:ML5b4C1z1s7h+cMxz+3//ysGAAAA","41":"b:ML5b4C1z1s7h+cMxz+3//ysGAAAA","49":"b:AJIYQAUABMoBIQIgSshv9yAAAAAA","57":"b:AJIYQAUABMoBIQIgSshv9yAAAAAA","58":"b:AJIYQAUABMoBIQIgSshv9yAAAAAA"},"packages/frontend/editor-ui/src/app/components/Banner.vue":{"22":"b:IIgBgCBxgAAgEEAQAAAACQAEAAAA","47":"b:IIgBgCBxgAAgEEAQAAAACQAEAAAA","53":"b:IIgBgCBxgAAgEEAQAAAACQAEAAAA","58":"b:IIgBgCBxgAAgEEAQAAAACQAEAAAA","62":"b:IIgBgCBxgAAgEEAQAAAACAAEAAAA","71":[86]},"packages/frontend/editor-ui/src/app/components/EnterpriseEdition.ee.vue":{"17":"b:cIgBgCBxgAA4EEAQAAAACQAGAAAA","18":"b:cIgBgCBxgAA4EEAQAAAACQAGAAAA"},"packages/frontend/editor-ui/src/app/components/FreeAiCreditsCallout.vue":{"21":"b:MJ5b4C1x1s7h+UMwz+3//ysGAAAA","55":"b:MJ5b4C1x1s7h+UMwz+3//ysGAAAA","57":"b:MJ5b4C1x1s7h+UMwz+3//ysGAAAA","63":"b:MJ5b4C1x1s7h+UMwz+3//ysGAAAA"},"packages/frontend/editor-ui/src/app/components/SaveButton.vue":{"12":"b:IIgBgCBxgAAgEMARAAAACQAEAAAA","36":"b:IIgBgCBxgAAgEMARAAAACQAEAAAA","45":"b:IIgBgCBxgAAgEMARAAAACQAEAAAA","73":"b:IIABgCAxAAAgEMARAAAAAQAEAAAA"},"packages/frontend/editor-ui/src/app/components/SettingsSidebar.vue":{"23":"b:ggAAAAAJAAAAANgPAAAAAAAAAAAA","26":"b:ggAAAAAJAAAAANgPAAAAAAAAAAAA","37":"b:ggAAAAAJAAAAANgPAAAAAAAAAAAA","41":"b:ggAAAAAJAAAAANgPAAAAAAAAAAAA"},"packages/frontend/editor-ui/src/app/components/TimeAgo.vue":{"20":"b:KACAgADxAQA+AEAQAAIAQBgOAAAA","21":"b:KACAgADxAQA+AEAQAAIAQBgOAAAA","31":"b:KACAgADxAQA+AEAQAAIAQBgOAAAA","37":"b:KACAgADxAQA+AEAQAAIAQBgOAAAA","41":"b:KACAgADxAQA+AEAQAAIAQBgOAAAA"},"packages/frontend/editor-ui/src/app/composables/useCollectionOverhaul.ts":{"5":"b:ML5b4C1z1s7h+cMxz+3//ysGAAAA","8":"b:MJ5b4C0z1s7h+YMhz+3//ysGAAAA"},"packages/frontend/editor-ui/src/app/composables/useNodeHelpers.ts":{"81":"b:ML5b4A0y1s7h+YMhz+3//ysCAAAA","111":"b:ML5b4A0w1s7h+QMgz+3//ysCAAAA","144":"b:MJ5b4A0w1s7h+QMgz+3//ysCAAAA","157":"b:MIABwAAwAAIhEAAAAEAACQAAAAAA","158":"b:MIABwAAwAAIhEAAAAEAACQAAAAAA","159":"b:MIABwAAwAAIhEAAAAEAACQAAAAAA","163":"b:MP5b4C9z1t/h/cMxz+3//ysPAAAA","183":[16,41,119],"244":"b:ANcbAA4iAP/BaAKAh/z/l8EIAAAA","260":[30,44,45,58],"274":"b:cP8b4A8w/v/h/wMg//////sPAAAA","294":"b:cP9/4A84/v/n/wOg//////8PAAAA","302":"b:cP8f4A84/v/n/wOg//////8PAAAA","314":"b:cP9/4A84/v/n/wOg//////8PAAAA","322":"b:MJQZoA0wgA6hAAEAx4WvHQMEAAAA","330":"b:cL4Z4A0w/m7h1gMg5+3vfesPAAAA","345":"b:MLQZoA0wgA6hAAEAx4WvHQMAAAAA","353":"b:cP9b4A8w/v/h/wMg//////sPAAAA","380":"b:cP8b4A8y/v/h/wMg//////sPAAAA","393":"b:MP8b4A8w1r/h/wMg3////+sNAAAA","425":"b:MPgb4Acy1pfhvQAgRe2gryAPAAAA","451":"b:cP8b4A8y/v/h/wMg//////sPAAAA","559":"b:MKABgAASAJMhEAAAAEAACQAEAAAA","614":[30,44,45,58],"622":[30,44],"633":[30,44],"636":"b:cP9/4A95/v/n/wOw//////8PAAAA","651":"b:MN5b4A0w1s7h+QMgz+3//ysCAAAA","655":"b:MN5b4A0w1s7h+QMgz+3//ysCAAAA","661":"b:MJ4b4A0w1o7h+QMgx+3//ysAAAAA","663":"b:AAYIAAQAAIzASAIAgsx/lwEAAAAA","669":"b:AAYIAAQAAIzASAIAiu1/twEAAAAA","677":"b:AAYIAAQAAIzASAIAgux/lwEAAAAA","683":"b:MN5b4A0w1s7h+QMgz+3//ysCAAAA","709":"b:AMYbAAQAAM7BaAIAgux/lwEAAAAA","717":"b:MN5b4A0w1s7h+QMgz+3//ysCAAAA","748":"b:AIAAAAAAAAAAAAAgRUAAAOAAAAAA","755":"b:AIAAAAAAAAAAAAAgRUAAAOAAAAAA","797":"b:cP974A8w/v/h/wOg//////sPAAAA","801":"b:AKABQAAgAJMgAAAAAEAAAAAEAAAA","817":"b:AKABQAAgAJMAAAAAAEAAAAAEAAAA","852":"b:ABYAAAQAACBAggMAREBgRQgBAAAA","856":"b:ABYAAAQAACBAggMAREBgRQgBAAAA","859":"b:ABYAAAQAACBAggMAREBgRQgBAAAA","877":[102],"911":"b:AAACAAAAAAgAAAAAAEhiBgAAAAAA","927":"b:MN5b4A0w1s7h+QMgz+3//ysCAAAA","996":"b:cIoZoAkw/k4h0AAg5y2vfaoCAAAA"},"packages/frontend/editor-ui/src/app/composables/useResolvedExpression.ts":{"25":"b:ML5b4C1z1s7h+cMxz+3//ysGAAAA","46":"b:MJ5b4C1x1s7h+cMxz+3//ysGAAAA","52":"b:ML5b4C1z1s7h+cMxz+3//ysGAAAA","53":"b:AAIAAAAAAIBAAAIAAEgHBwAAAAAA","54":"b:AIIBAAAQAoBAMUIAAUivHwAAAAAA","59":"b:ML5b4C1z1s7h+cMxz+3//ysGAAAA","61":"b:AIIBAAAQAoBAMUIAAUivHwAAAAAA","100":"b:ML5b4C1z1s7h+cMxz+3//ysGAAAA","126":"b:ML5b4C1z1s7h+cMxz+3//ysGAAAA","127":"b:ML5b4C1z1s7h+cMxz+3//ysGAAAA","128":"b:ML5b4C1z1s7h+cMxz+3//ysGAAAA"},"packages/frontend/editor-ui/src/app/layouts/SettingsLayout.vue":{"27":"b:ggAAAAAJAAAAANgPAAAAAAAAAAAA","34":"b:ggAAAAAJAAAAANgPAAAAAAAAAAAA","36":"b:ggAAAAAJAAAAANgPAAAAAAAAAAAA"},"packages/frontend/editor-ui/src/app/utils/credentialOnlyNodes.ts":{"5":"b:cP974C8z/v/h/8Px//////sPgAAA","9":[151,58],"13":"b:cP8f4A84/v/n/wMg//////8PgAAA","17":"b:cP8f4A84/v/n/wMg//////8PgAAA","52":"b:cP8f4A84/v/n/wMg//////8PgAAA"},"packages/frontend/editor-ui/src/app/utils/nodes/nodeTransforms.ts":{"28":"b:cJ4ZoA0w/m5h1gMg523vfasHgAAA","37":"b:cL8Z4A8w/v9h3wMg/9////sPgAAA","62":"b:MLgZ4Acw1pdhnQAgRU2gLyAPgAAA","72":[151,138,139],"86":"b:MKgBoAEQ1pdhnQAgBEGgLyANgAAA","100":"b:cL8Z4A8w/v9h3wMg/9////sPgAAA","106":"b:MKgBoAEQ1pdhnQAgBEGgLyANgAAA","117":"b:AAcCAAQAAESBKAAAgYhvFgAAgAAA","131":"b:ML5b4C1z1s7h+cMxz+3//ysGgAAA","151":"b:MJ5b4A0w1s7h+YMhx+3//ysCgAAA","170":"b:QP8bwA8wAP/haAKg1/3/1+sOgAAA","229":"b:AIABAAAAAJMhAAAAAEAAAAAEgAAA","230":"b:AIABAAAAAJMhAAAAAEAAAAAEgAAA"},"packages/frontend/editor-ui/src/app/utils/rbac/middleware/rbac.ts":{"11":[40,43,83,84,86,87,88,7,91]},"packages/frontend/editor-ui/src/app/utils/rbacUtils.ts":{"4":[40,43,83,84,86,87,88,7,91],"12":[40,43,83,84,86,87,88,7,91],"23":[40,43,83,84,86,87,88,7,91],"34":[86,7]},"packages/frontend/editor-ui/src/app/utils/typesUtils.ts":{"14":"b:AMZaAAQAAM7BaAIAyu1/lwEJAAAA","23":"b:cP5/4C97/u79/8Px7/3///8PAAAA","40":[138,139],"56":"b:KACAgADxAQA+AEAQAAIAQBgOAAAA","60":"b:AAAAAAAAAABAAAAAQAVvBwABAAAA","66":[122],"71":"b:AMZaAAQAAM7BaAIAiu1/twEAAAAA","119":[104,112,113,114,115,121,122],"124":[104,112,113,114,115,121,122],"166":[74,138,139],"170":"b:cP5b4C1z/u7/+8Nx/+///+sHAAAA","174":"b:IJAZgCXwAA6hEMARCAQvHwAEAAAA","201":"b:IJAZgCVykA6hEMARiAQvHwAEAAAA"},"packages/frontend/editor-ui/src/features/ai/chatHub/SettingsChatHubView.vue":{"26":[40],"42":[40],"44":[40],"46":[40],"54":[40],"72":[40],"93":[40],"108":[40]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/ChatProvidersTable.vue":{"25":[40],"47":[40],"56":[40],"65":[40],"75":[40],"81":[40],"89":[40],"93":[40],"116":[40],"123":[40],"136":[40],"140":[40],"163":[40],"172":[40],"176":[40],"190":[40],"193":[40],"199":[40],"204":[40]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/ProviderSettingsModal.vue":{"123":[40],"127":[40],"141":[40],"156":[40],"164":[40],"184":[40],"217":[40],"227":[40],"229":[40],"240":[40],"243":[40],"250":[40],"254":[40],"265":[40],"279":[40],"308":[40],"319":[40],"372":[40],"375":[40],"398":[40],"401":[40]},"packages/frontend/editor-ui/src/features/collaboration/projects/components/ProjectSharing.vue":{"68":[40,45,67,68,69,7,4,92,5,6,137],"76":[40,45,67,68,69,7,92,5,6,137],"79":[40,45,67,68,69,7,92,5,6,137],"88":[40,45,67,68,69,7,92,5,6,137],"98":[40,45,68,92,5,6,137],"104":[40,45,92,5,6,137],"110":[40,45,67,68,69,7,92,5,6,137],"117":[40,45,67,68,69,7,92,5,6,137],"121":[40,45,67,68,69,7,92,5,6,137],"123":[40,45,67,68,69,7,92,5,6,137],"137":[40,45,67,68,69,7,4,92,5,6,137],"153":[40,45,68,69,7,92,5,6],"159":[40,45,67,68,69,7,4,92,5,6,137],"163":[40,45,68,69,7,92,5,6],"169":[68,69,7,92,5,6],"183":[45],"200":[40,45,67,68,69,7,4,92,5,6,137],"201":[40,45,67,68,69,7,4,92,5,6,137],"216":[40,45,67,68,69,7,4,92,5,6,137],"233":[40,45,67,68,69,7,92,5,6,137],"241":[40,45,67,68,69,7,92,5,6,137],"244":[40,45,67,68,69,7,92,5,6,137],"248":[40,45,67,68,69,7,92,5,6,137],"272":[40,45,4,92,5,6,137],"273":[40,45,4,92,5,6,137],"295":[40,45,92,5,6],"312":[45]},"packages/frontend/editor-ui/src/features/collaboration/projects/components/ProjectSharingInfo.vue":{"14":[40,45,67,68,69,7,4,92,5,6,137],"25":[40,45,67,68,69,7,4,92,5,6,137],"31":[40,45,67,68,69,7,4,92,5,6,137]},"packages/frontend/editor-ui/src/features/credentials/components/CredentialEdit/CredentialConfig.vue":{"81":"b:IIgBgCBxgAAgEEAQAAAACQAEAAAA","116":"b:IIgBgCBxgAAgEEAQAAAACQAEAAAA","137":"b:IIgBgCBxgAAgEEAQAAAACQAEAAAA","140":[11,44,46,123,138],"145":"b:IIgBgCBxgAAgEEAQAAAACQAEAAAA","146":"b:IIgBgCBxgAAgEEAQAAAACQAEAAAA","149":"b:IIgBgCBxgAAgEEAQAAAACQAEAAAA","179":"b:IIgBgCBxgAAgEEAQAAAACQAEAAAA","184":[11,44,46,123,138],"192":"b:IIgBgCBxgAAgEEAQAAAACQAEAAAA","201":"b:IIgBgCBxgAAgEEAQAAAACQAEAAAA","211":"b:IIgBgCBxgAAgEEAQAAAACQAEAAAA","215":"b:IIgBgCBxgAAgEEAQAAAACQAEAAAA","217":"b:IIgBgCBxgAAgEEAQAAAACQAEAAAA","219":"b:IIgBgCBxgAAgEEAQAAAACQAEAAAA","230":[11],"234":"b:IIgBgCBxgAAgEEAQAAAACQAEAAAA","236":"b:IIABgCBxAAAgEEAQAAAACQAEAAAA","240":"b:IIgBgCBxgAAgEEAQAAAACQAEAAAA","244":"b:IIgBgCBxgAAgEEAQAAAACQAEAAAA","246":"b:IIgBgCBxgAAgEEAQAAAACQAEAAAA","251":"b:IIgBgCBxgAAgEEAQAAAACQAEAAAA","255":"b:IIgBgCBxAAAgEEAQAAAACQAEAAAA","259":"b:IIABgCBwAAAgEEAQAAAACQAEAAAA","272":[11,44],"276":[11],"294":[46],"299":"b:IIgBgCBxgAAgEEAQAAAACQAEAAAA","345":"b:IIgBgCBxAAAgEEAQAAAACQAEAAAA","347":"b:IIgBgCBxAAAgEEAQAAAACAAEAAAA","394":[11,44,46,123],"397":"b:IIgBgCAxgAAgEEAQAAAAAQAEAAAA","417":"b:IIgBgCBxgAAgEEAQAAAACQAEAAAA","552":[46,123,138],"560":"b:IIgBgCBxgAAgEAAQAAAACQAEAAAA","562":"b:IIgBgCBxgAAgEAAQAAAACAAEAAAA","564":"b:IIgBgCBxgAAgEAAQAAAACAAEAAAA"},"packages/frontend/editor-ui/src/features/credentials/components/CredentialEdit/CredentialEdit.vue":{"102":"b:IIgBgCBxgAAgEEAQAAAACQAEAAAA","104":[44,123,138],"109":[44,123,138],"159":"b:IIgBgCBxgAAgEEAQAAAACQAEAAAA","169":"b:IIgBgCBxgAAgEEAQAAAACQAEAAAA","174":"b:IIABgCBxAAAgEEAQAAAAAQAEAAAA","179":"b:IIgBgCBxgAAgEEAQAAAACQAEAAAA","188":"b:IIgBgCBwgAAgEEAQAAAACQAEAAAA","204":[11,15,16,55,76],"217":"b:IIgBgCBxgAAgEEAQAAAACQAEAAAA","234":"b:IIgBgCBxgAAgEEAQAAAACQAEAAAA","249":"b:IIgBgCBxgAAgEEAQAAAACQAEAAAA","254":"b:IIABgCBxAAAgEEAQAAAACQAEAAAA","259":"b:IIABgCAxAAAgEEAQAAAAAQAEAAAA","267":"b:IIABgCAxAAAgEAAQAAAAAQAEAAAA","270":"b:IIABgCAxAAAgEAAQAAAAAQAEAAAA","282":"b:IIABgCAxAAAgEAAQAAAAAQAEAAAA","290":"b:IIgBgCBxgAAgEEAQAAAACQAEAAAA","298":"b:IIgBgCBxgAAgEEAQAAAACQAEAAAA","309":"b:IIgBgCBxgAAgEEAQAAAACQAEAAAA","311":"b:AIgBgAAQgAAgEAAAAAAACQAAAAAA","316":[11,46],"320":"b:IIgBgCBxgAAgEEAQAAAACQAEAAAA","325":"b:IIgBgCBxgAAgEEAQAAAACQAEAAAA","331":"b:IIgBgCBxgAAgEEAQAAAACQAEAAAA","343":"b:IIgBgCBxgAAgEEAQAAAACQAEAAAA","350":"b:IIgBgCBxgAAgEEAQAAAACQAEAAAA","387":"b:IIgBgCBxgAAgEEAQAAAACQAEAAAA","393":"b:IIgBgCBxgAAgEEAQAAAACQAEAAAA","415":"b:IIgBgCBxgAAgEEAQAAAACQAEAAAA","425":"b:IIgBgCBxgAAgEEAQAAAACQAEAAAA","433":"b:IIgBgCBxgAAgEEAQAAAACQAEAAAA","440":[40,44,45,92,5],"444":"b:IIgBgCBxgAAgEEAQAAAACQAEAAAA","452":"b:IIgBgCBxgAAgEEAQAAAACQAEAAAA","463":"b:IIgBgCBxgAAgEEAQAAAACQAEAAAA","465":"b:IIgBgCBxgAAgEEAQAAAACQAEAAAA","484":"b:IIgBgCBxgAAgEEAQAAAACQAEAAAA","493":"b:IIgBgCBxgAAgEEAQAAAACQAEAAAA","564":"b:IIgBgCBxgAAgEEAQAAAACQAEAAAA","579":"b:IIABgCAxAAAgEEAQAAAACQAEAAAA","618":"b:IIgBgCBxgAAgEEAQAAAACQAEAAAA","642":"b:IIgBgCBxgAAgEEAQAAAACQAEAAAA","670":[40,44,45],"672":[40,44,45],"678":[40,44,45],"737":[40,45,92,5],"752":[92,5],"761":[40,45],"766":[11,44],"774":[11,44],"781":[11,44],"830":"b:IIABgCBwAAAgEEAQAAAACQAEAAAA","846":[15,16,31,44,69,76,120,138],"850":"b:IIgBgCBxgAAgEEAQAAAACQAEAAAA","866":[31,44,45,86,92,5,138],"872":"b:IIABgCBRAAAgEAAQAAAAAQAEAAAA","873":"b:IIABgCBRAAAgEAAQAAAAAQAEAAAA","888":[40,44,45],"913":"b:IIABgCARAAAgEAAQAAAAAQAEAAAA","926":"b:IIABgCBxAAAgEEAQAAAACQAEAAAA","927":"b:IIABgCBxAAAgEEAQAAAACQAEAAAA","932":"b:AIgBgAAQgAAgEAAAAAAACQAAAAAA","941":"b:IIABgCBxAAAgEEAQAAAACQAEAAAA","1016":"b:IIABgCBxAAAgEEAQAAAACQAEAAAA","1082":"b:IIABgCBxAAAgEEAQAAAAAQAEAAAA","1115":"b:IIABgCBwAAAgEEAQAAAACQAEAAAA","1138":"b:IIABgCBwAAAgEEAQAAAACQAEAAAA","1188":[40,44,45,92,5],"1236":[44],"1276":[46,123,138],"1353":[46],"1385":[46],"1389":[46],"1442":[11,44],"1499":[11,44],"1524":"b:IIgBgCBxgAAgEEAQAAAACQAEAAAA","1536":"b:IIgBgCBxgAAgEEAQAAAACQAEAAAA","1575":"b:IIgBgCBxgAAgEEAQAAAACQAEAAAA","1607":"b:IIgBgCBxgAAgEEAQAAAACQAEAAAA","1611":"b:IIgBgCBxgAAgEEAQAAAACQAEAAAA","1615":[40,45,92,5]},"packages/frontend/editor-ui/src/features/credentials/components/CredentialEdit/CredentialInputs.vue":{"21":"b:IIgBgCBxgAAgEEAQAAAACQAEAAAA","25":"b:IIgBgCBxgAAgEEAQAAAACQAEAAAA","29":"b:IIgBgCBxgAAgEEAQAAAACQAEAAAA","30":"b:IIgBgCBxgAAgEEAQAAAACQAEAAAA","39":"b:IIABgCBwAAAgEEAQAAAACQAEAAAA","41":"b:IIgBgCBxgAAgEEAQAAAACQAEAAAA","47":"b:IIgBgCBxgAAgEEAQAAAACQAEAAAA"},"packages/frontend/editor-ui/src/features/credentials/components/CredentialEdit/CredentialModeSelector.vue":{"27":"b:IIgBgCBxgAAgEEAQAAAACQAEAAAA","46":"b:IIgBgCBxgAAgEEAQAAAACQAEAAAA","47":"b:IIgBgCBxgAAgEEAQAAAACQAEAAAA","52":"b:AIgBgAAQgAAgEAAAAAAACQAAAAAA","53":"b:AIgBgAAQgAAgEAAAAAAACQAAAAAA","60":"b:IIgBgCBxgAAgEEAQAAAAAAAEAAAA","61":"b:IIgBgCBxgAAgEEAQAAAAAAAEAAAA","66":[11],"79":"b:IIgBgCBxgAAgEEAQAAAACQAEAAAA","90":"b:IIgBgCBxgAAgEEAQAAAACQAEAAAA","102":[11,31,44,69,120,123],"124":"b:IIgBgCBxgAAgEEAQAAAACQAEAAAA","146":[11,31,44,69,120,123],"168":"b:IIgBgCBxgAAgEEAQAAAACQAEAAAA","169":[11,31,44,69,120,123],"170":[11,31,44,69,120,123],"173":[11,31,44,69,120,123],"180":[11,31,44,69,120,123],"181":[11,31,44,69,120,123],"188":[11,44],"191":"b:IIgBgCBxgAAgEEAQAAAACQAEAAAA","198":[11,31,44,69,120,123],"208":[11,31,44,69,120,123],"210":[11,31,44,69,123]},"packages/frontend/editor-ui/src/features/credentials/components/CredentialEdit/CredentialSharing.ee.vue":{"38":[40,45,92,5],"61":[40,45,92,5],"69":[40,45,92,5],"70":[40,45,92,5],"82":[40,45,92,5],"86":[40,45,92,5],"90":[40,45,92,5],"96":[40,45,92,5],"102":[40,45,92,5],"103":[40,45,92,5],"116":[40,45,92,5],"122":[40,45,92,5],"128":[92,5],"139":[40,45,92,5],"168":[40,45,92,5],"198":[40,45]},"packages/frontend/editor-ui/src/features/credentials/components/CredentialPicker/CredentialPicker.vue":{"48":[38,40,74,138],"61":[38,40,74,138],"62":[38,40,138],"70":[38,40,74,138],"99":[38,40,74,138],"104":[38,40,74,138],"110":[40],"113":[138],"127":[40],"170":[138],"199":[38,40,138],"209":[38,40,74,138],"210":[38,40,74,138],"236":[38,40,138],"255":[38]},"packages/frontend/editor-ui/src/features/credentials/components/CredentialPicker/CredentialsDropdown.vue":{"39":[38,40,138],"48":[38,40],"52":[40],"86":[38,40,138],"91":[38,40,138],"92":[38,40,138],"97":[38,40,138]},"packages/frontend/editor-ui/src/features/credentials/composables/useCredentialOAuth.ts":{"41":"b:IKgB4CFz1gRgEUAwBAGgLyAEAAAA","59":"b:IKgB4CFz1gRgEUAwBAGgLyAEAAAA","72":"b:IIgBgCBxggAgEEAQAAAACQAEAAAA","82":"b:AKgA4AES1gRgEQAgBAGgLyAAAAAA","99":"b:AAgAoAAQEAAgAQAAAAAgLyAAAAAA","109":[11],"121":"b:AAgAoAAQEgAgAQAAAAAgLyAAAAAA","128":"b:AAgAoAAQEgAgAQAAAAAgLyAAAAAA","134":"b:AAgAoAAQEgAgAQAAAAAgLyAAAAAA","153":[11,49],"355":"b:ML4b4A0y1s7h+QMgz+3//ysCAAAA"},"packages/frontend/editor-ui/src/features/credentials/quickConnect/components/QuickConnectButton.vue":{"9":"b:IIgBgCBxggAgEEAQAAAACQAEAAAA","35":"b:IIgBgCAxggAgEEAQAAAAAQAEAAAA","44":"b:IIgBgCBxggAgEEAQAAAACQAEAAAA","49":"b:IIgBgCBxggAgEEAQAAAACQAEAAAA","64":"b:IIgBgCAxggAgEEAQAAAAAQAEAAAA"},"packages/frontend/editor-ui/src/features/credentials/quickConnect/composables/useQuickConnect.ts":{"33":"b:ML5b4A0y1s7h+QMgz+3//ysCAAAA","41":"b:MAgRoAgQ5AIhAAggxwFlPSIAAAAA","51":"b:AKgB4AES1gRgEQAgBAGgLyAAAAAA","64":"b:MAgRoAgQ5AIhAAggxwFlPSIAAAAA","71":"b:MJ5b4A0w1s7h+QMgz+3//ysCAAAA","117":"b:ML4b4C0z9s7h+Uswz+3//ysGAAAA"},"packages/frontend/editor-ui/src/features/integrations/externalSecrets.ee/externalSecrets.ee.store.ts":{"21":[86],"24":[86],"28":[86],"61":"b:ML5b4C1z1s7x+cMxz+3//ysGAAAA","67":"b:IIgBgCBxgAAgEEAQAAAACQAEAAAA","79":"b:ML5b4C1z1s7h+cMxz+3//ysGAAAA","93":[86],"94":[86],"98":[86],"101":[86],"102":[86],"142":"b:IIgBgCBxgAAgEEAQAAAACQAEAAAA","156":"b:IIgBgCBxgAAgEEAQAAAACQAEAAAA","182":"b:IIgBgCBxgAAgEEAQAAAACQAEAAAA","217":"b:IIgBgCBxgAAgEEAQAAAACQAEAAAA"},"packages/frontend/editor-ui/src/features/ndv/parameters/components/ExpressionEditModal.vue":{"38":"b:ML5b4C1z1s7h+cMxz+3//ysGAAAA","78":[114],"80":[114],"85":[114],"99":"b:ML5b4C1z1s7h+cMxz+3//ysGAAAA","100":[114],"136":[114],"141":[114],"156":"b:ML5b4C1z1s7h+cMxz+3//ysGAAAA","165":[114],"177":[114],"185":[114],"206":[114],"216":[114],"239":[114]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/ExpressionEditorModal/theme.ts":{"4":"b:ML5b4C1z1s7h+cMxz+3//ysGAAAA","33":[114],"39":"b:ML5b4C1z1s7h+cMxz+3//ysGAAAA"},"packages/frontend/editor-ui/src/features/ndv/parameters/components/ParameterInput.vue":{"146":"b:ML5b4C1z1s7h+cMxz+3//ysGAAAA","238":"b:ML5b4C1z1s7h+cMxz+3//ysGAAAA","244":[29,117,120],"248":"b:ML5b4C1z1s7h+cMxz+3//ysGAAAA","254":"b:ML5b4C1z1s7h+cMxz+3//ysGAAAA","258":"b:ML5b4C1z1s7h+cMxz+3//ysGAAAA","260":"b:ML5b4C1z1s7h+cMxz+3//ysGAAAA","264":"b:ML4b4C1z1s7h+cMxz+3//ysGAAAA","268":"b:IJAZgCVwAA4hEMARAAQiGQAEAAAA","282":[17,30,54,98,120,127],"298":[17,30,54,98,120,127],"302":[17,30,54,98,120,127],"310":"b:ML5b4C1z1s7h+cMxz+3//ysGAAAA","314":"b:ML5b4C1z1s7h+cMxz+3//ysGAAAA","321":"b:AIQCYAgAQAAAAAEAxwEggQAAAAAA","330":"b:MIgBgAAQFAAgEAAgAECgCSMAAAAA","334":"b:ML5b4C1z1s7h+cMxz+3//ysGAAAA","358":"b:ML5b4C1z1s7h+cMxz+3//ysGAAAA","372":"b:ML5b4C1z1s7h+cMxz+3//ysGAAAA","375":"b:AIQAIAgAAAAAAAEAxwAgAAAAAAAA","379":"b:AAQAIAgAAAAAAAEAxwAgAAAAAAAA","387":"b:AAQAIAgAAAAAAAEAxwAgAAAAAAAA","391":"b:ML5b4C1z1s7h+cMxz+3//ysGAAAA","465":"b:MIoBgAAQFoBgMUIgAUivHyMAAAAA","480":"b:ML5b4C1z1s7h+cMxz+3//ysGAAAA","513":"b:ML5b4C1z1s7h+cMxz+3//ysGAAAA","530":"b:ML5b4C1z1s7h+cMxz+3//ysGAAAA","570":"b:MJ5b4A0y1s7h+YMhz+3//ysCAAAA","601":[69,128,129],"620":"b:ML5b4C1z1s7h+cMxz+3//ysGAAAA","634":"b:ML5b4C1z1s7h+cMxz+3//ysGAAAA","641":"b:ML5b4C1z1s7h+cMxz+3//ysGAAAA","649":[41,44,75,119],"653":"b:ML5b4C1z1s7h+cMxz+3//ysGAAAA","680":"b:ML5b4C1z1s7h+cMxz+3//ysGAAAA","699":"b:AAQAIAgAAAAAAAEAxwAgAAAAAAAA","703":"b:ML5b4C1z1s7h+cMxz+3//ysGAAAA","707":"b:ML5b4C1z1s7h+cMxz+3//ysGAAAA","711":"b:AAQAIAgAAAAAAAEAxwAgAAAAAAAA","715":[104],"717":"b:IJAZgCVykA6hEMARiAQvHwAEAAAA","718":"b:AAAIAAEykAKBAIAAgAAHEwAAAAAA","720":[71,106,113],"721":"b:IJAZgCVwAA6hEMARCAQnGQAEAAAA","728":"b:ML5b4C1z1s7h+cMxz+3//ysGAAAA","740":[15,117],"742":"b:ML5b4C1z1s7h+cMxz+3//ysGAAAA","751":"b:ML5b4C1z1s7h+cMxz+3//ysGAAAA","755":[30,44,45],"769":"b:ML5b4C1z1s7h+cMxz+3//ysGAAAA","783":"b:ML5b4C1z1s7h+cMxz+3//ysGAAAA","791":"b:MJ5b4C1z1s7h+UMwz+3//ysGAAAA","799":[29,117,120,123],"851":[117],"856":[117],"861":[114],"865":[114],"895":[117],"907":[114],"922":"b:IJAZgCVykA6hEMARiAQvHwIEAAAA","930":"b:IJAZgCVykA6hEMARiAQvHwIEAAAA","991":"b:IJAZgCVwAA6hEMARAAQiGQAEAAAA","1014":"b:IJQZoC1ykA6hEMERxwUvHQMEAAAA","1101":"b:AAAAAAAAAAAAAEAAAAAPHQAAAAAA","1108":"b:IJAZgCVyEA6hEMARiAQvGQIEAAAA","1175":"b:IJAZgCVwAA6hEMARAAQiGQAEAAAA","1182":"b:AAAAAAAAAAAAAEAAAAAPHQIAAAAA","1262":"b:ML5b4C1z1s7h+cMxz+3//ysGAAAA","1296":[41,44,75,119],"1325":"b:IJob4CgzVkoh+UExz+3/fysGAAAA","1331":"b:ML5b4C1z1s7h+cMxz+3//ysGAAAA","1332":"b:ML5b4C1z1s7h+cMxz+3//ysGAAAA","1350":[117,120,123],"1356":"b:ML5b4C1z1s7h+cMxz+3//ysGAAAA","1357":"b:IJwZoC1xgA6hEMARxwQvHQMEAAAA","1367":[29,117,120],"1372":"b:AAAAAAAAAAAAAEAAAAAPHQIAAAAA","1382":"b:ML5b4C1z1s7h+cMxz+3//ysGAAAA","1385":[32,44],"1401":"b:ML5b4C1z1s7h+cMxz+3//ysGAAAA","1414":"b:ML5b4C1z1s7h+cMxz+3//ysGAAAA","1420":"b:AAAAAAAAAACAAIAAAAErHQAAAAAA","1543":[117],"1629":"b:AAQAIAgAAAAAAAEAxwAgAAAAAAAA","1634":[117],"1654":[104],"1699":[104],"1722":[15,117],"1745":[17,30,54,98,120,127],"1775":"b:IJAZgCVwAA4hEMARAAQiGQAEAAAA","1793":[12,87,113,117,120],"1798":"b:ML5b4C1z1s7h+cMxz+3//ysGAAAA","1909":[30,44,45],"1930":"b:ML5b4C1z1s7h+cMxz+3//ysGAAAA","1932":"b:ML5b4C1z1s7h+cMxz+3//isGAAAA","1937":"b:ML5b4C1z1s7h+cMxz+3//ysGAAAA","1969":[29,50,123],"1971":[29,50,123],"1975":[29,50,123]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/ParameterInputExpanded.vue":{"24":"b:IIgBgCBxgAAgEEAQAAAACQAEAAAA","61":"b:IIgBgCBxgAAgEEAQAAAACQAEAAAA","92":"b:IIgBgCBxgAAgEEAQAAAACQAEAAAA","114":"b:IIgBgCBxgAAgEEAQAAAACQAEAAAA","122":"b:IIgBgCBxgAAgEEAQAAAACQAEAAAA","129":"b:IIABgCBwAAAgEEAQAAAACQAEAAAA","133":"b:IIABgCBwAAAgEEAQAAAACQAEAAAA","142":[86],"146":"b:IIABgCBwAAAgEEAQAAAACQAEAAAA","169":[86],"171":"b:IIgBgCBxgAAgEEAQAAAACQAEAAAA","184":"b:IIgBgCBxgAAgEEAQAAAACQAEAAAA","194":"b:IIgBgCBxgAAgEEAQAAAACQAEAAAA"},"packages/frontend/editor-ui/src/features/ndv/parameters/components/ParameterInputWrapper.vue":{"50":"b:ML5b4C1z1s7h+cMxz+3//ysGAAAA","70":"b:ML5b4C1z1s7h+cMxz+3//ysGAAAA","74":"b:ML5b4C1z1s7h+cMxz+3//ysGAAAA","85":"b:MIgBgAAQFAAgEAAgAECgCSAAAAAA","91":"b:ML5b4C1z1s7h+cMxz+3//ysGAAAA","102":[72,86,112,113,114,121,123,124],"104":[121],"106":"b:ML5b4C1z1s7h+cMxz+3//ysGAAAA","111":"b:ML5b4C1z1s7h+cMxz+3//ysGAAAA","128":"b:ML5b4C1z1s7h+cMxz+3//ysGAAAA","132":"b:ML5b4C1z1s7h+cMxz+3//ysGAAAA","139":"b:IJAZgCVykA6hEMARiAQvHwIEAAAA","143":"b:IJAZgCVyEA6hEMARiAQvGQIEAAAA","151":"b:IJQZoC1ygA6hEMERxwUvHQMEAAAA","155":"b:IJAZgCVwAA6hEMARAAQiGQAEAAAA","160":[41,44,75,119],"161":[86],"168":"b:ML5b4C1z1s7h+cMxz+3//ysGAAAA","175":"b:ML5b4C1z1s7h+cMxz+3//ysGAAAA","206":"b:ML5b4C1z1s7h+cMxz+3//isGAAAA"},"packages/frontend/editor-ui/src/features/ndv/parameters/components/ParameterOptions.vue":{"40":"b:ML5b4C1z1s7h+cMxz+3//ysGAAAA","61":"b:ML4b4C1z1s7h+cMxz+3//ysGAAAA","62":"b:ML4b4C1z1s7h+cMxz+3//ysGAAAA","63":"b:MJob4CVx1s7h+cIwT+3//ysGAAAA","64":"b:ML4b4C1z1s7h+cMxz+3//ysGAAAA","67":"b:ML5b4C1z1s7h+cMxz+3//ysGAAAA","77":"b:ML5b4C1z1s7h+cMxz+3//ysGAAAA","96":"b:ML5b4C1z1s7h+cMxz+3//ysGAAAA","115":"b:MJob4CVx1s7h+cIwT+z//ysGAAAA","116":"b:ML4b4C1z1s7h+cMxz+3//ysGAAAA","120":"b:ML4b4C1z1s7h+cMxz+3//ysGAAAA","128":"b:ML4b4C1z1s7h+cMxz+3//ysGAAAA","173":[124],"174":"b:AAAAAAAAAAAAAEAAAAANHQIAAAAA","181":"b:ML5b4C1z1s7h+cMxz+3//ysGAAAA","189":[124],"215":[124]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/TextEdit.vue":{"10":"b:ML5b4C1z1s7h+cMxz+3//ysGAAAA","31":"b:ML5b4C1z1s7h+cMxz+3//ysGAAAA","41":"b:ML5b4C1z1s7h+cMxz+3//ysGAAAA","42":"b:IJwZoC1xgA4hEMARxwQiGQAEAAAA","48":"b:ML5b4C1z1s7h+cMxz+3//ysGAAAA","66":"b:ML5b4C1z1s7h+cMxz+3//ysGAAAA"},"packages/frontend/editor-ui/src/features/ndv/settings/composables/useNodeSettingsParameters.ts":{"56":"b:ML5b4C1z1s7h+cMxz+3//ysGAAAA","66":"b:MJQZoA0wgA6hAAEAx4WvHQMAAAAA","130":[120],"186":"b:ML5b4A0y1s7h+YMhz+3//ysCAAAA"},"packages/frontend/editor-ui/src/features/ndv/shared/composables/useBinaryDataAccessTooltip.ts":{"9":"b:ML5b4C1z1s7h+cMxz+3//ysGAAAA"},"packages/frontend/editor-ui/src/features/ndv/shared/ndv.utils.ts":{"41":"b:MJ5b4A0w1s7h+QMgz+3//ysCAAAA","57":"b:MJQZoA0wgA6hAAEAx4WvHQMAAAAA","139":"b:MJQZoA0wgA6hAAEAx4WvHQMAAAAA","268":"b:MJQZoA0wgA6hAAEAx4UvHQMAAAAA","274":"b:MJQZoA0wgA6hAAEAx4UvHQMAAAAA","296":[120,123],"297":[120,123],"300":[120],"314":"b:MJQZoA0wgA6hAAEAx4WvHQMAAAAA","335":"b:ML5b4C1z1s7h+cMxz+3//ysGAAAA","342":"b:ML5b4C1z1s7h+cMxz+3//ysGAAAA","346":"b:ML5b4C1z1s7h+cMxz+3//ysGAAAA","368":"b:MJQZoA0wgA6hAAEAx4WvHQMAAAAA","374":"b:AAAAAAAAAAAAAEAAAAAPHQIAAAAA","447":"b:MJ5b4A0y1s7h+YMhz+3//ysCAAAA","458":"b:MJ5b4A0y1s7h+QMgz+3//ysCAAAA","622":"b:MJ5b4A0w1s7h+QMgz+3//ysCAAAA","734":"b:MJ5b4A0y1s7h+QMgz+3//ysCAAAA"},"packages/frontend/editor-ui/src/features/workflows/canvas/experimental/composables/useIsInExperimentalNdv.ts":{"4":"b:ML5b4C1z1s7h+cMxz+3//ysGAAAA","8":"b:IAgAgCBxAAAgAEERCAAPHwAEAAAA"},"packages/@n8n/ai-utilities/src/index.ts":{"7":"b:AIEDAHAQAgAACAAAAECAAQAAAIAA","12":"b:AIEDAHAQAgAACAAAAECAAQAAAIAA","13":"b:AIEDAHAQAgAACAAAAECAAQAAAIAA","14":"b:AIEDAHAQAgAACAAAAECAAQAAAIAA","15":"b:AIEDAHAQAgAACAAAAECAAQAAAIAA","50":"b:AIEDAHAQAgAACAAAAECAAQAAAIAA","80":"b:AIEDAHAQAgAACAAAAECAAQAAAIAA","88":"b:AIEDAHAQAgAACAAAAECAAQAAAIAA","89":"b:AIEDAHAQAgAACAAAAECAAQAAAIAA","118":"b:AIEDAHAQAgAACAAAAECAAQAAAIAA","119":"b:AIEDAHAQAgAACAAAAECAAQAAAIAA","123":"b:AIEDAHAQAgAACAAAAECAAQAAAIAA"},"packages/@n8n/ai-utilities/src/utils/shared-fields.ts":{"37":"b:AIEDAHAQAgAACAAAAECAAQAAAIAA","46":"b:AIEDAHAQAgAACAAAAECAAQAAAIAA","110":"b:AIEDAHAQAgAACAAAAECAAQAAAIAA","115":"b:AIEDAHAQAgAACAAAAECAAQAAAIAA","120":"b:AIEDAHAQAgAACAAAAECAAQAAAIAA","125":"b:AIEDAHAQAgAACAAAAECAAQAAAIAA","132":"b:AIEDAHAQAgAACAAAAECAAQAAAIAA","158":"b:AIEDAHAQAgAACAAAAECAAQAAAIAA","164":"b:AIEDAHAQAgAACAAAAECAAQAAAIAA"},"packages/@n8n/api-types/src/dto/index.ts":{"1":"b:gNsWiA80ErXiDAABGFAAAYjUEAAA","3":"b:gNsWiA80ErXiDAABGFAAAYjUEAAA","4":"b:gNsWiA80ErXiDAABGFAAAYjUEAAA","12":"b:gNsWiA80ErXiDAABGFAAAYjUEAAA","16":"b:gNsWiA80ErXiDAABGFAAAYjUEAAA","36":"b:gNsWiA80ErXiDAABGFAAAYjUEAAA","37":"b:gNsWiA80ErXiDAABGFAAAYjUEAAA","40":"b:gNsWiA80ErXiDAABGFAAAYjUEAAA","42":"b:gNsWiA80ErXiDAABGFAAAYjUEAAA","49":"b:gNsWiA80ErXiDAABGFAAAYjUEAAA","51":"b:gNsWiA80ErXiDAABGFAAAYjUEAAA","53":"b:gNsWiA80ErXiDAABGFAAAYjUEAAA","57":"b:gNsWiA80ErXiDAABGFAAAYjUEAAA","59":"b:gNsWiA80ErXiDAABGFAAAYjUEAAA","62":"b:gNsWiA80ErXiDAABGFAAAYjUEAAA","64":"b:gNsWiA80ErXiDAABGFAAAYjUEAAA","70":"b:gNsWiA80ErXiDAABGFAAAYjUEAAA","71":"b:gNsWiA80ErXiDAABGFAAAYjUEAAA","81":"b:gNsWiA80ErXiDAABGFAAAYjUEAAA","84":"b:gNsWiA80ErXiDAABGFAAAYjUEAAA","90":"b:gNsWiA80ErXiDAABGFAAAYjUEAAA","99":"b:gNsWiA80ErXiDAABGFAAAYjUEAAA","100":"b:gNsWiA80ErXiDAABGFAAAYjUEAAA","102":"b:gNsWiA80ErXiDAABGFAAAYjUEAAA","110":"b:gNsWiA80ErXiDAABGFAAAYjUEAAA","111":"b:gNsWiA80ErXiDAABGFAAAYjUEAAA","112":"b:gNsWiA80ErXiDAABGFAAAYjUEAAA","113":"b:gNsWiA80ErXiDAABGFAAAYjUEAAA","114":"b:gNsWiA80ErXiDAABGFAAAYjUEAAA","116":"b:gNsWiA80ErXiDAABGFAAAYjUEAAA","118":"b:gNsWiA80ErXiDAABGFAAAYjUEAAA","134":"b:gNsWiA80ErXiDAABGFAAAYjUEAAA","140":"b:gNsWiA80ErXiDAABGFAAAYjUEAAA","147":"b:gNsWiA80ErXiDAABGFAAAYjUEAAA","148":"b:gNsWiA80ErXiDAABGFAAAYjUEAAA","157":"b:gNsWiA80ErXiDAABGFAAAYjUEAAA","158":"b:gNsWiA80ErXiDAABGFAAAYjUEAAA","182":"b:gNsWiA80ErXiDAABGFAAAYjUEAAA","187":"b:gNsWiA80ErXiDAABGFAAAYjUEAAA","189":"b:gNsWiA80ErXiDAABGFAAAYjUEAAA","199":"b:gNsWiA80ErXiDAABGFAAAYjUEAAA","202":"b:gNsWiA80ErXiDAABGFAAAYjUEAAA","203":"b:gNsWiA80ErXiDAABGFAAAYjUEAAA","209":"b:gNsWiA80ErXiDAABGFAAAYjUEAAA","211":"b:gNsWiA80ErXiDAABGFAAAYjUEAAA","237":"b:gNsWiA80ErXiDAABGFAAAYjUEAAA","240":"b:gNsWiA80ErXiDAABGFAAAYjUEAAA","241":"b:gNsWiA80ErXiDAABGFAAAYjUEAAA","243":"b:gNsWiA80ErXiDAABGFAAAYjUEAAA","244":"b:gNsWiA80ErXiDAABGFAAAYjUEAAA","253":"b:gNsWiA80ErXiDAABGFAAAYjUEAAA","254":"b:gNsWiA80ErXiDAABGFAAAYjUEAAA"},"packages/@n8n/api-types/src/dto/user/users-list-filter.dto.ts":{"51":"b:ANsWKQ98ApHwBHQEAFAAAYgEAAAA"},"packages/@n8n/api-types/src/dto/workflows/base-workflow.dto.ts":{"25":"b:ANsegA80EpPyBAAACFAAQcj0FCAA","30":"b:ANsegA80EpPyBAAACFAAQcj0FCAA","41":"b:ANsegA80EpPyBAAACFAAQcj0FCAA","53":"b:ANsegA80EpPyBAAACFAAQcj0FCAA","54":"b:ANsegA80EpPyBAAACFAAQcj0FCAA","68":"b:ANsegA80EpPyBAAACFAAQcj0FCAA","80":"b:ANsegA80EpPyBAAACFAAQcj0FCAA","89":"b:ANsegA80EpPyBAAACFAAQcj0FCAA","131":"b:ANsegA80EpPyBAAACFAAQcj0FCAA","134":"b:ANsegA80EpPyBAAACFAAQcj0FCAA"},"packages/@n8n/api-types/src/index.ts":{"90":"b:/NsWrX/+E5XwDHwEClACEYj0VDcA","110":"b:/NsWrX/+E5XwDHwEClACEYj0VDcA","118":"b:/NsWrX/+E5XwDHwEClACEYj0VDcA","238":"b:/NsWrX/+E5XwDHwEClACEYj0VDcA","472":"b:/NsWrX/+E5XwDHwEClACEYj0VDcA"},"packages/@n8n/config/src/index.ts":{"54":"b:ANACAHwwAoQAAACAAESAAQAAAAQA","56":"b:ANACAHwwAoQAAACAAESAAQAAAAQA","57":"b:ANACAHwwAoQAAACAAESAAQAAAAQA","59":"b:ANACAHwwAoQAAACAAESAAQAAAAQA","60":"b:ANACAHwwAoQAAACAAESAAQAAAAQA","65":"b:ANACAHwwAoQAAACAAESAAQAAAAQA","67":"b:ANACAHwwAoQAAACAAESAAQAAAAQA","75":"b:ANACAHwwAoQAAACAAESAAQAAAAQA","77":"b:ANACAHwwAoQAAACAAESAAQAAAAQA","78":"b:ANACAHwwAoQAAACAAESAAQAAAAQA","79":"b:ANACAHwwAoQAAACAAESAAQAAAAQA","83":"b:ANACAHwwAoQAAACAAESAAQAAAAQA","84":"b:ANACAHwwAoQAAACAAESAAQAAAAQA","94":"b:ANACAHwwAoQAAACAAESAAQAAAAQA"},"packages/@n8n/db/src/entities/user.ts":{"60":"b:ANsWiA8wEpHgBAAAClAAAYgEAAAA","84":"b:ANsWiA8wEpHgBAAAClAAAYgEAAAA","115":"b:ANsWiA8wEpHgBAAAClAAAYgEAAAA","117":"b:ANsWiA8wEpHgBAAAClAAAYgEAAAA","124":"b:ANsWiA8wEpHgBAAAClAAAYgEAAAA","129":"b:ANsWiA8wEpHgBAAAClAAAYgEAAAA","139":"b:ANsWiA8wEpHgBAAAClAAAYgEAAAA"},"packages/@n8n/db/src/repositories/index.ts":{"3":"b:ANsGgA80EpHwBAAACFAAAYj0FgAA","6":"b:ANsGgA80EpHwBAAACFAAAYj0FgAA","7":"b:ANsGgA80EpHwBAAACFAAAYj0FgAA","8":"b:ANsGgA80EpHwBAAACFAAAYj0FgAA","21":"b:ANsGgA80EpHwBAAACFAAAYj0FgAA","23":"b:ANsGgA80EpHwBAAACFAAAYj0FgAA","30":"b:ANsGgA80EpHwBAAACFAAAYj0FgAA","32":"b:ANsGgA80EpHwBAAACFAAAYj0FgAA","36":"b:ANsGgA80EpHwBAAACFAAAYj0FgAA","40":"b:ANsGgA80EpHwBAAACFAAAYj0FgAA","42":"b:ANsGgA80EpHwBAAACFAAAYj0FgAA","45":"b:ANsGgA80EpHwBAAACFAAAYj0FgAA","46":"b:ANsGgA80EpHwBAAACFAAAYj0FgAA","48":"b:ANsGgA80EpHwBAAACFAAAYj0FgAA","50":"b:ANsGgA80EpHwBAAACFAAAYj0FgAA","51":"b:ANsGgA80EpHwBAAACFAAAYj0FgAA","58":"b:ANsGgA80EpHwBAAACFAAAYj0FgAA","59":"b:ANsGgA80EpHwBAAACFAAAYj0FgAA"},"packages/@n8n/db/src/repositories/shared-workflow.repository.ts":{"21":"b:5Nuu7W80EpG2BBQUDF4gGZj2Fi0A","25":"b:5Nuu7W80EpG2BBQUDF4gGZj2Fi0A","32":"b:5Nuu7W80EpG2BBQUDF4gGZj2Fi0A","35":"b:5Nuu7W80EpG2BBQUDF4gGZj2Fi0A","45":"b:5Nuu7W80EpG2BBQUDF4gGZj2Fi0A","66":"b:5Nuu7W80EpG2BBQUDF4gGZj2Fi0A","76":"b:5Nuu7W80EpG2BBQUDF4gGZj2Fi0A","82":"b:5Nuu7W80EpG2BBQUDF4gGZj2Fi0A","94":"b:5Nuu7W80EpG2BBQUDF4gGZj2Fi0A","106":"b:5Nuu7W80EpG2BBQUDF4gGZj2Fi0A","118":"b:5Nuu7W80EpG2BBQUDF4gGZj2Fi0A","121":"b:5Nuu7W80EpG2BBQUDF4gGZj2Fi0A","129":"b:5Nuu7W80EpG2BBQUDF4gGZj2Fi0A","138":"b:5Nuu7W80EpG2BBQUDF4gGZj2Fi0A","147":"b:5Nuu7W80EpG2BBQUDF4gGZj2Fi0A","156":"b:5Nuu7W80EpG2BBQUDF4gGZj2Fi0A","161":"b:5Nuu7W80EpG2BBQUDF4gGZj2Fi0A","174":"b:5Nuu7W80EpG2BBQUDF4gGZj2Fi0A","212":"b:5Nuu7W80EpG2BBQUDF4gGZj2Fi0A"},"packages/@n8n/db/src/repositories/workflow-dependency.repository.ts":{"15":"b:ANsGgA80EpHwBAAACFAAAZj2FgAA","21":"b:ANsGgA80EpHwBAAACFAAAZj2FgAA","40":"b:ANsGgA80EpHwBAAACFAAAZj2FgAA","53":"b:ANsGgA80EpHwBAAACFAAAZj2FgAA","57":"b:ANsGgA80EpHwBAAACFAAAZj2FgAA","62":"b:ANsGgA80EpHwBAAACFAAAZj2FgAA","95":"b:ANsGgA80EpHwBAAACFAAAZj2FgAA","120":"b:ANsGgA80EpHwBAAACFAAAZj2FgAA","121":"b:ANsGgA80EpHwBAAACFAAAZj2FgAA","132":"b:ANsGgA80EpHwBAAACFAAAZj2FgAA","158":"b:ANsGgA80EpHwBAAACFAAAZj2FgAA"},"packages/@n8n/db/src/repositories/workflow.repository.ts":{"58":"b:6Nu+/X+8VrX+DBwkClaCEbv20C0B","68":"b:6Nu+/X+8VrX+DBwkClaCEbv20C0B","78":"b:6Nu+/X+8VrX+DBwkClaCEbv20C0B","84":"b:6Nu+/X+8VrX+DBwkClaCEbv20C0B","87":"b:6Nu+/X+8VrX+DBwkClaCEbv20C0B","94":"b:6Nu+/X+8VrX+DBwkClaCEbv20C0B","97":"b:6Nu+/X+8VrX+DBwkClaCEbv20C0B","103":"b:6Nu+/X+8VrX+DBwkClaCEbv20C0B","113":"b:6Nu+/X+8VrX+DBwkClaCEbv20C0B","128":"b:6Nu+/X+8VrX+DBwkClaCEbv20C0B","139":"b:6Nu+/X+8VrX+DBwkClaCEbv20C0B","145":"b:6Nu+/X+8VrX+DBwkClaCEbv20C0B","148":"b:6Nu+/X+8VrX+DBwkClaCEbv20C0B","164":"b:6Nu+/X+8VrX+DBwkClaCEbv20C0B","173":"b:6Nu+/X+8VrX+DBwkClaCEbv20C0B","180":"b:6Nu+/X+8VrX+DBwkClaCEbv20C0B","189":"b:6Nu+/X+8VrX+DBwkClaCEbv20C0B","196":"b:6Nu+/X+8VrX+DBwkClaCEbv20C0B","210":"b:6Nu+/X+8VrX+DBwkClaCEbv20C0B","217":"b:6Nu+/X+8VrX+DBwkClaCEbv20C0B","223":"b:6Nu+/X+8VrX+DBwkClaCEbv20C0B","229":"b:6Nu+/X+8VrX+DBwkClaCEbv20C0B","239":"b:6Nu+/X+8VrX+DBwkClaCEbv20C0B","328":"b:6Nu+/X+8VrX+DBwkClaCEbv20C0B","352":"b:6Nu+/X+8VrX+DBwkClaCEbv20C0B","374":"b:6Nu+/X+8VrX+DBwkClaCEbv20C0B","400":"b:6Nu+/X+8VrX+DBwkClaCEbv20C0B","411":"b:6Nu+/X+8VrX+DBwkClaCEbv20C0B","412":"b:6Nu+/X+8VrX+DBwkClaCEbv20C0B","415":"b:6Nu+/X+8VrX+DBwkClaCEbv20C0B","437":"b:6Nu+/X+8VrX+DBwkClaCEbv20C0B","481":"b:6Nu+/X+8VrX+DBwkClaCEbv20C0B","528":"b:6Nu+/X+8VrX+DBwkClaCEbv20C0B","556":"b:6Nu+/X+8VrX+DBwkClaCEbv20C0B","584":"b:6Nu+/X+8VrX+DBwkClaCEbv20C0B","661":"b:6Nu+/X+8VrX+DBwkClaCEbv20C0B","672":"b:6Nu+/X+8VrX+DBwkClaCEbv20C0B","677":"b:6Nu+/X+8VrX+DBwkClaCEbv20C0B","678":"b:6Nu+/X+8VrX+DBwkClaCEbv20C0B","681":"b:6Nu+/X+8VrX+DBwkClaCEbv20C0B","683":"b:6Nu+/X+8VrX+DBwkClaCEbv20C0B","684":"b:6Nu+/X+8VrX+DBwkClaCEbv20C0B","687":"b:6Nu+/X+8VrX+DBwkClaCEbv20C0B","702":"b:6Nu+/X+8VrX+DBwkClaCEbv20C0B","709":"b:6Nu+/X+8VrX+DBwkClaCEbv20C0B","710":"b:6Nu+/X+8VrX+DBwkClaCEbv20C0B","712":"b:6Nu+/X+8VrX+DBwkClaCEbv20C0B","721":"b:6Nu+/X+8VrX+DBwkClaCEbv20C0B","735":"b:6Nu+/X+8VrX+DBwkClaCEbv20C0B","754":"b:6Nu+/X+8VrX+DBwkClaCEbv20C0B","779":"b:6Nu+/X+8VrX+DBwkClaCEbv20C0B","835":"b:6Nu+/X+8VrX+DBwkClaCEbv20C0B","851":"b:6Nu+/X+8VrX+DBwkClaCEbv20C0B","864":"b:6Nu+/X+8VrX+DBwkClaCEbv20C0B","874":"b:6Nu+/X+8VrX+DBwkClaCEbv20C0B","888":"b:6Nu+/X+8VrX+DBwkClaCEbv20C0B","905":"b:6Nu+/X+8VrX+DBwkClaCEbv20C0B","917":"b:6Nu+/X+8VrX+DBwkClaCEbv20C0B","925":"b:6Nu+/X+8VrX+DBwkClaCEbv20C0B","948":"b:6Nu+/X+8VrX+DBwkClaCEbv20C0B","956":"b:6Nu+/X+8VrX+DBwkClaCEbv20C0B","962":"b:6Nu+/X+8VrX+DBwkClaCEbv20C0B","973":"b:6Nu+/X+8VrX+DBwkClaCEbv20C0B","979":"b:6Nu+/X+8VrX+DBwkClaCEbv20C0B","984":"b:6Nu+/X+8VrX+DBwkClaCEbv20C0B","995":"b:6Nu+/X+8VrX+DBwkClaCEbv20C0B","1007":"b:6Nu+/X+8VrX+DBwkClaCEbv20C0B","1028":"b:6Nu+/X+8VrX+DBwkClaCEbv20C0B","1041":"b:6Nu+/X+8VrX+DBwkClaCEbv20C0B","1050":"b:6Nu+/X+8VrX+DBwkClaCEbv20C0B","1071":"b:6Nu+/X+8VrX+DBwkClaCEbv20C0B","1082":"b:6Nu+/X+8VrX+DBwkClaCEbv20C0B","1098":"b:6Nu+/X+8VrX+DBwkClaCEbv20C0B","1100":"b:6Nu+/X+8VrX+DBwkClaCEbv20C0B","1123":"b:6Nu+/X+8VrX+DBwkClaCEbv20C0B","1150":"b:6Nu+/X+8VrX+DBwkClaCEbv20C0B","1154":"b:6Nu+/X+8VrX+DBwkClaCEbv20C0B","1164":"b:6Nu+/X+8VrX+DBwkClaCEbv20C0B","1196":"b:6Nu+/X+8VrX+DBwkClaCEbv20C0B","1204":"b:6Nu+/X+8VrX+DBwkClaCEbv20C0B","1210":"b:6Nu+/X+8VrX+DBwkClaCEbv20C0B","1220":"b:6Nu+/X+8VrX+DBwkClaCEbv20C0B","1225":"b:6Nu+/X+8VrX+DBwkClaCEbv20C0B","1241":"b:6Nu+/X+8VrX+DBwkClaCEbv20C0B","1250":"b:6Nu+/X+8VrX+DBwkClaCEbv20C0B","1257":"b:6Nu+/X+8VrX+DBwkClaCEbv20C0B","1264":"b:6Nu+/X+8VrX+DBwkClaCEbv20C0B","1271":"b:6Nu+/X+8VrX+DBwkClaCEbv20C0B","1281":"b:6Nu+/X+8VrX+DBwkClaCEbv20C0B","1296":"b:6Nu+/X+8VrX+DBwkClaCEbv20C0B","1330":"b:6Nu+/X+8VrX+DBwkClaCEbv20C0B","1337":"b:6Nu+/X+8VrX+DBwkClaCEbv20C0B","1341":"b:6Nu+/X+8VrX+DBwkClaCEbv20C0B","1356":"b:6Nu+/X+8VrX+DBwkClaCEbv20C0B","1363":"b:6Nu+/X+8VrX+DBwkClaCEbv20C0B","1399":"b:6Nu+/X+8VrX+DBwkClaCEbv20C0B","1415":"b:6Nu+/X+8VrX+DBwkClaCEbv20C0B","1451":"b:6Nu+/X+8VrX+DBwkClaCEbv20C0B","1466":"b:6Nu+/X+8VrX+DBwkClaCEbv20C0B","1502":"b:6Nu+/X+8VrX+DBwkClaCEbv20C0B"},"packages/@n8n/db/src/utils/transformers.ts":{"7":"b:ANsegH80EpXwDAAACFACEYj0Fi8B","8":"b:ANsegH80EpXwDAAACFACEYj0Fi8B","15":"b:ANsegH80EpXwDAAACFACEYj0Fi8B","16":"b:ANsegH80EpXwDAAACFACEYj0Fi8B","23":"b:ANsegH80EpXwDAAACFACEYj0Fi8B","24":"b:ANsegH80EpXwDAAACFACEYj0Fi8B","32":"b:ANsegH80EpXwDAAACFACEYj0Fi8B","34":"b:ANsegH80EpXwDAAACFACEYj0Fi8B","44":"b:ANsegH80EpXwDAAACFACEYj0Fi8B","45":"b:ANsegH80EpXwDAAACFACEYj0Fi8B"},"packages/@n8n/nodes-langchain/nodes/agents/Agent/Agent.node.ts":{"9":[15,36,37,38,44,49,75,110,119]},"packages/@n8n/nodes-langchain/nodes/agents/Agent/V1/AgentV1.node.ts":{"37":[15,36,37,38,44,49,75,110,119],"53":[15,36,37,38,44,49,75,110,119],"63":[15,36,37,38,44,49,75,110,119],"221":[15,36,37,38,44,49,75,110,119],"276":[15,36,37,38,44,49,75,110,119],"361":[15,36,37,38,44,49,75,110,119],"470":[15,36,37,38,44,49,75,110,119]},"packages/@n8n/nodes-langchain/nodes/agents/Agent/V2/AgentV2.node.ts":{"24":[15,36,37,38,44,49,75,110,119],"141":[15,36,37,38,44,49,75,110,119]},"packages/@n8n/nodes-langchain/nodes/agents/Agent/V3/AgentV3.node.ts":{"28":[15,36,37,38,44,49,75,110,119],"151":[15,36,37,38,44,49,75,110,119]},"packages/@n8n/nodes-langchain/nodes/agents/Agent/agents/ConversationalAgent/execute.ts":{"16":[15,36,37,38,44,49,75,110,119]},"packages/@n8n/nodes-langchain/nodes/agents/Agent/agents/OpenAiFunctionsAgent/execute.ts":{"15":[15,36,37,38,44,49,75,110,119]},"packages/@n8n/nodes-langchain/nodes/agents/Agent/agents/PlanAndExecuteAgent/execute.ts":{"18":[15,36,37,38,44,49,75,110,119]},"packages/@n8n/nodes-langchain/nodes/agents/Agent/agents/ReActAgent/execute.ts":{"21":[15,36,37,38,44,49,75,110,119]},"packages/@n8n/nodes-langchain/nodes/agents/Agent/agents/SqlAgent/execute.ts":{"25":[15,36,37,38,44,49,75,110,119],"28":[15,36,37,38,44,49,75,110,119],"29":[15,36,37,38,44,49,75,110,119],"43":[15,36,37,38,44,49,75,110,119],"55":[15,36,37,38,44,49,75,110,119],"144":[15,36,37,38,44,49,75,110,119],"150":[15,36,37,38,44,49,75,110,119]},"packages/@n8n/nodes-langchain/nodes/agents/Agent/agents/SqlAgent/other/handlers/mysql.ts":{"4":[15,36,37,38,44,49,75,110,119]},"packages/@n8n/nodes-langchain/nodes/agents/Agent/agents/SqlAgent/other/handlers/postgres.ts":{"6":[15,36,37,38,44,49,75,110,119]},"packages/@n8n/nodes-langchain/nodes/agents/Agent/agents/SqlAgent/other/handlers/sqlite.ts":{"8":[15,36,37,38,44,49,75,110,119],"38":[15,36,37,38,44,49,75,110,119]},"packages/@n8n/nodes-langchain/nodes/agents/Agent/agents/ToolsAgent/V1/execute.ts":{"36":[15,36,37,38,44,49,75,110,119]},"packages/@n8n/nodes-langchain/nodes/agents/Agent/agents/ToolsAgent/V2/description.ts":{"15":[15,36,37,38,44,49,75,110,119]},"packages/@n8n/nodes-langchain/nodes/agents/Agent/agents/ToolsAgent/V2/execute.ts":{"44":[15,36,37,38,44,49,75,110,119],"92":[15,36,37,38,44,49,75,110,119],"97":[15,36,37,38,44,49,75,110,119],"102":[15,36,37,38,44,49,75,110,119],"132":[15,36,37,38,44,49,75,110,119],"200":[15,36,37,38,44,49,75,110,119],"216":[15,36,37,38,44,49,75,110,119],"240":[15,36,37,38,44,49,75,110,119],"297":[15,36,37,38,44,49,75,110,119],"404":[15,36,37,38,44,49,75,110,119]},"packages/@n8n/nodes-langchain/nodes/agents/Agent/agents/ToolsAgent/V3/execute.ts":{"29":[15,36,37,38,44,49,75,110,119],"54":[15,36,37,38,44,49,75,110,119],"134":[15,36,37,38,44,49,75,110,119]},"packages/@n8n/nodes-langchain/nodes/agents/Agent/agents/ToolsAgent/V3/helpers/buildExecutionContext.ts":{"29":[15,36,37,38,44,49,75,110,119]},"packages/@n8n/nodes-langchain/nodes/agents/Agent/agents/ToolsAgent/V3/helpers/checkMaxIterations.ts":{"27":[15,36,37,38,44,49,75,110,119]},"packages/@n8n/nodes-langchain/nodes/agents/Agent/agents/ToolsAgent/V3/helpers/createAgentSequence.ts":{"25":[15,36,37,38,44,49,75,110,119],"66":[15,36,37,38,44,49,75,110,119]},"packages/@n8n/nodes-langchain/nodes/agents/Agent/agents/ToolsAgent/V3/helpers/executeBatch.ts":{"40":[15,36,37,38,44,49,75,110,119],"78":[15,36,37,38,44,49,75,110,119],"107":[15,36,37,38,44,49,75,110,119]},"packages/@n8n/nodes-langchain/nodes/agents/Agent/agents/ToolsAgent/V3/helpers/finalizeResult.ts":{"21":[15,36,37,38,44,49,75,110,119]},"packages/@n8n/nodes-langchain/nodes/agents/Agent/agents/ToolsAgent/V3/helpers/index.ts":{"11":[15,36,37,38,44,49,75,110,119]},"packages/@n8n/nodes-langchain/nodes/agents/Agent/agents/ToolsAgent/V3/helpers/prepareItemContext.ts":{"40":[15,36,37,38,44,49,75,110,119]},"packages/@n8n/nodes-langchain/nodes/agents/Agent/agents/ToolsAgent/V3/helpers/resolveSubAgentRequest.ts":{"25":[15,36,37,38,44,49,75,110,119],"40":[15,36,37,38,44,49,75,110,119],"49":[15,36,37,38,44,49,75,110,119]},"packages/@n8n/nodes-langchain/nodes/agents/Agent/agents/ToolsAgent/V3/helpers/runAgent.ts":{"39":[15,36,37,38,44,49,75,110,119]},"packages/@n8n/nodes-langchain/nodes/agents/Agent/agents/ToolsAgent/common.ts":{"25":[15,36,37,38,44,49,75,110,119],"38":[15,36,37,38,44,49,75,110,119],"49":[15,36,37,38,44,49,75,110,119],"64":[15,36,37,38,44,49,75,110,119],"72":[15,36,37,38,44,49,75,110,119],"73":[15,36,37,38,44,49,75,110,119],"144":[15,36,37,38,44,49,75,110,119],"149":[15,36,37,38,44,49,75,110,119],"152":[15,36,37,38,44,49,75,110,119],"154":[15,36,37,38,44,49,75,110,119],"199":[15,36,37,38,44,49,75,110,119],"219":[15,36,37,38,44,49,75,110,119],"220":[15,36,37,38,44,49,75,110,119],"228":[15,36,37,38,44,49,75,110,119],"229":[15,36,37,38,44,49,75,110,119],"255":[15,36,37,38,44,49,75,110,119],"275":[15,36,37,38,44,49,75,110,119],"276":[15,36,37,38,44,49,75,110,119],"279":[15,36,37,38,44,49,75,110,119],"342":[15,36,37,38,44,49,75,110,119],"376":[15,36,37,38,44,49,75,110,119],"392":[15,36,37,38,44,49,75,110,119],"407":[15,36,37,38,44,49,75,110,119],"422":[15,36,37,38,44,49,75,110,119],"469":[15,36,37,38,44,49,75,110,119]},"packages/@n8n/nodes-langchain/nodes/agents/Agent/agents/utils.ts":{"13":[15,36,37,38,44,49,75,110,119],"19":[15,36,37,38,44,49,75,110,119],"36":[15,36,37,38,44,49,75,110,119],"42":[15,36,37,38,44,49,75,110,119],"45":[15,36,37,38,44,49,75,110,119]},"packages/@n8n/nodes-langchain/nodes/agents/Agent/utils.ts":{"11":[15,36,37,38,44,49,75,110,119],"23":[15,36,37,38,44,49,75,110,119],"26":[15,36,37,38,44,49,75,110,119],"86":[15,36,37,38,44,49,75,110,119],"89":[15,36,37,38,44,49,75,110,119]},"packages/@n8n/nodes-langchain/nodes/trigger/ChatTrigger/ChatTrigger.node.ts":{"35":"b:AMACAHAQAgAAAACAAECAAAAAAAAA","229":"b:AMACAHAQAgAAAACAAECAAAAAAAAA","750":"b:AMACAHAQAgAAAACAAECAAAAAAAAA","813":"b:AMACAHAQAgAAAACAAECAAAAAAAAA","931":"b:AMACAHAQAgAAAACAAECAAAAAAAAA","932":"b:AMACAHAQAgAAAACAAECAAAAAAAAA"},"packages/@n8n/nodes-langchain/nodes/trigger/ChatTrigger/GenericFunctions.ts":{"7":"b:AMACAHAQAgAAAACAAECAAAAAAAAA","41":"b:AMACAHAQAgAAAACAAECAAAAAAAAA"},"packages/@n8n/nodes-langchain/nodes/trigger/ChatTrigger/error.ts":{"4":"b:AMACAHAQAgAAAACAAECAAAAAAAAA"},"packages/@n8n/nodes-langchain/nodes/trigger/ChatTrigger/templates.ts":{"5":"b:AMACAHAQAgAAAACAAECAAAAAAAAA","18":"b:AMACAHAQAgAAAACAAECAAAAAAAAA","23":"b:AMACAHAQAgAAAACAAECAAAAAAAAA","24":"b:AMACAHAQAgAAAACAAECAAAAAAAAA","39":"b:AMACAHAQAgAAAACAAECAAAAAAAAA","40":"b:AMACAHAQAgAAAACAAECAAAAAAAAA","43":"b:AMACAHAQAgAAAACAAECAAAAAAAAA","52":"b:AMACAHAQAgAAAACAAECAAAAAAAAA","59":"b:AMACAHAQAgAAAACAAECAAAAAAAAA"},"packages/@n8n/nodes-langchain/nodes/trigger/ChatTrigger/types.ts":{"8":"b:AMACAHAQAgAAAACAAECAAAAAAAAA","12":"b:AMACAHAQAgAAAACAAECAAAAAAAAA"},"packages/@n8n/nodes-langchain/utils/N8nTool.ts":{"11":"b:AIACAHAQAgAACAAgAECAAQAAAIAA","25":"b:AIACAHAQAgAACAAgAECAAQAAAIAA","28":"b:AIACAHAQAgAACAAgAECAAQAAAIAA","33":"b:AIACAHAQAgAACAAgAECAAQAAAIAA","50":"b:AIACAHAQAgAACAAgAECAAQAAAIAA","57":"b:AIACAHAQAgAACAAgAECAAQAAAIAA","62":"b:AIACAHAQAgAACAAgAECAAQAAAIAA"},"packages/@n8n/nodes-langchain/utils/agent-execution/buildResponseMetadata.ts":{"17":[15,36,37,38,44,49,75,110,119]},"packages/@n8n/nodes-langchain/utils/agent-execution/buildSteps.ts":{"34":[15,36,37,38,44,49,75,110,119],"84":[15,36,37,38,44,49,75,110,119],"132":[15,36,37,38,44,49,75,110,119],"156":[15,36,37,38,44,49,75,110,119],"193":[15,36,37,38,44,49,75,110,119],"206":[15,36,37,38,44,49,75,110,119],"218":[15,36,37,38,44,49,75,110,119],"261":[15,36,37,38,44,49,75,110,119],"265":[15,36,37,38,44,49,75,110,119],"272":[15,36,37,38,44,49,75,110,119],"284":[15,36,37,38,44,49,75,110,119],"288":[15,36,37,38,44,49,75,110,119],"317":[15,36,37,38,44,49,75,110,119],"342":[15,36,37,38,44,49,75,110,119],"364":[15,36,37,38,44,49,75,110,119]},"packages/@n8n/nodes-langchain/utils/agent-execution/createEngineRequests.ts":{"16":[15,36,37,38,44,49,75,110,119],"25":[15,36,37,38,44,49,75,110,119],"43":[15,36,37,38,44,49,75,110,119],"76":[15,36,37,38,44,49,75,110,119],"143":[15,36,37,38,44,49,75,110,119],"150":[15,36,37,38,44,49,75,110,119],"190":[15,36,37,38,44,49,75,110,119],"198":[15,36,37,38,44,49,75,110,119],"201":[15,36,37,38,44,49,75,110,119],"206":[15,36,37,38,44,49,75,110,119],"208":[15,36,37,38,44,49,75,110,119],"248":[15,36,37,38,44,49,75,110,119]},"packages/@n8n/nodes-langchain/utils/agent-execution/executeEngineAction.ts":{"17":[15,36,37,38,44,49,75,110,119],"22":[15,36,37,38,44,49,75,110,119],"47":[15,36,37,38,44,49,75,110,119]},"packages/@n8n/nodes-langchain/utils/agent-execution/index.ts":{"13":[15,36,37,38,44,49,75,110,119]},"packages/@n8n/nodes-langchain/utils/agent-execution/memoryManagement.ts":{"25":[15,36,37,38,44,49,75,110,119],"77":[15,36,37,38,44,49,75,110,119],"138":[15,36,37,38,44,49,75,110,119],"141":[15,36,37,38,44,49,75,110,119],"154":[15,36,37,38,44,49,75,110,119],"201":[15,36,37,38,44,49,75,110,119],"253":[15,36,37,38,44,49,75,110,119]},"packages/@n8n/nodes-langchain/utils/agent-execution/processEventStream.ts":{"20":[15,36,37,38,44,49,75,110,119]},"packages/@n8n/nodes-langchain/utils/agent-execution/processHitlResponses.ts":{"26":[15,36,37,38,44,49,75,110,119],"38":[15,36,37,38,44,49,75,110,119],"47":[15,36,37,38,44,49,75,110,119],"54":[15,36,37,38,44,49,75,110,119],"71":[15,36,37,38,44,49,75,110,119],"80":[15,36,37,38,44,49,75,110,119],"106":[15,36,37,38,44,49,75,110,119]},"packages/@n8n/nodes-langchain/utils/agent-execution/serializeIntermediateSteps.ts":{"10":[15,36,37,38,44,49,75,110,119],"15":[15,36,37,38,44,49,75,110,119],"29":[15,36,37,38,44,49,75,110,119]},"packages/@n8n/nodes-langchain/utils/agent-execution/types.ts":{"177":[15,36,37,38,44,49,75,110,119],"193":[15,36,37,38,44,49,75,110,119],"207":[15,36,37,38,44,49,75,110,119]},"packages/@n8n/nodes-langchain/utils/descriptions.ts":{"28":"b:AIACAHAQAgAACAAgAECAAQAAAIAA","54":"b:AIACAHAQAgAACAAgAECAAQAAAIAA","72":"b:AIACAHAQAgAACAAgAECAAQAAAIAA"},"packages/@n8n/nodes-langchain/utils/helpers.ts":{"17":"b:AIACAHASAgAACAAgAECAAQAAAIAA","64":"b:AIACAHASAgAACAAgAECAAQAAAIAA","77":"b:AIACAHASAgAACAAgAECAAQAAAIAA","81":"b:AIACAHASAgAACAAgAECAAQAAAIAA","145":"b:AIACAHASAgAACAAgAECAAQAAAIAA","147":"b:AIACAHASAgAACAAgAECAAQAAAIAA","159":"b:AIACAHASAgAACAAgAECAAQAAAIAA","180":"b:AIACAHASAgAACAAgAECAAQAAAIAA","192":"b:AIACAHASAgAACAAgAECAAQAAAIAA","213":"b:AIACAHASAgAACAAgAECAAQAAAIAA","217":"b:AIACAHASAgAACAAgAECAAQAAAIAA","221":"b:AIACAHASAgAACAAgAECAAQAAAIAA","274":"b:AIACAHASAgAACAAgAECAAQAAAIAA","296":"b:AIACAHASAgAACAAgAECAAQAAAIAA"},"packages/@n8n/nodes-langchain/utils/output_parsers/N8nItemListOutputParser.ts":{"10":"b:AIAAAHAQAgAACAAAAECAAQAAAAAA","26":"b:AIAAAHAQAgAACAAAAECAAQAAAAAA","29":"b:AIAAAHAQAgAACAAAAECAAQAAAAAA","30":"b:AIAAAHAQAgAACAAAAECAAQAAAAAA","42":"b:AIAAAHAQAgAACAAAAECAAQAAAAAA","57":"b:AIAAAHAQAgAACAAAAECAAQAAAAAA"},"packages/@n8n/nodes-langchain/utils/output_parsers/N8nOutputFixingParser.ts":{"15":"b:AIAAAHAQAgAACAAAAECAAQAAAAAA","24":"b:AIAAAHAQAgAACAAAAECAAQAAAAAA","35":"b:AIAAAHAQAgAACAAAAECAAQAAAAAA","42":"b:AIAAAHAQAgAACAAAAECAAQAAAAAA","88":"b:AIAAAHAQAgAACAAAAECAAQAAAAAA","92":"b:AIAAAHAQAgAACAAAAECAAQAAAAAA"},"packages/@n8n/nodes-langchain/utils/output_parsers/N8nOutputParser.ts":{"15":"b:AIAAAHAQAgAACAAAAECAAQAAAAAA"},"packages/@n8n/nodes-langchain/utils/output_parsers/N8nStructuredOutputParser.ts":{"22":"b:AIAAAHAQAgAACAAAAECAAQAAAAAA","31":"b:AIAAAHAQAgAACAAAAECAAQAAAAAA","131":"b:AIAAAHAQAgAACAAAAECAAQAAAAAA","148":"b:AIAAAHAQAgAACAAAAECAAQAAAAAA","175":"b:AIAAAHAQAgAACAAAAECAAQAAAAAA"},"packages/@n8n/nodes-langchain/utils/output_parsers/langchainParserError.ts":{"11":"b:AIAAAHAWAgAACAAAAECAAQAAAAAA","19":"b:AIAAAHAWAgAACAAAAECAAQAAAAAA","26":"b:AIAAAHAWAgAACAAAAECAAQAAAAAA","30":"b:AIAAAHAWAgAACAAAAECAAQAAAAAA","33":"b:AIAAAHAWAgAACAAAAECAAQAAAAAA","41":"b:AIAAAHAWAgAACAAAAECAAQAAAAAA"},"packages/@n8n/nodes-langchain/utils/tracing.ts":{"19":"b:AIACAHAQAgAACAAgAECAAAAAAAAA","83":"b:AIACAHAQAgAACAAgAECAAAAAAAAA"},"packages/cli/src/chat/chat-server.ts":{"21":"b:ANsWoH84EpHgBAAACFAAAYgEAAAA","23":"b:ANsWoH84EpHgBAAACFAAAYgEAAAA","24":"b:ANsWoH84EpHgBAAACFAAAYgEAAAA","28":"b:ANsWoH84EpHgBAAACFAAAYgEAAAA","34":"b:ANsWoH84EpHgBAAACFAAAYgEAAAA","39":"b:ANsWoH84EpHgBAAACFAAAYgEAAAA","42":"b:ANsWoH84EpHgBAAACFAAAYgEAAAA","51":"b:ANsWoH84EpHgBAAACFAAAYgEAAAA"},"packages/cli/src/collaboration/collaboration.message.ts":{"71":"b:ANsWgA8wEpHgBAAAClAAAYgEAAAA"},"packages/cli/src/collaboration/collaboration.service.ts":{"34":"b:IN8WwA80Er/gRAAAn3IAUZnmECUA","43":"b:IN8WwA80Er/gRAAAn3IAUZnmECUA","44":"b:IN8WwA80Er/gRAAAn3IAUZnmECUA","69":"b:IN8WwA80Er/gRAAAn3IAUZnmECUA","78":"b:IN8WwA80Er/gRAAAn3IAUZnmECUA","94":"b:IN8WwA80Er/gRAAAn3IAUZnmECUA","110":"b:IN8WwA80Er/gRAAAn3IAUZnmECUA","133":"b:IN8WwA80Er/gRAAAn3IAUZnmECUA","137":"b:IN8WwA80Er/gRAAAn3IAUZnmECUA","143":"b:IN8WwA80Er/gRAAAn3IAUZnmECUA","145":"b:IN8WwA80Er/gRAAAn3IAUZnmECUA","155":"b:IN8WwA80Er/gRAAAn3IAUZnmECUA","183":"b:IN8WwA80Er/gRAAAn3IAUZnmECUA","200":"b:IN8WwA80Er/gRAAAn3IAUZnmECUA","211":"b:IN8WwA80Er/gRAAAn3IAUZnmECUA","217":"b:IN8WwA80Er/gRAAAn3IAUZnmECUA","232":"b:IN8WwA80Er/gRAAAn3IAUZnmECUA","234":"b:IN8WwA80Er/gRAAAn3IAUZnmECUA","247":"b:IN8WwA80Er/gRAAAn3IAUZnmECUA","249":"b:IN8WwA80Er/gRAAAn3IAUZnmECUA","263":"b:IN8WwA80Er/gRAAAn3IAUZnmECUA","270":"b:IN8WwA80Er/gRAAAn3IAUZnmECUA","301":"b:IN8WwA80Er/gRAAAn3IAUZnmECUA","307":"b:IN8WwA80Er/gRAAAn3IAUZnmECUA","327":"b:IN8WwA80Er/gRAAAn3IAUZnmECUA","341":"b:IN8WwA80Er/gRAAAn3IAUZnmECUA","355":"b:IN8WwA80Er/gRAAAn3IAUZnmECUA"},"packages/cli/src/collaboration/collaboration.state.ts":{"35":"b:IN8WwA80EpvgRAAAn3IAEZnmEAQA","40":"b:IN8WwA80EpvgRAAAn3IAEZnmEAQA","52":"b:IN8WwA80EpvgRAAAn3IAEZnmEAQA","58":"b:IN8WwA80EpvgRAAAn3IAEZnmEAQA","86":"b:IN8WwA80EpvgRAAAn3IAEZnmEAQA","90":"b:IN8WwA80EpvgRAAAn3IAEZnmEAQA","105":"b:IN8WwA80EpvgRAAAn3IAEZnmEAQA","112":"b:IN8WwA80EpvgRAAAn3IAEZnmEAQA","117":"b:IN8WwA80EpvgRAAAn3IAEZnmEAQA","149":"b:IN8WwA80EpvgRAAAn3IAEZnmEAQA","160":"b:IN8WwA80EpvgRAAAn3IAEZnmEAQA","166":"b:IN8WwA80EpvgRAAAn3IAEZnmEAQA","177":"b:IN8WwA80EpvgRAAAn3IAEZnmEAQA","198":"b:IN8WwA80EpvgRAAAn3IAEZnmEAQA","203":"b:IN8WwA80EpvgRAAAn3IAEZnmEAQA","212":"b:IN8WwA80EpvgRAAAn3IAEZnmEAQA"},"packages/cli/src/controllers/active-workflows.controller.ts":{"8":"b:ANsWKQ84EpHwBBQECFAAAYgEAAAA","11":"b:ANsWKQ84EpHwBBQECFAAAYgEAAAA","16":"b:ANsWKQ84EpHwBBQECFAAAYgEAAAA"},"packages/cli/src/controllers/me.controller.ts":{"32":[15,49,77,89,90,93,110,119,120],"48":[15,49,77,89,90,93,110,119,120],"108":[15,49,77,89,90,93,110,119,120],"120":[15,49,77,89,90,93,110,119,120],"174":[15,49,77,89,90,93,110,119,120],"183":[15,49,77,89,90,93,110,119,120],"193":[15,49,77,89,90,93,110,119,120],"231":[15,49,77,89,90,93,110,119,120],"264":[15,49,77,89,90,93,110,119,120],"309":[15,49,77,89,90,93,110,119,120]},"packages/cli/src/controllers/users.controller.ts":{"55":"b:gNsWKQ98ApHwBHQEAFAAAYgEAAAA","81":"b:gNsWKQ98ApHwBHQEAFAAAYgEAAAA","105":"b:gNsWKQ98ApHwBHQEAFAAAYgEAAAA","114":"b:gNsWKQ98ApHwBHQEAFAAAYgEAAAA","127":"b:gNsWKQ98ApHwBHQEAFAAAYgEAAAA","134":"b:gNsWKQ98ApHwBHQEAFAAAYgEAAAA","151":"b:gNsWKQ98ApHwBHQEAFAAAYgEAAAA","173":"b:gNsWKQ98ApHwBHQEAFAAAYgEAAAA","201":"b:gNsWKQ98ApHwBHQEAFAAAYgEAAAA","222":"b:gNsWKQ98ApHwBHQEAFAAAYgEAAAA","279":"b:gNsWKQ98ApHwBHQEAFAAAYgEAAAA","310":"b:gNsWKQ98ApHwBHQEAFAAAYgEAAAA","320":"b:gNsWKQ98ApHwBHQEAFAAAYgEAAAA","343":"b:gNsWKQ98ApHwBHQEAFAAAYgEAAAA"},"packages/cli/src/credentials/credentials-finder.service.ts":{"15":"b:MPsGoH94EpGwBAAQCFAACYgUJAAA","24":"b:MPsGoH94EpGwBAAQCFAACYgUJAAA","36":"b:MPsGoH94EpGwBAAQCFAACYgUJAAA","43":"b:MPsGoH94EpGwBAAQCFAACYgUJAAA","56":"b:MPsGoH94EpGwBAAQCFAACYgUJAAA","64":"b:MPsGoH94EpGwBAAQCFAACYgUJAAA","69":"b:MPsGoH94EpGwBAAQCFAACYgUJAAA","71":"b:MPsGoH94EpGwBAAQCFAACYgUJAAA","73":"b:MPsGoH94EpGwBAAQCFAACYgUJAAA","85":"b:MPsGoH94EpGwBAAQCFAACYgUJAAA","122":"b:MPsGoH94EpGwBAAQCFAACYgUJAAA","171":"b:MPsGoH94EpGwBAAQCFAACYgUJAAA","200":"b:MPsGoH94EpGwBAAQCFAACYgUJAAA","211":"b:MPsGoH94EpGwBAAQCFAACYgUJAAA","213":"b:MPsGoH94EpGwBAAQCFAACYgUJAAA","230":"b:MPsGoH94EpGwBAAQCFAACYgUJAAA","261":"b:MPsGoH94EpGwBAAQCFAACYgUJAAA","275":"b:MPsGoH94EpGwBAAQCFAACYgUJAAA","298":"b:MPsGoH94EpGwBAAQCFAACYgUJAAA"},"packages/cli/src/license/license.controller.ts":{"15":"b:ANs2KQ84EpGwBBQECFAAAYgEAAAA","22":"b:ANs2KQ84EpGwBBQECFAAAYgEAAAA","28":"b:ANs2KQ84EpGwBBQECFAAAYgEAAAA","44":"b:ANs2KQ84EpGwBBQECFAAAYgEAAAA","60":"b:ANs2KQ84EpGwBBQECFAAAYgEAAAA","72":"b:ANs2KQ84EpGwBBQECFAAAYgEAAAA","77":"b:ANs2KQ84EpGwBBQECFAAAYgEAAAA"},"packages/cli/src/license/license.service.ts":{"25":"b:ANs2KQ84EpGwBBQECFAAAYgEAAAA","34":"b:ANs2KQ84EpGwBBQECFAAAYgEAAAA","59":"b:ANs2KQ84EpGwBBQECFAAAYgEAAAA","69":"b:ANs2KQ84EpGwBBQECFAAAYgEAAAA","108":"b:ANs2KQ84EpGwBBQECFAAAYgEAAAA","116":"b:ANs2KQ84EpGwBBQECFAAAYgEAAAA","142":"b:ANs2KQ84EpGwBBQECFAAAYgEAAAA","160":"b:ANs2KQ84EpGwBBQECFAAAYgEAAAA","175":"b:ANs2KQ84EpGwBBQECFAAAYgEAAAA","189":"b:ANs2KQ84EpGwBBQECFAAAYgEAAAA"},"packages/cli/src/load-nodes-and-credentials.ts":{"64":"b:MPsC4H9yVpvwzUAQCPGEhYj0toAA","73":"b:MPsC4H9yVpvwzUAQCPGEhYj0toAA","134":"b:MPsC4H9yVpvwzUAQCPGEhYj0toAA","138":"b:MPsC4H9yVpvwzUAQCPGEhYj0toAA","154":"b:MPsC4H9yVpvwzUAQCPGEhYj0toAA","169":"b:MPsC4H9yVpvwzUAQCPGEhYj0toAA","173":"b:MPsC4H9yVpvwzUAQCPGEhYj0toAA","177":"b:MPsC4H9yVpvwzUAQCPGEhYj0toAA","181":"b:MPsC4H9yVpvwzUAQCPGEhYj0toAA","185":"b:MPsC4H9yVpvwzUAQCPGEhYj0toAA","189":"b:MPsC4H9yVpvwzUAQCPGEhYj0toAA","230":"b:MPsC4H9yVpvwzUAQCPGEhYj0toAA","237":"b:MPsC4H9yVpvwzUAQCPGEhYj0toAA","241":"b:MPsC4H9yVpvwzUAQCPGEhYj0toAA","259":"b:MPsC4H9yVpvwzUAQCPGEhYj0toAA","282":"b:MPsC4H9yVpvwzUAQCPGEhYj0toAA","293":"b:MPsC4H9yVpvwzUAQCPGEhYj0toAA","299":"b:MPsC4H9yVpvwzUAQCPGEhYj0toAA","308":"b:MPsC4H9yVpvwzUAQCPGEhYj0toAA","319":"b:MPsC4H9yVpvwzUAQCPGEhYj0toAA","322":"b:MPsC4H9yVpvwzUAQCPGEhYj0toAA","323":"b:MPsC4H9yVpvwzUAQCPGEhYj0toAA","334":"b:MPsC4H9yVpvwzUAQCPGEhYj0toAA","345":"b:MPsC4H9yVpvwzUAQCPGEhYj0toAA","346":"b:MPsC4H9yVpvwzUAQCPGEhYj0toAA","353":"b:MPsC4H9yVpvwzUAQCPGEhYj0toAA","369":"b:MPsC4H9yVpvwzUAQCPGEhYj0toAA","373":"b:MPsC4H9yVpvwzUAQCPGEhYj0toAA","382":"b:MPsC4H9yVpvwzUAQCPGEhYj0toAA","393":"b:MPsC4H9yVpvwzUAQCPGEhYj0toAA","404":"b:MPsC4H9yVpvwzUAQCPGEhYj0toAA","414":"b:MPsC4H9yVpvwzUAQCPGEhYj0toAA","491":"b:MPsC4H9yVpvwzUAQCPGEhYj0toAA","504":"b:MPsC4H9yVpvwzUAQCPGEhYj0toAA","521":"b:MPsC4H9yVpvwzUAQCPGEhYj0toAA","533":"b:MPsC4H9yVpvwzUAQCPGEhYj0toAA","539":"b:MPsC4H9yVpvwzUAQCPGEhYj0toAA","544":"b:MPsC4H9yVpvwzUAQCPGEhYj0toAA","576":"b:MPsC4H9yVpvwzUAQCPGEhYj0toAA","595":"b:MPsC4H9yVpvwzUAQCPGEhYj0toAA","602":"b:MPsC4H9yVpvwzUAQCPGEhYj0toAA","619":"b:MPsC4H9yVpvwzUAQCPGEhYj0toAA","636":"b:MPsC4H9yVpvwzUAQCPGEhYj0toAA","637":"b:MPsC4H9yVpvwzUAQCPGEhYj0toAA","639":"b:MPsC4H9yVpvwzUAQCPGEhYj0toAA","641":"b:MPsC4H9yVpvwzUAQCPGEhYj0toAA","654":"b:MPsC4H9yVpvwzUAQCPGEhYj0toAA","679":"b:MPsC4H9yVpvwzUAQCPGEhYj0toAA","683":"b:MPsC4H9yVpvwzUAQCPGEhYj0toAA","684":"b:MPsC4H9yVpvwzUAQCPGEhYj0toAA","690":"b:MPsC4H9yVpvwzUAQCPGEhYj0toAA","700":"b:MPsC4H9yVpvwzUAQCPGEhYj0toAA","701":"b:MPsC4H9yVpvwzUAQCPGEhYj0toAA","702":"b:MPsC4H9yVpvwzUAQCPGEhYj0toAA"},"packages/cli/src/modules/mcp-registry/mcp-registry-node-loader.ts":{"52":[49],"57":[49],"61":[49],"71":[49],"109":[49],"115":[49],"121":[49],"129":[49],"134":[49],"138":[49],"142":[49]},"packages/cli/src/modules/mcp-registry/mcp-registry-test.controller.ts":{"17":[49],"23":[49],"29":[49],"38":[49]},"packages/cli/src/modules/mcp-registry/registry/mcp-registry.service.ts":{"33":[49],"45":[49],"55":[49],"61":[49],"66":[49],"72":[49],"79":[49],"88":[49],"93":[49],"98":[49],"102":[49],"107":[49],"116":[49],"121":[49],"135":[49],"165":[49],"170":[49],"171":[49],"173":[49],"174":[49],"176":[49],"177":[49],"191":[49],"202":[49],"214":[49],"238":[49],"242":[49],"246":[49]},"packages/cli/src/modules/workflow-index/workflow-index.service.ts":{"33":"b:ANsewA80EpfwRAAAClAAkbv2Fi0B","45":"b:ANsewA80EpfwRAAAClAAkbv2Fi0B","46":"b:ANsewA80EpfwRAAAClAAkbv2Fi0B","48":"b:ANsewA80EpfwRAAAClAAkbv2Fi0B","50":"b:ANsewA80EpfwRAAAClAAkbv2Fi0B","53":"b:ANsewA80EpfwRAAAClAAkbv2Fi0B","56":"b:ANsewA80EpfwRAAAClAAkbv2Fi0B","59":"b:ANsewA80EpfwRAAAClAAkbv2Fi0B","71":"b:ANsewA80EpfwRAAAClAAkbv2Fi0B","74":"b:ANsewA80EpfwRAAAClAAkbv2Fi0B","76":"b:ANsewA80EpfwRAAAClAAkbv2Fi0B","82":"b:ANsewA80EpfwRAAAClAAkbv2Fi0B","95":"b:ANsewA80EpfwRAAAClAAkbv2Fi0B","143":"b:ANsewA80EpfwRAAAClAAkbv2Fi0B","157":"b:ANsewA80EpfwRAAAClAAkbv2Fi0B","175":"b:ANsewA80EpfwRAAAClAAkbv2Fi0B","182":"b:ANsewA80EpfwRAAAClAAkbv2Fi0B","204":"b:ANsewA80EpfwRAAAClAAkbv2Fi0B","222":"b:ANsewA80EpfwRAAAClAAkbv2Fi0B","223":"b:ANsewA80EpfwRAAAClAAkbv2Fi0B","265":"b:ANsewA80EpfwRAAAClAAkbv2Fi0B","275":"b:ANsewA80EpfwRAAAClAAkbv2Fi0B","292":"b:ANsewA80EpfwRAAAClAAkbv2Fi0B","314":"b:ANsewA80EpfwRAAAClAAkbv2Fi0B","329":"b:ANsewA80EpfwRAAAClAAkbv2Fi0B","343":"b:ANsewA80EpfwRAAAClAAkbv2Fi0B","358":"b:ANsewA80EpfwRAAAClAAkbv2Fi0B"},"packages/cli/src/node-types.ts":{"17":"b:AN8CgH8wEpHgBAAACFAAAYj0FgAA","22":"b:AN8CgH8wEpHgBAAACFAAAYj0FgAA","35":"b:AN8CgH8wEpHgBAAACFAAAYj0FgAA","61":"b:AN8CgH8wEpHgBAAACFAAAYj0FgAA","65":"b:AN8CgH8wEpHgBAAACFAAAYj0FgAA","89":"b:AN8CgH8wEpHgBAAACFAAAYj0FgAA","128":"b:AN8CgH8wEpHgBAAACFAAAYj0FgAA","132":"b:AN8CgH8wEpHgBAAACFAAAYj0FgAA","150":"b:AN8CgH8wEpHgBAAACFAAAYj0FgAA","153":"b:AN8CgH8wEpHgBAAACFAAAYj0FgAA","160":"b:AN8CgH8wEpHgBAAACFAAAYj0FgAA","163":"b:AN8CgH8wEpHgBAAACFAAAYj0FgAA","174":"b:AN8CgH8wEpHgBAAACFAAAYj0FgAA","175":"b:AN8CgH8wEpHgBAAACFAAAYj0FgAA"},"packages/cli/src/push/index.ts":{"57":"b:ANsWoH84ErXgDAAAClQCEYgEAAAA","67":"b:ANsWoH84ErXgDAAAClQCEYgEAAAA","70":"b:ANsWoH84ErXgDAAAClQCEYgEAAAA","75":"b:ANsWoH84ErXgDAAAClQCEYgEAAAA","78":"b:ANsWoH84ErXgDAAAClQCEYgEAAAA","80":"b:ANsWoH84ErXgDAAAClQCEYgEAAAA","84":"b:ANsWoH84ErXgDAAAClQCEYgEAAAA","99":"b:ANsWoH84ErXgDAAAClQCEYgEAAAA","104":"b:ANsWoH84ErXgDAAAClQCEYgEAAAA","116":"b:ANsWoH84ErXgDAAAClQCEYgEAAAA","171":"b:ANsWoH84ErXgDAAAClQCEYgEAAAA","176":"b:ANsWoH84ErXgDAAAClQCEYgEAAAA","185":"b:ANsWoH84ErXgDAAAClQCEYgEAAAA","194":"b:ANsWoH84ErXgDAAAClQCEYgEAAAA","199":"b:ANsWoH84ErXgDAAAClQCEYgEAAAA","220":"b:ANsWoH84ErXgDAAAClQCEYgEAAAA","227":"b:ANsWoH84ErXgDAAAClQCEYgEAAAA","242":"b:ANsWoH84ErXgDAAAClQCEYgEAAAA","249":"b:ANsWoH84ErXgDAAAClQCEYgEAAAA"},"packages/cli/src/push/push-helpers.ts":{"5":"b:ANsWoH84EpHgBAAACFAAAYgEAAAA","9":"b:ANsWoH84EpHgBAAACFAAAYgEAAAA","14":"b:ANsWoH84EpHgBAAACFAAAYgEAAAA","18":"b:ANsWoH84EpHgBAAACFAAAYgEAAAA"},"packages/cli/src/push/websocket.push.ts":{"9":"b:MNsWoH86GpHgBQAAz1gAkYgEAAAA","15":"b:MNsWoH86GpHgBQAAz1gAkYgEAAAA","21":"b:MNsWoH86GpHgBQAAz1gAkYgEAAAA","60":"b:MNsWoH86GpHgBQAAz1gAkYgEAAAA","71":"b:MNsWoH86GpHgBQAAz1gAkYgEAAAA","75":"b:MNsWoH86GpHgBQAAz1gAkYgEAAAA","79":"b:MNsWoH86GpHgBQAAz1gAkYgEAAAA","88":"b:MNsWoH86GpHgBQAAz1gAkYgEAAAA"},"packages/cli/src/services/access.service.ts":{"13":"b:AN8WwA8wEpvgRAAAC1AAEYkEAAAA","19":"b:AN8WwA8wEpvgRAAAC1AAEYkEAAAA","31":"b:AN8WwA8wEpvgRAAAC1AAEYkEAAAA"},"packages/cli/src/services/active-workflows.service.ts":{"13":"b:oNseKQ84FrHwBBQUCFAAAaoGAAAA","21":"b:oNseKQ84FrHwBBQUCFAAAaoGAAAA","24":"b:oNseKQ84FrHwBBQUCFAAAaoGAAAA","27":"b:oNseKQ84FrHwBBQUCFAAAaoGAAAA","33":"b:oNseKQ84FrHwBBQUCFAAAaoGAAAA","38":"b:oNseKQ84FrHwBBQUCFAAAaoGAAAA","41":"b:oNseKQ84FrHwBBQUCFAAAaoGAAAA"},"packages/cli/src/services/cache/cache.service.ts":{"26":"b:ANsewH80EpXwDCAACHICFbj2FC0B","32":"b:ANsewH80EpXwDCAACHICFbj2FC0B","39":"b:ANsewH80EpXwDCAACHICFbj2FC0B","55":"b:ANsewH80EpXwDCAACHICFbj2FC0B","69":"b:ANsewH80EpXwDCAACHICFbj2FC0B","79":"b:ANsewH80EpXwDCAACHICFbj2FC0B","83":"b:ANsewH80EpXwDCAACHICFbj2FC0B","87":"b:ANsewH80EpXwDCAACHICFbj2FC0B","91":"b:ANsewH80EpXwDCAACHICFbj2FC0B","103":"b:ANsewH80EpXwDCAACHICFbj2FC0B","115":"b:ANsewH80EpXwDCAACHICFbj2FC0B","121":"b:ANsewH80EpXwDCAACHICFbj2FC0B","139":"b:ANsewH80EpXwDCAACHICFbj2FC0B","160":"b:ANsewH80EpXwDCAACHICFbj2FC0B","180":"b:ANsewH80EpXwDCAACHICFbj2FC0B","218":"b:ANsewH80EpXwDCAACHICFbj2FC0B","256":"b:ANsewH80EpXwDCAACHICFbj2FC0B","300":"b:ANsewH80EpXwDCAACHICFbj2FC0B","308":"b:ANsewH80EpXwDCAACHICFbj2FC0B","320":"b:ANsewH80EpXwDCAACHICFbj2FC0B","339":"b:ANsewH80EpXwDCAACHICFbj2FC0B","355":"b:ANsewH80EpXwDCAACHICFbj2FC0B"},"packages/cli/src/services/naming.service.ts":{"6":"b:IL40oC941kQhFECQA1CEEYgEgAAA","11":"b:IL40oC941kQhFECQA1CEEYgEgAAA","15":"b:IL40oC941kQhFECQA1CEEYgEgAAA","19":"b:IL40oC941kQhFECQA1CEEYgEgAAA","28":"b:IL40oC941kQhFECQA1CEEYgEgAAA"},"packages/cli/src/services/ownership.service.ts":{"27":"b:qNuWgP90ApXwDEAACXAGEYj2NCcA","44":"b:qNuWgP90ApXwDEAACXAGEYj2NCcA","50":"b:qNuWgP90ApXwDEAACXAGEYj2NCcA","57":"b:qNuWgP90ApXwDEAACXAGEYj2NCcA","64":"b:qNuWgP90ApXwDEAACXAGEYj2NCcA","74":"b:qNuWgP90ApXwDEAACXAGEYj2NCcA","88":"b:qNuWgP90ApXwDEAACXAGEYj2NCcA","111":"b:qNuWgP90ApXwDEAACXAGEYj2NCcA","123":"b:qNuWgP90ApXwDEAACXAGEYj2NCcA","143":"b:qNuWgP90ApXwDEAACXAGEYj2NCcA","150":"b:qNuWgP90ApXwDEAACXAGEYj2NCcA","157":"b:qNuWgP90ApXwDEAACXAGEYj2NCcA","169":"b:qNuWgP90ApXwDEAACXAGEYj2NCcA","211":"b:qNuWgP90ApXwDEAACXAGEYj2NCcA","217":"b:qNuWgP90ApXwDEAACXAGEYj2NCcA","237":"b:qNuWgP90ApXwDEAACXAGEYj2NCcA"},"packages/cli/src/utils.ts":{"10":"b:cPuS/X9wErf2HFQUCFYinZn0Pq8B","14":"b:cPuS/X9wErf2HFQUCFYinZn0Pq8B","15":"b:cPuS/X9wErf2HFQUCFYinZn0Pq8B","17":"b:cPuS/X9wErf2HFQUCFYinZn0Pq8B","22":"b:cPuS/X9wErf2HFQUCFYinZn0Pq8B","42":"b:cPuS/X9wErf2HFQUCFYinZn0Pq8B","46":"b:cPuS/X9wErf2HFQUCFYinZn0Pq8B","48":"b:cPuS/X9wErf2HFQUCFYinZn0Pq8B","53":"b:cPuS/X9wErf2HFQUCFYinZn0Pq8B","58":"b:cPuS/X9wErf2HFQUCFYinZn0Pq8B","64":"b:cPuS/X9wErf2HFQUCFYinZn0Pq8B","77":"b:cPuS/X9wErf2HFQUCFYinZn0Pq8B","79":"b:cPuS/X9wErf2HFQUCFYinZn0Pq8B","84":"b:cPuS/X9wErf2HFQUCFYinZn0Pq8B","104":"b:cPuS/X9wErf2HFQUCFYinZn0Pq8B","111":"b:cPuS/X9wErf2HFQUCFYinZn0Pq8B","131":"b:cPuS/X9wErf2HFQUCFYinZn0Pq8B","143":"b:cPuS/X9wErf2HFQUCFYinZn0Pq8B","147":"b:cPuS/X9wErf2HFQUCFYinZn0Pq8B","155":"b:cPuS/X9wErf2HFQUCFYinZn0Pq8B"},"packages/cli/src/workflow-helpers.ts":{"33":"b:ANsewH90ErfwTACAGlAClYn0Fi4B","60":"b:ANsewH90ErfwTACAGlAClYn0Fi4B","66":"b:ANsewH90ErfwTACAGlAClYn0Fi4B","72":"b:ANsewH90ErfwTACAGlAClYn0Fi4B","91":"b:ANsewH90ErfwTACAGlAClYn0Fi4B","110":"b:ANsewH90ErfwTACAGlAClYn0Fi4B","114":"b:ANsewH90ErfwTACAGlAClYn0Fi4B","126":"b:ANsewH90ErfwTACAGlAClYn0Fi4B","146":"b:ANsewH90ErfwTACAGlAClYn0Fi4B","150":"b:ANsewH90ErfwTACAGlAClYn0Fi4B","191":"b:ANsewH90ErfwTACAGlAClYn0Fi4B","199":"b:ANsewH90ErfwTACAGlAClYn0Fi4B","205":"b:ANsewH90ErfwTACAGlAClYn0Fi4B","228":"b:ANsewH90ErfwTACAGlAClYn0Fi4B","264":"b:ANsewH90ErfwTACAGlAClYn0Fi4B","382":"b:ANsewH90ErfwTACAGlAClYn0Fi4B","395":"b:ANsewH90ErfwTACAGlAClYn0Fi4B","414":"b:ANsewH90ErfwTACAGlAClYn0Fi4B","442":"b:ANsewH90ErfwTACAGlAClYn0Fi4B","485":"b:ANsewH90ErfwTACAGlAClYn0Fi4B","507":"b:ANsewH90ErfwTACAGlAClYn0Fi4B"},"packages/cli/src/workflows/utils.ts":{"15":"b:ANsGgA80EpHwBAAACFAAAYj0FgAA","22":"b:ANsGgA80EpHwBAAACFAAAYj0FgAA","23":"b:ANsGgA80EpHwBAAACFAAAYj0FgAA","31":"b:ANsGgA80EpHwBAAACFAAAYj0FgAA","37":"b:ANsGgA80EpHwBAAACFAAAYj0FgAA","42":"b:ANsGgA80EpHwBAAACFAAAYj0FgAA"},"packages/cli/src/workflows/workflow-creation.service.ts":{"42":"b:ANsGgA80EpHwBAAACFAAAYj0FgAA","63":"b:ANsGgA80EpHwBAAACFAAAYj0FgAA","168":"b:ANsGgA80EpHwBAAACFAAAYj0FgAA","259":"b:ANsGgA80EpHwBAAACFAAAYj0FgAA","264":"b:ANsGgA80EpHwBAAACFAAAYj0FgAA"},"packages/cli/src/workflows/workflow-finder.service.ts":{"15":"b:SNumlA+0EpG+BAAACFIAAZj0FgAA","21":"b:SNumlA+0EpG+BAAACFIAAZj0FgAA","54":"b:SNumlA+0EpG+BAAACFIAAZj0FgAA","72":"b:SNumlA+0EpG+BAAACFIAAZj0FgAA","95":"b:SNumlA+0EpG+BAAACFIAAZj0FgAA","141":"b:SNumlA+0EpG+BAAACFIAAZj0FgAA","152":"b:SNumlA+0EpG+BAAACFIAAZj0FgAA","155":"b:SNumlA+0EpG+BAAACFIAAZj0FgAA","186":"b:SNumlA+0EpG+BAAACFIAAZj0FgAA","217":"b:SNumlA+0EpG+BAAACFIAAZj0FgAA","220":"b:SNumlA+0EpG+BAAACFIAAZj0FgAA","224":"b:SNumlA+0EpG+BAAACFIAAZj0FgAA","233":"b:SNumlA+0EpG+BAAACFIAAZj0FgAA","245":"b:SNumlA+0EpG+BAAACFIAAZj0FgAA","248":"b:SNumlA+0EpG+BAAACFIAAZj0FgAA","265":"b:SNumlA+0EpG+BAAACFIAAZj0FgAA"},"packages/cli/src/workflows/workflow-history/workflow-history.service.ts":{"26":"b:APs2gA80EpXyDAAgCFIAAbj2FiUA","35":"b:APs2gA80EpXyDAAgCFIAAbj2FiUA","70":"b:APs2gA80EpXyDAAgCFIAAbj2FiUA","103":"b:APs2gA80EpXyDAAgCFIAAbj2FiUA","125":"b:APs2gA80EpXyDAAgCFIAAbj2FiUA","167":"b:APs2gA80EpXyDAAgCFIAAbj2FiUA","209":"b:APs2gA80EpXyDAAgCFIAAbj2FiUA","257":"b:APs2gA80EpXyDAAgCFIAAbj2FiUA","272":"b:APs2gA80EpXyDAAgCFIAAbj2FiUA","297":"b:APs2gA80EpXyDAAgCFIAAbj2FiUA","300":"b:APs2gA80EpXyDAAgCFIAAbj2FiUA","318":"b:APs2gA80EpXyDAAgCFIAAbj2FiUA"},"packages/cli/src/workflows/workflow-validation.service.ts":{"52":"b:IPsewA80EpPwBACACFAACbr2Fq0B","63":"b:IPsewA80EpPwBACACFAACbr2Fq0B","125":"b:IPsewA80EpPwBACACFAACbr2Fq0B","126":"b:IPsewA80EpPwBACACFAACbr2Fq0B","149":"b:IPsewA80EpPwBACACFAACbr2Fq0B","181":"b:IPsewA80EpPwBACACFAACbr2Fq0B","242":"b:IPsewA80EpPwBACACFAACbr2Fq0B","263":"b:IPsewA80EpPwBACACFAACbr2Fq0B","298":"b:IPsewA80EpPwBACACFAACbr2Fq0B","334":"b:IPsewA80EpPwBACACFAACbr2Fq0B","336":"b:IPsewA80EpPwBACACFAACbr2Fq0B","341":"b:IPsewA80EpPwBACACFAACbr2Fq0B","360":"b:IPsewA80EpPwBACACFAACbr2Fq0B","383":"b:IPsewA80EpPwBACACFAACbr2Fq0B","388":"b:IPsewA80EpPwBACACFAACbr2Fq0B","422":"b:IPsewA80EpPwBACACFAACbr2Fq0B","441":"b:IPsewA80EpPwBACACFAACbr2Fq0B","466":"b:IPsewA80EpPwBACACFAACbr2Fq0B","474":"b:IPsewA80EpPwBACACFAACbr2Fq0B","495":"b:IPsewA80EpPwBACACFAACbr2Fq0B"},"packages/cli/src/workflows/workflow.service.ee.ts":{"43":"b:YPsW4A80Erf7TACAHnACGYj0FIEA","60":"b:YPsW4A80Erf7TACAHnACGYj0FIEA","73":"b:YPsW4A80Erf7TACAHnACGYj0FIEA","75":"b:YPsW4A80Erf7TACAHnACGYj0FIEA","82":"b:YPsW4A80Erf7TACAHnACGYj0FIEA","93":"b:YPsW4A80Erf7TACAHnACGYj0FIEA","105":"b:YPsW4A80Erf7TACAHnACGYj0FIEA","115":"b:YPsW4A80Erf7TACAHnACGYj0FIEA","119":"b:YPsW4A80Erf7TACAHnACGYj0FIEA","131":"b:YPsW4A80Erf7TACAHnACGYj0FIEA","132":"b:YPsW4A80Erf7TACAHnACGYj0FIEA","146":"b:YPsW4A80Erf7TACAHnACGYj0FIEA","150":"b:YPsW4A80Erf7TACAHnACGYj0FIEA","154":"b:YPsW4A80Erf7TACAHnACGYj0FIEA","159":"b:YPsW4A80Erf7TACAHnACGYj0FIEA","167":"b:YPsW4A80Erf7TACAHnACGYj0FIEA","191":"b:YPsW4A80Erf7TACAHnACGYj0FIEA","203":"b:YPsW4A80Erf7TACAHnACGYj0FIEA","215":"b:YPsW4A80Erf7TACAHnACGYj0FIEA","219":"b:YPsW4A80Erf7TACAHnACGYj0FIEA","222":"b:YPsW4A80Erf7TACAHnACGYj0FIEA","239":"b:YPsW4A80Erf7TACAHnACGYj0FIEA","248":"b:YPsW4A80Erf7TACAHnACGYj0FIEA","261":"b:YPsW4A80Erf7TACAHnACGYj0FIEA","265":"b:YPsW4A80Erf7TACAHnACGYj0FIEA","270":"b:YPsW4A80Erf7TACAHnACGYj0FIEA","272":"b:YPsW4A80Erf7TACAHnACGYj0FIEA","281":"b:YPsW4A80Erf7TACAHnACGYj0FIEA","335":"b:YPsW4A80Erf7TACAHnACGYj0FIEA","357":"b:YPsW4A80Erf7TACAHnACGYj0FIEA","426":"b:YPsW4A80Erf7TACAHnACGYj0FIEA","449":"b:YPsW4A80Erf7TACAHnACGYj0FIEA","474":"b:YPsW4A80Erf7TACAHnACGYj0FIEA","499":"b:YPsW4A80Erf7TACAHnACGYj0FIEA","514":"b:YPsW4A80Erf7TACAHnACGYj0FIEA","540":"b:YPsW4A80Erf7TACAHnACGYj0FIEA","551":"b:YPsW4A80Erf7TACAHnACGYj0FIEA","575":"b:YPsW4A80Erf7TACAHnACGYj0FIEA","579":"b:YPsW4A80Erf7TACAHnACGYj0FIEA","601":"b:YPsW4A80Erf7TACAHnACGYj0FIEA","606":"b:YPsW4A80Erf7TACAHnACGYj0FIEA","619":"b:YPsW4A80Erf7TACAHnACGYj0FIEA","633":"b:YPsW4A80Erf7TACAHnACGYj0FIEA","639":"b:YPsW4A80Erf7TACAHnACGYj0FIEA","660":"b:YPsW4A80Erf7TACAHnACGYj0FIEA"},"packages/cli/src/workflows/workflow.service.ts":{"77":"b:7Nue3X+0Erf2RBwEClIAEbr2VC0B","105":"b:7Nue3X+0Erf2RBwEClIAEbr2VC0B","166":"b:7Nue3X+0Erf2RBwEClIAEbr2VC0B","210":"b:7Nue3X+0Erf2RBwEClIAEbr2VC0B","214":"b:7Nue3X+0Erf2RBwEClIAEbr2VC0B","217":"b:7Nue3X+0Erf2RBwEClIAEbr2VC0B","221":"b:7Nue3X+0Erf2RBwEClIAEbr2VC0B","227":"b:7Nue3X+0Erf2RBwEClIAEbr2VC0B","239":"b:7Nue3X+0Erf2RBwEClIAEbr2VC0B","242":"b:7Nue3X+0Erf2RBwEClIAEbr2VC0B","243":"b:7Nue3X+0Erf2RBwEClIAEbr2VC0B","246":"b:7Nue3X+0Erf2RBwEClIAEbr2VC0B","247":"b:7Nue3X+0Erf2RBwEClIAEbr2VC0B","251":"b:7Nue3X+0Erf2RBwEClIAEbr2VC0B","257":"b:7Nue3X+0Erf2RBwEClIAEbr2VC0B","262":"b:7Nue3X+0Erf2RBwEClIAEbr2VC0B","268":"b:7Nue3X+0Erf2RBwEClIAEbr2VC0B","276":"b:7Nue3X+0Erf2RBwEClIAEbr2VC0B","283":"b:7Nue3X+0Erf2RBwEClIAEbr2VC0B","287":"b:7Nue3X+0Erf2RBwEClIAEbr2VC0B","289":"b:7Nue3X+0Erf2RBwEClIAEbr2VC0B","304":"b:7Nue3X+0Erf2RBwEClIAEbr2VC0B","370":"b:7Nue3X+0Erf2RBwEClIAEbr2VC0B","595":"b:7Nue3X+0Erf2RBwEClIAEbr2VC0B","677":"b:7Nue3X+0Erf2RBwEClIAEbr2VC0B","701":"b:7Nue3X+0Erf2RBwEClIAEbr2VC0B","711":"b:7Nue3X+0Erf2RBwEClIAEbr2VC0B","729":"b:7Nue3X+0Erf2RBwEClIAEbr2VC0B","889":"b:7Nue3X+0Erf2RBwEClIAEbr2VC0B","969":"b:7Nue3X+0Erf2RBwEClIAEbr2VC0B","994":"b:7Nue3X+0Erf2RBwEClIAEbr2VC0B","995":"b:7Nue3X+0Erf2RBwEClIAEbr2VC0B","1007":"b:7Nue3X+0Erf2RBwEClIAEbr2VC0B","1074":"b:7Nue3X+0Erf2RBwEClIAEbr2VC0B","1109":"b:7Nue3X+0Erf2RBwEClIAEbr2VC0B","1113":"b:7Nue3X+0Erf2RBwEClIAEbr2VC0B","1117":"b:7Nue3X+0Erf2RBwEClIAEbr2VC0B","1121":"b:7Nue3X+0Erf2RBwEClIAEbr2VC0B","1133":"b:7Nue3X+0Erf2RBwEClIAEbr2VC0B","1141":"b:7Nue3X+0Erf2RBwEClIAEbr2VC0B","1150":"b:7Nue3X+0Erf2RBwEClIAEbr2VC0B","1151":"b:7Nue3X+0Erf2RBwEClIAEbr2VC0B","1162":"b:7Nue3X+0Erf2RBwEClIAEbr2VC0B","1163":"b:7Nue3X+0Erf2RBwEClIAEbr2VC0B","1168":"b:7Nue3X+0Erf2RBwEClIAEbr2VC0B","1174":"b:7Nue3X+0Erf2RBwEClIAEbr2VC0B","1182":"b:7Nue3X+0Erf2RBwEClIAEbr2VC0B","1189":"b:7Nue3X+0Erf2RBwEClIAEbr2VC0B","1200":"b:7Nue3X+0Erf2RBwEClIAEbr2VC0B","1202":"b:7Nue3X+0Erf2RBwEClIAEbr2VC0B","1209":"b:7Nue3X+0Erf2RBwEClIAEbr2VC0B","1219":"b:7Nue3X+0Erf2RBwEClIAEbr2VC0B","1220":"b:7Nue3X+0Erf2RBwEClIAEbr2VC0B","1240":"b:7Nue3X+0Erf2RBwEClIAEbr2VC0B","1267":"b:7Nue3X+0Erf2RBwEClIAEbr2VC0B","1306":"b:7Nue3X+0Erf2RBwEClIAEbr2VC0B"},"packages/cli/src/workflows/workflows.controller.ts":{"69":"b:YNu+/Q88Ur/2TB4EGtaCkbv21C0B","93":"b:YNu+/Q88Ur/2TB4EGtaCkbv21C0B","130":"b:YNu+/Q88Ur/2TB4EGtaCkbv21C0B","155":"b:YNu+/Q88Ur/2TB4EGtaCkbv21C0B","171":"b:YNu+/Q88Ur/2TB4EGtaCkbv21C0B","205":"b:YNu+/Q88Ur/2TB4EGtaCkbv21C0B","288":"b:YNu+/Q88Ur/2TB4EGtaCkbv21C0B","295":"b:YNu+/Q88Ur/2TB4EGtaCkbv21C0B","343":"b:YNu+/Q88Ur/2TB4EGtaCkbv21C0B","354":"b:YNu+/Q88Ur/2TB4EGtaCkbv21C0B","375":"b:YNu+/Q88Ur/2TB4EGtaCkbv21C0B","409":"b:YNu+/Q88Ur/2TB4EGtaCkbv21C0B","443":"b:YNu+/Q88Ur/2TB4EGtaCkbv21C0B","477":"b:YNu+/Q88Ur/2TB4EGtaCkbv21C0B","508":"b:YNu+/Q88Ur/2TB4EGtaCkbv21C0B","551":"b:YNu+/Q88Ur/2TB4EGtaCkbv21C0B","557":"b:YNu+/Q88Ur/2TB4EGtaCkbv21C0B","571":"b:YNu+/Q88Ur/2TB4EGtaCkbv21C0B","572":"b:YNu+/Q88Ur/2TB4EGtaCkbv21C0B","576":"b:YNu+/Q88Ur/2TB4EGtaCkbv21C0B","577":"b:YNu+/Q88Ur/2TB4EGtaCkbv21C0B","581":"b:YNu+/Q88Ur/2TB4EGtaCkbv21C0B","582":"b:YNu+/Q88Ur/2TB4EGtaCkbv21C0B","603":"b:YNu+/Q88Ur/2TB4EGtaCkbv21C0B","627":"b:YNu+/Q88Ur/2TB4EGtaCkbv21C0B","634":"b:YNu+/Q88Ur/2TB4EGtaCkbv21C0B","651":"b:YNu+/Q88Ur/2TB4EGtaCkbv21C0B","671":"b:YNu+/Q88Ur/2TB4EGtaCkbv21C0B","697":"b:YNu+/Q88Ur/2TB4EGtaCkbv21C0B","710":"b:YNu+/Q88Ur/2TB4EGtaCkbv21C0B","728":"b:YNu+/Q88Ur/2TB4EGtaCkbv21C0B"},"packages/community-node-types-utils.ts":{"34":"b:ANs2oA84EpGgBAAACBAAAYgEAAAA","40":"b:ANs2oA84EpGgBAAACBAAAYgEAAAA","57":"b:ANs2oA84EpGgBAAACBAAAYgEAAAA"},"packages/community-node-types.controller.ts":{"9":"b:ANs2oA84EpGgBAAACBAAAYgEAAAA","12":"b:ANs2oA84EpGgBAAACBAAAYgEAAAA","17":"b:ANs2oA84EpGgBAAACBAAAYgEAAAA"},"packages/community-node-types.service.ts":{"29":"b:ANs2oA84EpGgBAAACBAAAYgEAAAA","35":"b:ANs2oA84EpGgBAAACBAAAYgEAAAA","52":"b:ANs2oA84EpGgBAAACBAAAYgEAAAA","83":"b:ANs2oA84EpGgBAAACBAAAYgEAAAA","125":"b:ANs2oA84EpGgBAAACBAAAYgEAAAA","133":"b:ANs2oA84EpGgBAAACBAAAYgEAAAA","149":"b:ANs2oA84EpGgBAAACBAAAYgEAAAA","151":"b:ANs2oA84EpGgBAAACBAAAYgEAAAA","164":"b:ANs2oA84EpGgBAAACBAAAYgEAAAA","186":"b:ANs2oA84EpGgBAAACBAAAYgEAAAA","192":"b:ANs2oA84EpGgBAAACBAAAYgEAAAA","197":"b:ANs2oA84EpGgBAAACBAAAYgEAAAA","202":"b:ANs2oA84EpGgBAAACBAAAYgEAAAA","204":"b:ANs2oA84EpGgBAAACBAAAYgEAAAA","206":"b:ANs2oA84EpGgBAAACBAAAYgEAAAA","209":"b:ANs2oA84EpGgBAAACBAAAYgEAAAA","216":"b:ANs2oA84EpGgBAAACBAAAYgEAAAA","222":"b:ANs2oA84EpGgBAAACBAAAYgEAAAA","229":"b:ANs2oA84EpGgBAAACBAAAYgEAAAA","234":"b:ANs2oA84EpGgBAAACBAAAYgEAAAA"},"packages/core/src/index.ts":{"5":"b:AKoAoHhQRpjwBAAQAEAAAAAEgAAA","24":"b:AKoAoHhQRpjwBAAQAEAAAAAEgAAA"},"packages/core/src/nodes-loader/directory-loader.ts":{"37":"b:ANsawH8yEpXhBQAADNAAhaj0FiwB","88":"b:ANsawH8yEpXhBQAADNAAhaj0FiwB","108":"b:ANsawH8yEpXhBQAADNAAhaj0FiwB","117":"b:ANsawH8yEpXhBQAADNAAhaj0FiwB","123":"b:ANsawH8yEpXhBQAADNAAhaj0FiwB","135":"b:ANsawH8yEpXhBQAADNAAhaj0FiwB","139":"b:ANsawH8yEpXhBQAADNAAhaj0FiwB","143":"b:ANsawH8yEpXhBQAADNAAhaj0FiwB","145":"b:ANsawH8yEpXhBQAADNAAhaj0FiwB","146":"b:ANsawH8yEpXhBQAADNAAhaj0FiwB","147":"b:ANsawH8yEpXhBQAADNAAhaj0FiwB","150":"b:ANsawH8yEpXhBQAADNAAhaj0FiwB","166":"b:ANsawH8yEpXhBQAADNAAhaj0FiwB","230":"b:ANsawH8yEpXhBQAADNAAhaj0FiwB","243":"b:ANsawH8yEpXhBQAADNAAhaj0FiwB","261":"b:ANsawH8yEpXhBQAADNAAhaj0FiwB","290":"b:ANsawH8yEpXhBQAADNAAhaj0FiwB","311":"b:ANsawH8yEpXhBQAADNAAhaj0FiwB","314":"b:ANsawH8yEpXhBQAADNAAhaj0FiwB","326":"b:ANsawH8yEpXhBQAADNAAhaj0FiwB","328":"b:ANsawH8yEpXhBQAADNAAhaj0FiwB","333":"b:ANsawH8yEpXhBQAADNAAhaj0FiwB","345":"b:ANsawH8yEpXhBQAADNAAhaj0FiwB","370":"b:ANsawH8yEpXhBQAADNAAhaj0FiwB","401":"b:ANsawH8yEpXhBQAADNAAhaj0FiwB","407":"b:ANsawH8yEpXhBQAADNAAhaj0FiwB","413":"b:ANsawH8yEpXhBQAADNAAhaj0FiwB","425":"b:ANsawH8yEpXhBQAADNAAhaj0FiwB","444":"b:ANsawH8yEpXhBQAADNAAhaj0FiwB","461":"b:ANsawH8yEpXhBQAADNAAhaj0FiwB","480":"b:ANsawH8yEpXhBQAADNAAhaj0FiwB","500":"b:ANsawH8yEpXhBQAADNAAhaj0FiwB","514":"b:ANsawH8yEpXhBQAADNAAhaj0FiwB","534":"b:ANsawH8yEpXhBQAADNAAhaj0FiwB","535":"b:ANsawH8yEpXhBQAADNAAhaj0FiwB","538":"b:ANsawH8yEpXhBQAADNAAhaj0FiwB"},"packages/core/src/nodes-loader/index.ts":{"2":"b:AKoAoHhQRpjwBAAQAEAAAAAEgAAA","4":"b:AKoAoHhQRpjwBAAQAEAAAAAEgAAA"},"packages/core/src/observability/tracing/tracing.ts":{"37":"b:ANsGgA80EpHwBAAACFAAAYj0FgAA","61":"b:ANsGgA80EpHwBAAACFAAAYj0FgAA","68":"b:ANsGgA80EpHwBAAACFAAAYj0FgAA","76":"b:ANsGgA80EpHwBAAACFAAAYj0FgAA","81":"b:ANsGgA80EpHwBAAACFAAAYj0FgAA","89":"b:ANsGgA80EpHwBAAACFAAAYj0FgAA"},"packages/workflow/src/index.ts":{"93":"b:APsWgH8wEr/hDQAgClxiEYn0EC4B"},"packages/workflow/src/utils.ts":{"18":"b:APseoH82ErfxDQIgCFQCmYn2FCcA","29":"b:APseoH82ErfxDQIgCFQCmYn2FCcA","37":"b:APseoH82ErfxDQIgCFQCmYn2FCcA","58":"b:APseoH82ErfxDQIgCFQCmYn2FCcA","97":"b:APseoH82ErfxDQIgCFQCmYn2FCcA","102":"b:APseoH82ErfxDQIgCFQCmYn2FCcA","103":"b:APseoH82ErfxDQIgCFQCmYn2FCcA","110":"b:APseoH82ErfxDQIgCFQCmYn2FCcA","128":"b:APseoH82ErfxDQIgCFQCmYn2FCcA","130":"b:APseoH82ErfxDQIgCFQCmYn2FCcA","157":"b:APseoH82ErfxDQIgCFQCmYn2FCcA","200":"b:APseoH82ErfxDQIgCFQCmYn2FCcA","206":"b:APseoH82ErfxDQIgCFQCmYn2FCcA","216":"b:APseoH82ErfxDQIgCFQCmYn2FCcA","241":"b:APseoH82ErfxDQIgCFQCmYn2FCcA","245":"b:APseoH82ErfxDQIgCFQCmYn2FCcA","246":"b:APseoH82ErfxDQIgCFQCmYn2FCcA","250":"b:APseoH82ErfxDQIgCFQCmYn2FCcA","251":"b:APseoH82ErfxDQIgCFQCmYn2FCcA","259":"b:APseoH82ErfxDQIgCFQCmYn2FCcA","267":"b:APseoH82ErfxDQIgCFQCmYn2FCcA","278":"b:APseoH82ErfxDQIgCFQCmYn2FCcA","296":"b:APseoH82ErfxDQIgCFQCmYn2FCcA","300":"b:APseoH82ErfxDQIgCFQCmYn2FCcA","302":"b:APseoH82ErfxDQIgCFQCmYn2FCcA","309":"b:APseoH82ErfxDQIgCFQCmYn2FCcA","322":"b:APseoH82ErfxDQIgCFQCmYn2FCcA","326":"b:APseoH82ErfxDQIgCFQCmYn2FCcA","343":"b:APseoH82ErfxDQIgCFQCmYn2FCcA","360":"b:APseoH82ErfxDQIgCFQCmYn2FCcA","363":"b:APseoH82ErfxDQIgCFQCmYn2FCcA","370":"b:APseoH82ErfxDQIgCFQCmYn2FCcA","407":"b:APseoH82ErfxDQIgCFQCmYn2FCcA","413":"b:APseoH82ErfxDQIgCFQCmYn2FCcA","417":"b:APseoH82ErfxDQIgCFQCmYn2FCcA","426":"b:APseoH82ErfxDQIgCFQCmYn2FCcA","438":"b:APseoH82ErfxDQIgCFQCmYn2FCcA","446":"b:APseoH82ErfxDQIgCFQCmYn2FCcA","454":"b:APseoH82ErfxDQIgCFQCmYn2FCcA","473":"b:APseoH82ErfxDQIgCFQCmYn2FCcA","492":"b:APseoH82ErfxDQIgCFQCmYn2FCcA","495":"b:APseoH82ErfxDQIgCFQCmYn2FCcA"},"packages/workflow/src/versioned-node-type.ts":{"10":"b:ANoSQHYwEpVgBQAACEAAgYjkFCAA","19":"b:ANoSQHYwEpVgBQAACEAAgYjkFCAA","23":"b:ANoSQHYwEpVgBQAACEAAgYjkFCAA"},"packages/workflow/src/workflow-checksum.ts":{"46":"b:ANsGgA80EpHwBAAACFAAAYj0FAAA","50":"b:ANsGgA80EpHwBAAACFAAAYj0FAAA","74":"b:ANsGgA80EpHwBAAACFAAAYj0FAAA","99":"b:ANsGgA80EpHwBAAACFAAAYj0FAAA"},"packages/workflow/src/workflow-structure-validation.ts":{"94":"b:ANsGgA80EpHwBAAACFAAAYj0FgAA","97":"b:ANsGgA80EpHwBAAACFAAAYj0FgAA","103":"b:ANsGgA80EpHwBAAACFAAAYj0FgAA","105":"b:ANsGgA80EpHwBAAACFAAAYj0FgAA","113":"b:ANsGgA80EpHwBAAACFAAAYj0FgAA","119":"b:ANsGgA80EpHwBAAACFAAAYj0FgAA","190":"b:ANsGgA80EpHwBAAACFAAAYj0FgAA"},"packages/@n8n/composables/src/structuralComputed.ts":{"21":"b:cP974A8y/v/h/4Ph//////sPgAAA","27":"b:cP974A8w/v/h/wPg//////sPgAAA"},"packages/@n8n/composables/src/useShortKeyPress.ts":{"6":"b:cP9/4A84/v/n/wPg//////8PgAAA","22":[151],"33":"b:ADIAAAAAAAAAAAAABAEJHQAAgAAA"},"packages/@n8n/composables/src/useThrottleWithReactiveDelay.ts":{"7":"b:cP8f4A84/v/n/wOg//////8PAAAA","12":"b:cP8f4A84/v/n/wOg//////8PAAAA"},"packages/@n8n/design-system/src/components/N8nBlockUi/BlockUi.vue":{"12":"b:MN5b4A0w1s7h+QMgz+3//ysCAAAA","13":"b:MN5b4A0w1s7h+QMgz+3//isCAAAA"},"packages/@n8n/design-system/src/components/N8nIcon/custom/bolt-filled.svg":{"9":"b:cP974A8w/v/h/wPg3/////sPAAAA"},"packages/@n8n/design-system/src/components/N8nIcon/custom/grip-lines-vertical.svg":{"9":[15,16,49,69,119,120]},"packages/@n8n/design-system/src/components/N8nIcon/custom/node-ellipsis.svg":{"11":"b:cP974A8w/v/h/wOg//////sPAAAA"},"packages/@n8n/design-system/src/components/N8nIcon/custom/node-play.svg":{"11":"b:cP8b4A8w/v/h/wOg3/////sPAAAA"},"packages/@n8n/design-system/src/components/N8nIcon/custom/node-power.svg":{"11":"b:cP8b4A8w/v/h/wMg3/////sPAAAA"},"packages/@n8n/design-system/src/components/N8nIcon/custom/node-trash.svg":{"11":"b:cP8b4A8w/v/h/wMg//////sPAAAA"},"packages/@n8n/design-system/src/components/N8nIcon/custom/node-validation-error.svg":{"11":"b:ML4Z4AEw1gZhnQAgBU2iL+INAAAA"},"packages/@n8n/design-system/src/components/N8nIcon/custom/pop-out.svg":{"8":"b:cP8f4A84/v/n/wOg//////8PAAAA"},"packages/@n8n/design-system/src/components/N8nIcon/custom/vector-square.svg":{"9":[15,16,49,69,119,120]},"packages/@n8n/design-system/src/components/N8nIcon/icons.ts":{"777":"b:cP974A8w/v/h/wPg3/////sPAAAA","781":"b:cP974A8y/v/h+0Pg3/////sPAAAA"},"packages/@n8n/design-system/src/components/N8nIcon/nodes/ai-agent.svg":{"11":"b:AIABAAAQAgAAGAAAAUCAAQAAAAAA"},"packages/@n8n/design-system/src/components/N8nIcon/nodes/call-n8n-sub-workflow-tool.svg":{"11":[15,41,49,119]},"packages/@n8n/design-system/src/components/N8nIcon/nodes/chat-trigger.svg":{"11":"b:cMoboAkw/k4h8ACgx02vfaoCAAAA"},"packages/@n8n/design-system/src/components/N8nIcon/nodes/form-trigger.svg":{"11":"b:cIoZoAkw/k4h0AAgxw2vfaoCAAAA"},"packages/@n8n/design-system/src/components/N8nIcon/nodes/http-request.svg":{"11":"b:AJAAYAUyAgQBgEAAAQSABAAIAAAA"},"packages/@n8n/design-system/src/components/N8nIcon/nodes/manual-trigger.svg":{"11":"b:cJ974A8w/v/h2gNg13///+sCAAAA"},"packages/@n8n/design-system/src/components/N8nIcon/nodes/schedule-trigger.svg":{"11":"b:cKoZoAkw/k4h0QAgz82vfboDAAAA"},"packages/@n8n/design-system/src/components/N8nIcon/nodes/sub-workflow-trigger.svg":{"11":"b:cIoZoAkw/k4h0AAgxw2vfaoCAAAA"},"packages/@n8n/design-system/src/components/N8nIcon/nodes/webhook.svg":{"11":"b:cIpZoAsw/s4h0AAgx42vfaoCAAAA"},"packages/@n8n/design-system/src/components/N8nNodeCreatorNode/NodeCreatorNode.vue":{"32":"b:cIoZoAkw/k4h0AAgxy3vfaoCAAAA","33":"b:cIoZoAkw/k4h0AAgxy3vfCoCAAAA","58":"b:MIAAgAAQIAggAAAAAgEgASAAAAAA","61":[15,49,119]},"packages/@n8n/errors/src/application.error.ts":{"18":"b:qILhNCA2AwJgMFAGAUClG8BMAIAA"},"packages/@n8n/tournament/src/ExpressionBuilder.ts":{"25":"b:MP9b4HcwVp7h/0KgX+///6vnEK4A","29":"b:MP9b4HcwVp7h/0KAX+///6vmEK4A","33":"b:AONbIHMQBoJhOgKgQ8jqn4PjEK4A","37":"b:AMMaAHIAAIJBAAIAAkhPhIHiEK4A","50":"b:MP9b4HcwVp7h/0KgX+///6vnEK4A","54":"b:AMMaAHIAAIJBAgIAAkhKhIHiEK4A","58":"b:AMMaAHIAAIJBAAIAAkhKhIHiEK4A","62":"b:AMNbIHMQAoJBOgKgQ8jqh4HjEK4A","71":"b:MP9b4HcwVp7h/0KgX+///6vnEK4A","75":"b:AMMaAHIAAIJBCAIgAkjKhIHiEK4A","88":"b:MP9b4HcwVp7h/0KgX+///6vnEK4A","103":"b:MP9b4HcwVp7h/0KgX+///6vnEK4A","110":"b:AOMaAHIAAIJBIwIAAkhqhIHiEK4A","136":"b:MP9b4HcwVp7h/0KgX+///6vnEK4A","137":"b:AMMaAHIAAIJBCAIgAkjKhIHiEK4A","141":"b:AMMaAHIAAIJBCAIgAkjKhIHiEK4A","157":"b:MP9b4HcwVp7h/0KgX+///6vnEK4A","158":"b:MP9b4HcwVp7h/0KgX+///6vnEK4A","171":"b:MP9b4HcwVp7h/0KgX+///6vnEK4A","188":"b:MP9b4HcwVp7h/0KgX+///6vnEK4A","197":"b:MP9b4HcwVp7h/0KgX+///6vnEK4A","198":"b:MP9b4HcwVp7h/0KgX+///6vnEK4A","263":"b:AOMaAHIAAIJBIwIAAkhqhIHiEK4A"},"packages/@n8n/tournament/src/ExpressionSplitter.ts":{"19":"b:MP9T4HcwVp7h/0KgX+///6vnECQA","23":"b:MP9T4HcwVp7h/0KgX+///6vnECQA","27":"b:MP9T4HcwVp7h/0KgX+///6vnECQA","101":"b:AMMSAHIAAIBAAAIAAEACgIHiECQA","105":"b:AMMSAHIAAIBAAAIAAEACgIHiECQA","107":"b:AMMSAHIAAIBAAAIAAEACgIHiECQA"},"packages/@n8n/tournament/src/FunctionEvaluator.ts":{"6":"b:AMMSAHIAAIBAAAIAAEACgIHiECQA","8":"b:MP9T4HcwVp7h/0KgX+///6vnECQA","18":"b:MP9T4HcwVp7h/0KgX+///6vnECQA"},"packages/@n8n/tournament/src/Parser.ts":{"5":"b:MP9T4HcwVp7h/0KgX+///6vnECQA"},"packages/@n8n/tournament/src/VariablePolyfill.ts":{"12":"b:AMEbAHIQAoBBGAIAAUCChIHiEC4A","22":"b:MP9b4HcwVp7h/0KgX+///6vnEC4A","33":"b:MP9b4HcwVp7h/0KgX+///6vnEC4A","46":"b:MP9b4HcwVp7h/0KgX+///6vnEC4A","73":"b:MP9b4HcwVp7h/0KgX+///6vnEC4A","78":"b:AMEaAHIAAIBBAAIAAEAChIHiEC4A","83":"b:AMFbIHMQAoBBOgKgQ8jnh4HjEC4A","102":"b:AMEaAHIAAIBBAAIAAEAChIHiEC4A","107":"b:AMFbIHMQAoBBGgIgQ8jih4HjEC4A","114":"b:MP9b4HcwVp7h/0KgX+///6vnEC4A","119":"b:AMEaAHIAAIBBAAIAAEAChIHiEC4A","122":"b:MP9b4HcwVp7h/0KgX+///6vnEC4A"},"packages/@n8n/utils/src/event-queue.ts":{"7":"b:cP9/4A84/v/n/wvo//////8PAAAA","17":"b:cP8fwA8wAP/naQKgn///1/8OAAAA","44":"b:cP8fwA8wAP/naQKgn///1/8OAAAA"},"packages/@n8n/utils/src/search/reRankSearchResults.ts":{"1":"b:cIoZoAkw/k4h0AAgxy3vfSoCgAAA","6":"b:cIoZoAkw/k4h0AAgxy3vfSoCgAAA","9":"b:cIoZoAkw/k4h0AAgxy3vfSoCgAAA","23":"b:MIoJoAkQ5EghEAAgxwGvZSACgAAA"},"packages/@n8n/utils/src/search/sublimeSearch.ts":{"25":"b:cIoZoAkw/k4h0AAgxy3vfSoCgAAA","41":"b:cIoZoAkw/k4h0AAgxy3vfSoCgAAA","182":"b:cIoZoAkw/k4h0AAgxy3vfSoCgAAA","205":"b:cIoZoAkw/k4h0AAgxy3vfSoCgAAA","222":"b:cIoZoAkw/k4h0AAgxy3vfSoCgAAA","231":"b:cIoZoAkw/k4h0AAgxy3vfSoCgAAA","285":"b:MIoJoAkQ5EghEAAgxwGvZSACgAAA"},"packages/frontend/editor-ui/src/app/api/workflows.ts":{"26":"b:cL59oA84/m5l1gPg503vff4PAAAA","39":"b:cL59oA84/m5l1gPg503vff4PAAAA","65":"b:cMcTQA4gALv9aQIgnvrzw9sOAAAA","69":"b:cL4doA84/m5l0gMg503vfb4DAAAA","73":[93,137],"87":[83],"98":"b:uACAXQCAAQA+ABAEAAIAQBsKAAAA","114":"b:+P+f/Q+4/////xMk//////8PAAAA","136":"b:ANcLAA4gAP/BaAKAh/x/l8EAAAAA","149":"b:MMECQAIAAJugKQAAHvryw9kOAAAA","160":"b:cP8fwA8wAP/laQIgn///1/8OAAAA"},"packages/frontend/editor-ui/src/app/components/BreakpointsObserver.vue":{"30":"b:cP8f4A84/v/n/wMg//////8PAAAA","37":"b:cP8f4A84/v/n/wMg//////8PAAAA","53":"b:cP8f4A84/v/n/wMg//////8PAAAA","72":[65,108],"76":[65,108],"84":"b:cP8f4A84/v/n/wMg//////8PAAAA","88":[65,69,105,126,132],"91":"b:cP8f4A84/v/n/wMg//////8PAAAA"},"packages/frontend/editor-ui/src/app/components/ConnectionTracker.vue":{"26":"b:cP8f4A84/v/n/wMo//////8PAAAA"},"packages/frontend/editor-ui/src/app/components/Draggable.vue":{"40":"b:ON7b4A2w187/+QMgz+///zsKAAAA","44":"b:AAAAAAAAAAA+AAAAAAJSAggCAAAA","78":[65,113],"105":[65,113],"115":[65,66,67,68,69,105,113,137],"127":[65,66,67,68,69,105,113,137],"135":"b:CNKbYAiwV06/+QEgz+//dykCAAAA","149":"b:ON7b4A2w187/+QMgz+///zsKAAAA"},"packages/frontend/editor-ui/src/app/components/DraggableTarget.vue":{"15":"b:ML5b4A0y1s7h+cMhz+3//ysCAAAA","31":"b:ML4b4A0y1s7h+cMgz+3//ysCAAAA","32":[113],"34":"b:ML5b4A0y1s7h+cMhz+3//ysCAAAA","37":"b:ML5b4A0y1s7h+cMhz+3//ysCAAAA","39":[113],"49":"b:AKpZ4A0ykAYhwUAAx+lv3woAAAAA","53":"b:AIpZ4A0ykAYhwUAAx+lv3woAAAAA","57":"b:AIAYQAUykAYhAEAAgIEvHwIAAAAA","64":[113],"79":"b:ML5b4A0y1s7h+cMhz+3//ysCAAAA"},"packages/frontend/editor-ui/src/app/components/FocusSidebar.vue":{"33":"b:cP9/4A84/v/n/wOg//////8PAAAA","52":"b:cP9/4A84/v/n/wOg//////8PAAAA","53":[80,99],"54":"b:cP9f4A84/v/n/wOg//////8HAAAA","56":[80,99],"63":[80,99],"66":[80,99],"74":[80,99],"86":[80,99],"91":"b:cP9f4A84/v/n/wOg//////8HAAAA","99":[80,99],"115":[80,99],"119":"b:cP9/4A84/v/n/wOg//////8PAAAA","123":"b:cP9/4A84/v/n/wOg//////8PAAAA","124":"b:cP9/4A84/v/n/wOg//////8PAAAA","135":"b:cP9f4A84/v/n/wOg//////8HAAAA","163":"b:cP9/4A84/v/n/wOg//////8PAAAA","167":"b:AIAAAAAAAAAgAAAgBF4AQNAIAAAA","170":"b:cP9/4A84/v/n/wOg//////8PAAAA","192":[80,99]},"packages/frontend/editor-ui/src/app/components/MainHeader/ActionsDropdownMenu.vue":{"44":"b:cP8f4A84/v/n/wMg//////8PAAAA","74":"b:cP8f4A84/v/n/wMg//////8PAAAA","78":"b:cP8f4A84/v/n/wMg//////8PAAAA","86":"b:cP8f4A84/v/n/wMg//////8PAAAA","88":"b:cP8f4A84/v/n/wMg//////8PAAAA","92":"b:ABYAAAQAACBCggMAAEBgRQABAAAA","96":"b:ABYAAAQAACBCggMAAEBgRQABAAAA","118":"b:cP8f4A84/v/n/wMg//////8PAAAA","246":"b:UBYAAAQAACBCggMAQEBgRRABAAAA","420":"b:cP8f4A84/v/n/wMg//////8PAAAA","428":"b:ABYAAAQAACBCggMAAEBgRQABAAAA"},"packages/frontend/editor-ui/src/app/components/MainHeader/MainHeader.vue":{"60":"b:cP8f4A84/v/n/wMg//////8PAAAA","68":"b:cP8f4A84/v/n/wMg//////8PAAAA","69":"b:cP8f4A84/v/n/wMg//////8PAAAA","74":"b:cP8f4A84/v/n/wMg//////8PAAAA","75":"b:cP8f4A84/v/n/wMg//////8PAAAA","76":"b:cP8f4A84/v/n/wMg//////8PAAAA","77":"b:cP8f4A84/v/n/wMg//////8PAAAA","78":"b:cP8f4A84/v/n/wMg//////8PAAAA","80":"b:cP8f4A84/v/n/wMg//////8PAAAA","83":[65],"86":"b:cP8f4A84/v/n/wMg//////8PAAAA","94":"b:cP8f4A84/v/n/wMg//////8PAAAA","104":"b:cL4f4A0w1u7n/QMgx/////8OAAAA","108":"b:cP8f4A84/v/n/wMg//////8PAAAA","112":[65,105,126,132],"116":"b:cP8f4A84/v/n/wMg//////8PAAAA","121":"b:cP8f4A84/v/n/wMg//////8PAAAA","128":"b:cP8f4A84/v/n/wMg//////8PAAAA","138":"b:cP8f4A84/v/n/wMg//////8PAAAA","158":"b:AIAAAAAAAAACAAAABFwAAMAAAAAA","179":[15,65,98,135],"210":"b:AIAAAAAAAAACAAAABFwAAMAAAAAA","236":[65],"254":[65],"258":[65]},"packages/frontend/editor-ui/src/app/components/MainHeader/TabBar.vue":{"22":"b:AIAAAAAAAAACAAAABFwAAMAAAAAA","24":"b:cP8f4A84/v/n/wMg//////8PAAAA"},"packages/frontend/editor-ui/src/app/components/MainHeader/WorkflowDetails.vue":{"47":"b:cP8f4A84/v/n/wMg//////8PAAAA","93":[65,130],"99":[65],"102":"b:cP8f4A84/v/n/wMg//////8PAAAA","106":"b:cP8f4A84/v/n/wMg//////8PAAAA","110":"b:cP8f4A84/v/n/wMg//////8PAAAA","115":"b:cP8f4A84/v/n/wMg//////8PAAAA","120":"b:AAAAAAAAAAACAAEAAAAAQBwNAAAA","122":"b:cP8f4A84/v/n/wMg//////8PAAAA","134":"b:cP8f4A84/v/n/wMg//////8PAAAA","135":[65,69,126,132],"142":[65,130],"150":[65,130],"157":[65,130],"186":[65],"191":[65],"197":"b:QBYAAAQgACBGggMAAEBgRQADAAAA","223":[65,132],"267":[65],"288":[65],"324":[65,132],"334":[65,132],"386":[65],"388":[65],"394":"b:ABYAAAQAACBCggMAAEBgRQABAAAA","400":"b:cP8f4A84/v/n/wMg//////8PAAAA","409":[65,69,105,126,132],"417":"b:cP8f4A84/v/n/wMg//////8PAAAA","428":"b:cP8f4A84/v/n/wMg//////8PAAAA","434":"b:cP8f4A84/v/n/wMg/////n8PAAAA","493":[132],"500":"b:cP8f4A84/v/n/wMg//////8PAAAA"},"packages/frontend/editor-ui/src/app/components/MainHeader/WorkflowHeaderDraftPublishActions.vue":{"65":"b:cP8f4A84/v/n/wMg//////8PAAAA","80":"b:cP8f4A84/v/n/wMg//////8PAAAA","87":"b:cP8f4A84/v/n/wMg//////8PAAAA","89":[65],"98":"b:ABYAAAQAACBCggMAAEBgRQABAAAA","100":"b:cP8f4A84/v/n/wMg//////8PAAAA","104":"b:cP8f4A84/v/n/wMg//////8PAAAA","108":"b:cP8fwA8wBv/neQIgn///9/8PAAAA","112":"b:AOoTIAMQBsIDNQAgSsivbTAPAAAA","122":"b:cP8f4A84/v/n/wMg//////8PAAAA","146":"b:cP8fwA8wAP/naQIgn///1/8OAAAA","147":"b:cP8fwA8wAP/naQIgn///1/8OAAAA","148":"b:cP8f4A84/v/n/wMg//////8PAAAA","149":[33,63,65,93,132,133,137],"151":"b:cL4doA84/m5n1gMg503vfb4PAAAA","157":[65,137],"182":[63,65,93,132,133,137],"198":"b:cP8f4A84/v/n/wMg//////8PAAAA","309":"b:cP8f4A84/v/n/wMg//////8PAAAA","314":"b:cP8f4A84/v/n/wMg//////8PAAAA","323":"b:cP8f4A84/v/n/wMg//////8PAAAA","325":[65],"332":[65],"337":"b:cP8f4A84/v/n/wMg//////8PAAAA","342":"b:cP8f4A84/v/n/wMg//////8PAAAA","344":"b:cP8f4A84/v/n/wMg//////8PAAAA","379":"b:cP8f4A84/v/n/wMg//////8PAAAA","384":"b:cP8f4A84/v/n/wMg//////8PAAAA","387":[65],"412":[65],"447":[65],"457":[65],"477":[65],"502":[65],"503":[65],"508":[65],"512":[65],"517":[65],"523":"b:cP8f4A84/v/n/wMg//////8PAAAA","528":[65,69,105,126,132],"536":"b:cP8f4A84/v/n/wMg//////8PAAAA","571":"b:cP8f4A84/v/n/wMg//////8PAAAA","581":"b:cP8f4A84/v/n/wMg/////n8PAAAA","609":"b:cP8f4A84/v/n/wMg//////8PAAAA"},"packages/frontend/editor-ui/src/app/components/NodeExecuteButton.vue":{"15":"b:MJ4b4A0w1s7h+QMgz+3//ysCAAAA","59":"b:MJ4b4A0w1s7h+QMgz+3//ysCAAAA","74":"b:AAYDAAQAAESBIAAAgIBqFgAAAAAA","81":"b:MJ4b4A0w1s7h+QMgz+3//ysCAAAA","93":"b:MJ4b4A0w1s7h+QMgz+3//ysCAAAA","99":"b:MJ4b4A0w1s7h+QMgz+3//ysCAAAA","105":"b:MJ4b4A0w1s7h+QMgz+3//ysCAAAA","116":"b:MJ4b4A0w1k6h8QEgz83vfyoAAAAA","120":"b:AAYTAAQAAEaBIAAAgIBqFwAAAAAA","132":"b:AAYDAAQAAESBIAAAgIBqFgAAAAAA","136":"b:MJ4b4A0w1s7h+QMgz+3//ysCAAAA","148":"b:MJ4b4A0w1s7h+QMgz+3//ysCAAAA"},"packages/frontend/editor-ui/src/app/components/NodeIcon.vue":{"43":"b:cP5b4A0y/s7h/QOgz+3//6sOAAAA","44":"b:cP5b4A0y/s7h/QOgz+3//6sOAAAA","48":"b:cP974A8y/v/h/wPg3/////sPAAAA","50":"b:cP974A8y/v/h/wPg3/////sPAAAA","51":"b:cP974A8y/v/h/wPg3/////sPAAAA","56":"b:cP974A8y/v/h/wPg3/////sPAAAA","61":"b:cP974A8y/v/h/wPg3/////sPAAAA","66":"b:cP974A8y/v/h/wPg3/////sPAAAA","71":"b:cP974A8y/v/h/wPg3/////sPAAAA"},"packages/frontend/editor-ui/src/app/components/TidyUpIcon.vue":{"2":"b:cP8f4A84/v/n/wMg//////8PgAAA"},"packages/frontend/editor-ui/src/app/components/app/AppHeader.vue":{"6":"b:cP8f4A84/v/n/wMg//////8PAAAA"},"packages/frontend/editor-ui/src/app/components/transitions/SlideTransition.vue":{"3":"b:cP8f4A84/v/n/wMg//////8PAAAA"},"packages/frontend/editor-ui/src/app/composables/canvasConnectionReplacement.utils.ts":{"86":"b:MIgZoAgwkgYh0AAg5yWvfSIAAAAA","94":"b:MIgZoAgwgAYhEAAg5wUvbSIAAAAA","102":"b:MIgZoAgwkgYh0AAg5yWvfSIAAAAA","192":[78,79,96],"212":[78,79,96],"221":[78,79,96],"227":[78,79,96],"249":[78,79,96],"264":[78,79,96]},"packages/frontend/editor-ui/src/app/composables/useActivityDetection.ts":{"6":"b:cP9/4A84/v/n/wOg//////8PAAAA","9":"b:ALwAwAkAAAKhIAAgFaSGV/kGAAAA","15":"b:ILwAwAkQAIKhYAAgl+WGV/kGAAAA","16":"b:ILwAwAkQAIKhYAAgl+WGV/kGAAAA","21":"b:MIAAQAAAAAAkAAAgFF4AQNgOAAAA","22":"b:MIAAQAAAAAAkAAAgFF4AQNgOAAAA","28":"b:cP9/4A84/v/n/wOg//////8PAAAA","29":"b:ILwAwAkQAIKhYAAgl+WGV/kGAAAA","39":"b:cP9/4A84/v/n/wOg//////8PAAAA","46":"b:MIAAAAAAAAAkAAAgBF4AQNgOAAAA"},"packages/frontend/editor-ui/src/app/composables/useAutocompleteTelemetry.ts":{"11":"b:AIIBAAAQAoBAMUIAAUivHwIAAAAA","55":"b:AAAAAAAAAAAAAEAAAAAPHQAAAAAA","59":"b:AAAAAAAAAAAAAEAAAAAPHQAAAAAA","94":"b:AAAAAAAAAAAAAEAAAAAPHQAAAAAA","101":"b:AIIBAAAQAoBAMUIAAUivHwIAAAAA","107":"b:AIIBAAAQAoBAMUIAAUivHwIAAAAA"},"packages/frontend/editor-ui/src/app/composables/useCalloutHelpers.ts":{"33":"b:cIoZoAkw/k4h0AAgxy3vfaoCAAAA","111":[15,16,44,49,76,96,107,119,120]},"packages/frontend/editor-ui/src/app/composables/useCanvasOperations.ts":{"238":"b:cIoZoAkw/k4hUAAgxw2vfaoCAAAA","242":"b:cL4ZoA0w/m5h1gMg523vfasPAAAA","252":[13],"265":[13],"282":[13,77,96,97,100,102,131],"290":[13,77,96,97,100,102,131],"299":[13,77,78,79,96,97,100,102,131],"321":[102],"330":[79,128],"358":[128],"370":[98,120,129],"426":[73,96,97,100,102,110,128],"505":[73,96,97,100,102,110,128],"544":[96,97,100,102,128],"549":[96,97,100,102,128],"556":[102,128],"561":[73,96,97,100,102,110,128],"580":[128],"601":[128],"764":"b:MJ5b4A0w1s7h+QMgx+3//ysCAAAA","774":"b:MJ5b4A0w1s7h+QMgx+3//ysCAAAA","797":"b:cN9b4A0w/u7h+wMg/+3///sHAAAA","813":"b:AIAAAAAAAAAAAAAgRUAAAOAAAAAA","826":[102],"869":"b:cP974A8w/v/h/wOg//////sPAAAA","889":"b:cL4ZoA0w/m5h1gMg523vfasPAAAA","897":"b:cL4ZoA0w/m5h1gMg523vfasPAAAA","977":"b:cL4ZoA0w/m5h1gMg523vfasPAAAA","996":"b:cL4ZoA0w/m5h1gMg523vfasPAAAA","1010":[98,131],"1021":"b:cL4ZoA0w/m5h1gMg523vfasPAAAA","1044":"b:cL4ZoA0w/m5h1gMg523vfasPAAAA","1093":[102,128],"1102":[78,79,96],"1113":"b:cL4ZoA0w/m5h1gMg523vfasPAAAA","1186":"b:cIoZoAkw/k4h0AAg5y2vfaoCAAAA","1196":[101],"1202":"b:cIoZoAkw/k4h0AAgxy2vfaoCAAAA","1232":"b:cL4ZoA0w/m5h1gMg523vfasPAAAA","1275":"b:cL4ZoA0w/m5h1gMg523vfasPAAAA","1281":"b:cL4ZoA0w/m5h1gMg523vfasPAAAA","1286":"b:cL4ZoA0w/m5h1gMg523vfasPAAAA","1306":"b:cIoZoAkw/k4h0AAg5y2vfaoCAAAA","1318":"b:cP974A8w/v/h/wOg//////sPAAAA","1330":"b:cL4ZoA0w/m5h1gMg523vfasPAAAA","1456":"b:AIABAAAQAgABkAAAxyGFdAAAAAAA","1469":"b:MIgZoAgwkgYh0AAgxyWvfSIAAAAA","1490":[78,79,96],"1546":"b:MIgZoAgwkgYh0AAgxyWvfSIAAAAA","1551":[15,16,44,49,76,119],"1574":"b:AIAAAAAAAAABgAAAxyEFdAAAAAAA","1614":"b:cL4ZoA0w/m5h1gMg523vfasPAAAA","1620":"b:cP974A8w/v/h/wOg//////sPAAAA","1635":[78,79,96],"1657":[78,79,96],"1694":[78,79,96],"1709":[79],"1714":[78,79,96],"1716":[78,79,96],"1722":[79],"1736":[79],"1748":[79],"1762":[79],"1769":[79],"1776":[78,79,96],"1783":[78,79,96],"1791":[79,96],"1800":[79,96],"1804":[78,79,96],"1816":[78,79,96],"1819":[78,79,96],"1822":[78,79,96],"1923":[79],"1970":[78,79,96],"1989":[78,79,96],"2033":"b:ML4ZoA0w1i5h0gMg92XvfSsBAAAA","2073":"b:ML4ZoA0w1i5h0gMg12XvfSsBAAAA","2083":[102,128],"2098":[73,96,97,100,102,110,128],"2164":"b:ACAAAAAAAAAAwgAAU0AAAAEAAAAA","2200":"b:ACAAAAAAAAAAwgAAU0AAAAEAAAAA","2214":[102,128],"2225":[15,32,64,97,128],"2242":[15,97,128],"2269":[15,128],"2273":[32,64,97,128],"2277":"b:ML4ZoA0w1i5h0gMg92XvfSsBAAAA","2285":"b:ML4ZoA0w1i5h0gMg92XvfSsBAAAA","2291":"b:ML4ZoA0w1i5h0gMg12XvfSsBAAAA","2298":"b:ML4ZoA0w1i5h0gMg12XvfSsBAAAA","2302":"b:ML4ZoA0w1i5h0gMg12XvfSsBAAAA","2307":"b:ML4ZoA0w1i5h0gMg12XvfSsBAAAA","2386":"b:ML4ZoA0w1i5h0gMg12XvfSsBAAAA","2417":"b:cL4ZoA0w/m5h0gMg523vfaoDAAAA","2444":"b:cP9/4A84/v/n/wPg//////8PAAAA","2491":"b:cMdzQA4gALvhaQKAnvrzw9kOAAAA","2497":"b:YMdzQA4gALvhaQCAnvrzw9kOAAAA","2498":"b:YMdzQA4gALvhaQCAnvrzw9kOAAAA","2499":"b:YMdzQA4gALvhaQCAnvrzw9kOAAAA","2501":"b:YMdzQA4gALvhaQCAnvrzw9kOAAAA","2543":"b:ABYAAAQAACBAggMAREBgRQgBAAAA","2559":"b:ABYAAAQAACBAggMAREBgRQgBAAAA","2578":"b:ABYAAAQAACBAggMAREBgRQgBAAAA","2595":"b:ABYAAAQAACBAggMAREBgRQgBAAAA","2598":"b:ABYAAAQAACBAggMAREBgRQgBAAAA","2641":"b:ABYAAAQAACBAggMAREBgRQgBAAAA","2771":"b:ABYAAAQAACBAggMAREBgRQgBAAAA","2805":"b:ABYAAAQAACBAggMAREBgRQgBAAAA","2820":"b:ABYAAAQAACBAggMAREBgRQgBAAAA","2827":"b:ABYAAAQAACBAggMAREBgRQgBAAAA","2834":"b:ABYAAAQAACBAggMAREBgRQgBAAAA","2835":"b:ABYAAAQAACBAggMAREBgRQgBAAAA","2956":"b:ABYAAAQAACBAggMAREBgRQgBAAAA","2979":[61,79,80,118,120,122,126,136],"2981":[136],"2984":[80,126,136],"2988":[80,126,136],"2998":[80,126,136],"2999":[80,126,136],"3010":[136],"3033":[96,98,102,122,131,138],"3047":"b:ABYAAAQAACBAggMAREBgRQgBAAAA","3071":[96,98,102,122,131,138],"3083":[96,98,102,122,131,138],"3125":[138],"3130":[138],"3139":[96,98,102,122,131,138],"3160":[96,98,131,138],"3167":[96,98,131,138],"3168":[96,98,131,138],"3179":[98,102,122],"3186":[98,102,122],"3189":[96,131,138],"3201":[96,131,138],"3211":[110,134,135],"3261":[15,16,17,77,95],"3276":[15,16,17,77,95],"3281":[74,138,139],"3378":"b:cIoZoAkw/k4h0AAg5y2vfaoCAAAA","3404":"b:AIABAAEQ1ggAUAAAAACgGQgAAAAA","3454":"b:cP9/4A84/v/l/wPg//////8PAAAA","3455":"b:cP9/4A84/v/l/wPg//////8PAAAA","3458":[74,138,139],"3466":[74,138,139],"3473":[74,138,139]},"packages/frontend/editor-ui/src/app/composables/useDataSchema.ts":{"31":"b:cP9/4A84/v/n/wOg//////8PgAAA","34":"b:ACYKAAQAAIzASAIAiu1/twEAgAAA","57":[151],"64":"b:AAAAAAAAAAhAAAAACEAaAwAAgAAA","74":"b:AAYKAAQAAIzASAIAiu1/twEAgAAA","99":"b:ACYKAAQAAIzASAIAiu1/twEAgAAA","109":[151,111,125],"129":[151,111,125],"150":[151,111,125],"162":"b:AAYaAAQAAM6BSAIAgsx/lwEAgAAA","178":"b:ML5b4A0w1s7h+QMg3+3//ysCgAAA","206":"b:ML5b4A0w1s7h+QMg3+3//ysCgAAA","215":"b:AABAAAAAAAAAAAAACAVfBwEAgAAA","220":"b:AABAAAAAAAAAAAAACAVfBwEAgAAA","227":[151,118],"235":"b:AAYKAAQAAIzASAIAiu1/twEAgAAA","240":[151,118],"364":"b:AAYKAAQAAIzASAIAiu1/twEAgAAA","366":"b:AAYIAAQAAIzASAIAguxktgAAgAAA","377":[151,111,125],"384":"b:AAYKAAQAAIzASAIAiu1/twEAgAAA","393":"b:AAYKAAQAAIzASAIAiu1/twEAgAAA","395":"b:AAYKAAQAAIzASAIAiu1/twEAgAAA","398":[151,113,118],"406":"b:AAYKAAQAAIzASAIAiu1/twEAgAAA","467":"b:AAYKAAQAAIzASAIAiu1/twEAgAAA","508":"b:AAYIAAQAAIzASAIAiu1/twEAgAAA","513":"b:AAYIAAQAAIzASAIAiu1/twEAgAAA"},"packages/frontend/editor-ui/src/app/composables/useGlobalLinkActions.ts":{"14":"b:cP9/4A84/v/l/wOg//////8PAAAA","15":"b:cP9/4A84/v/l/wOg//////8PAAAA","18":"b:MIAAAAAAAAAkAAAgBF4AQNgOAAAA","22":[120],"34":"b:cP9f4A84/v/n+wOg//////8HAAAA","55":[120],"60":"b:cP9/4A84/v/n/wOg//////8PAAAA","69":"b:MIAAAAAAAAAkAAAgBF4AQNgOAAAA"},"packages/frontend/editor-ui/src/app/composables/useLayoutProps.ts":{"4":"b:cP8f4A84/v/n/wMg//////8PAAAA","7":"b:cP8f4A84/v/n/wMg//////8PAAAA"},"packages/frontend/editor-ui/src/app/composables/useNodeConnections.ts":{"12":"b:cP9/4A84/v/n/wPg//////8PgAAA","25":"b:cP9/4A84/v/n/wPg//////8PgAAA","26":"b:MP974A8w1r/h/wPg3////+sNgAAA","29":"b:cP9/4A84/v/n/wPg//////8PgAAA","30":"b:MP974A8w1r/h/wPg3////+sNgAAA","33":"b:cP9/4A84/v/n/wPg//////8PgAAA","34":"b:AIEDAAAQAgAAGAAgAUCAAQAAgAAA","37":"b:MP974A8w1r/h/wPg3////+sNgAAA","45":"b:cP9/4A84/v/n/wPg//////8PgAAA","46":"b:cP974A8w/v/h/wPg3/////sPgAAA","49":"b:cP9/4A84/v/n/wPg//////8PgAAA","50":"b:cP974A8w/v/h/wPg3/////sPgAAA","53":"b:cP974A8w/v/h/wPg3/////sPgAAA","61":[151,97,100,128]},"packages/frontend/editor-ui/src/app/composables/useNodeDocsUrl.ts":{"5":"b:cP9/4A84/v/n/wOg//////8PAAAA","8":[55],"10":[44,55,118,119],"18":"b:MJ5b4A0w1s7h+QMgz+3//ysCAAAA"},"packages/frontend/editor-ui/src/app/composables/useNodeExecution.ts":{"81":"b:ML4b4A0w1s7h+QMgz+3//ysCAAAA","105":"b:ML4b4A0w1s7h+QMgz+3//ysCAAAA","114":"b:ML4b4A0w1s7h+QMgz+3//ysCAAAA","118":"b:ML4b4A0w1s7h+QMgx+3//ysCAAAA","124":"b:ML4b4A0w1s7h+QMgz+3//ysCAAAA","128":[20,57,64],"130":"b:ML4b4A0w1s7h+QMgx+3//ysCAAAA","132":"b:AAYDAAQAAESBIAAAgIBqFgAAAAAA","138":"b:ML4b4A0w1s7h+QMgx+3//ysAAAAA","140":"b:ML4b4A0w1s7h+QMgx+3//ysAAAAA","142":[9,20,57,62,64,122],"144":"b:ML4b4A0w1s7h+QMgx+3//ysCAAAA","146":"b:ML4b4A0w1s7h+QMgz+3//ysCAAAA","156":"b:ML4b4A0w1s7h+QMgz+3//ysCAAAA","169":"b:ML4b4A0w1s7h+QMgx+3//ysCAAAA","177":"b:ML4b4A0w1s7h+QMgz+3//ysCAAAA","183":"b:AKoRIAEQBEIBAQAgQom/bCACAAAA","190":"b:MJ4b4A0w1s7h+QMgz+3//ysCAAAA","214":"b:ML4b4A0w1s7h+QMgx+3//ysCAAAA","242":"b:ML4b4A0w1s7h+QMgx+3//ysCAAAA","248":"b:ML4b4A0w1s7h+QMgz+3//ysCAAAA","348":[16,17,77],"357":"b:AAYDAAQAAESBIAAAgIBqFgAAAAAA"},"packages/frontend/editor-ui/src/app/composables/useNodeIconSource.ts":{"6":"b:cP9/4A86/v/l/wPg//////8PAAAA","12":"b:cP5b4A0y/s7h/QOgz+3//6sOAAAA"},"packages/frontend/editor-ui/src/app/composables/useNodeType.ts":{"8":"b:cP9/4A84/v/l/wOg//////8PAAAA","16":"b:cJ5b4A0w/s7h+QMgz+3//6sCAAAA","29":"b:cJ5b4A0w/s7h+QMgz+3//6sCAAAA","31":"b:MJ5b4A0w1s7h8QMgx+3//ysCAAAA"},"packages/frontend/editor-ui/src/app/composables/usePinnedData.ts":{"72":"b:MN5b4A0w1s7h+QMgz+3//ysDAAAA","80":"b:MN5b4A0w1s7h+QMgz+3//ysCAAAA","85":"b:MJ5b4A0w1s7h+QMgx+3//ysCAAAA","95":"b:MJ5b4A0w1s7h+QMg3+3//ysCAAAA","106":"b:MJ5b4A0w1s7h+QMgz+3//ysCAAAA","111":"b:MJ5b4A0w1s7h+QMgz+3//ysCAAAA","173":"b:AAAAAAAAAABAAAAAQAVvBwABAAAA","177":"b:AAAAAAAAAABAAAAAQAVvBwABAAAA","227":"b:AAAAAAAAAABAAAAAQAVvBwABAAAA","246":[122],"268":"b:AAAAAAAAAABAAAAAQAVvBwABAAAA"},"packages/frontend/editor-ui/src/app/composables/usePostMessageHandler.ts":{"39":"b:cP9/4A84/v/n/wOg//////8PAAAA","43":"b:cP9/4A84/v/n/wPg//////8PAAAA","65":"b:cP9/4A84/v/n/wPg//////8PAAAA","78":[65],"84":[21,22,65,95],"131":[65,110,134,135],"160":[65,110,134,135],"183":[65],"232":"b:cP9/4A84/v/n/wPg//////8PAAAA","294":"b:cP9/4A84/v/n/wPg//////8PAAAA","300":[65,105,126,132]},"packages/frontend/editor-ui/src/app/composables/usePushConnection/usePushConnection.ts":{"44":"b:cP9/4A84/v/n/wvo//////8PAAAA","45":"b:cP8fwA8wAP/naQKgn///1/8OAAAA","50":[65,105,126,132],"59":"b:cP8fwA8wAP/naQKgn///1/8OAAAA"},"packages/frontend/editor-ui/src/app/composables/useWorkflowExtraction.ts":{"39":"b:cP9/4A84/v/l/wOg//////8PAAAA","87":[128],"102":[128],"105":[128],"128":[128],"139":[128],"147":[128],"148":[128],"154":[128],"155":[128],"209":[128],"234":[128],"261":[128],"266":[128],"267":[128],"274":[128],"308":[128],"327":[128],"346":[128],"351":[128],"367":[128],"370":[128],"371":[128],"379":[128],"432":[128],"439":[128],"442":[128],"451":[128],"452":[128],"458":[128],"459":[128],"475":[128],"503":[128],"504":[128],"512":[128],"519":[128],"531":[128],"547":[128]},"packages/frontend/editor-ui/src/app/composables/useWorkflowImport.ts":{"11":"b:cP9/4A84/v/n/wPg//////8PAAAA","17":[21,22,65,95],"19":[21,22,65,95]},"packages/frontend/editor-ui/src/app/composables/useWorkflowInitialization.ts":{"81":"b:cP9/4A84/v/n/wPg//////8PAAAA","92":"b:cP8f4A84/v/n+wMg//////8PAAAA","93":"b:cP9/4A84/v/n+wPg//////8PAAAA","94":"b:cP9/4A84/v/n/wPg//////8PAAAA","95":[65],"96":"b:cP8f4A84/v/n/wMg//////8PAAAA","98":"b:cP8f4A84/v/n/wMg//////8PAAAA","123":"b:cP9/4A84/v/n/wPg//////8PAAAA","188":"b:MMECQAIAAJuiKQAAHv7yw9kOAAAA","205":"b:cP9/4A84/v/n/wPg//////8PAAAA","207":"b:cP9/4A84/v/n/wPg//////8PAAAA","243":"b:MMECQAIAAJuiKQAAHvryw9kOAAAA","295":"b:cL59oA84/m5n0gPg503vff4DAAAA","307":"b:cL59oA84/m5n0gPg503vff4DAAAA","338":"b:MMECQAIAAJuiKQAAHvryw9kOAAAA","393":"b:cP9/4A84/v/n/wPg//////8PAAAA","463":[65,105,126,132]},"packages/frontend/editor-ui/src/app/layouts/WorkflowLayout.vue":{"40":"b:cP8f4A84/v/n/wMg//////8PAAAA","49":[65,69,74,126,132,138,139],"62":[65,106],"70":[65,105,126,132],"79":"b:cP8f4A84/v/n/wMg//////8PAAAA","81":"b:cP8f4A84/v/n/wMg//////8PAAAA","83":"b:cP8f4A84/v/n/wMg//////8PAAAA","88":"b:cP8f4A84/v/n/wMg//////8PAAAA","91":"b:cP8f4A84/v/n/wMg//////8PAAAA"},"packages/frontend/editor-ui/src/app/stores/executionData.store.ts":{"58":"b:cP9/4A84/v/n/wPg//////8PgAAA","65":"b:cP9/4A84/v/n/wPg//////8PgAAA","75":"b:cP9/4A84/v/n/wPg//////8PgAAA","76":"b:cP9/4A84/v/n/wPg//////8PgAAA","85":"b:cP9/4A84/v/n/wPg//////8PgAAA","89":[151],"102":"b:ANcbAA4gAP/BaAKAh/x/l8EAgAAA","119":"b:ANcbAA4gAP/BaAKAh/x/l8EAgAAA","122":"b:ANcbAA4gAP/BaAKAh/x/l8EAgAAA","125":"b:ANcbAA4gAP/BaAKAh/x/l8EAgAAA","128":"b:AAYAAAAAAACBAAAABMhAEoAAgAAA","131":"b:AAYAAAAAAACBAAAABMhAEoAAgAAA","137":"b:cP9/4A84/v/n/wPg//////8PgAAA","145":"b:cP9/4A84/v/n/wPg//////8PgAAA","176":"b:cP9/4A84/v/n/wPg//////8PgAAA","183":"b:ANcbAA4gAP/BaAKAh/x/l8EIgAAA","187":"b:cP9/4A84/v/n/wPg//////8PgAAA","202":"b:ANcbAA4gAP/BaAKAh/x/l8EIgAAA","215":"b:ANcbAA4gAP/BaAKAh/x/l8EIgAAA","222":"b:ANcbAA4gAP/BaAKAh/x/l8EIgAAA","258":"b:ANcbAA4gAP/BaAKAh/x/l8EIgAAA","261":"b:ANcbAA4gAP/BaAKAh/x/l8EIgAAA","264":"b:ANcbAA4gAP/BaAKAh/x/l8EIgAAA","273":"b:ANcbAA4gAP/BaAKAh/x/l8EIgAAA","277":"b:ANcbAA4gAP/BaAKAh/x/l8EIgAAA","280":[151,128],"283":[151,128],"291":"b:cP9/4A84/v/n/wPg//////8PgAAA","299":"b:cP9/4A84/v/n/wPg//////8PgAAA","315":"b:cP9/4A84/v/n/wPg//////8PgAAA","325":"b:AMcbAA4gAL/BaAIAhvx3l8EAgAAA","416":"b:ANcbAA4gAP/BaAKAh/x/l8EIgAAA","423":[151],"437":"b:ANcLAA4gAP/BaAIAh/x/l8EAgAAA","441":"b:ANcbAA4gAP/BaAKAh/x/l8EIgAAA","453":"b:ANcbAA4gAP/BaAKAh/x/l8EAgAAA","461":"b:ANcbAA4gAP/BaAKAh/x/l8EAgAAA","476":[151,110],"481":"b:ANcbAA4gAP/BaAKAh/x/l8EAgAAA","500":"b:AAAKAAAAAIIAAAAAAEBAggEAgAAA","505":"b:AAAKAAAAAIIAAAAAAEBAggEAgAAA","524":"b:ANcbAA4gAP/BaAKAh/x/l8EAgAAA","528":[151],"546":"b:ANcbAA4gAP/BaAKAh/x/l8EAgAAA","549":"b:ANcbAA4gAP/BaAKAh/x/l8EAgAAA","561":[151],"572":[151,98],"592":[151],"593":[151],"597":[151],"609":[151,98],"610":[151,98],"618":[151,98],"654":[151,110],"662":[151,110],"678":[151],"726":"b:cP9/4A84/v/n/wPg//////8PgAAA"},"packages/frontend/editor-ui/src/app/stores/workflowDocument/useWorkflowDocumentRenderData.ts":{"95":"b:cP974A8w/v/h/wPg//////sPgAAA","101":"b:cP974A8w/v/h/wPg//////sPgAAA","111":"b:cP974A8w/v/h/wPg3/////sPgAAA","117":"b:cP974A8w/v/h/wPg//////sPgAAA","138":"b:cP974A8w/v/h/wPg3/////sPgAAA","159":"b:cP974A8w/v/h/wPg3/////sPgAAA","210":"b:cP974A8w/v/h/wPg//////sPgAAA","235":[151,70,79,101,107,127,136,139],"247":[151],"251":[151],"255":"b:cP974A8w/v/h/wPg3/////sPgAAA","289":"b:cP974A8w/v/h/wPg//////sPgAAA","304":"b:cP974A8w/v/h/wPg//////sPgAAA","307":"b:cP974A8w/v/h/wPg//////sPgAAA","310":"b:cP974A8w/v/h/wPg3/////sPgAAA","314":"b:cP974A8w/v/h/wPg3/////sPgAAA","318":"b:cP974A8w/v/h/wPg//////sPgAAA","322":"b:cP974A8w/v/h/wPg3/////sPgAAA","326":"b:cP974A8w/v/h/wPg3/////sPgAAA","330":"b:cP974A8w/v/h/wPg//////sPgAAA","334":"b:cP974A8w/v/h/wPg//////sPgAAA","337":"b:AIAgAAAAAAAgAgAgV14AQNEAgAAA","340":"b:AAAgAAAAAAAAAgAAU0AAAAEAgAAA","352":"b:cP9/4A84/v/n/wPg//////8PgAAA","362":"b:cL554A0w/m7h/wOg9+3vf/sPgAAA","395":"b:AIAAAAAAAAAgBACgBF4AQNAMgAAA","407":"b:cP9/4A84/v/n/wPg//////8PgAAA","428":[151,79,101,127],"429":[151,70,79,101,107,127,136,139],"463":"b:cP9/4A84/v/n/wPg//////8PgAAA","466":"b:cP9/4A84/v/n/wPg//////8PgAAA","469":"b:cP974A8w/v/h/wPg3/////sPgAAA","472":"b:MP974A8w1r/h/wPg3////+sNgAAA","475":"b:cP9/4A84/v/n/wPg//////8PgAAA","494":"b:cP974A8w/v/h/wPg3/////sPgAAA","497":"b:cP9/4A84/v/n/wPg//////8PgAAA","500":"b:cP9/4A84/v/n/wPg//////8PgAAA","503":"b:cP9/4A84/v/n/wPg//////8PgAAA","506":"b:cP9/4A84/v/n/wPg//////8PgAAA","509":"b:cP9/4A84/v/n/wPg//////8PgAAA","512":"b:cP9/4A84/v/n/wPg//////8PgAAA"},"packages/frontend/editor-ui/src/app/utils/aiUtils.ts":{"57":[15,110],"82":[110],"87":[110],"236":[15,110],"248":[15,110],"263":[15,110],"264":[15,110],"274":[14,15,16,17,77,95,110],"286":[110],"300":"b:cP974A8w/v/h/wOg//////sPAAAA"},"packages/frontend/editor-ui/src/app/utils/expressions.ts":{"17":[151],"21":[151,113,114],"25":[151,86],"26":[151,86],"34":"b:AIIBAAAQAgBAMAAAAUClGgAAgAAA","38":"b:AIIBAAAQAgAAMAAAAUCBGAAAgAAA","42":"b:AIIBAAAQAgAAMAAAAUGNGAAAgAAA","48":[9,151,123,124],"52":[9,151,123,124],"56":[9,151,123,124],"60":[9,151,123,124],"64":[9,151,123,124],"68":"b:AIIBAAAQAoBAMEIAAUmvHwAAgAAA","83":"b:AIIAAAAAAABAAAAAAACFGgAAgAAA","126":"b:AIIBAAAQAoBAMUIAAUivHwAAgAAA","150":"b:IJQZoC1ygA6hEMERxwUvHQMEgAAA","160":"b:IJAZoClyAA6hEMERxwUqHQIEgAAA"},"packages/frontend/editor-ui/src/app/utils/nodeIcon.ts":{"79":"b:cP974A8y/v/h+0Pg3/////sPAAAA","93":"b:cP974A8y/v/h/0Pg3/////sPAAAA","103":"b:cP974A8y/v/h+0Pg3/////sPAAAA","111":"b:MKoJoAgSftzgnQAgx+nv7yANAAAA","116":"b:cP974A8y/v/h/0Pg3/////sPAAAA","123":"b:MKoJoAgSftzgnQAgx+nv7yANAAAA","129":"b:cP974A8y/v/h+0Pg3/////sPAAAA","150":"b:cP974A8y/v/h/0Pg3/////sPAAAA"},"packages/frontend/editor-ui/src/app/utils/objectUtils.ts":{"3":"b:cP974A8y1v/h+wOg3/////sPAAAA","7":"b:cP974A8y1v/h+4Oh3/////sPAAAA","11":"b:cP974A8y1v/h+4Oh3/////sPAAAA","15":[116,118],"16":[116,118],"28":[9,10,11,12]},"packages/frontend/editor-ui/src/app/views/NodeView.vue":{"154":"b:cP8f4A84/v/n/wMg//////8PAAAA","161":"b:cP9/4A84/v/n/wOg//////8PAAAA","165":"b:cP8f4A84/v/n/wMg//////8PAAAA","166":"b:cP8f4A84/v/n/wMg/////n8PAAAA","181":"b:QL4RwA0wACJlQAIgl03nQ+8GAAAA","192":"b:cP9/4A84/v/n/wOg//////8PAAAA","281":"b:cP9/4A84/v/n/wOg//////8PAAAA","292":"b:cP9/4A84/v/n/wOg//////8PAAAA","296":"b:cP9/4A84/v/n/wOg//////8PAAAA","298":"b:cP9/4A84/v/n/wOg//////8PAAAA","299":"b:cIoZoAkw/k4h0AAg522vfeoCAAAA","300":"b:cP9/4A84/v/n/wOg//////8PAAAA","303":"b:cP9/4A84/v/n/wOg//////8PAAAA","309":"b:cP9/4A84/v/n/wOg//////8PAAAA","321":"b:cP9/4A84/v/n/wOg//////8PAAAA","335":"b:cP9/4A84/v/n/wOg//////8PAAAA","337":"b:cP9/4A84/v/n/wOg//////8PAAAA","341":"b:AMADAAAQAgAAMACAAECAAAAAAAAA","347":"b:cP9/4A84/v/n/wOg//////8PAAAA","380":"b:cP9/4A84/v/n/wOg//////8PAAAA","385":"b:cP9/4A84/v/n/wOg//////8PAAAA","427":"b:cP9/4A84/v/n/wOg//////8PAAAA","429":"b:cP974A8w/v/h/wOg//////sPAAAA","435":"b:cL8a4A8w/P/hzwMg3/////sPAAAA","437":"b:cL8a4A8w/P/hzwMg3/////sPAAAA","438":"b:cL8a4A8w/P/hzwMg3/////sPAAAA","442":"b:cP9/4A84/v/n/wOg//////8PAAAA","443":"b:cP974A8w/v/h/wOg3/////sPAAAA","445":"b:ANcbAA4gAP/BaAKAh/x/l8EIAAAA","452":[13],"463":[128],"467":[77,96,97,100,102,131],"475":[102],"479":[73,96,110],"488":[96,97,100,102],"492":[102,128],"496":[93,96,110],"504":[102],"508":[15,98,102,133,134,135],"516":"b:ABZbQAQAAIrhKQMA3+33h/kEAAAA","521":"b:ABZbQAQAAIrgKQMAhO33hwEAAAAA","543":"b:cN9b4A0w/u7h+wMg/+3///sHAAAA","548":[96,131,138],"554":[98,102,131,132],"602":[98,102,131],"615":[98,102,122],"639":"b:cP9/4A84/v/n/wOg//////8PAAAA","643":"b:MIAAAAAAAAAkAAAgBF4AQNgOAAAA","662":[98],"684":[98],"703":[98],"730":[128],"746":[15],"750":[32,64,97],"754":"b:AIABIAAAOgAAAAAAAyAAEAAAAAAA","794":[97,100,128],"798":[102,128],"802":"b:AIABIAAAOgAAAAAAAyAAEAAAAAAA","830":[96,102],"834":[102,128],"842":"b:ABYAAAQAACBAggMAAEBgRQABAAAA","857":"b:ABYAAAQAACBAggMAAEBgRQABAAAA","873":[136],"883":[136],"886":"b:cP9/4A84/v/n/wOg//////8PAAAA","892":"b:MIAAAAAAAAAkAAAgBF4AQNgOAAAA","903":"b:cIoZoAkw/k4h0AAgxy3vfaoCAAAA","907":"b:cIoZoAkw/k4h0AAg5y2vfaoCAAAA","939":[102,128],"943":[103,104,119,124],"951":[119],"964":"b:cIoZoAkw/k4h0AAgxy3vfaoCAAAA","977":[135],"990":"b:cN9b4A0w/u7h+wMg/+3///sHAAAA","996":[101],"1000":[78,79,96],"1065":"b:cP8f4A84/v/n/wMg//////8PAAAA","1071":"b:cL4doA84/m5l1gMg503vfb4PAAAA","1073":"b:MCAAgAIQAAAkAAAAAAAAQAoCAAAA","1084":"b:cP9/4A84/v/n/wOg//////8PAAAA","1085":"b:cP8f4A84/v/n/wOg//////8PAAAA","1089":"b:cL8a4A8w/P/hzwMg3/////sPAAAA","1101":"b:cP8f4A84/v/n/wOg//////8PAAAA","1104":"b:cP8f4A84/v/n/wOg//////8PAAAA","1107":"b:cP8f4A84/v/n/wOg//////8PAAAA","1111":[8,17,75,77,96,107,111,112,114],"1181":[8,17,75,77,96,107,111,112,114],"1193":[110,134,135],"1226":[110,134,135],"1237":"b:cP9/4A84/v/n/wOg//////8PAAAA","1242":"b:MIAAAAAAAAAkAAAgBF4AQNgOAAAA","1247":[110],"1257":"b:AJAYAA4gALtBQAIABvxwh8EAAAAA","1261":"b:ABAYAA4gALtBQAIABvxwh8EAAAAA","1269":"b:cP4foA84/m5n9gOg503vfb4PAAAA","1270":"b:AMADAAAQAgAAsACAZUCgAAAAAAAA","1275":"b:cP8f4A84/v/n/wOg//////8PAAAA","1278":"b:cP8b4A8w/v/h/wOg//////sPAAAA","1286":"b:cP8f4A84/v/n/wOg//////8PAAAA","1287":"b:cP8b4A8w/v/h/wOg3/////sPAAAA","1290":"b:cP4foA84/m5n9gOg503vfb4PAAAA","1296":"b:cP9/4A84/v/n/wOg//////8PAAAA","1312":[15,95],"1320":[15],"1399":"b:cP9/4A84/v/n/wOg//////8PAAAA","1410":"b:MIAAAAAAAAAkAAAgBF4AQNgOAAAA","1445":"b:cP9/4A84/v/n/wOg//////8PAAAA","1449":"b:MIAAAAAAAAAkAAAgBF4AQNgOAAAA","1456":"b:cP9/4A84/v/n/wOg//////8PAAAA","1460":"b:MIAAAAAAAAAkAAAgBF4AQNgOAAAA","1468":"b:cIoZoAkw/k4h0AAg522vfeoCAAAA","1511":"b:cP9/4A84/v/n/wOg//////8PAAAA","1529":[106],"1545":"b:cJ4ZoA0w/m5h0gMg523vfaoDAAAA","1549":"b:cP9/4A84/v/n/wOg//////8PAAAA","1555":"b:cJ4ZoA0w/m5h0gMg523vfaoDAAAA","1556":"b:cJ4ZoA0w/m5h0gMg523vfaoDAAAA","1563":"b:AEECIAAAAAABIAAAP0BgAAEAAAAA","1568":"b:AEECIAAAAAABIAAAP0BgAAEAAAAA","1576":[96],"1598":"b:cP9/4A84/v/n/wOg//////8PAAAA","1608":[120],"1638":"b:MIAAAAAAAAAkAAAgBF4AQNgOAAAA","1644":"b:cP9/4A84/v/n/wOg//////8PAAAA","1651":"b:cP9/4A84/v/n/wOg//////8PAAAA","1667":"b:MJ4b4A0w1s7h+QMgx+3//ysCAAAA","1685":"b:cP9/4A84/v/n/wOg//////8PAAAA","1690":"b:cP9/4A84/v/n/wOg//////8PAAAA","1696":"b:cL4doA84/m5n1gMg503vfb4PAAAA","1728":"b:cP9/4A84/v/n/wOg//////8PAAAA","1730":"b:MJ4b4A0w1s7h+QMgx+3//ysCAAAA","1739":"b:cP9/4A84/v/n/wOg//////8PAAAA","1741":"b:MJ5b4A0w1s7h+QMgx+3//ysCAAAA","1759":"b:cP9/4A84/v/n/wOg//////8PAAAA","1760":"b:cL4Z4A0w/m7l9gMg9+3vf+8PAAAA","1778":"b:cP9/4A84/v/n/wOg//////8PAAAA","1779":[13,18],"1791":"b:cP9/4A84/v/n/wOg//////8PAAAA","1801":"b:AAcCAAQAAESBCAAAgchvFgAAAAAA","1802":"b:AAcCAAQAAESBCAAAgchvFgAAAAAA","1807":"b:cP9/4A84/v/n/wOg//////8PAAAA","1816":"b:cL8aoA4wkP/hygIg1/1///sAAAAA","1826":"b:cL8aoA4wkP/hygIg1/1///sAAAAA","1827":"b:cL8aoA4wkP/hygIg1/1///sAAAAA","1838":"b:AIAAAAAAAAAgAAAgBF4AQNAAAAAA","1887":"b:cP9/4A84/v/n/wOg//////8PAAAA","1889":"b:QIYRAAwgACJBQAIAhkhhARAAAAAA","1910":"b:cP9/4A84/v/n/wOg//////8PAAAA","1934":"b:MIAAAAAAAAAkAAAgBF4AQNgOAAAA","2003":[139],"2013":"b:cP9/4A84/v/n/wOg//////8PAAAA","2033":"b:AJAYAA4gALtBQAIABvxwh8EAAAAA","2048":"b:AMADAAAQAgAAMACAAECAAAAAAAAA"},"packages/frontend/editor-ui/src/experiments/aiTemplatesStarterCollection/stores/aiTemplatesStarterCollection.store.ts":{"20":"b:+P///Q+4/////xPk//////8PAAAA","33":"b:OACACQCAAQA+ABAEAAIAQBgKAAAA"},"packages/frontend/editor-ui/src/experiments/emptyStateBuilderPrompt/stores/emptyStateBuilderPrompt.store.ts":{"23":"b:+P///Q+4/////xOk//////8PAAAA","58":[24,27,69,84,90,131],"86":"b:cP9/4A84/v/l/wOg//////8PAAAA"},"packages/frontend/editor-ui/src/experiments/evaluationsWizardSidepanel/useEvaluationsWizardSidepanelExperiment.ts":{"6":"b:cP9/4A84/v/n/wOg//////8PAAAA","9":"b:cP8f4A84/v/n/wMg//////8PAAAA"},"packages/frontend/editor-ui/src/experiments/readyToRunWorkflows/stores/readyToRunWorkflows.store.ts":{"21":"b:+P///Q+4/////xPk//////8PAAAA","30":"b:uACAXQCAAQA+ABAEAAIAQBgKAAAA","42":"b:uACAXQCAAQA+ABAEAAIAQBgKAAAA"},"packages/frontend/editor-ui/src/features/ai/assistant/components/Agent/BuildModeEmptyState.vue":{"5":"b:cMF74A8w/v/h/4Mh//////sPAAAA","6":"b:cMF74A8w/v/h/4Mh/////nsPAAAA"},"packages/frontend/editor-ui/src/features/ai/evaluation.ee/components/EvaluationsCanvasInfoCard/EvaluationsCanvasInfoCard.vue":{"25":"b:cP8f4A84/v/n/wMg//////8PAAAA","74":"b:cP8f4A84/v/n/wMg//////8PAAAA","85":"b:cP8f4A84/v/n/wMg//////8PAAAA","99":"b:cP8f4A84/v/n/wMg//////8PAAAA","103":"b:cP8f4A84/v/n/wMg//////8PAAAA","134":"b:cP8f4A84/v/n/wMg//////8PAAAA","150":[74,138,139],"159":"b:cP8f4A84/v/n/wMg//////8PAAAA","182":"b:cP8f4A84/v/n/wMg//////8PAAAA"},"packages/frontend/editor-ui/src/features/ai/evaluation.ee/composables/useAiRootNodes.ts":{"15":"b:cP9/4A84/v/n/wOg//////8PAAAA"},"packages/frontend/editor-ui/src/features/ai/evaluation.ee/composables/useEvaluationsLicense.ts":{"9":[65],"10":[65],"12":"b:cP9/4A84/v/n/wOg//////8PAAAA"},"packages/frontend/editor-ui/src/features/ai/evaluation.ee/evaluation.store.ts":{"10":"b:cP8f4A84/v/n/wMg//////8PgAAA","24":"b:cP8f4A84/v/n/wMg//////8PgAAA","26":[151],"28":[151],"29":[151],"43":[151],"50":[151],"63":[151,93],"67":[151],"79":[151],"85":[151],"97":[151],"106":[151],"125":[151],"136":[151],"137":[151],"143":[151],"148":[151],"159":[151],"160":[151]},"packages/frontend/editor-ui/src/features/ai/evaluation.ee/wizardSidepanel.store.ts":{"28":"b:cP9/4A84/v/n/wOg//////8PAAAA","31":"b:cP8f4A84/v/n/wMg//////8PAAAA"},"packages/frontend/editor-ui/src/features/core/dataTable/components/NodeStorageLimitCallout.vue":{"9":"b:MJ5b4A0w1s7h+QMgz+3//ysCAAAA","13":"b:MJ5b4A0w1s7h+QMgz+3//ysCAAAA","28":"b:MJ5b4A0w1s7h+QMgz+3//ysCAAAA"},"packages/frontend/editor-ui/src/features/core/folders/components/FolderBreadcrumbs.vue":{"59":"b:cP+f4A+4/////wMg//////8PAAAA","65":"b:cP+f4A+4/////wMg//////8PAAAA","67":"b:cP+f4A+4/////wMg//////8PAAAA","76":[66],"88":"b:cP+f4A+4/////wMg//////8PAAAA","92":[66,67],"96":"b:MACAAACAAQA+AAAAAAAAAAgCAAAA","107":"b:cP+f4A+4/////wMg//////8PAAAA","111":"b:cP+f4A+4/////wMg//////8PAAAA","147":[66],"162":[66],"174":[66,67],"178":[65],"185":[65,66,67],"196":[66],"208":"b:cP+f4A+4/////wMg//////8PAAAA","209":"b:cP+f4A+4/////wMg//////8PAAAA","212":"b:cP+f4A+4/////wMg//////8PAAAA","219":"b:MACAAACAAQA+AAAAAAIAQBgCAAAA","242":[65,66,67],"249":[65,66,67],"275":"b:MACAAACAAQA+AAAAAAAAAAgCAAAA","305":[66,67]},"packages/frontend/editor-ui/src/features/core/folders/components/ProjectBreadcrumb.vue":{"30":"b:cP+f4A+4/////wMg//////8PAAAA","52":"b:cP+f4A+4/////wMg//////8PAAAA","63":"b:cP+f4A+4/////wMg//////8PAAAA","75":[65,66,67],"79":[65],"91":[65,66,67],"100":"b:cP+f4A+4/////wMg//////8PAAAA"},"packages/frontend/editor-ui/src/features/core/folders/composables/useParentFolder.ts":{"5":"b:cP9/4A84/v/n/wPg//////8PAAAA","11":"b:cL59oA84/m5n0gPg503vff4DAAAA"},"packages/frontend/editor-ui/src/features/credentials/components/NodeCredentials.vue":{"116":"b:MKgB4AEy1AZhEQAgBEGgLyAAAAAA","131":"b:MLgZ4AUy1gZhkQAgBc2gLyACAAAA","133":"b:ML4b4A0y1s7h+QMgz+3//ysCAAAA","146":"b:ML4b4A0y1s7h+QMgz+3//ysCAAAA","150":"b:MIgBoAES1gZhEQAgBEGgLyAAAAAA","161":"b:MKgB4AEy1gZhEQAgBEGgLyAAAAAA","165":"b:MKABwAAyAAIhEAAAAEAACQAAAAAA","173":"b:MKgB4AEy1gZhEQAgBEGgLyAAAAAA","200":"b:ML4b4A0y1s7h+QMgz+3//ysCAAAA","201":"b:ML4b4A0y1s7h+QMgz+3//ysCAAAA","226":"b:ML4b4A0y1s7h+QMgz+3//ysCAAAA","231":"b:MKgBoAEy1gRhEQAgBEGgLyAAAAAA","245":"b:MIABgAAyAAAhEAAAAEAACQAAAAAA","261":"b:ML4b4A0y1s7h+QMgz+3//ysCAAAA","273":"b:ML4b4A0y1s7h+QMgz+3//ysCAAAA","274":"b:ML4b4A0y1s7h+QMgz+3//ysCAAAA","281":"b:AIgBgAAQgAAgEAAAAAAACQAAAAAA","365":"b:ML4b4A0y1s7h+QMgz+3//ysCAAAA","370":"b:MKABwAAyAAIhEAAAAEAACQAAAAAA","377":[30],"381":"b:MKABwAAyAAIhEAAAAEAACQAAAAAA","389":[44],"408":"b:AIgBgAAQgAAgEAAAAAAACQAAAAAA","439":[123],"449":"b:MIABwAAyAAAhEAAAAEAACQAAAAAA","527":[31,44,69,4,5,120,123],"562":"b:MKgBwAAyAgIhEAAAAEAACQAAAAAA","566":"b:MKgB4AEy1gZhEQAgBEGgLyAAAAAA","611":"b:MKABwAAyAAIhEAAAAEAACQAAAAAA","624":[44],"639":"b:MKgB4AEy1gZhEQAgBEGgLyAAAAAA","658":[15,16,30,41,45],"662":"b:MKABwAAyAAIhEAAAAEAACQAAAAAA","666":[15,16],"667":[15,16],"672":[11,49],"677":"b:AKgA4AES1gRgEQAgBAGgLyAAAAAA","678":"b:AKgA4AES1gRgEQAgBAGgLyAAAAAA","684":"b:AKgAoAES1gRgEQAgBAGgLyAAAAAA","688":"b:MKgB4AEy1AZhEQAgBEGgLyAAAAAA","692":[11,49],"738":"b:MKgB4AEy1gZhEQAgBEGgLyAAAAAA","740":[13],"776":[11],"784":[11],"785":[11],"807":[11,15,31,44,55,69,76,120,123],"808":"b:AKgAoAES1ARgEQAgBAGgLyAAAAAA","827":[30,41,45],"834":"b:MKABwAAyAAIhEAAAAEAACQAAAAAA","839":"b:MKABwAAyAAIhEAAAAEAACQAAAAAA","865":"b:MKABwAAyAAIhEAAAAEAACQAAAAAA","866":"b:MKABwAAyAAIhEAAAAEAACQAAAAAA","872":[15,16],"902":[30],"917":[44]},"packages/frontend/editor-ui/src/features/credentials/composables/useNodeCredentialOptions.ts":{"30":"b:ML5b4A0y1s7h+QMgz+3//ysCAAAA","38":"b:MKgBoAAS1gRhEQAgBEGgLyAAAAAA","40":"b:ML4b4A0y1s7h+QMgz+3//ysCAAAA","44":"b:ML4b4A0y1s7h+QMgz+3//ysCAAAA","45":"b:MKgB4AEy1gZhEQAgBEGgLyAAAAAA","55":"b:MKgB4AEy1gZhEQAgBEGgLyAAAAAA","57":"b:MKgB4AEy1gZhEQAgBEGgLyAAAAAA","59":"b:MKABwAAyAAIhEAAAAEAACQAAAAAA","69":[30,44,45],"75":"b:MLgZ4AUy1gZhkQAgBc2gLyACAAAA","92":"b:MKgB4AEy1gZhEQAgBEGgLyAAAAAA","102":"b:MKgB4AEy1gZhEQAgBEGgLyAAAAAA","107":"b:MAgAoAAQFAAgAQAAAAAgLyAAAAAA","114":[13],"120":"b:MKgB4AEy1gZhEQAgBEGgLyAAAAAA","126":"b:MKABwAAyAAIhEAAAAEAACQAAAAAA"},"packages/frontend/editor-ui/src/features/execution/executions/composables/useExecutionData.ts":{"8":"b:MJ5b4A0w1s7h+QMgx+3//ysCAAAA","12":"b:MJ5b4A0w1s7h+QMgx+3//ysCAAAA","23":"b:MJ5b4A0w1s7h+QMgx+3//ysCAAAA"},"packages/frontend/editor-ui/src/features/execution/executions/composables/useExecutionRedaction.ts":{"10":"b:MN5b4A0w1s7h+QMgz+3//ysCAAAA","17":[14,15,16,17,77,110],"19":[14,15,16,17,77,110]},"packages/frontend/editor-ui/src/features/execution/logs/components/ChatMessagesPanel.vue":{"30":"b:AMADAAAQAgACMACAAECAAAAAAAAA","57":[14,15,16,17,65,77,95,110],"61":"b:AMADAAAQAgACMACAAECAAAAAAAAA","67":[14,65],"76":[14,15,16,17,65,77,95,110],"96":[14,15,16,17,65,77,95,110],"105":"b:AMADAAAQAgACMACAAECAAAAAAAAA","107":[14,15,16,17,65,77,95,110],"117":"b:AMADAAAQAgACMACAAECAAAAAAAAA","119":[15,16,65,110],"135":"b:AMADAAAQAgACMACAAECAAAAAAAAA","137":"b:AMADAAAQAgACMACAAECAAAAAAAAA","145":[65],"154":"b:AMADAAAQAgACMACAAECAAAAAAAAA","156":[65],"166":"b:AMADAAAQAgACMACAAECAAAAAAAAA","168":[65,110],"182":"b:AMADAAAQAgACMACAAECAAAAAAAAA","190":[14,15,17,65,110],"193":"b:AMADAAAQAgACMACAAECAAAAAAAAA","208":"b:AMADAAAQAgACMACAAECAAAAAAAAA","210":[65],"214":"b:AMADAAAQAgACMACAAECAAAAAAAAA","221":"b:AMADAAAQAgACMACAAECAAAAAAAAA","227":"b:AMADAAAQAgACMACAAECAAAAAAAAA"},"packages/frontend/editor-ui/src/features/execution/logs/components/LogsOverviewPanel.vue":{"39":"b:cP8f4A84/v/n/wOg//////8PAAAA","51":[14,15,16,17,65,77,95,110],"52":[14,15,16,17,65,77,95,110],"57":[14,15,16,17,65,77,95,110],"59":[14,15,16,17,65,77,95,110],"67":[14,15,16,17,65,77,95,110],"72":[14,15,16,17,65,77,95,110],"75":[14,15,16,17,65,77,95,110],"78":[65],"80":"b:cP8f4A84/v/n/wOg//////8PAAAA","94":"b:cP8f4A84/v/n/wOg//////8PAAAA","98":"b:ANcLAA4gAP/BaAIAh/x/l8EAAAAA","107":"b:ANcLAA4gAP/BaAIAh/x/l8EAAAAA","125":[14,15,16,17,77,95,110],"147":[110],"148":[14,110]},"packages/frontend/editor-ui/src/features/execution/logs/components/LogsPanel.vue":{"21":"b:cP8f4A84/v/n/wOg//////8PAAAA","31":"b:cP8f4A84/v/n/wOg//////8PAAAA","70":"b:cP8f4A84/v/n/wOg//////8PAAAA","71":"b:cP8f4A84/v/n/wOg//////8PAAAA","74":"b:cP8f4A84/v/n/wOg//////8PAAAA","83":[14,15,16,17,65,77,110],"88":[14,15,16,17,65,77,110],"94":"b:cP8f4A84/v/n/wOg//////8PAAAA","112":[65],"120":[65,110],"123":[65,110],"133":[65],"138":[65],"141":"b:cP8f4A84/v/n/wOg//////8PAAAA","173":"b:AMADAAAQAgAAMACAAECAAAAAAAAA","199":"b:cP8f4A84/v/n/wOg//////8PAAAA","242":[14,15,16,17,77,110]},"packages/frontend/editor-ui/src/features/execution/logs/components/LogsPanelActions.vue":{"19":"b:cP8f4A84/v/n/wOg//////8PAAAA","22":"b:cP8f4A84/v/n/wOg//////8PAAAA","23":"b:cP8f4A84/v/n/wOg//////8PAAAA","26":[14,15,16,17,65,77,95,110],"35":[65],"44":"b:cP8f4A84/v/n/wOg//////8PAAAA","51":"b:cP8f4A84/v/n/wOg//////8PAAAA","75":"b:cP8f4A84/v/n/wOg//////8PAAAA"},"packages/frontend/editor-ui/src/features/execution/logs/components/LogsPanelHeader.vue":{"8":"b:cP8f4A84/v/n/wOg//////8PAAAA","10":[14,15,65,110],"13":"b:cP8f4A84/v/n/wOg//////8PAAAA","20":"b:cP8f4A84/v/n/wOg//////8PAAAA"},"packages/frontend/editor-ui/src/features/execution/logs/components/LogsViewKeyboardEventListener.vue":{"8":"b:cP8f4A84/v/n/wOg//////8PAAAA","11":"b:AKAAIAAARAAC0AAAdyCAQPkOAAAA","24":[65],"27":"b:cP8f4A84/v/n/wOg//////8PAAAA"},"packages/frontend/editor-ui/src/features/execution/logs/composables/useChatState.ts":{"41":"b:cP8f4A84/v/n/wOg//////8PAAAA","48":[14,15,16,17,65,69,77,95,110],"61":[14,15,16,17,65,77,95,110],"62":[65,110],"65":[14,15,16,17,65,77,95,110],"67":[65],"68":"b:AMADAAAQAgACMACAAECAAAAAAAAA","76":"b:AMADAAAQAgACMACAAECAAAAAAAAA","103":"b:AMADAAAQAgACMACAAECAAAAAAAAA","122":"b:AMADAAAQAgACMACAAECAAAAAAAAA","127":"b:AMADAAAQAgACMACAAECAAAAAAAAA","132":"b:AMADAAAQAgACMACAAECAAAAAAAAA","137":[14,15,16,17,65,77,95,110],"151":[14,15,16,17,65,77,95,110],"167":[14,15,16,17,65,77,95,110],"179":[65],"180":[65],"181":[65],"185":[65],"186":[65],"232":[14,15,16,17,65,77,95,110],"278":[14,15,16,17,65,77,95,110],"292":[14,15,16,17,65,77,95,110],"323":[65,110],"331":[14,15,17,65,69,95],"344":[65],"352":"b:cP8f4A84/v/n/wOg//////8PAAAA","353":"b:cP8f4A84/v/n/wOg//////8PAAAA","364":"b:AMADAAAQAgACMACAAECAAAAAAAAA"},"packages/frontend/editor-ui/src/features/execution/logs/composables/useClearExecutionButtonVisible.ts":{"9":"b:cP8f4A84/v/n/wOg//////8PAAAA","14":"b:cP8f4A84/v/n/wMg//////8PAAAA","17":"b:cP8b4A8w/v/j/wMg3/////sPAAAA","18":"b:cP8f4A84/v/n/wMg//////8PAAAA","19":"b:cP8f4A84/v/n/wOg//////8PAAAA","21":"b:cP8f4A84/v/n/wMg//////8PAAAA","22":"b:cP8f4A84/v/n/wMg//////8PAAAA","24":"b:cP8b4A8w/v/j/wMg//////sPAAAA","25":"b:cP8b4A8w/v/j/wMg3/////sPAAAA","28":"b:cP8f4A84/v/n/wOg//////8PAAAA"},"packages/frontend/editor-ui/src/features/execution/logs/composables/useLogsExecutionData.ts":{"34":"b:cP8f4A84/v/n/wOg//////8PAAAA","45":"b:cP8f4A84/v/n/wOg//////8PAAAA","52":"b:cP8f4A84/v/n/wOg//////8PAAAA","58":"b:cP8f4A84/v/n/wOg//////8PAAAA","59":"b:ANcbAA4gAP/BaAKAh/x/l8EIAAAA","74":"b:cP8f4A84/v/n/wOg//////8PAAAA","84":"b:cP8f4A84/v/n/wOg//////8PAAAA","89":"b:cP8f4A84/v/n/wOg//////8PAAAA","108":"b:cP8f4A84/v/n/wOg//////8PAAAA","121":[65],"149":"b:cP8f4A84/v/n/wOg//////8PAAAA","150":"b:cP8f4A84/v/n/wOg//////8PAAAA","151":"b:cP8f4A84/v/n/wOg//////8PAAAA","152":"b:cP8f4A84/v/n/wOg//////8PAAAA","153":"b:cP8f4A84/v/n/wOg//////8PAAAA","155":"b:cP8f4A84/v/n/wOg//////8PAAAA","178":"b:cP8f4A84/v/n/wOg//////8PAAAA","179":"b:cP8f4A84/v/n/wOg//////8PAAAA","188":"b:cP8f4A84/v/n/wOg//////8PAAAA","198":"b:cP8f4A84/v/n/wOg//////8PAAAA"},"packages/frontend/editor-ui/src/features/execution/logs/composables/useLogsPanelLayout.ts":{"16":"b:cP8f4A84/v/n/wOg//////8PAAAA","30":"b:cP8f4A84/v/n/wOg//////8PAAAA","32":[65],"38":"b:AMADAAAQAgACMACAAECAAAAAAAAA","40":[65],"45":"b:cP8f4A84/v/n/wOg//////8PAAAA","51":"b:cP8f4A84/v/n/wOg//////8PAAAA","56":[14,15,16,17,65,77,110],"57":"b:cP8f4A84/v/n/wOg//////8PAAAA","58":"b:cP8f4A84/v/n/wOg//////8PAAAA","67":[65],"77":[14,15,65,110],"91":[65],"97":[65],"110":"b:cP8f4A84/v/n/wOg//////8PAAAA","133":"b:AIAAAAAAAAACAAAgBF4AQNAAAAAA"},"packages/frontend/editor-ui/src/features/execution/logs/composables/useLogsSelection.ts":{"20":"b:cP8f4A84/v/n/wOg//////8PAAAA","29":"b:cP8f4A84/v/n/wOg//////8PAAAA","30":"b:cP8f4A84/v/n/wOg//////8PAAAA","38":[14,65,110],"46":[14,65,110],"63":[65],"78":[65],"94":"b:cP8f4A84/v/n/wOg//////8PAAAA","105":"b:cP8f4A84/v/n/wOg//////8PAAAA","120":"b:cP8f4A84/v/n/wOg//////8PAAAA","126":[15,16,17,77,110]},"packages/frontend/editor-ui/src/features/execution/logs/composables/useLogsTreeExpand.ts":{"10":"b:cP8f4A84/v/n/wOg//////8PAAAA","14":[15,65,110]},"packages/frontend/editor-ui/src/features/execution/logs/composables/usePopOutWindow.ts":{"32":[65],"39":[65],"61":[65],"77":"b:cP8f4A84/v/n/wOg//////8PAAAA","88":"b:cP8f4A84/v/n/wOg//////8PAAAA","89":"b:cP8f4A84/v/n/wOg//////8PAAAA","90":"b:cP8f4A84/v/n/wOg//////8PAAAA","93":"b:cP8f4A84/v/n/wOg//////8PAAAA","104":[65],"121":[65],"141":[65],"168":[65],"171":"b:cP8f4A84/v/n/wOg//////8PAAAA","180":"b:cP8f4A84/v/n/wOg//////8PAAAA","185":"b:cP8f4A84/v/n/wOg//////8PAAAA","194":"b:AIAAAAAAAAACAAAgBF4AQNAAAAAA","199":"b:AIAAAAAAAAACAAAgBF4AQNAAAAAA"},"packages/frontend/editor-ui/src/features/execution/logs/logs.utils.ts":{"33":[14,15,16,17,65,77,95,110],"34":[14,15,16,17,65,77,95,110],"48":[14,15,16,17,65,77,95,110],"56":[14,15,16,17,65,77,95,110],"80":[14,15,16,17,65,77,95,110],"110":[15,16,65,110],"118":[15,16,65,110],"119":[15,16,65,110],"123":[15,16,65,110],"144":[14,15,16,17,65,77,95,110],"162":[14,15,16,17,65,77,95,110],"166":[14,15,16,17,65,77,95,110],"172":[14,15,16,17,65,77,95,110],"186":"b:ANcKAA4gAP/DaAIAh/x/l8EAAAAA","187":[14,15,65,77,110],"193":[14,15,65,77,110],"207":[14,15,16,17,65,77,95,110],"213":[14,15,16,17,65,77,95,110],"229":[14,15,16,17,65,77,95,110],"237":[65],"242":[15,16,65,110],"260":[14,15,16,17,65,77,95,110],"276":[14,15,16,17,65,77,95,110],"284":[14,15,16,17,65,77,95,110],"303":[65],"304":[65],"307":"b:cN8b4A8w/v/j+wMg//3///sHAAAA","326":"b:cP8f4A84/v/n/wOg//////8PAAAA","337":[14,15,16,17,77,110],"360":"b:cP8f4A84/v/n/wOg//////8PAAAA","376":[65],"381":[65],"386":[14,15,16,17,65,77,95,110],"404":[14,15,16,17,65,77,95,110],"418":[14,15,16,17,65,77,95,110],"423":[14,15,16,17,65,77,95,110],"428":[14,15,16,17,65,77,95,110],"438":[65,110],"440":[14,15,16,17,65,77,95,110],"463":[14,15,16,17,65,77,95,110],"467":[14,15,16,17,65,77,95,110],"495":[14,65,110],"507":[65,110],"518":[65,110],"543":[65,110],"595":[65,110],"602":[65,110],"614":[65,110],"677":[14,15,16,17,65,77,110],"681":[14,15,16,17,65,77,110],"691":"b:ANcbAA4gAP/DaAKAh/x/l8EIAAAA","699":"b:ANcbAA4gAP/DaAKAh/x/l8EAAAAA"},"packages/frontend/editor-ui/src/features/ndv/panel/components/InputPanel.vue":{"61":"b:MJ4b4A0w1o7h+QMgz+3//ysAAAAA","111":"b:MJ4b4A0w1o7h+QMgz+3//ysAAAAA","119":"b:MJ4b4A0w1o7h+QMgz+3//ysAAAAA","127":"b:MJ4b4A0w1o7h+QMgz+3//ysAAAAA","131":"b:MJ4b4A0w1g7h+QEgz+Xv/yoAAAAA","151":"b:MJ4b4A0w1o7h+QMgz+3//ysAAAAA","152":"b:MJ4b4A0w1o7h+QMgz+3//ysAAAAA","161":"b:MJ4b4A0w1o7h+QMgz+3//ysAAAAA","185":"b:MJ4b4A0w1o7h8QMgz+3//ysAAAAA","186":[15,120],"190":"b:MJ4b4A0w1o7h+QMgz+3//ysAAAAA","198":"b:MJ4b4A0w1o7h+QMgz+3//ysAAAAA","214":"b:AAYAAAQAAASAAAAAgIBvlgAAAAAA","223":"b:MJ4b4A0w1g7h+QEgz+Xv/yoAAAAA","228":"b:MJ4b4A0w1o7h+QMgz+3//ysAAAAA","243":"b:MJ4b4A0w1o7h+QMgz+3//ysAAAAA","244":"b:MJ4b4A0w1o7h8QMgz+3//ysAAAAA","247":"b:MJ4b4A0w1o7h+QMgz+3//ysAAAAA","254":"b:MJ4b4A0w1o7h8QMgz+3//ysAAAAA","258":"b:MJ4b4A0w1o7h+QMgz+3//ysAAAAA","259":"b:MJ4b4A0w1o7h8QMgz+3//ysAAAAA","265":"b:MJ4b4A0w1o7h+QMgz+3//ysAAAAA","284":"b:MJ4b4A0w1o7h+QMgz+3//ysAAAAA","286":"b:MJ4b4A0w1g6h8QEgx8XnfyoAAAAA","291":"b:MJ4b4A0w1o7h+QMgz+3//ysAAAAA","304":"b:AAAQAAAAAAIBAAAACAAPFwAAAAAA","306":"b:AAAQAAAAAAIBAAAAAAAPFQAAAAAA","324":"b:MJ4b4A0w1o7h8QMgz+3//ysAAAAA","344":[103,113],"357":"b:MJ4b4A0w1o7h+QMgz+3//ysAAAAA","361":[17,118],"365":"b:MJ4b4A0w1g7h+QEgz+Xv/yoAAAAA","369":[116],"373":[113,118,121],"382":[110,113,116,117,118,121],"386":[113,121],"387":[113,121],"403":"b:AAACAAAAAAAACAAAgUDyCwAAAAAA","409":"b:MJ4b4A0w1o7h+QMgz+3//ysAAAAA","445":[75,110,113,116,117,118,121],"448":"b:MJ4b4A0w1o7h+QMgz+3//ysAAAAA","455":"b:MJ4b4A0w1o7h+QMgz+3//ysAAAAA","467":[75,110,113,116,117,118,121],"476":[16,44,75,76,120],"480":[16,44,75,76,120],"489":"b:MJ4b4A0w1g6h8QEgx8XnfyoAAAAA","523":"b:MJ4b4A0w1g6h8QEgx8XnfyoAAAAA","525":"b:MJ4b4A0w1g6h8QEgx8XnfioAAAAA","631":"b:IAABIAAQAAAhEAAAAgAgRQAAAAAA","676":[17]},"packages/frontend/editor-ui/src/features/ndv/panel/components/NDVFloatingNodes.vue":{"13":"b:cP9/4A84/v/l/wOg//////8PAAAA","18":"b:MJ5b4A0w1s7h+QMgx+3//ysCAAAA","30":"b:MJ5b4A0w1s7h+QMgx+3//ysCAAAA","32":[119],"39":"b:AJAAoAAQRACA0AAARyH/XQACAAAA","53":"b:MJ5b4A0w1s7h+QMgx+3//ysCAAAA","55":"b:MJ5b4A0w1o7h+QMgx+3//ysAAAAA","65":"b:MJ5b4A0w1o7h+QMgx+3//ysAAAAA","68":"b:MJ5b4A0w1s7h+QMgx+3//ysCAAAA","97":"b:MJ5b4A0w1s7h+QMgx+3//ysCAAAA","101":"b:AJobYAgwVkoh+QEgx+3/dykCAAAA","107":"b:MJ5b4A0w1s7h+QMgx+3//ysCAAAA","125":"b:MJ5b4A0w1o7h+QMgx+3//ysAAAAA","131":[103,104,119,124]},"packages/frontend/editor-ui/src/features/ndv/panel/components/NDVHeader.vue":{"27":"b:MJ5b4A0w1s7j+QMgx+3//ysCAAAA","32":[65],"34":"b:MJ5b4A0w1s7j+QMgx+3//ysCAAAA","62":"b:MJ5b4A0w1s7j+QMgx+3//ysCAAAA","64":"b:MJ5b4A0w1s7j+QMgx+3//ysCAAAA","70":[65],"72":"b:MJ5b4A0w1s7j+QMgx+3//ysCAAAA"},"packages/frontend/editor-ui/src/features/ndv/panel/components/NDVSubConnections.vue":{"25":"b:MJ5b4A0w1s7h+QMgx+3//ysCAAAA","57":"b:MJ5b4A0w1s7h+QMgx+3//ysCAAAA","61":"b:MJ5b4A0w1s7h+QMgx+3//ysCAAAA","66":[16,119],"84":[15,16,44,49,76,93,96,119,120],"87":[15,16,44,49,76,93,96,119,120],"99":[16,119],"110":[15,16,44,49,76,93,96,119,120],"127":[15,16,44,49,76,93,96,119,120],"131":[15,16,44,49,76,93,96,119,120],"133":[15,16,44,49,76,93,96,119,120],"137":[15,16,44,49,76,93,96,119,120],"145":[15,16,44,49,76,93,96,119,120],"152":[15,16,44,49,93,119,120],"167":[15,16,44,49,76,93,96,119,120],"169":[16,119],"183":[16,119],"186":[15,16,44,49,76,93,96,119,120],"193":"b:MJ4b4A0w1o7h8QMgx+3//ysAAAAA","201":"b:MJ5b4A0w1s7h+QMgx+3//ysCAAAA","210":"b:MJ4b4A0w1o7h8QMgx+3//ysAAAAA","231":[119],"250":"b:AAYAAAQAAESAAAAAgIBqFgAAAAAA","253":"b:AAYAAAQAAESAAAAAgIBqFgAAAAAA","259":"b:MJ5b4A0w1s7h+QMgx+3//ysCAAAA","260":"b:MJ5b4A0w1s7h+QMgx+3//ysCAAAA","262":"b:MJ5b4A0w1s7h+QMgx+3//ysCAAAA","274":"b:MJ5b4A0w1s7h+QMgx+3//ysCAAAA","296":[15,16,44,49,93,119,120],"297":[15,16,44,49,76,93,96,119,120],"305":[119],"317":[119],"335":[15,16,44,49,76,93,96,119,120],"355":[16,119],"376":[16,119]},"packages/frontend/editor-ui/src/features/ndv/panel/components/OutputPanel.vue":{"35":"b:MJ5b4A0w1s7h+QMgx+3//ysCAAAA","84":"b:MJ5b4A0w1s7h+QMgx+3//ysCAAAA","89":"b:MJ5b4A0w1s7h+QMgx+3//ysCAAAA","90":"b:AAYKAAQAAM6BAAIAgMx6lwEAAAAA","115":"b:MJ5b4A0w1s7h+QMgx+3//ysCAAAA","119":"b:MJ5b4A0w1s7h+QMgx+3//ysCAAAA","125":"b:MJ4b4A0w1k7h+QEgx+3v/yoCAAAA","129":"b:MJ5b4A0w1s7h+QMgx+3//ysCAAAA","146":"b:MJ5b4A0w1s7h+QMgx+3//ysCAAAA","155":"b:MJ5b4A0w1s7h+QMgx+3//ysCAAAA","159":"b:MJ5b4A0w1s7h+QMgx+3//ysCAAAA","167":"b:MJ5b4A0w1s7h+QMgx+3//ysCAAAA","169":"b:AAYKAAQAAM6BAAIAgMx6lwEAAAAA","187":"b:MJ5b4A0w1s7h+QMgx+3//ysCAAAA","205":"b:AAYKAAQAAM6BAAIAgMx6lwEAAAAA","213":"b:MJ5b4A0w1s7h+QMgx+3//ysCAAAA","217":"b:MJ4b4A0w1k7h+QEgx+3v/yoCAAAA","221":"b:MJ5b4A0w1s7h+QMgx+3//ysCAAAA","244":"b:MJ5b4A0w1s7h+QMgx+3//ysCAAAA","265":[118],"269":[118],"288":[17,118,121,127],"293":"b:MJ5b4A0w1s7h+QMgx+3//ysCAAAA","306":"b:MJ5b4A0w1s7h+QMgx+3//ysCAAAA","312":"b:MJ5b4A0w1s7h+QMgx+3//ysCAAAA","343":"b:AABaAAQAAM6BAAIAgM1/lwEAAAAA","344":[113,116,118,121],"345":[116,118],"346":[104,107,118,121],"349":"b:MJ5b4A0w1s7h+QMgx+3//ysCAAAA","375":"b:MJ4b4A0w1k7h+QEgx+3v/yoCAAAA","398":"b:AIoRIAEQBEIBAQAgQomvbCACAAAA","406":"b:MJ4b4A0w1g7h+QEgx+Xv/yoAAAAA","408":"b:MJ4b4A0w1k7h+QEgx+3v/yoCAAAA","419":"b:AIABAAAQEggAWAAAAECAAwAAAAAA","457":"b:MJ4b4A0w1kbh8QEgx63v/yoCAAAA","491":[110],"493":[110],"497":[17],"536":[17,110,118,121,127]},"packages/frontend/editor-ui/src/features/ndv/panel/components/PanelDragButtonV2.vue":{"11":"b:MJ4b4A0w1o7j+QMgx+3//ysCAAAA","17":[65],"21":[65],"25":[65],"27":"b:MJ4b4A0w1o7j+QMgx+3//ysCAAAA"},"packages/frontend/editor-ui/src/features/ndv/panel/composables/useNdvLayout.ts":{"21":"b:cP9/4A84/v/n/wOg//////8PAAAA","29":"b:cP9/4A84/v/n/wOg//////8PAAAA","35":"b:cP9/4A84/v/n/wOg//////8PAAAA","37":"b:MJ5b4A0w1s7j+QMgx+3//ysCAAAA","41":"b:cP9/4A84/v/n/wOg//////8PAAAA","45":"b:cP9/4A84/v/n/wOg//////8PAAAA","46":"b:MJ5b4A0w1s7j+QMgx+3//ysCAAAA","51":"b:cP9/4A84/v/n/wOg//////8PAAAA","53":"b:cP9/4A84/v/n/wOg//////8PAAAA","75":"b:cP9/4A84/v/n/wOg//////8PAAAA","102":[65],"106":"b:cP9/4A84/v/n/wOg//////8PAAAA","119":[65],"123":[65],"157":[65],"175":"b:MJ5b4A0w1s7j+QMgx+3//ysCAAAA","182":"b:cP9/4A84/v/n/wOg//////8PAAAA"},"packages/frontend/editor-ui/src/features/ndv/parameters/components/Collection/CollectionParameter.vue":{"9":"b:AJpbYAUyVo4h+YIhT+3/7wsCAAAA","25":"b:AJpbYAUyVo4h+YIhT+3/7gsCAAAA","34":[57,64]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/Collection/CollectionParameterLegacy.vue":{"24":"b:AJpbYAUyVo4h+YIhT+3/7wsCAAAA","44":"b:AJobYAUyVo4h+YIhT+3/bwsCAAAA","48":"b:AJobYAUyVo4h+YIhT+3/bwsCAAAA","55":"b:AJobYAUyVo4h+YIhT+3/bwgCAAAA","61":"b:AJobYAUyVo4h+YIhT+3/bwgCAAAA","73":"b:AJpbYAUyVo4h+YIhT+3/7wsCAAAA","89":[12,34,57,64,72,118,127],"93":[12,34,57,64,72,118,127],"110":"b:AJpbYAUyVo4h+YIhT+3/7wsCAAAA","112":"b:AJpbYAUyVo4h+YIhT+3/7wsCAAAA","113":[12,34,57,64,72,118,127],"116":[12,34,57,64,72,118,127],"118":[12,34,57,64,72,118,127],"129":"b:AJpbYAUyVo4h+YIhT+3/7wsCAAAA","131":"b:AJpbYAUyVo4h+YIhT+3/7wsCAAAA","143":"b:AJpbYAUyVo4h+YIhT+3/7wsCAAAA","144":"b:AJpbYAUyVo4h+YIhT+3/7wsCAAAA","147":[57,64],"201":[57,64],"203":"b:AJpbYAUyVo4h+YIhT+3/7wsCAAAA","210":"b:AIpbYAEyVo4h+YIhT+3/bwsCAAAA","243":"b:AJobYAUyVo4h+YIhT+3/bwgCAAAA","246":"b:AJobYAUyVo4h+YIhT+3/bggCAAAA"},"packages/frontend/editor-ui/src/features/ndv/parameters/components/ExpressionFunctionIcon.vue":{"8":"b:AIABAAAQAgBAEUAAAQinGgIAAAAA"},"packages/frontend/editor-ui/src/features/ndv/parameters/components/ExpressionParameterInput.vue":{"26":"b:AIIBAAAQAoBAMUIAAUivHwIAAAAA","67":"b:AIIBAAAQAoBAMUIAAUivHwIAAAAA","68":"b:AIIBAAAQAoBAMUIAAUivHwIAAAAA","78":"b:AAAAAAAAAAAAAEAAAAAPHwAAAAAA","84":"b:AAAAAAAAAAAAAEAAAAAPHwAAAAAA","89":"b:AAAAAAAAAAAAAEAAAAAPGwAAAAAA","97":"b:AIIBAAAQAgAAIUAAAEivGwAAAAAA","100":"b:AIIAAAAAAAAAAEAAAEiPGwAAAAAA","128":"b:AIIAAAAAAIBAAUIAAEiPHwAAAAAA","137":"b:AIIBAAAQAoBAMUIAAUivHwIAAAAA","148":[113],"160":[113],"166":[113],"175":[113],"181":"b:AIIBAAAQAoBAMUIAAUivHwIAAAAA","185":"b:AIIBAAAQAgAAMUAAAUiFAgAAAAAA","189":[113],"196":"b:AIIBAAAQAgAAIUAAAEivGwAAAAAA","199":"b:AIIBAAAQAoBAMUIAAUivHwIAAAAA","219":"b:AIIBAAAQAoBAMUIAAUivHwIAAAAA","244":[114]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/ParameterInputFull.vue":{"62":"b:ML5b4A0y1s7h+YMhz+3//ysCAAAA","96":"b:ML5b4A0y1s7h+YMhz+3//ysCAAAA","107":"b:ML5b4A0y1s7h+YMhz+3//ysCAAAA","114":"b:ML5b4A0y1s7h+YMhz+3//ysCAAAA","118":"b:ML5b4A0y1s7h+YMhz+3//ysCAAAA","122":"b:ML5b4A0y1s7h+YMhz+3//ysCAAAA","125":"b:ML5b4A0y1s7h+YMhz+3//ysCAAAA","132":"b:ALobYAUy1s7h+YIgT+z//ysCAAAA","134":"b:ML5b4A0y1s7h+YMhz+3//ysCAAAA","143":"b:ML5b4A0y1s7h+YMhz+3//ysCAAAA","161":"b:ABAYAAUykA6hAIABiAQvHwIAAAAA","169":"b:ABAYAAUyEA6hAIABiAQvGQIAAAAA","185":"b:AKpZ4A0ykg4hkYAAx83vnwIAAAAA","189":"b:AIpZ4A0ykg4hkYAAx83vnwIAAAAA","193":"b:AAAAAAAAAAAAAAAAAAANHQIAAAAA","200":"b:AJQZIA0ygA6hAIEBxwUvHQMAAAAA","204":"b:ABAYAAUgAA6BAIABAAQiEQAAAAAA","210":[113],"218":[113],"289":"b:ML5b4A0y1s7h+YMhz+3//ysCAAAA","294":"b:ML5b4A0y1s7h+YMhz+3//ysCAAAA","295":[124],"304":"b:AKpZ4A0ykg4hkYAAx83vnwIAAAAA","309":[41,44,75,119],"313":[41],"350":"b:ML5b4A0y1s7h+YMhz+3//ysCAAAA","435":"b:ML5b4A0y1s7h+YMhz+3//ysCAAAA","439":[41,44,75,119],"452":"b:ML5b4A0y1s7h+YMhz+3//ysCAAAA","473":"b:ML5b4A0y1s7h+YMhz+3//ysCAAAA","506":[41,44,75,119]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/ParameterInputList.vue":{"65":"b:MJoZwAUQFEIhAQAgQoD/ZyAAAAAA","68":"b:AJpbYAUyVo4h+YIhT+3/7wsCAAAA","123":"b:MJ5b4A0yVs4h+YMhz+3/7ysCAAAA","144":"b:ML5b4A0y1s7h+YMhz+3//ysCAAAA","146":"b:ML5b4A0y1s7h+YMhz+3//ysCAAAA","175":"b:ML5b4A0y1s7h+YMhz+3//ysCAAAA","188":"b:ML5b4A0y1s7h+YMhz+3//ysCAAAA","194":"b:ML5b4A0y1s7h+YMhz+3//ysCAAAA","195":"b:ML5b4A0y1s7h+YMhz+3//ysCAAAA","217":"b:ML5b4A0y1s7h+YMhz+3//ysCAAAA","241":"b:ML5b4A0y1s7h+YMhz+3//ysCAAAA","268":"b:AAYSAAACAAIBIAEBgAHhEQIAAAAA","269":"b:AAYSAAACAAIBIAEBgAHhEQIAAAAA","275":"b:ML5b4A0y1s7h+YMhz+3//ysCAAAA","276":"b:ML5b4A0y1s7h+YMhz+3//ysCAAAA","279":"b:ML5b4A0y1s7h+YMhz+3//ysCAAAA","280":"b:ML5b4A0y1s7h+YMhz+3//ysCAAAA","283":"b:ML5b4A0y1s7h+YMhz+3//ysCAAAA","300":"b:ML5b4A0y1s7h+YMhz+3//ysCAAAA","309":[20,57],"312":[20,57],"335":[20,57],"353":[19],"356":[19],"391":[20,57],"394":[20,57],"398":[20,57],"403":"b:ABAYAAUyEAahAIABgAQnGQIAAAAA","407":"b:ML5b4A0y1s7h+YMhz+3//ysCAAAA","414":"b:MDhZ4AUwFAYhgQAAAcygLyACAAAA","421":"b:ML5b4A0y1s7h+YMhz+3//ysCAAAA","425":"b:ML5b4A0y1s7h+YMhz+3//ysCAAAA","440":"b:ML5b4A0y1s7h+YMhz+3//ysCAAAA","447":[15,16],"462":"b:ML5b4A0y1s7h+YMhz+3//ysCAAAA","479":"b:AJQZIA0ygA6hAIEBx4UvHQMAAAAA","489":"b:ML5b4A0y1s7h+YMhz+3//ysCAAAA","504":"b:ML5b4A0y1s7h+YMhz+3//ysCAAAA","508":"b:ML5b4A0y1s7h+YMhz+3//ysCAAAA","536":"b:ML5b4A0y1s7h+YMhz+3//ysCAAAA","542":[15,16,44,49,76,96,119,120],"546":[15,16,44,49,76,96,119,120],"556":"b:MAgQoAASVAJhCQAgBAFlPyAAAAAA","561":[31,41,44,69,4,5,120,123],"643":"b:ML5b4A0y1s7h+YMhz+3//ysCAAAA","666":"b:ML5b4A0y1s7h+YMhz+3//ysCAAAA","725":[15,16,44,49,76,96,119,120],"740":[120],"746":[15,16,44,49,76,96,119,120],"798":"b:MJpb4AUyVs4h+YIhT+3/7ysCAAAA","821":"b:MJpb4AUyVs4h+YIhT+3/7ysCAAAA","823":"b:MJpb4AUyVs4h+YIhT+3/7isCAAAA","944":"b:ABAYAAUyEAahAIABgAQnGQIAAAAA"},"packages/frontend/editor-ui/src/features/ndv/parameters/utils/fromAIOverride.utils.ts":{"38":[41],"79":[75],"86":[41,44,75,119],"102":[41],"113":"b:AIABAAASAAAgGAAAAECACQMAAAAA","117":[41],"128":[41],"134":[41],"149":[41],"174":[41,44,75,119],"196":"b:ML5b4A0y1s7h+YMhz+3//ysCAAAA","205":"b:ML5b4A0y1s7h+YMhz+3//ysCAAAA","209":"b:ML5b4A0y1s7h+YMhz+3//ysCAAAA","227":"b:ML5b4A0y1s7h+YMhz+3//ysCAAAA"},"packages/frontend/editor-ui/src/features/ndv/runData/components/RunData.vue":{"103":"b:AMBaAAQAAM6BIAIAgM1/lwEAAAAA","104":[75,107,110,113,118],"106":"b:AIYKAAQAAIzAyAIAiu1/twEAAAAA","109":[15,110],"111":"b:AMZaAAQAAM7BaAIAis1/lwEAAAAA","262":"b:AEYYAAQAAM6BAAIAgM1/lwEAAAAA","263":"b:MN5b4A0w1s7h8QMgx+3//ysCAAAA","264":"b:MN5b4A0w1s7h+QMgz+3//ysCAAAA","272":"b:AIAAAAAAAACACAAAAG1/BgAAAAAA","273":"b:MN5b4A0w1s7h+QMgz+3//ysCAAAA","279":"b:MN5b4A0w1s7h+QMgz+3//ysCAAAA","280":"b:AIYKAAQAAIzASAIAis1/lwEAAAAA","282":"b:MN5b4A0w1s7h+QMgz+3//ysCAAAA","283":"b:AAZaAAQAAM7BSAIAgs1/lwEAAAAA","284":"b:MN5b4A0w1s7h+QMgz+3//ysCAAAA","285":"b:MN5b4A0w1s7h+QMgz+3//ysCAAAA","286":"b:MN5b4A0w1s7h+QMgx+3//ysCAAAA","289":"b:MJ4b4A0w1o6h+QMgx+3//ysAAAAA","293":"b:MN5b4A0w1s7h+QMgx+3//ysCAAAA","301":"b:AIYKAAQAAIzAyAIAiu1/twEAAAAA","302":"b:MJ5b4A0w1s7h+QMgz+3//ysCAAAA","303":"b:MJ5b4A0w1s7h+QMgz+3//ysCAAAA","304":"b:AABYAAQAAM6BAAIAgM1/lwEAAAAA","312":"b:AIYKAAQAAIzAyAIAiu1/twEAAAAA","322":"b:MN5b4A0w1s7h+QMgz+3//ysCAAAA","328":"b:MN5b4A0w1s7h+QMgz+3//ysCAAAA","332":"b:AMZbAAQAAM7B6AIAiu1/twEAAAAA","336":"b:AMZaAAQAAM7B6AIAiu1/twEAAAAA","345":"b:AMZaAAQAAM7B6AIAiu1/twEAAAAA","349":"b:AMZaAAQAAM7B6AIAiu1/twEAAAAA","359":"b:MN5b4A0w1s7h+QMgx+3//ysCAAAA","361":"b:MJ5b4A0w1s7h+QMgz+3//ysCAAAA","370":"b:MN5b4A0w1s7h+QMgz+3//ysCAAAA","379":"b:AMZbAAQAAM7BaAIAis1/lwEAAAAA","383":"b:MN5b4A0w1s7h+QMgz+3//ysCAAAA","388":"b:MN5b4A0w1s7h+QMgz+3//ysCAAAA","399":"b:MN5b4A0w1s7h+QMgx+3//ysCAAAA","405":"b:MN5b4A0w1s7h+QMgz+3//ysCAAAA","412":"b:MN5b4A0w1s7h+QMgz+3//ysCAAAA","422":"b:MN5b4A0w1s7h+QMgz+3//ysCAAAA","425":"b:MN5b4A0w1s7h+QMgz+3//ysCAAAA","435":"b:MN5b4A0w1s7h+QMgz+3//ysCAAAA","439":"b:MN5b4A0w1s7h+QMgz+3//ysCAAAA","443":"b:AEYQAAQAAEaBAAAAgMBvlgAAAAAA","447":"b:MN5b4A0w1s7h+QMgz+3//ysCAAAA","455":"b:MN5b4A0w1s7h+QMgz+3//ysCAAAA","458":"b:AMJIAAQAAIhAaAIACs1/hwEAAAAA","459":"b:MN5b4A0w1s7h+QMgz+3//ysCAAAA","467":"b:AMBaAAQAAM6BIAIAgM1/lwEAAAAA","468":"b:MN5b4A0w1s7h+QMgz+3//ysCAAAA","472":"b:MN5b4A0w1s7h+QMgz+3//ysCAAAA","477":[17,110,118,121,127],"487":[17,110,118,121,127],"493":"b:MN5b4A0w1s7h+QMgz+3//ysCAAAA","497":"b:MN5b4A0w1s7h+QMgz+3//ysCAAAA","498":"b:MN5b4A0w1s7h+QMgz+3//ysCAAAA","499":"b:MN5b4A0w1s7h+QMgz+3//ysCAAAA","503":"b:MN5b4A0w1s7h+QMgz+3//ysCAAAA","504":"b:MN5b4A0w1s7h+QMgz+3//ysCAAAA","514":"b:MN5b4A0w1s7h+QMgz+3//ysCAAAA","524":[15,17,59,110,116,117,118,121],"525":[15,17,59,110,116,117,118,121],"565":"b:MN5b4A0w1s7h+QMgz+3//ysCAAAA","569":"b:MJ4b4A0w1s7h8QMgx+3//ysCAAAA","570":"b:MN5b4A0w1s7h+QMgz+3//ysCAAAA","576":"b:MN5b4A0w1s7h+QMgz+3//ysCAAAA","587":"b:AMZaAAQAAM7B6AIAiu1/twEAAAAA","591":"b:MN5b4A0w1s7h+QMgx+3//ysCAAAA","603":"b:MN5b4A0w1s7h+QMgz+3//ysCAAAA","620":"b:MN5b4A0w1s7h+QMgz+3//ysCAAAA","625":"b:MN5b4A0w1s7h+QMgz+3//ysCAAAA","634":"b:AABYAAQAAM6BAAIAgM1/lwEAAAAA","638":"b:MN5b4A0w1s7h+QMgz+3//ysCAAAA","656":[17],"662":"b:MN5b4A0w1s7h+QMgz+3//ysCAAAA","665":"b:MJ4b4A0w1o7h+QMgz+3//ysAAAAA","668":"b:MN5b4A0w1s7h+QMgz+3//ysCAAAA","670":"b:MN5b4A0w1s7h+QMgz+3//ysCAAAA","673":"b:AAAAAAAAAIAAgQAAAKFApAAAAAAA","674":"b:AAAAAAAAAIAAgQAAAKFApAAAAAAA","691":"b:MN5b4A0w1s7h+QMgz+3//ysCAAAA","698":"b:MN5b4A0w1s7h+QMgz+3//ysCAAAA","702":"b:MN5b4A0w1s7h+QMgz+3//ysCAAAA","703":[15,110],"706":"b:MN5b4A0w1s7h+QMgz+3//ysCAAAA","710":[110],"716":"b:AEYQAAAAAAIBAAAAgEHjEwIAAAAA","721":"b:AMYTAAQAAEaBIAAAgMFvlgAAAAAA","731":"b:MN5b4A0w1s7h+QMgz+3//ysCAAAA","736":"b:AMZaAAQAAM6BaAIAis1/lwEAAAAA","743":"b:AMYTAAQQAk6BOAAAgMX/lwIAAAAA","752":"b:AMYTAAQAAE6BIAAAgMH/lwIAAAAA","760":[9,10,15,110,117,121],"767":[116,118],"773":"b:MN5b4A0w1s7h+QMgz+3//ysCAAAA","782":"b:MN5b4A0w1s7h+QMgz+3//ysCAAAA","803":[106,110],"814":"b:ANobYAgwVkoh+QEgz+3/dykCAAAA","819":"b:MN5b4A0w1s7h+QMgz+3//ysCAAAA","835":[52,70,72,78,107,118,125,129],"862":"b:MN5b4A0w1s7h+QMgz+3//ysCAAAA","901":[113,116,118,121],"923":"b:MN5b4A0w1s7h+QMgx+3//ysCAAAA","939":"b:AAYAAAAAAAKBAAAAgIEfFAAAAAAA","947":"b:ANobYAgwVkoh+QEgz+3/dykCAAAA","955":"b:AEYQAAQAAEaBAAAAgMU/FAAAAAAA","960":"b:AAAAAAAAAAAAAAAAACEPBgAAAAAA","996":"b:AAAAAAAAAAAAAAAAACEPBgAAAAAA","1020":[104,112,113,114,115,121,122],"1047":[104,112,113,114,115,121,122],"1057":[106,122],"1111":[121],"1135":[17,118],"1143":[17,118],"1147":[17,118],"1151":[71],"1164":"b:AMYSAAQAAEaBIAAAgEF/lgAAAAAA","1187":"b:AIAAAAAAAAAACAAAAEhyAgAAAAAA","1218":[17,110,118,121,127],"1246":"b:MN5b4A0w1s7h+QMgz+3//ysCAAAA","1271":"b:MN5b4A0w1s7h+QMgz+3//ysCAAAA","1274":"b:AABAAAAAAAAAAAAACAVfBwEAAAAA","1286":"b:MN5b4A0w1s7h+QMgz+3//ysCAAAA","1292":[116,118],"1295":"b:MN5b4A0w1s7h+QMgz+3//ysCAAAA","1313":"b:MN5b4A0w1s7h+QMgz+3//ysCAAAA","1323":"b:MN5b4A0w1s7h+QMgz+3//ysCAAAA","1350":"b:MN5b4A0w1s7h+QMgz+3//ysCAAAA","1377":[15,17,59,110,116,117,118,121],"1395":"b:MN5b4A0w1s7h+QMgz+3//ysCAAAA","1398":"b:AMZaAAQAAM6BaAIAis1/lwEAAAAA","1404":"b:MN5b4A0w1s7h+QMgz+3//ysCAAAA","1411":[17,118,121,127],"1428":"b:MN5b4A0w1s7h+QMgx+3//ysCAAAA","1434":"b:MN5b4A0w1s7h+QMgx+3//ysCAAAA","1440":"b:MN5b4A0w1s7h+QMgx+3//ysCAAAA","1493":"b:AAAAAAAAAAAAAAAAAAVfBgAAAAAA","1497":"b:AABAAAAAAAAAAAAAAAVfBgAAAAAA","1505":"b:AABAAAAAAAAAAAAAAAVfBgAAAAAA","1520":"b:AAAAAAAAAAAAAAAAACUPBgAAAAAA","1571":"b:AAAAAAAAAAAAAAAAACEPBgAAAAAA","1584":[106,122],"1630":[17,118,121,127],"1632":[17,110,118,121,127],"1633":[17,110,118,121,127],"1634":[17,110,118,121,127],"1645":[17,118,121],"1679":[52,72,78,125,129],"1684":[52,72,78,125,129],"1756":"b:AMYTAAQAAEaBIAAAgMBvlgAAAAAA","1794":[109],"1800":[104,112,113,114,115,121,122],"1805":"b:AAAAAAAAAAAAAAAAACEPBgAAAAAA","1807":"b:AAAAAAAAAAAAAAAAACEPBgAAAAAA","2066":"b:AMJIAAQAAIhAaAIACs1/hwEAAAAA","2109":[116],"2111":[116],"2134":"b:AMBaAAQAAM6BIAIAgM1/lwEAAAAA"},"packages/frontend/editor-ui/src/features/ndv/runData/components/RunDataDisplayModeSelect.vue":{"18":"b:MN5b4A0w1s7h+QMgx+3//ysCAAAA","21":"b:MN5b4A0w1s7h+QMgx+3//ysCAAAA","45":"b:MN5b4A0w1s7h+QMgx+3//ysCAAAA","47":"b:MN5b4A0w1s7h+QMgx+3//ysCAAAA","53":"b:MN5b4A0w1s7h+QMgx+3//ysCAAAA","62":[75,107,110,113,116,117,118,121],"64":[14,15,16,17,77,110]},"packages/frontend/editor-ui/src/features/ndv/runData/schemaPreview.store.ts":{"11":"b:MN9b4A8w1v/h+QOgz/3//+sCAAAA","21":"b:ANcbAA4gAP/B6QKAh/1/t8EAAAAA","30":"b:AAAAAAAAAIBAwQAAAKFEpAAAAAAA","49":"b:ANcbAA4gAP/BaAKAh/x/l8EAAAAA"},"packages/frontend/editor-ui/src/features/ndv/settings/components/NodeSettings.vue":{"160":"b:MJ5b4A0w1s7h+QMgz+3//ysCAAAA","163":"b:MJ5b4A0w1s7h+QMgz+3//ysCAAAA","164":[69],"167":"b:MJ5b4A0w1s7h+QMgz+3//ysCAAAA","168":[69],"171":"b:MJ5b4A0w1s7h+QMgz+3//ysCAAAA","174":"b:MJ5b4A0w1s7h+QMgz+3//ysCAAAA","176":"b:MJ5b4A0w1s7h+QMgz+3//ysCAAAA","182":"b:MJ5b4A0w1s7h+QMgz+3//ysCAAAA","185":"b:AAAAAAAAAAAAAAAAACEPBgAAAAAA","187":"b:MJ5b4A0w1s7h+QMgz+3//ysCAAAA","189":"b:MJ5b4A0w1s7h8QMgz+3//ysCAAAA","191":"b:MJ5b4A0w1s7h+QMgx+3//ysCAAAA","195":"b:MJ5b4A0w1s7h+QMgz+3//ysCAAAA","200":"b:MJ5b4A0w1s7h+QMgz+3//ysCAAAA","202":"b:MJ5b4A0w1s7h+QMgz+3//ysCAAAA","206":"b:MJ5b4A0w1s7h+QMgz+3//ysCAAAA","220":"b:MJ5b4A0w1s7h+QMgz+3//ysCAAAA","234":"b:MJ5b4A0w1s7h+QMgz+3//ysCAAAA","242":"b:MJ5b4A0w1s7h+QMgz+3//ysCAAAA","246":"b:MJ5b4A0w1s7h+QMgz+3//ysCAAAA","250":"b:MJhZ4AUw1gZhkQAgBc2gLyACAAAA","254":"b:MJ5b4A0w1s7h+QMgz+3//ysCAAAA","257":"b:MJhZ4AUw1gZhkQAgBc2gLyACAAAA","258":"b:MIgBoAEQ1gZhEQAgBEGgLyAAAAAA","262":"b:MJ5b4A0w1s7h+QMgz+3//ysCAAAA","266":"b:MJ5b4A0w1s7h+QMgz+3//ysCAAAA","275":"b:MJ5b4A0w1s7h+QMgz+3//ysCAAAA","278":"b:AJ5bYA0wls6h+QMgz+3//ysCAAAA","281":"b:MJ5b4A0w1s7h+QMgz+3//ysCAAAA","283":[117],"304":"b:MJ5b4A0w1s7h+QMgz+3//ysCAAAA","311":"b:MJ5b4A0w1s7h+QMgz+3//ysCAAAA","320":"b:MJQZoA0wgA6hAAEAx4WvHQMAAAAA","487":[119],"495":"b:MJ5b4A0w1s7h+QMgz+3//ysCAAAA","498":"b:MIoZoAkw1k4h0AEgz2WvfSoCAAAA","504":"b:MJ5b4A0w1s7h+QMgz+3//ysCAAAA","514":"b:AJAZAAUwEAahAAAAgAQlGQIAAAAA","515":"b:AIAZAAEwEAYhAAAAgAQlGQIAAAAA","523":"b:AAYAAAQAAESAAAAAgIBqFgAAAAAA","529":"b:MIABgAAQAAAhEAAAAEAACQAAAAAA","553":"b:MJ5b4A0w1s7h+QMgz+3//ysCAAAA","578":[117],"595":"b:AAYSAAAAAAIBIAAAgAHhEQIAAAAA","599":"b:MJ5b4A0w1s7h+QMgz+3//ysCAAAA","610":"b:AJobYAgwVkoh+QEgz+3/dykCAAAA","616":"b:MJhZ4AUw1gZhkQAgBc2gLyACAAAA","782":"b:MJ5b4A0w1s7h+QMgz+3//ysCAAAA"},"packages/frontend/editor-ui/src/features/ndv/settings/components/NodeSettingsHeader.vue":{"22":"b:MJ5b4A0w1s7h+QMgz+3//ysCAAAA","40":[117]},"packages/frontend/editor-ui/src/features/ndv/settings/components/NodeSettingsHint.vue":{"13":"b:MJ5b4A0w1s7h+QMgx+3//ysCAAAA","16":"b:MJ5b4A0w1s7h+QMgx+3//ysCAAAA","68":"b:MJ5b4A0w1s7h+QMgx+3//ysCAAAA","72":[117],"77":[117]},"packages/frontend/editor-ui/src/features/ndv/settings/components/NodeSettingsTabs.vue":{"29":"b:MJ5b4A0w1s7h+QMgz+3//ysCAAAA","45":[80,99],"49":"b:MJ5b4A0w1s7h+QMgz+3//ysCAAAA","53":[55],"55":"b:MJ5b4A0w1s7h+QMgz+3//ysCAAAA","63":"b:MJ5b4A0w1s7h+QMgz+3//ysCAAAA","130":[117],"161":"b:MJ5b4A0w1s7h+QMgz+3//ysCAAAA"},"packages/frontend/editor-ui/src/features/ndv/settings/components/NodeWebhooks.vue":{"21":"b:MJ5b4A0w1s7h+QMgz+3//ysCAAAA","38":"b:AABQIAEQBAIBAAAAAIggDAACAAAA","45":"b:AABQIAEAAAIBAAAAAIggBAACAAAA","53":"b:MJ5b4A0w1s7h+QMgz+3//ysCAAAA","58":"b:AAhZIAEQFAIBAQAAAMggDwACAAAA","70":"b:MJ5b4A0w1s7h+QMgz+3//ysCAAAA","124":"b:AABQIAEQBAIBAAAAAIggDAACAAAA","192":"b:MJ5b4A0w1s7h+QMgz+3//ysCAAAA","193":"b:AAYQAAAAAAIBAAAAgAHhEQIAAAAA","200":"b:MJ5b4A0w1s7h+QMgz+3//ysCAAAA","218":"b:AABQIAEAAAIBAAAAAIggBAACAAAA","224":"b:AABQIAEAAAIBAAAAAIggBAACAAAA"},"packages/frontend/editor-ui/src/features/ndv/shared/views/NodeDetailsViewV2.vue":{"70":"b:cP9/4A84/v/n/wOg//////8PAAAA","86":"b:cP9/4A84/v/n/wOg//////8PAAAA","103":"b:ML5b4A0w1s7j+QMgx+3//zsCAAAA","105":"b:MJ5b4A0w1s7j+QMgx+3//ysCAAAA","109":"b:cP9/4A84/v/n/wOg//////8PAAAA","118":[9,10,65,103,113,118,122],"120":"b:MJ5b4A0w1s7j+QMgx+3//ysCAAAA","134":"b:cP9/4A84/v/n/wOg//////8PAAAA","139":"b:MJ4b4A0w1o7h8QMgx+3//ysAAAAA","146":"b:cP9/4A84/v/n/wOg//////8PAAAA","159":"b:cP9/4A84/v/n/wOg//////8PAAAA","165":"b:MJ5b4A0w1s7h+QMgx+3//ysCAAAA","186":"b:cP9/4A84/v/n/wOg//////8PAAAA","193":"b:MJ5b4A0w1s7j+QMgx+3//ysCAAAA","195":"b:cP9/4A84/v/n/wOg//////8PAAAA","199":"b:MJ5b4A0w1s7j+QMgx+3//ysCAAAA","213":[20,57,64,65,107],"219":"b:cP9/4A84/v/n/wOg//////8PAAAA","223":"b:MJ5b4A0w1s7j+QMgx+3//ysCAAAA","225":"b:cP9/4A84/v/n/wOg//////8PAAAA","243":"b:cP9/4A84/v/n/wOg//////8PAAAA","249":"b:cP9/4A84/v/n/wOg//////8PAAAA","270":"b:MJ4b4A0w1o7h+QMgx+3//ysAAAAA","285":"b:cP9/4A84/v/n/wOg//////8PAAAA","296":"b:MJ5b4A0w1s7j+QMgx+3//ysCAAAA","300":"b:MJ5b4A0w1s7j+QMgx+3//ysCAAAA","302":"b:ALoZYAgwVkoj2QEgx+3/djkCAAAA","304":"b:MJ5b4A0w1s7j+QMgx+3//ysCAAAA","306":"b:MJ5b4A0w1s7j+QMgx+3//ysCAAAA","312":"b:MJ5b4A0w1s7j+QMgx+3//ysCAAAA","314":"b:MJ5b4A0w1s7j+QMgx+3//ysCAAAA","318":"b:MJ4b4A0w1s7j+QMgx+3//ysCAAAA","320":"b:MJ4b4A0w1o7j+QMgx+3//ysAAAAA","322":"b:MJ5b4A0w1s7j+QMgx+3//ysCAAAA","324":"b:cP9/4A84/v/n/wOg//////8PAAAA","326":"b:MJ5b4A0w1s7j+QMgx+3//ysCAAAA","330":"b:MJ5b4A0w1s7j+QMgx+3//ysCAAAA","342":"b:cP9/4A84/v/n/wOg//////8PAAAA","353":"b:AAYAAAAAAAKDAAAAgIEfFAAAAAAA","357":[65,110],"361":"b:AJAAoAAQRACC0AAARyH/XQACAAAA","367":[65,113,118,121],"382":[65,110,113,116,117,118,121],"386":[65],"391":[65,113,116,118,121],"406":[65],"421":[65],"425":[65,118],"430":"b:MJ4b4A0w1g7j+QEgx+Xv/yoAAAAA","436":"b:AAYAAAQAAESCAAAAgIBqFgAAAAAA","437":[9,10,65,103,113,118,122],"445":[65],"449":"b:MJ4b4A0w1g7j+QEgx+Xv/yoAAAAA","458":[17,65,118],"464":[65,103,104,119,124],"468":[65,119],"472":"b:ALoZYAgwVkoj2QEgx+3/djkCAAAA","512":"b:MJ4b4A0w1o7j+QMgx+3//ysAAAAA","521":[17,65,118,121,127],"526":"b:MJ4b4A0w1o7j+QMgx+3//ysAAAAA","534":"b:AABaAAQAAM6DAAIAgM1/lwEAAAAA","538":[65,113,121],"552":[65],"556":"b:AAACAAAAAAACCAAAgUDyCwAAAAAA","561":"b:MJ5b4A0w1s7j+QMgx+3//ysCAAAA","566":[65,116,118],"570":"b:MJ5b4A0w1s7j+QMgx+3//ysCAAAA","574":"b:cP9/4A84/v/n/wOg//////8PAAAA","578":[65],"582":"b:AAAAAAAAAAACCAAAAElyAgAAAAAA","588":"b:cP9/4A84/v/n/wOg//////8PAAAA","606":"b:MJ5b4A0w1s7h+QMgx+3//ysCAAAA","616":"b:AI4bQAkwAAIhQAAgx03/PyIAAAAA","654":[17,65,110,118,121,127],"658":[17,65,118,121],"662":"b:MJ4b4A0w1o7j+QMgx+3//ysAAAAA","663":"b:MJ4b4A0w1o7j+QMgx+3//ysAAAAA","668":[17,65,118,121],"669":[17,65,118,121],"674":"b:MJ5b4A0w1s7j+QMgx+3//ysCAAAA","679":"b:MJ5b4A0w1s7j+QMgx+3//ysCAAAA","682":"b:MJ5b4A0w1s7j+QMgx+3//ysCAAAA","703":"b:cP9/4A84/v/n/wOg//////8PAAAA","709":"b:AIAAAAAAAAAiAAAgBF4AQNAAAAAA","783":"b:MJ4b4A0w1g7h+QEgx+Xv/yoAAAAA","791":[75,110,113,116,117,118,121],"809":"b:MJ5b4A0w1s7h+QMgx+3//ysCAAAA","850":[118],"857":[104,107,118,121]},"packages/frontend/editor-ui/src/features/settings/communityNodes/communityNodes.store.ts":{"12":"b:MJ5b4A0w1s7h+Qsgz+3//ysCAAAA","22":[55,83],"30":[83],"36":[55,83],"37":[83],"46":[55,83],"55":[55,83],"60":[83],"74":[83],"79":[83],"84":[83],"88":[83],"103":[55]},"packages/frontend/editor-ui/src/features/settings/communityNodes/composables/useInstalledCommunityPackage.ts":{"10":"b:MJ5b4A0w1s7h+QMgz+3//ysCAAAA","16":"b:MJ5b4A0w1s7h+QMgz+3//ysCAAAA","17":"b:MJ5b4A0w1s7h+QMgz+3//ysCAAAA","25":[55],"32":"b:MJ5b4A0w1s7h+QMgz+3//ysCAAAA","34":[17,55,77,119],"41":"b:MJ5b4A0w1s7h+QMgz+3//ysCAAAA","51":"b:MJ5b4A0w1s7h+QMgz+3//ysCAAAA"},"packages/frontend/editor-ui/src/features/settings/usage/usage.store.ts":{"38":"b:+P///Q+4/////xOk//////8PAAAA","74":"b:eP//6Q+4/////xOk//////8PAAAA","79":"b:+P///Q+4/////xOk//////8PAAAA"},"packages/frontend/editor-ui/src/features/shared/contextMenu/components/ContextMenu.vue":{"17":"b:cP9/4A84/v/n/wPg//////8PgAAA","24":"b:AIAAAAAAAAAAIAAAdgAABAEAgAAA","28":"b:AIAAAAAAAAAAIAAAdgAABAEAgAAA","49":"b:AIAAAAAAAAAAIAAAdgAABAEAgAAA","54":"b:AIAAAAAAAAAAIAAAdgAABAEAgAAA","61":"b:AIAAAAAAAAAAIAAAdgAABAEAgAAA","64":"b:cP9/4A84/v/n/wPg//////8PgAAA","72":"b:AIAAAAAAAAAAIAAAdgAABAEAgAAA","88":"b:AIAAAAAAAAAAIAAAdgAABAEAgAAA","95":"b:AIAAAAAAAAAAIAAAdgAABAEAgAAA","96":"b:AIAAAAAAAAAAIAAAdgAABAEAgAAA"},"packages/frontend/editor-ui/src/features/shared/contextMenu/composables/useContextMenu.ts":{"16":"b:cP9/4A84/v/n/wPg//////8PgAAA","18":"b:cP9/4A84/v/n/wPg//////8PgAAA","20":"b:AIAAAAAAAAAAIAAAdgAABAEAgAAA","27":"b:cP9/4A84/v/n/wOg//////8PgAAA","32":"b:AIAAAAAAAAAAIAAAdgAABAEAgAAA","53":"b:cP9/4A84/v/n/wPg//////8PgAAA","59":"b:AIAAAAAAAAAAIAAAdgAABAEAgAAA"},"packages/frontend/editor-ui/src/features/shared/contextMenu/composables/useContextMenuItems.ts":{"52":"b:AIAAAAAAAAAAIAAAdgAABAEAgAAA","58":"b:cP9/4A84/v/n/wPg//////8PgAAA","72":"b:AIAAAAAAAAAAIAEAdgAABAEAgAAA","76":"b:AIAAAAAAAAAAIAEAdgAABAEAgAAA","85":[151],"95":"b:AIAAAAAAAAAAIAEAdgAABAEAgAAA","97":"b:AIAAAAAAAAAAIAEAdgAABAEAgAAA","101":"b:AIAAAAAAAAAAIAEAdgAABAEAgAAA","102":"b:AIAAAAAAAAAAIAEAdgAABAEAgAAA","108":"b:AIAAAAAAAAAAIAEAdgAABAEAgAAA","116":"b:AIAAAAAAAAAAIAEAVgAABAEAgAAA","120":"b:AIAAAAAAAAAAIAAAVgAABAEAgAAA","135":"b:AIAAAAAAAAAAIAAAdgAABAEAgAAA","144":"b:AIAAAAAAAAAAIAEAdgAABAEAgAAA","146":"b:AIAAAAAAAAAAIAEAdgAABAEAgAAA","230":"b:AIAAAAAAAAAAIAEAVgAABAEAgAAA","238":"b:AIAAAAAAAAAAIAEAVgAABAEAgAAA","242":"b:AIAAAAAAAAAAIAEAVgAABAEAgAAA"},"packages/frontend/editor-ui/src/features/shared/editors/components/InlineExpressionEditor/InlineExpressionEditorInput.vue":{"26":"b:AIIBAAAQAoBAMUIAAUivHwIAAAAA","39":"b:AIIBAAAQAoBAMUIAAUivHwIAAAAA","51":"b:AIIBAAAQAoBAMUIAAUivHwIAAAAA","75":"b:AIIBAAAQAoBAMUIAAUivHwIAAAAA","81":"b:AIIAAAAAAIBAAUIAAEiPHwAAAAAA","88":"b:AIIBAAAQAoBAMUIAAUivHwIAAAAA","97":"b:AAAAAAAAAAAAAEAAAAAPHwAAAAAA","104":"b:AAAAAAAAAAAAAEAAAAAPHwAAAAAA","107":"b:AAAAAAAAAAAAAEAAAAAPHQAAAAAA","118":"b:AIIBAAAQAoBAMUIAAUivHwIAAAAA"},"packages/frontend/editor-ui/src/features/shared/editors/components/InlineExpressionEditor/InlineExpressionEditorOutput.vue":{"32":"b:AIIBAAAQAoBAMUIAAUmvHwIAAAAA","38":"b:AIIBAAAQAgAAMUAAAUmFAgAAAAAA","45":"b:AIIBAAAQAoBAMUIAAUmvHwIAAAAA","62":"b:AAAAAAAAAAAAAEAAAAEPHgAAAAAA","66":"b:AAAAAAAAAAAAAEAAAAEPHwAAAAAA","72":"b:AAAAAAAAAAAAAEAAAAEPHwAAAAAA"},"packages/frontend/editor-ui/src/features/shared/editors/components/InlineExpressionEditor/theme.ts":{"4":"b:AIIBAAAQAoBAMUIAAUmvHwIAAAAA","18":"b:AIIBAAAQAoBAMUIAAUivHwIAAAAA","58":"b:AIIBAAAQAoBAMUIAAUmvHwIAAAAA"},"packages/frontend/editor-ui/src/features/shared/editors/composables/useExpressionEditor.ts":{"59":"b:AIIBAAAQAoBAMUIAAUmvHwIAAAAA","70":"b:AAAAAAAAAAAAAEAAAAAPHQAAAAAA","103":"b:AIIBAAAQAoBAMUIAAUmvHwIAAAAA","108":"b:AIIBAAAQAoBAMUIAAUmPHwAAAAAA","122":"b:AIIBAAAQAoBAMUIAAUmPHwAAAAAA","142":"b:AIIBAAAQAoBAMUIAAUmPHwAAAAAA","176":"b:AIIBAAAQAoBAMUIAAUmvHwIAAAAA","180":"b:AIIAAAAAAIBAAUIAAEmPHwAAAAAA","186":"b:AIIBAAAQAoBAMUIAAUmvHwIAAAAA","197":"b:AIIBAAAQAoBAMUIAAUmvHwIAAAAA","201":"b:AIIBAAAQAoBAMUIAAUmvHwIAAAAA","212":"b:AIIBAAAQAgAAEEAAAQGvGwAAAAAA","220":"b:AIIBAAAQAgAAEEAAAQGvHwAAAAAA","227":"b:AAAAAAAAAAAAAAAAAAEPHQAAAAAA","238":"b:AIIBAAAQAoBAMUIAAUivHwIAAAAA","249":"b:AIIBAAAQAoBAMUIAAUmvHwIAAAAA","276":"b:AAAAAAAAAAAAAEAAAAEPHwAAAAAA","281":"b:AAAAAAAAAAAAAEAAAAAPHwAAAAAA","293":"b:AAAAAAAAAAAAAEAAAAENHwAAAAAA","309":"b:AIIBAAAQAoBAMUIAAUmvHwIAAAAA","317":"b:AIIBAAAQAoBAMUIAAUmvHwIAAAAA","327":"b:AIIBAAAQAoBAMUIAAUmvHwIAAAAA","339":"b:AIIBAAAQAoBAMUIAAUmvHwIAAAAA","350":"b:AIIBAAAQAoBAMUIAAUmvHwIAAAAA","354":"b:AIIBAAAQAgAAMUAAAUmFAgAAAAAA","361":"b:AIABAAAQAgAAMAAAAUCBAAAAAAAA","363":"b:AIABAAAQAgAAMAAAAUCBAAAAAAAA","369":"b:AIABAAAQAgAAMAAAAUCBAAAAAAAA","379":"b:AIIBAAAQAoBAMEIAAUmPHwAAAAAA","441":"b:AIIBAAAQAoBAMUIAAUmvHwIAAAAA","443":"b:AIIBAAAQAoBAMUIAAUmvHwIAAAAA","444":"b:AIIAAAAAAIBAAUIAAEmPHwAAAAAA","447":"b:AIIAAAAAAIBAAUIAAEmPHwAAAAAA","448":"b:AIIAAAAAAIBAAUIAAEmPHwAAAAAA","478":"b:AIIBAAAQAoBAMUIAAUivHwIAAAAA","481":"b:AIIAAAAAAIBAAUIAAEiPHwAAAAAA","511":"b:AIIAAAAAAIBAAUIAAEiPHwAAAAAA","527":"b:AIIBAAAQAoBAMUIAAUmvHwIAAAAA","535":"b:AAAAAAAAAAAAAEAAAAAPHQAAAAAA","555":"b:AAAAAAAAAAAAAEAAAAAPHQAAAAAA"},"packages/frontend/editor-ui/src/features/shared/editors/plugins/codemirror/completions/addCompletions.ts":{"8":"b:AIIBAAAQAoBAMUIAAUmvHwIAAAAA","15":"b:AIIBAAAQAoBAMUIAAUmvHwIAAAAA"},"packages/frontend/editor-ui/src/features/shared/editors/plugins/codemirror/dragAndDrop.ts":{"15":"b:AIYDYAgQQoBAMUMAx2mvnwIAAAAA","18":"b:AIYBAAgQAoBAMUMAgWmvnwIAAAAA","20":"b:AIYBAAgQAoBAMUIAgWmvnwIAAAAA","35":"b:AIYDYAgQQoBAMUMAx2mvnwIAAAAA","42":"b:AIYDYAgQQoBAMUMAx2mvnwIAAAAA","46":"b:AIYDYAgQQoBAMUMAx2mvnwIAAAAA","93":"b:AIIDIAgQQgAAMUEAx0mvBwAAAAAA","97":"b:AAABAAgAAAAAAUAAAAEvnwAAAAAA","104":"b:AAAAAAAAAAAAAEAAgAEvHwAAAAAA","112":"b:AAABAAgAAAAAAUAAAAEPnwAAAAAA","115":"b:AAAAAAAAAAAAAEAAAAEvHwAAAAAA","123":[113],"127":[113],"139":[113],"143":[113],"163":"b:AIYDYAgQQoBAMUMAx2mvnwIAAAAA"},"packages/frontend/editor-ui/src/features/shared/editors/plugins/codemirror/expressionCloseBrackets.ts":{"10":"b:AIIBAAAQAoBAMUIAAUmvHwIAAAAA","14":"b:AAAAAAAAAAAAAEAAAAEPHQAAAAAA","36":"b:AIIBAAAQAoBAMUIAAUmvHwIAAAAA"},"packages/frontend/editor-ui/src/features/shared/editors/plugins/codemirror/n8nLang.ts":{"11":[72,113,114,115],"14":"b:AIIBAAAQAoBAMUIAAUivHwIAAAAA","25":"b:AIIBAAAQAoBAMUIAAUivHwIAAAAA","28":"b:AIIBAAAQAoBAMUIAAUivHwIAAAAA","32":"b:AIIDQAAQQoBAMUIABWmvnwIAAAAA","37":[112,113,120,122]},"packages/frontend/editor-ui/src/features/shared/nodeCreator/components/ItemTypes/CategoryItem.vue":{"12":"b:MIoZoAkQfkojEAAgxwHvfSICAAAA","16":"b:MIoZoAkQfkojEAAgxwHvfSICAAAA","20":"b:MIoZoAkQfkojEAAgxwHvfSICAAAA"},"packages/frontend/editor-ui/src/features/shared/nodeCreator/components/ItemTypes/NodeItem.vue":{"38":"b:cIoZoAkw/k4j0AAgxy3vfaoCAAAA","58":"b:cIoZoAkw/k4j0AAgxy3vfaoCAAAA","78":"b:cIoZoAkw/k4j0AAgxy3vfaoCAAAA","85":"b:cIoZoAkw/k4j0AAgxy3vfaoCAAAA","90":"b:cIoZoAkw/k4j0AAgxy3vfaoCAAAA","94":"b:cIoZoAkw/k4j0AAgxy3vfaoCAAAA","98":"b:cIoZoAkw/k4j0AAgxy3vfaoCAAAA","102":"b:cIoZoAkw/k4j0AAgxy3vfaoCAAAA","108":"b:cIoZoAkw/k4j0AAgxy3vfaoCAAAA","110":"b:cIoZoAkw/k4j0AAgxy3vfaoCAAAA","115":"b:cIoZoAkw/k4j0AAgxy3vfaoCAAAA","116":"b:cIoZoAkw/k4j0AAgxy3vfaoCAAAA","118":"b:cIoZoAkw/k4j0AAgxy3vfaoCAAAA","127":"b:cIoZoAkw/k4j0AAgxy3vfaoCAAAA","131":"b:cIoZoAkw/k4j0AAgxy3vfaoCAAAA","135":"b:cIoZoAkw/k4j0AAgxy3vfaoCAAAA","139":[65],"143":"b:cIoZoAkw/k4j0AAgxy3vfaoCAAAA","155":"b:cIoZoAkw/k4j0AAgxy3vfaoCAAAA","157":[65],"171":[65],"173":[65],"178":[65],"181":"b:cIoZoAkw/k4j0AAgxy3vfaoCAAAA","201":"b:cIoZoAkw/k4j0AAgxy3vfaoCAAAA","214":"b:MIgJoAkQTAgjEAAgxwGiJSACAAAA","215":[65],"217":"b:MIgJoAkQTAgjEAAgxwGiJSACAAAA","227":[55,65],"229":[65],"232":[55,65],"246":"b:cIoZoAkw/k4j0AAgxy3vfaoCAAAA","258":[65]},"packages/frontend/editor-ui/src/features/shared/nodeCreator/components/ItemTypes/SubcategoryItem.vue":{"13":"b:cIoZoAkw/k4j0AAgxy3vfaoCAAAA","15":"b:cIoZoAkw/k4j0AAgxy3vfaoCAAAA","16":"b:cIoZoAkw/k4j0AAgxy3vfaoCAAAA"},"packages/frontend/editor-ui/src/features/shared/nodeCreator/components/Modes/NodesMode.vue":{"54":"b:cIoZoAkw/k4j0AAgxy3vfaoCAAAA","68":"b:cIoZoAkw/k4j0AAgxy3vfaoCAAAA","70":"b:cIoZoAkw/k4j0AAgxy3vfaoCAAAA","73":"b:cIoZoAkw/k4j0AAgxy3vfaoCAAAA","75":"b:cIoZoAkw/k4j0AAgxy3vfaoCAAAA","87":"b:cIoZoAkw/k4j0AAgxy3vfaoCAAAA","97":"b:cIoZoAkw/k4j0AAgxy3vfaoCAAAA","111":"b:cIoZoAkw/k4j0AAgxy3vfaoCAAAA","194":"b:MAgRoAgQZAIjAAAgxwFlPSIAAAAA","253":[15,49,51,52,65],"273":[15,49,51,52,65],"289":"b:cIoZoAkw/k4j0AAgxy3vfaoCAAAA","295":[65],"299":[29,65,96],"307":[29,65,96],"315":[29,65,96],"321":[65],"324":"b:cIoZoAkw/k4j0AAgxy3vfaoCAAAA","333":"b:cIoZoAkw/k4j0AAgxy3vfaoCAAAA","343":[65],"344":[65]},"packages/frontend/editor-ui/src/features/shared/nodeCreator/components/NodeCreator.vue":{"54":"b:cP8f4A84/v/n/wMg//////8PAAAA","56":"b:cIoZoAkw/k4j0AAgxy3vfaoCAAAA","64":"b:cIoZoAkw/k4j0AAgxy3vfaoCAAAA","72":[65,96],"83":"b:cKodoAkw/k4j0AAgx3/vffoCAAAA","87":"b:cIoZoAkw/k4j0AAgxy3vfaoCAAAA","91":"b:cIoZoAkw/k4j0AAgxy3vfaoCAAAA","96":[65],"99":[65],"119":"b:cP8f4A84/v/n/wMg//////8PAAAA","123":"b:cP8f4A84/v/n/wMg//////8PAAAA","124":"b:cIoZoAkw/k4j0AAgxy3vfaoCAAAA","134":"b:cIoZoAkw/k4j0AAgxy3vfaoCAAAA","142":[29,51,65,120],"145":"b:cP8f4A84/v/n/wMg//////8PAAAA","149":"b:cP8f4A84/v/n/wMg//////8PAAAA","160":"b:AKAEAAAAAAAiAAAgBF4AQNAAAAAA","165":[65,118]},"packages/frontend/editor-ui/src/features/shared/nodeCreator/components/NodeCreatorShortcutCoachmark.vue":{"14":"b:cP8f4A84/v/n/wMg//////8PAAAA","28":"b:cP8f4A84/v/n/wMg//////8PAAAA","31":[65],"45":[65]},"packages/frontend/editor-ui/src/features/shared/nodeCreator/components/Panel/NodesListPanel.vue":{"41":"b:cIoZoAkw/k4j0AAgxy3vfaoCAAAA","51":"b:cIoZoAkw/k4j0AAgxy3vfaoCAAAA","53":"b:cIoZoAkw/k4j0AAgxy3vfaoCAAAA","55":"b:cIoZoAkw/k4j0AAgxy3vfaoCAAAA","57":"b:cIoZoAkw/k4j0AAgxy3vfaoCAAAA","59":"b:cIoZoAkw/k4j0AAgxy3vfaoCAAAA","75":"b:cIoZoAkw/k4j0AAgxy3vfaoCAAAA","80":"b:cIoZoAkw/k4j0AAgxy3vfaoCAAAA","82":[55,65],"86":"b:cIoZoAkw/k4j0AAgxy3vfaoCAAAA","93":"b:cIoZoAkw/k4j0AAgxy3vfaoCAAAA","105":"b:cIoZoAkw/k4j0AAgxy3vfSoCAAAA","125":"b:MIgRoAgQ/gIjAAAgxwHlPSIAAAAA","130":"b:cIoZoAkw/k4j0AAgxy3vfaoCAAAA","134":"b:cIoZoAkw/k4j0AAgxy3vfaoCAAAA","139":"b:cIoZoAkw/k4j0AAgxy3vfaoCAAAA","144":"b:cIoZoAkw/k4j0AAgxy3vfaoCAAAA","145":"b:cIoZoAkw/k4j0AAgxy3vfaoCAAAA","194":[51,53,65],"196":"b:cIoZoAkw/k4j0AAgxy3vfaoCAAAA","208":[29,50,51,65,98,102]},"packages/frontend/editor-ui/src/features/shared/nodeCreator/components/Panel/SearchBar.vue":{"16":"b:cIoZoAkw/k4j0AAgxy3vfaoCAAAA","26":"b:cIoZoAkw/k4j0AAgxy3vfaoCAAAA","30":"b:cIoZoAkw/k4j0AAgxy3vfSoCAAAA","35":[65],"39":"b:cIoZoAkw/k4j0AAgxy3vfaoCAAAA","44":"b:cIoZoAkw/k4j0AAgxy3vfaoCAAAA","52":"b:cIoZoAkw/k4j0AAgxy3vfaoCAAAA"},"packages/frontend/editor-ui/src/features/shared/nodeCreator/components/Renderers/CategorizedItemsRenderer.vue":{"28":"b:MIoZoAkQfkojEAAgxwHvfSICAAAA","38":"b:MIoZoAkQfkojEAAgxwHvfSICAAAA","39":"b:MIoZoAkQfkojEAAgxwHvfSICAAAA","41":"b:MIoZoAkQfkojEAAgxwHvfSICAAAA","45":[54,65],"49":[50,54,65],"62":"b:MIoZoAkQfkojEAAgxwHvfSICAAAA","68":[65],"74":[65],"83":"b:MIoZoAkQfkojEAAgxwHvfSICAAAA","84":[50,65],"92":[65],"97":[29,65,96],"103":[65],"106":"b:MIoZoAkQfkojEAAgxwHvfSICAAAA","122":"b:MIoZoAkQfkojEAAgxwHvfSICAAAA","126":[65],"150":"b:MIoZoAkQfkojEAAgxwHvfSICAAAA","151":[50,65,117,120,123,124]},"packages/frontend/editor-ui/src/features/shared/nodeCreator/components/Renderers/ItemsRenderer.vue":{"28":"b:cIoZoAkw/k4j0AAgxy3vfaoCAAAA","43":"b:cIoZoAkw/k4j0AAgxy3vfaoCAAAA","45":"b:cIoZoAkw/k4j0AAgxy3vfaoCAAAA","47":"b:cIoZoAkw/k4j0AAgxy3vfaoCAAAA","51":"b:cIoZoAkw/k4j0AAgxy3vfaoCAAAA","61":"b:cIoZoAkw/k4j0AAgxy3vfaoCAAAA","78":"b:cIoZoAkw/k4j0AAgxy3vfaoCAAAA","104":[65],"108":[65],"112":[65],"116":[65],"120":"b:cIoZoAkw/k4j0AAgxy3vfaoCAAAA","124":"b:cIoZoAkw/k4j0AAgxy3vfaoCAAAA","131":"b:cIoZoAkw/k4j0AAgxy3vfaoCAAAA","132":"b:cIoZoAkw/k4j0AAgxy3vfSoCAAAA","139":"b:cIoZoAkw/k4j0AAgxy3vfaoCAAAA","152":"b:cIoZoAkw/k4j0AAgxy3vfaoCAAAA","161":[15,52,65,119],"180":"b:cIoZoAkw/k4j0AAgxy3vfaoCAAAA"},"packages/frontend/editor-ui/src/features/shared/nodeCreator/composables/useActions.ts":{"65":"b:MAgRoAgQZAIhAAAgxwFlPSIAAAAA","72":"b:MAgRoAgQZAIhAAAgxwFlPSIAAAAA","76":"b:MAgRoAgQZAIhAAAgxwFlPSIAAAAA","77":"b:MAgRoAgQZAIhAAAgxwFlPSIAAAAA","97":"b:MAgRoAgQZAIhAAAgxwFlPSIAAAAA","98":"b:MAgRoAgQZAIhAAAgxwFlPSIAAAAA","103":"b:MAgRoAgQZAIhAAAgxwFlPSIAAAAA","154":"b:MAgRoAgQZAIhAAAgxwFlPSIAAAAA","170":"b:MAgRoAgQRAIhAAAgxwElPSIAAAAA","173":"b:MAgAoAgQQAAgAAAgxwElLSAAAAAA","188":"b:MAgRoAgQRAIhAAAgxwElPSIAAAAA","217":"b:cIoZoAkw/k4h0AAgxy3vfaoCAAAA","243":"b:cIoZoAkwvkYh0AAg5y2vfaICAAAA","251":"b:cIoZoAkw/k4h0AAg5y2vfaoCAAAA","253":"b:cIoZoAkw/k4h0AAg5y2vfaoCAAAA","256":"b:cIoZoAkw/k4h0AAg5y2vfaoCAAAA","269":"b:cIoZoAkw/k4h0AAg5y2vfaoCAAAA","278":"b:cIoZoAkw/k4h0AAg5y2vfaoCAAAA","282":[15,16,96],"286":"b:cIoZoAkw/k4h0AAg5y2vfaoCAAAA","290":"b:cIoZoAkw/k4h0AAg5y2vfaoCAAAA","298":"b:cIoZoAkw/k4h0AAg5y2vfaoCAAAA","306":"b:cIoZoAkw/k4h0AAg5y2vfaoCAAAA","338":"b:cIoZoAkw/k4h0AAg5y2vfaoCAAAA","374":"b:MAgRoAgQVAIhAAAgxwElPSIAAAAA","379":"b:MAgRoAgQVAIhAAAgxwElPSIAAAAA","389":"b:MAgRoAgQRAIhAAAgxwElPSIAAAAA"},"packages/frontend/editor-ui/src/features/shared/nodeCreator/composables/useKeyboardNavigation.ts":{"14":"b:cP8f4A84/v/l/wMg//////8PAAAA","20":[29,51,96,120],"43":[29,96],"46":"b:cIoZoAkw/k4h0AAgxy3vfaoCAAAA","49":"b:cIoZoAkw/k4h0AAgxy3vfaoCAAAA","50":"b:cIoZoAkw/k4h0AAgxy3vfaoCAAAA","53":"b:cIoZoAkw/k4h0AAgxy3vfaoCAAAA","56":"b:cIoZoAkw/k4h0AAgxy3vfaoCAAAA","62":[29,51,96,120],"64":[29,51,96,120],"66":[29,51,96,120],"79":[9,29,50,51,96,98,102,120],"102":[29,51,96,120],"127":"b:cIoZoAkw/k4h0AAgxy3vfaoCAAAA","131":"b:cIoZoAkw/k4h0AAgxy3vfaoCAAAA","141":"b:cIoZoAkw/k4h0AAgxy3vfaoCAAAA","147":"b:cIoZoAkw/k4h0AAgxy3vfaoCAAAA","151":"b:cIoZoAkw/k4h0AAgxy3vfaoCAAAA","156":"b:cP8f4A84/v/l/wMg//////8PAAAA","157":"b:cP8f4A84/v/n/wMg//////8PAAAA","166":"b:cIoZoAkw/k4h0AAgxy3vfaoCAAAA","171":"b:MIgRoAgQ/gIhAAAgxwFlPSIAAAAA","172":"b:MIgRoAgQ/gIhAAAgxwFlPSIAAAAA"},"packages/frontend/editor-ui/src/features/shared/nodeCreator/composables/useNodeCreatorShortcutCoachmark.ts":{"12":"b:cP8f4A84/v/n/wMg//////8PAAAA","22":"b:AKAEAAAAAAAgAAAgBF4AQNAAAAAA"},"packages/frontend/editor-ui/src/features/shared/nodeCreator/nodeCreator.utils.ts":{"51":"b:cIoZoAkw/k4h0AAgxy3vfSoCgAAA","72":[151,51,52],"78":[151,51,52],"82":[151,51,52],"94":[151,51,52],"105":"b:MIgRoAgQfgIhEAAgxwHlPSIAgAAA","106":"b:MIgRoAgQfgIhAAAgxwHlPSAAgAAA","118":"b:cIoZoAkw/k4h0AAgxy3vfSoCgAAA","123":"b:cIoAoAgwuEQgAAAgxw0vTSIAgAAA","130":"b:cIoZoAkw/k4h0AAgxy3vfSoCgAAA","137":[151],"148":"b:cIoZoAkw/k4h0AAgxy3vfSoCgAAA","151":"b:cIoZoAkw/k4h0AAgxy3vfaoCgAAA","152":"b:cIoZoAkw/k4h0AAgxy3vfaoCgAAA","154":"b:cIoZoAkw/k4h0AAgxy3vfaoCgAAA","168":[15,151,49,119],"173":[15,151,49,119],"187":[15,151,49,119],"202":[15,16,151,44,49,52,76,119,120],"207":[15,16,151,44,49,52,119,120],"211":[15,16,151,44,49,52,76,119,120],"212":[15,16,151,44,49,52,119,120],"213":[15,16,151,44,49,52,119,120],"222":[15,16,151,44,49,52,76,119,120],"226":[15,16,151,44,49,52,119,120],"237":[15,16,151,44,49,52,119,120],"238":[15,16,151,44,49,52,119,120],"254":[15,16,151,44,49,52,76,119,120],"256":[15,16,151,119,120],"270":[15,16,151,44,49,52,76,119,120],"278":"b:cP8f4A84/v/n/wMg//////8PgAAA","286":"b:cP974A8w/v/h/wug//////sPgAAA","289":"b:cP974A8y/v/h/0Pg3/////sPgAAA","291":"b:cIoZoAkw/k4h0AAgxy3vfaoCgAAA","327":"b:cIoZoAkw/k4h0AAgxy3vfaoCgAAA","329":"b:cIoZoAkw/k4h0AAgxy3vfaoCgAAA","336":[151],"342":[151],"347":"b:cIoZoAkw/k4h0AAgxy3vfaoCgAAA","372":[151],"373":[151],"377":"b:cIoJoAkQ/E4h0AAgxy3vfSoCgAAA","382":[151,55],"405":[151],"431":[151,53],"449":[151,120],"468":"b:cIoZoAkw/k4h0AAgxy3vfaoCgAAA","472":"b:cIoZoAkw/k4h0AAgxy3vfaoCgAAA","478":"b:cIoZoAkw/k4h0AAgxy3vfaoCgAAA","486":[151,52],"487":[151,52]},"packages/frontend/editor-ui/src/features/shared/nodeCreator/views/NodeCreation.vue":{"40":"b:cP8f4A84/v/n/wMg//////8PAAAA","65":"b:cP8f4A84/v/n/wMg//////8PAAAA","72":"b:cIoZoAkwvk4jUAAgxwXvfSoAAAAA","79":[65,101],"93":"b:cIoZoAkw/k4j0AAgxy3vfaoCAAAA","100":"b:cIoZoAkw/k4j0AAgxy2vfaoCAAAA","105":[65,80,99],"119":[9,12,65],"136":[65],"139":[65],"155":"b:cP8f4A84/v/n/wMg//////8PAAAA","159":"b:cP8f4A84/v/n/wMg/////n8PAAAA","174":"b:cP8f4A84/v/n/wMg//////8PAAAA","188":"b:cP8f4A84/v/n/wMg//////8PAAAA","202":"b:cP8f4A84/v/n/wMg//////8PAAAA","218":[9,10,11,12,13,18],"227":[9,10,11,12,13,18]},"packages/frontend/editor-ui/src/features/shared/nodeCreator/views/viewsData.ts":{"122":[120],"139":[120],"141":[120],"145":[120],"148":[120],"174":[120],"197":[120],"250":[15,16,49,119,120],"253":[15,16,49,119,120],"263":[15,16,49,119,120],"389":"b:cIoZoAkw/k4h0AAgxw2vfaoCAAAA","515":"b:MIoZoAgwuAYh0AAgxyVvfSIAAAAA","526":"b:MIoZoAgwuAYh0AAgxyVvfSIAAAAA","528":"b:MIoZoAgwuAYh0AAgxyVvfSIAAAAA","529":"b:MIoZoAgwuAYh0AAgxyVvfSIAAAAA","651":"b:MIoZoAgwuAYh0AAgxyVvfSIAAAAA"},"packages/frontend/editor-ui/src/features/workflows/canvas/components/Canvas.vue":{"197":"b:cP9/4A84/v/n/wPg//////8PgAAA","199":"b:cP9/4A84/v/n/wOg//////8PgAAA","203":"b:cP9/4A84/v/n/wPg//////8PgAAA","206":"b:cP9/4A84/v/n/wPg7/////8PgAAA","248":"b:cP9/4A84/v/n/wPg//////8PgAAA","249":"b:cN5b4A0w/u7h+wMg/+3///sHgAAA","251":[151,96,97,98,102,131,138],"252":[151,96,97,98,102,131,138],"258":"b:cP9/4A84/v/n/wPg//////8PgAAA","275":"b:AAAAAAAAAAAAAAAAdwAgABkMgAAA","281":"b:ADIAAAAAAAAAAAAAdwEtHVkMgAAA","301":[151],"316":"b:AKAAIAAARAAA0AAAdyCAQPkOgAAA","318":[151,96],"326":[151,96],"334":[151],"336":[151],"345":[151],"347":[151],"356":[151,128],"358":[151,128],"361":[151,96],"363":[151,96],"366":[151],"378":[151,100],"382":[151,100],"394":[151],"397":[151],"402":"b:ACAAAAAAAAAAAAAAdwAAAPkMgAAA","404":[151],"406":[151,96,131,138],"407":[151,96,131,138],"409":[151],"410":[151,96,97,98,102,131,138],"412":[151],"413":[151],"414":[151],"415":[151],"422":[151],"423":[151],"424":[151],"429":[151],"435":[151],"436":[151,96,97,102],"437":[151,98],"438":[151,98,102,133,134,135],"439":[151],"440":[151,98],"441":[151],"443":[151],"444":[151],"448":[151,101],"449":[151],"450":[151],"451":[151,139],"454":[151],"455":[151],"456":[151],"457":[151],"458":[151],"459":[151],"460":[151],"461":[151],"466":[151],"470":[151],"471":[151],"486":"b:AAAAAAAAAAAAAAAARwAAAOgEgAAA","487":"b:cP9/4A84/v/n/wPg//////8PgAAA","490":"b:AP9fYAQA+orh6wMg/+/3l/kHgAAA","491":"b:AP9fYAQA+orh6wMg/+/3l/kHgAAA","500":"b:ANdbYAQAOorh6wMg3+/3l/kFgAAA","507":"b:cP9/4A84/v/n/wPg//////8PgAAA","508":"b:cN4b4A0wku7h+wMg/83//+sEgAAA","513":"b:cP9/4A84/v/n/wPg//////8PgAAA","519":"b:cP9/4A84/v/n/wPg//////8PgAAA","520":[9,10,11,12,13,151,18],"528":"b:AIABIAAAOgAAAAAAAyAAEAAAgAAA","532":[151,77,96,97,100,102,131],"536":[151],"542":[151,100],"543":[151],"544":[151,100],"545":[151,77,96,97,100,102,131],"546":[151,100],"549":[151,77,96,97,100,102,131],"553":[151,77,96,97,100,102,131],"557":[151,77,96,97,100,102,131],"562":[151],"566":[151],"570":[151,100],"574":[151,100],"578":"b:ABZbQAQAAIrhKQMA3+33h/kEgAAA","595":[151],"600":"b:AEECIAAAAAABIAAAP0BgAAEAgAAA","608":"b:ABZbQAQAAIrgKQMAhO33hwEAgAAA","613":[151],"617":"b:cN4ZoA0w/m5h8gMg923vfasDgAAA","621":"b:cN5b4A0w/u7h+wMg/+3///sHgAAA","625":"b:cN4ZoA0w/m5h8gMg923vfasDgAAA","642":[151,93,96,110],"646":[151,73,96,110],"650":[151],"654":[15,151],"658":[15,151],"661":[151,32,64,97],"665":[151,32,64,97],"668":[151],"681":[151],"685":[151],"690":[151],"706":"b:AIABIAAAOgAAAAAAEyAAEAEAgAAA","713":[151,97,100,128],"720":"b:AIABIAAAOgAAAAAAEyAAEAEAgAAA","731":[151,96,102],"735":[151,78,79,96],"748":"b:AAAAAAAAAAAgwAEAQUAAQAEAgAAA","754":[151,78,79,80,96,102],"772":[151,69,78,79,80,96,102,110],"777":[151,69,78,79,80,96,102,110],"784":"b:AL9fYAQA+orhKwMg/+33l/kHgAAA","788":"b:AL5fYAQA+orhKQMg/+33l/kDgAAA","796":[8,17,151,75,96,107,111,112,114],"804":"b:ACAAAAAAAAAAAAAAdwAAAPkMgAAA","812":"b:ACAAAAAAAAAAAAAAdwAAAPkMgAAA","829":"b:ANdbYAQAOorhKQMA/+33l/kEgAAA","839":"b:AEECIAAAAAABIAAAP0BgAAEAgAAA","843":[151],"847":"b:cP9/4A84/v/n/wPg//////8PgAAA","855":[151,98],"859":[151,98,105],"863":[151,98],"867":[151,98],"871":"b:cP9/4A84/v/n/wPg//////8PgAAA","880":[151],"884":"b:cP9/4A84/v/n/wPg//////8PgAAA","890":"b:cP9/4A84/v/n/wOg//////8PgAAA","891":"b:cP9/4A84/v/n/wOg//////8PgAAA","899":[151],"900":[151],"914":[151,97,98,101,128],"922":[151],"926":"b:AIAAAAAAAAAAIAAAdgAABAEAgAAA","941":"b:AIAAAAAAAAAAIAAAdgAABAEAgAAA","990":[13,151,94],"1021":[151,96],"1025":[151,96],"1035":"b:cP9/4A84/v/n/wPg//////8PgAAA","1039":"b:cP9/4A84/v/n/wPg//////8PgAAA","1044":[151],"1052":[151],"1061":[151],"1062":[151],"1067":[151],"1071":[151],"1079":[151,134],"1098":"b:AAAAQAAAAAAkAAAAFiAAQAkCgAAA","1105":[151,21,22,95],"1113":[151,21,22,95],"1121":"b:cP9/4A84/v/n/wPg//////8PgAAA","1126":[151],"1132":"b:AIAAAAAAAAAgAAAgBF4AQNAIgAAA","1142":"b:cP9/4A84/v/n/wPg//////8PgAAA","1151":"b:cP9/4A84/v/n/wPg//////8PgAAA","1167":"b:cP9/4A84/v/n/wPg//////8PgAAA","1177":"b:AEECIAAAAAABIAAAP0BgAAEAgAAA","1181":"b:cP9/4A84/v/n/wPg//////8PgAAA","1184":[151],"1191":[151],"1218":"b:cP9/4A84/v/n/wPg//////8PgAAA","1261":[151,100],"1273":"b:cP9/4A84/v/n/wPg//////8PgAAA","1300":[151],"1307":"b:MP974A8w1r/h/wPg3////+sNgAAA","1317":[151,69,78,79,80,96,102,110],"1322":"b:AIABIAAAOgAAAAAAEyAAEAEAgAAA","1324":"b:cP9/4A84/v/n/wPg//////8PgAAA","1328":"b:cP9/4A84/v/n/wOg//////8PgAAA","1337":[151],"1341":"b:cP9/4A84/v/n/wPg//////8PgAAA"},"packages/frontend/editor-ui/src/features/workflows/canvas/components/WorkflowCanvas.vue":{"69":"b:cP9/4A84/v/n/wOg//////8PAAAA","70":"b:cP9/4A84/v/n/wOg//////8PAAAA","74":"b:cP9/4A84/v/n/wOg//////8PAAAA","80":"b:AIAAAAAAAAAgAAAgBF4AQNAIAAAA","84":"b:cP9/4A84/v/n/wOg//////8PAAAA","89":"b:cP9/4A84/v/n/wOg//////8PAAAA","91":"b:cP9/4A84/v/n/wOg//////8PAAAA","92":"b:cP8f4A84/v/n/wMg//////8PAAAA","95":"b:cP974A8w/v/h/wOg3/////sPAAAA","108":"b:cP9/4A84/v/n/wOg//////8PAAAA","111":[100],"112":[100],"117":"b:cP9/4A84/v/n/wOg//////8PAAAA","123":"b:cP9/4A84/v/n/wOg//////8PAAAA","139":[98,102,122,131,136],"147":[98,102,122,131,136],"153":[98,102,122,131,136],"204":"b:cP9/4A84/v/n/wOg//////8PAAAA"},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/background/CanvasBackground.vue":{"13":"b:cP9/4A84/v/n/wPg//////8PgAAA"},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/buttons/CanvasChatButton.vue":{"9":"b:AMADAAAQAgAAMACAAECAAAAAAAAA"},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/buttons/CanvasControlButtons.vue":{"10":"b:cP9/4A84/v/n/wPg//////8PgAAA","36":"b:cP9/4A84/v/n/wPg//////8PgAAA","38":"b:cP9/4A84/v/n/wPg//////8PgAAA","40":"b:cP9/4A84/v/n/wPg//////8PgAAA","42":[151,98],"46":[151,98,105],"50":[151,98],"54":"b:AMECAAAAAAAAIAMAX+hgggEBgAAA","58":[151],"62":[151],"64":"b:cP9/4A84/v/n/wPg//////8PgAAA","71":"b:cP9/4A84/v/n/wPg//////8PgAAA","82":"b:cP9/4A84/v/n/wPg//////8PgAAA","92":"b:cP9/4A84/v/n/wPg//////8PgAAA","107":[151],"126":"b:AAACAAAAAAAAAABABErAggAAgAAA","140":"b:cP8f4A84/v/n/wMg//////8PgAAA","149":"b:cP8f4A84/v/n/wMg//////8PgAAA","157":[151],"170":[151]},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/edges/CanvasArrowHeadMarker.vue":{"6":"b:cP9/4A84/v/n/wPg//////8PgAAA"},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/edges/CanvasConnectionLine.vue":{"11":"b:AIABIAAAOgAAAAAAEyAAEAEAgAAA","17":"b:AIABIAAAOgAAAAAAEyAAEAEAgAAA","21":"b:AIABIAAAOgAAAAAAEyAAEAEAgAAA","28":"b:AIABIAAAOgAAAAAAEyAAEAEAgAAA","34":"b:AIABIAAAOgAAAAAAEyAAEAEAgAAA","38":"b:AIABIAAAOgAAAAAAEyAAEAEAgAAA","46":"b:AIABIAAAOgAAAAAAEyAAEAEAgAAA","47":"b:AIABIAAAMgAAAAAAAyAAEAEAgAAA","51":"b:AIABIAAAOgAAAAAAEyAAEAEAgAAA"},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/edges/CanvasEdge.vue":{"35":"b:MP974A8w1r/h/wPg3////+sNgAAA","43":"b:MP974A8w1r/h/wPg3////+sNgAAA","45":"b:MP974A8w1r/h/wPg3////+sNgAAA","46":"b:MP974A8w1r/h/wPg3////+sNgAAA","52":"b:IP8bwA8wkr/h/QMg3////+sMgAAA","60":"b:MP974A8w1r/h/wPg3////+sNgAAA","62":"b:MP974A8w1r/h/wPg3////+sNgAAA","64":"b:MP974A8w1r/h/wPg3////+sNgAAA","66":"b:MP974A8w1r/h/wPg3////+sNgAAA","71":"b:MP974A8w1r/h/wPg3////+sNgAAA","77":"b:MP974A8w1r/h/wPg3////+sNgAAA","82":"b:MP974A8w1r/h/wPg3////+sNgAAA","89":"b:MP974A8w1r/h/wPg3////+sNgAAA","95":"b:MP974A8w1r/h/wPg3////+sNgAAA","97":"b:MP974A8w1r/h/wPg3////+sNgAAA","99":[151,78,79,96,102],"106":"b:MP974A8w1r/h/wPg3////+sNgAAA","116":"b:MP974A8w1r/h/wPg3////+sNgAAA","117":"b:MP974A8w1r/h/wPg3////+sNgAAA","121":"b:MP974A8w1r/h/wPg3////+sNgAAA","132":[151,78,79,96],"136":[151,96,102],"140":[151,69,78,79,80,96,102,110],"144":[151,69,78,79,80,96],"146":"b:MP974A8w1r/h/wPg3////+sNgAAA","160":"b:MP974A8w1r/h/wPg3////+sNgAAA"},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/edges/utils/getEdgeRenderData.ts":{"11":"b:MP974A8w/r/h/wPg3////+sNgAAA","13":"b:MP974A8w/r/h/wPg3////+sNgAAA"},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/handles/CanvasHandleRenderer.vue":{"15":"b:cP974A8w/v/h/wPg3/////sPgAAA","43":"b:cP974A8w/v/h/wPg3/////sPgAAA","47":"b:cP974A8w/v/h/wPg3/////sPgAAA","53":"b:cP974A8w/v/h/wPg3/////sPgAAA","57":"b:cP974A8w/v/h/wPg3/////sPgAAA","63":"b:cP974A8w/v/h/wPg3/////sPgAAA","69":"b:cP974A8w/v/h/wPg3/////sPgAAA","77":"b:cP974A8w/v/h/wPg3/////sPgAAA","87":"b:cP974A8w/v/h/wPg3/////sPgAAA","89":"b:cP974A8w/v/h/wPg3/////sPgAAA","113":"b:AIABIAAAOgAAAAAAAyAAEAAAgAAA","142":"b:cP974A8w/v/h/wPg3/////sPgAAA"},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/handles/render-types/CanvasHandleMainInput.vue":{"14":"b:MP974A8w1r/h/wPg3////+sNgAAA","22":"b:MP974A8w1r/h/wPg3////+sNgAAA","26":"b:MP974A8w1r/h/wPg3////+sNgAAA"},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/handles/render-types/CanvasHandleMainOutput.vue":{"22":"b:cP8b4A8w/v/h/wNg3/////sPgAAA","27":"b:cP974A8w/v/h/wPg3/////sPgAAA","29":"b:cP974A8w/v/h/wPg3/////sPgAAA","38":"b:cP8b4A8w/v/h/wNg3/////sPgAAA","40":"b:AIcLAA4gALvBSAIAhvx3l4EAgAAA","49":"b:cP8b4A8w/v/h/wNg3/////sPgAAA","51":"b:cP8b4A8w/v/h/wNg3/////sPgAAA","53":"b:cP8b4A8w/v/h/wNg3/////sPgAAA","58":"b:ACBAIAMAEIhBwgAAQspyBgALgAAA","63":"b:AIcLAA4gALvBSAIAhvx3l4EAgAAA","70":"b:cP974A8w/v/h/wPg3/////sPgAAA","75":"b:AAAAIAAAOAAAAAAAByAAEAAAgAAA","79":[151,29,52,53,96,97,109,124],"83":[151,29,51,52,53,96,97,109,124],"85":"b:cP974A8w/v/h/wPg3/////sPgAAA"},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/handles/render-types/CanvasHandleNonMainInput.vue":{"19":"b:AIEDAAAQAgAAGAAgAUCAAQAAgAAA","21":"b:AIEDAAAQAgAAGAAgAUCAAQAAgAAA","27":"b:AIEDAAAQAgAAGAAgAUCAAQAAgAAA","33":"b:AIABAAAQAgAAGAAgAUCAAQAAgAAA","39":"b:AIEDAAAQAgAAGAAgAUCAAQAAgAAA","44":[15,16,151,49],"48":[15,16,151,49],"52":[15,16,151,49],"54":"b:AIEDAAAQAgAAGAAgAUCAAQAAgAAA"},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/handles/render-types/CanvasHandleNonMainOutput.vue":{"13":"b:AIEDAAAQAgAAGAAAAECAAQAAgAAA","15":"b:AIEDAAAQAgAAGAAAAECAAQAAgAAA","23":"b:AIEDAAAQAgAAGAAAAECAAQAAgAAA","27":"b:AIEDAAAQAgAAGAAAAECAAQAAgAAA"},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/handles/render-types/parts/CanvasHandleDiamond.vue":{"13":"b:AIEDAAAQAgAAGAAgAUCAAQAAgAAA"},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/handles/render-types/parts/CanvasHandleDot.vue":{"4":"b:cP974A8w/v/h/wPg3/////sPgAAA","13":"b:cP974A8w/v/h/wPg3/////sPgAAA","14":"b:cP974A8w/v/h/wPg3/////sPgAAA"},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/handles/render-types/parts/CanvasHandlePlus.vue":{"6":"b:cP8b4A8w/v/h/wNg3/////sPgAAA","34":"b:cP8b4A8w/v/h/wNg3/////sPgAAA","41":"b:cP8b4A8w/v/h/wNg3/////sPgAAA","57":"b:cP8b4A8w/v/h/wNg3/////sPgAAA","64":"b:cP8b4A8w/v/h/wNg3/////sPgAAA","89":"b:cP8b4A8w/v/h/wNg3/////sPgAAA","102":"b:AIABIAAAOgAAAAAAAyAAEAAAgAAA","104":"b:cP8b4A8w/v/h/wNg3/////sPgAAA"},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/nodes/CanvasNode.vue":{"49":"b:cP9/4A84/v/n/wPg//////8PgAAA","89":"b:cP9/4A84/v/n/wPg//////8PgAAA","90":"b:cP9/4A84/v/n/wPg//////8PgAAA","91":"b:cP974A8w/v/h/wPg3/////sPgAAA","105":"b:cP974A8w/v/h/wPg3/////sPgAAA","107":"b:cP9/4A84/v/n/wPg//////8PgAAA","115":[151],"118":"b:cP9/4A84/v/n/wPg//////8PgAAA","120":"b:cP9/4A84/v/n/wPg//////8PgAAA","136":"b:ABZbQAQAAIrgKQMApO33hwEAgAAA","146":"b:cP9/4A84/v/n/wPg//////8PgAAA","150":"b:cP9/4A84/v/n/wPg//////8PgAAA","154":"b:cP9/4A84/v/n/wPg//////8PgAAA","161":"b:cP9/4A84/v/n/wPg//////8PgAAA","165":"b:cP974A8w/v/h/wPg3/////sPgAAA","172":"b:cP9/4A84/v/n/wPg//////8PgAAA","249":"b:AIABIAAAOgAAAAAAAyAAEAAAgAAA","253":[151,73,96,110],"257":[8,17,151,75,96,107,111,112,114],"261":[151,93,96,110],"265":"b:ABZbQAQAAIrgKQMAgO33hwEAgAAA","269":[151],"273":[151,98],"277":"b:AIAAAAAAAAAAIAAAdgAABAEAgAAA","281":[151],"285":[151],"289":[151],"293":[151],"297":[151],"301":[151],"304":[151],"326":"b:cP9/4A84/v/n/wOg//////8PgAAA","331":"b:cP9/4A84/v/n/wPg//////8PgAAA","340":"b:cP9/4A84/v/n/wPg//////8PgAAA","341":"b:cN5b4A0w/u7h+wMg/+3///sHgAAA","347":[15,151,74,138,139],"353":[151,32,64,74,97,138,139],"359":"b:cP9/4A84/v/n/wPg//////8PgAAA","364":"b:cL49oA0w/m5h1gMg91/vffsPgAAA","368":"b:cP9/4A84/v/n/wPg//////8PgAAA","378":"b:cP974A8w/v/h/wPg3/////sPgAAA","395":"b:MP974A8w1r/h/wPg3////+sNgAAA"},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/nodes/CanvasNodeRenderer.vue":{"10":"b:cP9/4A84/v/n/wPg//////8PgAAA","12":"b:cP9/4A84/v/n/wPg//////8PgAAA","33":"b:cP9/4A84/v/n/wPg//////8PgAAA"},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/nodes/CanvasNodeToolbar.vue":{"17":"b:cP974A8w/v/h/wOg//////sPgAAA","54":"b:AIEDAAAQAgAAGAAAAECAAQAAgAAA","57":"b:AIEDAAAQAgAAGAAAAECAAQAAgAAA","59":"b:cP8b4A8w/v/h/wMg3/////sPgAAA","66":"b:cP974A8w/v/h/wOg//////sPgAAA","73":"b:cP974A8w/v/h/wOg//////sPgAAA","82":"b:cP974A8w/v/h/wOg//////sPgAAA","86":"b:cP974A8w/v/h/wOg//////sPgAAA","88":"b:cP974A8w/v/h/wOg//////sPgAAA","92":"b:cP974A8w/v/h/wOg//////sPgAAA","97":"b:cP974A8w/v/h/wOg//////sPgAAA","101":[8,17,151,75,96,107,111,112,114],"105":[151,93,96,110],"109":[151,73,96,110],"113":[151],"119":[151,98],"123":"b:AAECAAAAAAAACgAgBcgFAAEAgAAA","127":"b:AAACAAAAAAAACAAgBMgFAAEAgAAA","131":[151],"137":[151],"140":"b:cP974A8w/v/h/wOg//////sPgAAA","150":"b:AAECAAAAAAAACgAgBcgFAAAAgAAA","151":[151],"159":"b:cP8b4A8w/v/h/wOg3/////sPgAAA","202":[151]},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/nodes/render-types/CanvasNodeAddNodes.vue":{"18":"b:cJ4ZoA84/m5n1gMg503vfb4PgAAA","26":"b:cJ4ZoA84/m5n1gMg503vfb4PgAAA","30":"b:cJ4ZoA84/m5n1gMg503vfb4PgAAA","35":"b:cJ4ZoA0w/m5h1gMg503vfaoPgAAA","40":[151],"44":[151],"48":"b:AAoAIAAAyAAgAAAARAkEAAACgAAA","55":[151],"63":"b:cJ4ZoA84/m5n1gMg503vfb4PgAAA","71":[151],"83":[151]},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/nodes/render-types/CanvasNodeDefault.vue":{"22":"b:cP974A8w/v/h/wPg3/////sPgAAA","52":"b:cP974A8w/v/h/wPg3/////sPgAAA","53":"b:cP974A8w/v/h/wPg3/////sPgAAA","54":"b:cP974A8w/v/h/wPg3/////sPgAAA","57":"b:cP974A8w/v/h/wPg3/////sPgAAA","66":"b:cP974A8w/v/h/wPg3/////sPgAAA","67":[151],"69":"b:cP974A8w/v/h/wPg3/////sPgAAA","90":"b:cP974A8w/v/h/wPg3/////sPgAAA","96":"b:cP974A8w/v/h/wPg3/////sPgAAA","109":"b:cP974A8w/v/h/wPg3/////sPgAAA","117":"b:cP974A8w/v/h/wPg3/////sPgAAA","130":"b:cP974A8w/v/h/wPg3/////sPgAAA","139":"b:cP974A8w/v/h/wPg3/////sPgAAA","151":"b:IMFiQAIAAJugLQDAHv7yw9kOgAAA","157":"b:MP974A8w1v/h/wPg3/////sPgAAA","159":"b:MP974A8w1v/h/wPg3/////sPgAAA","164":"b:AIAAAAAAAAAAIAAAVgAABAEAgAAA","168":"b:ABZbQAQAAIrgKQMAgO33hwEAgAAA","175":"b:cP974A8w/v/h/wPg3/////sPgAAA"},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/nodes/render-types/parts/CanvasNodeSettingsIcons.vue":{"16":"b:cP974A8w/v/h/wPg3/////sPgAAA","17":"b:cP974A8w/v/h/wPg3/////sPgAAA","19":[151],"23":[151],"30":[151],"43":[151],"46":"b:cP974A8w/v/h/wPg3/////sPgAAA","51":[151],"60":[151,117],"68":[151],"77":[151],"85":[151],"94":[151],"104":[151],"113":[151],"121":[151],"131":[151]},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/nodes/render-types/parts/CanvasNodeStatusIcons.vue":{"23":"b:cP974A8w/v/h/wPg3/////sPgAAA","39":"b:cP974A8w/v/h/wPg3/////sPgAAA","42":"b:cP974A8w/v/h/wPg3/////sPgAAA","43":"b:cP974A8w/v/h/wPg3/////sPgAAA","46":"b:ML4Z4AEw1gZhnQAgBU2iL+INgAAA","47":[151],"48":"b:cP974A8w/v/h/wPg3/////sPgAAA","52":"b:MP9b4A8w1v/h/QKgz/3/v+MNgAAA","58":[151],"59":[151],"67":[151],"71":"b:cP974A8w/v/h/wPg3/////sPgAAA","80":[151],"81":[151],"93":[151],"95":"b:AIYBAAAgAAAAAAAAAEwgAMAAgAAA","105":[151],"107":"b:ML4Z4AEw1gZhnQAgBU2iL+INgAAA","123":[151],"126":"b:AAAAAAAAAACBQAAAgIAAFQEAgAAA"},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/nodes/render-types/parts/CanvasNodeTrigger.vue":{"33":"b:cP974A8w/v/h/wPg3/////sPgAAA","34":"b:cP974A8w/v/h/wPg3/////sPgAAA","45":"b:cP8b4A8w/v/h/wNg3/////sPgAAA","53":[151],"54":[151],"58":"b:AMADAAAQAgAAMAAAAECAAAAAgAAA","63":[151],"64":"b:AMADAAAQAgAAMAAAAECAAAAAgAAA","67":"b:cP8b4A8w/v/h/wNg3/////sPgAAA","68":"b:cP8b4A8w/v/h/wNg3/////sPgAAA","70":[151],"78":[151],"86":[151,63,107],"89":"b:cP974A8w/v/h/wPg3/////sPgAAA","94":[151,63,107],"116":"b:AMADAAAQAgAAMAAAAECAAAAAgAAA"},"packages/frontend/editor-ui/src/features/workflows/canvas/composables/useCanvas.ts":{"4":"b:cP9/4A84/v/n/wPg//////8PgAAA"},"packages/frontend/editor-ui/src/features/workflows/canvas/composables/useCanvasLayout.ts":{"54":"b:cP9/4A84/v/n/wPg//////8PgAAA","67":[13,151,94],"71":[13,151,94],"76":[13,151,94],"81":[13,151,94],"82":[13,151,94],"83":[13,151,94],"90":[13,151,94],"94":[13,151,94],"98":[13,151,94],"124":[13,151,94],"126":[13,151,94],"129":[13,151,94],"133":[13,151,94],"135":[13,151,94],"142":[13,151,94],"144":[13,151,94],"146":[13,151,94],"151":[13,151,94],"165":[151],"170":[13,151,94],"171":[13,151,94],"177":[13,151,94],"178":[13,151,94],"183":[13,151,94],"192":[13,151],"194":[13,151,94],"198":[13,151,94],"206":[151],"220":[151],"225":[151],"226":[151],"232":[151],"233":[151],"239":[13,151,94],"240":[13,151,94],"261":[13,151,94],"271":[13,151,94],"280":[13,151,94],"282":[13,151,94],"286":[13,151,94],"291":[151],"305":[151],"311":[151],"329":[13,151,94],"337":[151],"341":[151],"351":[151],"352":[151],"353":[151],"359":[13,151,94],"363":[13,151,94],"364":[13,151,94],"369":[13,151,94],"376":[13,151,94],"380":[13,151,94],"385":[151],"396":[151],"399":[151],"407":[151],"418":[13,151,94],"427":[13,151,94],"430":[151],"436":[13,151,94],"449":[151],"460":[151],"479":[13,151,94],"491":[13,151,94],"492":[151],"495":[151],"501":[151],"502":[151],"513":[13,151,94],"517":[13,151,94],"525":[13,151,94],"526":[151],"530":[151],"532":[151],"540":[151],"541":[151],"559":[13,151,94],"561":[13,151,94]},"packages/frontend/editor-ui/src/features/workflows/canvas/composables/useCanvasMapping.groups.ts":{"28":[151,100],"36":[151,100],"53":[151,100],"57":[151,100],"75":[151,100],"81":[151,100],"122":"b:cP9/4A84/v/n/wOg//////8PgAAA","132":[151,100]},"packages/frontend/editor-ui/src/features/workflows/canvas/composables/useCanvasMapping.ts":{"37":"b:cP9/4A84/v/n/wPg//////8PgAAA","50":"b:cP9/4A84/v/n/wPg//////8PgAAA","52":"b:ANcbAA4gAP/BaAKAh/x/l8EAgAAA","58":"b:cP9/4A84/v/n/wOg//////8PgAAA","77":"b:cP9/4A84/v/n/wPg//////8PgAAA","84":"b:cP9/4A84/v/n/wPg//////8PgAAA","133":"b:cP9/4A84/v/n/wPg//////8PgAAA","134":"b:MP974A8w1r/h/wPg3////+sNgAAA","145":"b:MP974A8w1r/h/wPg3////+sNgAAA","183":"b:MP974A8w1r/h/wPg3////+sNgAAA","184":"b:MP974A8w1r/h/wPg3////+sNgAAA","196":"b:MP974A8w1r/h/wPg3////+sNgAAA"},"packages/frontend/editor-ui/src/features/workflows/canvas/composables/useCanvasNode.ts":{"8":"b:cP974A8w/v/h/wPg//////sPgAAA","10":"b:cP974A8w/v/h/wPg//////sPgAAA","33":"b:cP974A8w/v/h/wPg//////sPgAAA","34":"b:cP974A8w/v/h/wPg3/////sPgAAA","36":"b:cP974A8w/v/h/wPg3/////sPgAAA","37":"b:cP974A8w/v/h/wPg3/////sPgAAA","38":"b:cP974A8w/v/h/wPg3/////sPgAAA","40":"b:cP974A8w/v/h/wPg3/////sPgAAA","41":[151,70,79,101,107,127,136,139],"42":"b:cP974A8w/v/h/wPg//////sPgAAA","44":[151],"45":[151],"46":"b:cP974A8w/v/h/wPg3/////sPgAAA","48":"b:cP974A8w/v/h/wPg3/////sPgAAA","49":"b:cP974A8w/v/h/wPg3/////sPgAAA","50":"b:cP974A8w/v/h/wPg3/////sPgAAA","51":"b:cP974A8w/v/h/wPg3/////sPgAAA","53":"b:cP974A8w/v/h/wPg3/////sPgAAA","54":"b:ANcbAA4gAP/BaAKAh/x/l8EAgAAA","55":"b:cP974A8w/v/h/wPg3/////sPgAAA","57":"b:cP974A8w/v/h/wPg//////sPgAAA","59":[151,70,79,101,107,127,136,139],"63":"b:cP974A8w/v/h/wPg3/////sPgAAA"},"packages/frontend/editor-ui/src/features/workflows/canvas/composables/useCanvasNodeGroupActions.ts":{"10":"b:cP9/4A84/v/n/wPg//////8PgAAA","18":[151,100],"20":[151,100],"21":[151,100],"24":[151,100],"29":[151],"39":[151],"41":[151,100],"49":[151]},"packages/frontend/editor-ui/src/features/workflows/canvas/composables/useCanvasNodeGroupDrag.ts":{"30":"b:cP9/4A84/v/n/wPg//////8PgAAA","38":[151],"44":[151],"60":[151],"70":[151],"89":[151],"94":[151,77,96,97,100,102,131],"99":[151,77,96,97,100,102,131],"110":[151,77,96,97,100,102,131],"145":[151,100],"153":[151,77,96,97,100,102,131],"160":[151,77,96,97,100,102,131],"178":[151,77,96,97,100,102,131],"190":[151,77,96,97,100,102,131],"199":[151,77,96,97,100,102,131],"222":[151],"232":[151],"236":[151]},"packages/frontend/editor-ui/src/features/workflows/canvas/composables/useCanvasNodeHandle.ts":{"11":"b:cP974A8w/v/h/wPg3/////sPgAAA","14":"b:cP974A8w/v/h/wPg3/////sPgAAA","15":"b:cP974A8w/v/h/wPg3/////sPgAAA","16":"b:cP8b4A8w/v/h/wNg3/////sPgAAA","17":"b:cP974A8w/v/h/wPg3/////sPgAAA","18":"b:cP974A8w/v/h/wPg3/////sPgAAA","19":[8,15,16,17,151,49,75,110,119],"20":[151],"21":[151],"22":[151],"23":"b:cP974A8w/v/h/wPg3/////sPgAAA"},"packages/frontend/editor-ui/src/features/workflows/canvas/composables/useCanvasNodeHover.ts":{"10":"b:cP9/4A84/v/n/wPg//////8PgAAA","17":"b:AP9fYAQA+orh6wMg/+/3l/kHgAAA","31":"b:ANdbYAQAOorh6wMg3+/3l/kFgAAA","64":[151],"73":"b:cP9/4A84/v/n/wPg//////8PgAAA","77":"b:AIAAAAAAAAAgAAAgBF4AQNAIgAAA"},"packages/frontend/editor-ui/src/features/workflows/canvas/composables/useCanvasTraversal.ts":{"4":"b:cP9/4A84/v/n/wPg//////8PgAAA","5":[151,96],"6":[151],"9":[151,96],"13":[151,96],"17":[151],"18":[151],"21":[151],"26":[151],"27":[151],"32":[151,128],"42":[151,128],"43":[151,128],"46":[151,96],"56":[151,96],"57":[151,96]},"packages/frontend/editor-ui/src/features/workflows/canvas/composables/useViewportAutoAdjust.ts":{"7":"b:cP9/4A84/v/n/wPg//////8PgAAA","21":"b:cP9/4A84/v/n/wPg//////8PgAAA","27":"b:cP9/4A84/v/n/wPg//////8PgAAA","46":"b:AIAAAAAAAAAgAAAgBF4AQNAIgAAA","51":"b:cP9/4A84/v/n/wPg//////8PgAAA"},"packages/frontend/editor-ui/src/features/workflows/canvas/composables/useZoomAdjustedValues.ts":{"8":"b:cP974A8w/v/h/wPg3/////sPgAAA","17":"b:cP974A8w/v/h/wPg3/////sPgAAA","39":"b:cP974A8w/v/h/wPg3/////sPgAAA","40":"b:cP974A8w/v/h/wPg3/////sPgAAA","60":"b:cP974A8w/v/h/wPg3/////sPgAAA","61":"b:cP974A8w/v/h/wPg3/////sPgAAA","76":"b:cP974A8w/v/h/wPg3/////sPgAAA","77":"b:cP974A8w/v/h/wPg3/////sPgAAA"},"packages/frontend/editor-ui/src/features/workflows/templates/components/SetupWorkflowCredentialsButton.vue":{"28":[65,74],"32":"b:cP8f4A84/v/n/wMg//////8PAAAA","36":"b:cP8f4A84/v/n/wMg//////8PAAAA","46":"b:cL8Z4A8w/v9h3wMg/9////sPAAAA","49":"b:cP8f4A84/v/n/wMg//////8PAAAA","55":[65,74,138,139],"59":"b:cP8f4A84/v/n/wMg//////8PAAAA","76":[65,74,138,139],"84":"b:MIgBoAEQ1gRjkAAgBEGgLSAFAAAA","94":[65],"99":[65,74,138],"103":[65,74,138],"111":"b:AKAEAAAAAAAiAAAgBF4AQNAAAAAA","115":"b:cP8f4A84/v/n/wMg//////8PAAAA"},"packages/frontend/editor-ui/src/features/workflows/workflowHistory/components/WorkflowHistoryButton.vue":{"12":"b:cP8f4A84/v/n/wMg//////8PAAAA","24":"b:QK4RgA0wACJjQAIgh03nB+MEAAAA","31":"b:cP8f4A84/v/n/wMg//////8PAAAA","32":"b:QL4dwA0wAGbnYAIgl83vV+8OAAAA","42":"b:cMUDQAYgAJviKQAgnv/3w9sOAAAA","49":"b:cP8fwA8wAP/naQIgn///1/8OAAAA","52":"b:cP8f4A84/v/n/wMg//////8PAAAA","55":"b:cP8f4A84/v/n/wMg//////8PAAAA","62":"b:cP8f4A84/v/n/wMg/////n8PAAAA"},"packages/localhost-44601/assets/_plugin-vue_export-helper-Da88TEg1.js":{"2":[49]},"packages/localhost-44601/assets/chunk-CC9Q-vWm.js":{"8":[49],"9":[49],"10":[49],"19":[49],"23":[49],"29":[49],"33":[49],"34":[49]},"packages/cli/src/abstract-server.ts":{"76":"b:KoECACQCAQIyAAACAlIAAIAAAIAA","109":"b:KoECACQCAQIyAAACAlIAAIAAAIAA","113":"b:KoECACQCAQIyAAACAlIAAIAAAIAA","117":"b:KoECACQCAQIyAAACAlIAAIAAAIAA","121":"b:KoECACQCAQIyAAACAlIAAIAAAIAA","129":"b:KoECACQCAQIyAAACAlIAAIAAAIAA","133":"b:KoECACQCAQIyAAACAlIAAIAAAIAA","136":"b:KoECACQCAQIyAAACAlIAAIAAAIAA","140":"b:KoECACQCAQIyAAACAlIAAIAAAIAA","147":"b:KoECACQCAQIyAAACAlIAAIAAAIAA","153":"b:KoECACQCAQIyAAACAlIAAIAAAIAA","162":"b:KoECACQCAQIyAAACAlIAAIAAAIAA","170":"b:KoECACQCAQIyAAACAlIAAIAAAIAA","175":"b:KoECACQCAQIyAAACAlIAAIAAAIAA","184":"b:KoECACQCAQIyAAACAlIAAIAAAIAA","190":"b:KoECACQCAQIyAAACAlIAAIAAAIAA","220":"b:KoECACQCAQIyAAACAlIAAIAAAIAA","229":"b:KoECACQCAQIyAAACAlIAAIAAAIAA","286":"b:KoECACQCAQIyAAACAlIAAIAAAIAA","290":"b:KoECACQCAQIyAAACAlIAAIAAAIAA","312":"b:KoECACQCAQIyAAACAlIAAIAAAIAA","339":"b:KoECACQCAQIyAAACAlIAAIAAAIAA","348":"b:KoECACQCAQIyAAACAlIAAIAAAIAA"},"packages/cli/src/modules/external-secrets.ee/external-secrets-providers.ee.ts":{"13":[23,42,3,69,147,86,5,131,137],"23":[23,42,3,69,147,86,5,131,137],"27":[23,42,3,69,147,86,5,131,137],"31":[23,42,3,69,147,86,5,131,137],"35":[23,42,3,69,147,86,5,131,137]},"packages/cli/src/modules/external-secrets.ee/providers/aws-secrets-manager.ts":{"102":[23,42,3,69,147,5,131,137],"107":[23,42,3,69,147,5,131,137],"118":[23,42,3,69,147,5,131,137],"124":[23,42,3,69,147,5,131,137],"134":[23,42,3,69,147,5,131,137],"144":[23,42,3,69,147,5,131,137],"148":[23,42,3,69,147,5,131,137],"154":[23,42,3,69,147,5,131,137],"160":[23,42,3,69,147,5,131,137],"164":[23,42,3,69,147,5,131,137],"168":[23,42,3,69,147,5,131,137],"172":[23,42,3,69,147,5,131,137],"178":[23,42,3,69,147,5,131,137],"188":[23,42,3,69,147,5,131,137],"197":[23,42,3,69,147,5,131,137],"224":[23,42,3,69,147,5,131,137],"225":[23,42,3,69,147,5,131,137]},"packages/cli/src/modules/external-secrets.ee/providers/azure-key-vault/azure-key-vault.ts":{"66":[23,42,3,69,86,5,131,137],"71":[23,42,3,69,86,5,131,137],"77":[23,42,3,69,86,5,131,137],"80":[23,42,3,69,86,5,131,137],"81":[23,42,3,69,86,5,131,137],"89":[23,42,3,69,86,5,131,137],"100":[23,42,3,69,86,5,131,137],"104":[23,42,3,69,86,5,131,137],"112":[23,42,3,69,86,5,131,137],"143":[23,42,3,69,86,5,131,137],"147":[23,42,3,69,86,5,131,137],"151":[23,42,3,69,86,5,131,137]},"packages/cli/src/modules/external-secrets.ee/providers/gcp-secrets-manager/gcp-secrets-manager.ts":{"40":[23,42,3,69,86,5,131,137],"45":[23,42,3,69,86,5,131,137],"49":[23,42,3,69,86,5,131,137],"52":[23,42,3,69,86,5,131,137],"62":[23,42,3,69,86,5,131,137],"73":[23,42,3,69,86,5,131,137],"77":[23,42,3,69,86,5,131,137],"84":[23,42,3,69,86,5,131,137],"94":[23,42,3,69,86,5,131,137],"139":[23,42,3,69,86,5,131,137],"147":[23,42,3,69,86,5,131,137],"151":[23,42,3,69,86,5,131,137],"155":[23,42,3,69,86,5,131,137],"159":[23,42,3,69,86,5,131,137]},"packages/cli/src/modules/external-secrets.ee/providers/infisical.ts":{"154":[23,42,3,69,86,5,131,137],"159":[23,42,3,69,86,5,131,137],"165":[23,42,3,69,86,5,131,137],"175":[23,42,3,69,86,5,131,137],"193":[23,42,3,69,86,5,131,137],"204":[23,42,3,69,86,5,131,137],"208":[23,42,3,69,86,5,131,137],"237":[23,42,3,69,86,5,131,137],"257":[23,42,3,69,86,5,131,137],"268":[23,42,3,69,86,5,131,137],"270":[23,42,3,69,86,5,131,137],"273":[23,42,3,69,86,5,131,137],"274":[23,42,3,69,86,5,131,137],"283":[23,42,3,69,86,5,131,137],"286":[23,42,3,69,86,5,131,137],"293":[23,42,3,69,86,5,131,137],"299":[23,42,3,69,86,5,131,137],"313":[23,42,3,69,86,5,131,137],"325":[23,42,3,69,86,5,131,137],"337":[23,42,3,69,86,5,131,137],"341":[23,42,3,69,86,5,131,137],"345":[23,42,3,69,86,5,131,137]},"packages/cli/src/modules/external-secrets.ee/providers/one-password.ts":{"50":[23,42,3,69,86,5,131,137],"55":[23,42,3,69,86,5,131,137],"73":[23,42,3,69,86,5,131,137],"74":[23,42,3,69,86,5,131,137],"91":[23,42,3,69,86,5,131,137],"102":[23,42,3,69,86,5,131,137],"106":[23,42,3,69,86,5,131,137],"141":[23,42,3,69,86,5,131,137],"145":[23,42,3,69,86,5,131,137],"149":[23,42,3,69,86,5,131,137]},"packages/cli/src/modules/external-secrets.ee/providers/vault.ts":{"264":[23,42,3,69,86,5,131,137],"269":[23,42,3,69,86,5,131,137],"276":[23,42,3,69,86,5,131,137],"281":[23,42,3,69,86,5,131,137],"291":[23,42,3,69,86,5,131,137],"317":[23,42,3,69,86,5,131,137],"321":[23,42,3,69,86,5,131,137],"328":[23,42,3,69,86,5,131,137],"345":[23,42,3,69,86,5,131,137],"354":[23,42,3,69,86,5,131,137],"374":[23,42,3,69,86,5,131,137],"392":[23,42,3,69,86,5,131,137],"407":[23,42,3,69,86,5,131,137],"412":[23,42,3,69,86,5,131,137],"421":[23,42,3,69,86,5,131,137],"449":[23,42,3,69,86,5,131,137],"473":[23,42,3,69,86,5,131,137],"474":[23,42,3,69,86,5,131,137],"481":[23,42,3,69,86,5,131,137],"485":[23,42,3,69,86,5,131,137],"493":[23,42,3,69,86,5,131,137],"496":[23,42,3,69,86,5,131,137],"504":[23,42,3,69,86,5,131,137],"507":[23,42,3,69,86,5,131,137],"520":[23,42,3,69,86,5,131,137],"526":[23,42,3,69,86,5,131,137],"530":[23,42,3,69,86,5,131,137],"542":[23,42,3,69,86,5,131,137],"548":[23,42,3,69,86,5,131,137],"556":[23,42,3,69,86,5,131,137],"562":[23,42,3,69,86,5,131,137],"588":[23,42,3,69,86,5,131,137],"592":[23,42,3,69,86,5,131,137],"596":[23,42,3,69,86,5,131,137],"597":[23,42,3,69,86,5,131,137],"603":[23,42,3,69,86,5,131,137]},"packages/cli/src/modules/external-secrets.ee/secrets-providers-connections.controller.ee.ts":{"32":[23,42,3,69,86,5,131,137],"41":[23,42,3,69,86,5,131,137],"81":[23,42,3,69,86,5,131,137],"104":[23,42,3,69,86,5,131,137],"122":[23,42,3,69,86,5,131,137],"135":[23,42,3,69,86,5,131,137],"138":[23,42,3,69,86,5,131,137],"145":[23,42,3,69,86,5,131,137],"157":[23,42,3,69,86,5,131,137],"172":[23,42,3,69,86,5,131,137]},"packages/cli/src/modules/external-secrets.ee/secrets-providers-project.controller.ee.ts":{"32":[23,42,3,69,86,5,131,137],"42":[23,42,3,69,86,5,131,137],"56":[23,42,3,69,86,5,131,137],"89":[23,42,3,69,86,5,131,137],"96":[23,42,3,69,86,5,131,137],"101":[23,42,3,69,86,5,131,137],"125":[23,42,3,69,86,5,131,137],"160":[23,42,3,69,86,5,131,137],"181":[23,42,3,69,86,5,131,137]},"packages/cli/src/modules/external-secrets.ee/secrets-providers-types.controller.ee.ts":{"16":[23,42,3,69,86,5,131,137],"25":[23,42,3,69,86,5,131,137],"41":[23,42,3,69,86,5,131,137],"44":[23,42,3,69,86,5,131,137],"51":[23,42,3,69,86,5,131,137]},"packages/cli/src/modules/external-secrets.ee/types.ts":{"29":[23,42,3,69,147,5,131,137],"52":[23,42,3,69,147,5,131,137],"75":[23,42,3,69,147,5,131,137],"92":[23,42,3,69,147,5,131,137],"93":[23,42,3,69,147,5,131,137],"99":[23,42,3,69,147,5,131,137]},"packages/cli/src/modules/instance-registry/checks/check.service.ts":{"46":"b:iABAAACQAQABAAAkcwAAADAAAAAA","57":"b:iABAAACQAQABAAAkcwAAADAAAAAA","63":"b:iABAAACQAQABAAAkcwAAADAAAAAA","75":"b:iABAAACQAQABAAAkcwAAADAAAAAA","83":"b:iABAAACQAQABAAAkcwAAADAAAAAA","88":"b:iABAAACQAQABAAAkcwAAADAAAAAA","90":"b:iABAAACQAQABAAAkcwAAADAAAAAA","96":"b:iABAAACQAQABAAAkcwAAADAAAAAA","111":"b:iABAAACQAQABAAAkcwAAADAAAAAA","115":"b:iABAAACQAQABAAAkcwAAADAAAAAA","133":"b:iABAAACQAQABAAAkcwAAADAAAAAA","148":"b:iABAAACQAQABAAAkcwAAADAAAAAA","157":"b:iABAAACQAQABAAAkcwAAADAAAAAA","193":"b:iABAAACQAQABAAAkcwAAADAAAAAA","214":"b:iABAAACQAQABAAAkcwAAADAAAAAA","228":"b:iABAAACQAQABAAAkcwAAADAAAAAA","239":"b:iABAAACQAQABAAAkcwAAADAAAAAA","245":"b:iABAAACQAQABAAAkcwAAADAAAAAA","254":"b:iABAAACQAQABAAAkcwAAADAAAAAA","277":"b:iABAAACQAQABAAAkcwAAADAAAAAA","301":"b:iABAAACQAQABAAAkcwAAADAAAAAA"},"packages/cli/src/modules/instance-registry/instance-registry.service.ts":{"29":"b:iptipLewEYgxBHAkc1AAALgEEBAA","37":"b:iptipLewEYgxBHAkc1AAALgEEBAA","52":"b:iptipLewEYgxBHAkc1AAALgEEBAA","72":"b:iptipLewEYgxBHAkc1AAALgEEBAA","76":"b:iptipLewEYgxBHAkc1AAALgEEBAA","80":"b:iptipLewEYgxBHAkc1AAALgEEBAA","84":"b:iptipLewEYgxBHAkc1AAALgEEBAA","88":"b:iptipLewEYgxBHAkc1AAALgEEBAA","92":"b:iptipLewEYgxBHAkc1AAALgEEBAA","96":"b:iptipLewEYgxBHAkc1AAALgEEBAA","109":"b:iptipLewEYgxBHAkc1AAALgEEBAA","113":"b:iptipLewEYgxBHAkc1AAALgEEBAA","114":"b:iptipLewEYgxBHAkc1AAALgEEBAA","118":"b:iptipLewEYgxBHAkc1AAALgEEBAA","122":"b:iptipLewEYgxBHAkc1AAALgEEBAA","123":"b:iptipLewEYgxBHAkc1AAALgEEBAA","133":"b:iptipLewEYgxBHAkc1AAALgEEBAA"},"packages/cli/src/modules/instance-registry/stale-member-cleanup.service.ts":{"17":"b:iABAAACQAQABAAAkcwAAADAAAAAA","25":"b:iABAAACQAQABAAAkcwAAADAAAAAA","30":"b:iABAAACQAQABAAAkcwAAADAAAAAA","34":"b:iABAAACQAQABAAAkcwAAADAAAAAA","42":"b:iABAAACQAQABAAAkcwAAADAAAAAA","47":"b:iABAAACQAQABAAAkcwAAADAAAAAA","59":"b:iABAAACQAQABAAAkcwAAADAAAAAA"},"packages/cli/src/modules/instance-registry/storage/memory-storage.ts":{"9":"b:iptipLewEYgxBHAkc1AAALgEEBAA","16":"b:iptipLewEYgxBHAkc1AAALgEEBAA","20":"b:iptipLewEYgxBHAkc1AAALgEEBAA","24":"b:iptipLewEYgxBHAkc1AAALgEEBAA","30":"b:iptipLewEYgxBHAkc1AAALgEEBAA","34":"b:iptipLewEYgxBHAkc1AAALgEEBAA","41":"b:iptipLewEYgxBHAkc1AAALgEEBAA","45":"b:iptipLewEYgxBHAkc1AAALgEEBAA","49":"b:iptipLewEYgxBHAkc1AAALgEEBAA","53":"b:iptipLewEYgxBHAkc1AAALgEEBAA"},"packages/cli/src/modules/provisioning.ee/provisioning.controller.ee.ts":{"13":[27,42,48,3,69,86,7,5],"21":[27,42,48,3,69,86,7,5],"31":[27,42,48,3,69,86,7,5]},"packages/cli/src/modules/workflow-index/workflow-dependency-query.service.ts":{"37":"b:eACAFACwAQA2AAAQAAIAQBgCAAAA","48":"b:eACAFACwAQA2AAAQAAIAQBgCAAAA","73":"b:eACAFACwAQA2AAAQAAIAQBgCAAAA","128":"b:eACAFACwAQA2AAAQAAIAQBgCAAAA","152":"b:eACAFACwAQA2AAAQAAIAQBgCAAAA","205":"b:eACAFACwAQA2AAAQAAIAQBgCAAAA","220":"b:eACAFACwAQA2AAAQAAIAQBgCAAAA","259":"b:eACAFACwAQA2AAAQAAIAQBgCAAAA","273":"b:eACAFACwAQA2AAAQAAIAQBgCAAAA","281":"b:eACAFACwAQA2AAAQAAIAQBgCAAAA","289":"b:eACAFACwAQA2AAAQAAIAQBgCAAAA","302":"b:eACAFACwAQA2AAAQAAIAQBgCAAAA","306":"b:eACAFACwAQA2AAAQAAIAQBgCAAAA"},"packages/cli/src/modules/workflow-index/workflow-dependency.controller.ts":{"9":"b:aACAFACwAAA0AAAAAAIAABgAAAAA","12":"b:aACAFACwAAA0AAAAAAIAABgAAAAA","25":"b:aACAFACwAAA0AAAAAAIAABgAAAAA"},"packages/cli/src/requests.ts":{"54":"b:aAiAXXL0AAA2AFQEAAIAABgAQCAA","63":"b:aAiAXXL0AAA2AFQEAAIAABgAQCAA","66":"b:aAiAXXL0AAA2AFQEAAIAABgAQCAA"},"packages/core/src/execution-engine/ssh-clients-manager.ts":{"10":"b:KPMCYH4mgJXECABIAHCCGZDQECcA","16":"b:KPMCYH4mgJXECABIAHCCGZDQECcA","17":"b:KPMCYH4mgJXECABIAHCCGZDQECcA","61":"b:KPMCYH4mgJXECABIAHCCGZDQECcA","66":"b:KPMCYH4mgJXECABIAHCCGZDQECcA","69":"b:KPMCYH4mgJXECABIAHCCGZDQECcA","74":"b:KPMCYH4mgJXECABIAHCCGZDQECcA","94":"b:KPMCYH4mgJXECABIAHCCGZDQECcA","119":"b:KPMCYH4mgJXECABIAHCCGZDQECcA","121":"b:KPMCYH4mgJXECABIAHCCGZDQECcA","143":"b:KPMCYH4mgJXECABIAHCCGZDQECcA","144":"b:KPMCYH4mgJXECABIAHCCGZDQECcA","148":"b:KPMCYH4mgJXECABIAHCCGZDQECcA","152":"b:KPMCYH4mgJXECABIAHCCGZDQECcA","156":"b:KPMCYH4mgJXECABIAHCCGZDQECcA","166":"b:KPMCYH4mgJXECABIAHCCGZDQECcA","177":"b:KPMCYH4mgJXECABIAHCCGZDQECcA","185":"b:KPMCYH4mgJXECABIAHCCGZDQECcA"},"packages/@n8n/design-system/src/components/N8nUserInfo/UserInfo.vue":{"22":[23,42,48,3,69,86,7,5,131,137],"29":[23,42,48,3,69,86,7,5,131,137],"35":[23,42,48,3,69,86,7,5,131,137],"50":[23,42,48,3,69,86,7,5,131,137],"58":[23,42,48,3,69,86,7,5,131,137]},"packages/@n8n/design-system/src/components/N8nUserSelect/UserSelect.vue":{"22":[23,42,48,3,69,86,5,131,137],"40":[23,42,48,3,69,86,5,131,137],"43":[42,48,3,69,86,5],"63":[23,42,48,3,69,86,5,131,137],"64":[42,48,3,69,86,5],"80":[42,3],"88":[42],"89":[42,3],"91":[42,48,3,69,86,5],"93":[23,42,48,3,69,86,5,131,137],"112":[23,42,48,3,69,86,5,131,137],"114":[23,42,48,3,69,86,5,131,137],"117":[42,48,3,69,86,5],"124":[42,48,3,69,86,5]},"packages/frontend/editor-ui/src/app/api/workflow-dependencies.ts":{"9":"b:KACAAACwAQA+AAAAAAIAQBgKAAAA"},"packages/frontend/editor-ui/src/app/components/WorkflowCard.vue":{"55":"b:CACAAACAAQA+AAAAAAIAQBgKAAAA","133":"b:CACAAACAAQA+AAAAAAIAQBgKAAAA","136":"b:CACAAACAAQAwAAAAAAIAQBgKAAAA","137":[137],"138":"b:CACAAACAAQA+AAAAAAIAQBgKAAAA","140":"b:CACAAACAAQA+AAAAAAIAQBgKAAAA","143":[69,131],"146":[69,131],"150":"b:CACAAACAAQA+AAAAAAIAQBgKAAAA","154":"b:CACAAACAAQAwAAAAAAIAQBgKAAAA","165":"b:CACAAACAAQAwAAAAAAIAQBgKAAAA","185":"b:CACAAACAAQA+AAAAAAIAQBgKAAAA","285":"b:CACAAACAAQA+AAAAAAIAQBgKAAAA","306":"b:CACAAACAAQA+AAAAAAIAQBgKAAAA","310":"b:CACAAACAAQAwAAAAAAIAQBgKAAAA","316":"b:CACAAACAAQA+AAAAAAIAQBgKAAAA","320":"b:CACAAACAAQA+AAAAAAIAQBgKAAAA","324":"b:CACAAACAAQA+AAAAAAIAQBgKAAAA","326":[69,105,131,137],"352":[65,67,68,69,137],"416":[137],"426":[137],"461":[137],"465":[137],"503":[137],"552":[137],"592":[137],"594":[137],"596":"b:CACAAACAAQA+AAAAAAIAQBgKAAAA","607":"b:CACAAACAAQA+AAAAAAIAQBgKAAAA","619":[131],"656":"b:CACAAACAAQA+AAAAAAIAQBgKAAAA","674":"b:CACAAACAAQA+AAAAAAIAQBgKAAAA","691":"b:CACAAACAAQAwAAAAAAIAQBgKAAAA","717":[137]},"packages/frontend/editor-ui/src/app/composables/useAutoScrollOnDrag.ts":{"13":"b:uACAXQCAAQA+ABAEAAIAQBgKAAAA","20":"b:uACAXQCAAQA+ABAEAAIAQBgKAAAA","99":[65],"103":"b:uACAXQCAAQA+ABAEAAIAQBgKAAAA","108":"b:uACAXQCAAQA+ABAEAAIAQBgKAAAA","117":"b:OACAEACAAQA+AAAEAAIAQBgKAAAA","125":"b:OACAEACAAQA0AAAEAAIAQBgCAAAA"},"packages/frontend/editor-ui/src/app/composables/useDependencies.ts":{"14":"b:uAiA3QDwAQA+AFAUAAIAQBgKAAAA","18":"b:KAiAgADwAQA+AEAQAAIAQBgKAAAA","59":[45,69,5,126,137,139],"67":"b:KACAgADwAQA+AEAQAAIAQBgKAAAA","70":[45,69,5,126,137,139],"73":"b:KACAgADwAQA+AEAQAAIAQBgKAAAA"},"packages/frontend/editor-ui/src/app/composables/useLatestFetch.ts":{"1":"b:uACAXQCAAQA+ABAEAAIAQBgKAAAA","4":"b:uACAXQCAAQA+ABAEAAIAQBgKAAAA","6":"b:OACACQCAAQA+ABAEAAIAQBgKAAAA"},"packages/frontend/editor-ui/src/app/utils/formatters/textFormatter.ts":{"8":[3]},"packages/frontend/editor-ui/src/app/views/WorkflowsView.vue":{"226":[65,66,67],"271":[65,66,67],"273":[65,66,67],"278":[65,66,67],"280":[65,66,67],"285":"b:uACAXQCAAQA+ABAEAAIAQBgKAAAA","289":"b:uACAXQCAAQA+ABAEAAIAQBgKAAAA","293":"b:OACAAACAAQA+AAAAAAIAQBgKAAAA","295":"b:CACAAACAAQA+AAAAAAIAQBgKAAAA","299":"b:CACAAACAAQA+AAAAAAIAQBgKAAAA","303":"b:CACAAACAAQA+AAAAAAIAQBgKAAAA","310":"b:uACAXQCAAQA+ABAEAAIAQBgKAAAA","314":"b:uACAXQCAAQA+ABAEAAIAQBgKAAAA","318":"b:MACAAACAAQA+AAAAAAAAAAgCAAAA","324":"b:uACAXQCAAQA+ABAEAAIAQBgKAAAA","328":"b:uACAXQCAAQA+ABAEAAIAQBgKAAAA","332":"b:CACAAACAAQA+AAAAAAIAQBgKAAAA","336":"b:uACAXQCAAQA+ABAEAAIAQBgKAAAA","341":"b:uACAXQCAAQA+ABAEAAIAQBgKAAAA","348":"b:MACAAACAAQA+AAAAAAAAAAgCAAAA","354":"b:CACAAACAAQA+AAAAAAIAQBgKAAAA","360":[65,66,67],"366":[65,66,67],"371":"b:MACAAACAAQA+AAAAAAAAAAgCAAAA","377":"b:OACAAACAAQA+AAAAAAIAQBgKAAAA","379":"b:MACAAACAAQA+AAAAAAAAAAgCAAAA","383":"b:MACAAACAAQA+AAAAAAAAAAgCAAAA","396":"b:MACAAACAAQA+AAAAAAAAAAgCAAAA","421":"b:MACAAACAAQA+AAAAAAAAAAgCAAAA","444":"b:MACAAACAAQA+AAAAAAAAAAgCAAAA","456":"b:MACAAACAAQA+AAAAAAAAAAgCAAAA","484":"b:MACAAACAAQA+AAAAAAAAAAgCAAAA","493":[65,66,67],"497":"b:uACAXQCAAQA+ABAEAAIAQBgKAAAA","498":"b:CACAAACAAQA+AAAAAAIAQBgKAAAA","536":[137],"551":"b:uACAXQCAAQA+ABAEAAIAQBgKAAAA","565":"b:uACAXQCAAQA+ABAEAAIAQBgKAAAA","576":"b:uACAXQCAAQA+ABAEAAIAQBgKAAAA","585":"b:uACAXQCAAQA+ABAEAAIAQBgKAAAA","591":"b:uACAXQCAAQA+ABAEAAIAQBgKAAAA","595":"b:uACAXQCAAQA+ABAEAAIAQBgKAAAA","608":"b:uACAXQCAAQA+ABAEAAIAQBgKAAAA","612":"b:uACAXQCAAQA+ABAEAAIAQBgKAAAA","617":"b:uACAXQCAAQA+ABAEAAIAQBgKAAAA","625":"b:MACACQCAAQA8ABAEAAAAAAgCAAAA","638":"b:uACAXQCAAQA+ABAEAAIAQBgKAAAA","642":"b:uACAXQCAAQA+ABAEAAIAQBgKAAAA","644":[65,66,67],"663":[68,69,137],"673":[67],"706":"b:uACAXQCAAQA+ABAEAAIAQBgKAAAA","716":"b:MACACQCAAQA8ABAEAAAAAAgCAAAA","720":"b:MACACQCAAQA8ABAEAAAAAAgCAAAA","728":"b:uACAXQCAAQA+ABAEAAIAQBgKAAAA","742":"b:OACAEACAAQA0AAAEAAIAQBgCAAAA","757":"b:uACAXQCAAQA+ABAEAAIAQBgKAAAA","780":"b:uACAXQCAAQA+ABAEAAIAQBgKAAAA","794":[137],"828":"b:CACAAACAAQA+AAAAAAIAQBgKAAAA","829":[65,66,67],"847":"b:CACAAACAAQA+AAAAAAIAQBgKAAAA","848":"b:CACAAACAAQA+AAAAAAIAQBgKAAAA","881":"b:uACAXQCAAQA+ABAEAAIAQBgKAAAA","902":[47,65,66,67,68,69,131,137],"910":[66,137],"921":"b:uACAXQCAAQA+ABAEAAIAQBgKAAAA","951":[47,65,66,67,68,69,131,137],"991":"b:uACAXQCAAQA+ABAEAAIAQBgKAAAA","996":"b:uACAXQCAAQA+ABAEAAIAQBgKAAAA","1025":[137],"1067":[69],"1080":[69],"1203":[137],"1204":[137],"1213":[65,67],"1214":[65,67],"1220":[67],"1244":[65,66,67],"1267":[65],"1289":[65],"1297":[65],"1316":[65],"1348":[66,67],"1579":[66,67],"1640":[66,67],"1678":[66],"1724":[67],"1759":[66,67],"1778":[67],"1794":[65,67],"1921":[67,68,69],"1948":[68,69],"1995":[65,67],"2008":[65],"2066":[67],"2141":"b:uACAXQCAAQA+ABAEAAIAQBgKAAAA","2178":"b:uACAXQCAAQA+ABAEAAIAQBgKAAAA","2245":"b:uACAXQCAAQA+ABAEAAIAQBgKAAAA","2281":"b:CACAAACAAQA+AAAAAAIAQBgKAAAA","2291":[65,66,67],"2294":[65,66,67],"2295":[65,66,67],"2335":"b:CACAAACAAQA+AAAAAAIAQBgKAAAA","2338":"b:CACAAACAAQA+AAAAAAIAQBgKAAAA","2339":"b:CACAAACAAQA+AAAAAAIAQBgKAAAA","2377":"b:MACACQCAAQA8ABAEAAAAAAgCAAAA","2390":"b:MACACQCAAQA8ABAEAAAAAAgCAAAA","2393":"b:MACACQCAAQA8ABAEAAAAAAgCAAAA","2402":"b:MACACQCAAQA8ABAEAAAAAAgCAAAA","2411":"b:MACACQCAAQA8ABAEAAAAAAgCAAAA","2420":[137],"2433":[137],"2448":[137],"2464":[137],"2468":"b:uACAXQCAAQA+ABAEAAIAQBgKAAAA","2476":"b:CACAAACAAQA+AAAAAAIAQAgKAAAA","2478":"b:CACAAACAAQA+AAAAAAIAQAgKAAAA"},"packages/frontend/editor-ui/src/experiments/credentialsAppSelection/stores/credentialsAppSelection.store.ts":{"14":"b:uACAXQCAAQA+ABAEAAIAQBgKAAAA","23":[24,27,69,84,90,131],"25":[24,27,69,84,90,131],"29":[24,27,69,84,90,131],"35":[24,27,69,84,90,131]},"packages/frontend/editor-ui/src/experiments/personalizedTemplates/stores/personalizedTemplates.store.ts":{"66":"b:uACAXQCAAQA+ABAEAAIAQBgKAAAA","91":"b:OACACQCAAQA+ABAEAAIAQBgKAAAA","164":"b:uACAXQCAAQA+ABAEAAIAQBgKAAAA"},"packages/frontend/editor-ui/src/experiments/personalizedTemplatesV3/stores/personalizedTemplatesV3.store.ts":{"12":"b:uACAXQCAAQA+ABAEAAIAQBgKAAAA","26":"b:OACAXQCAAQA8ABAEAAIAQBgKAAAA","35":"b:uACAXQCAAQA+ABAEAAIAQBgKAAAA","129":"b:uACAXQCAAQA+ABAEAAIAQBgKAAAA"},"packages/frontend/editor-ui/src/experiments/templateRecoV2/stores/templateRecoV2.store.ts":{"14":"b:uACAXQCAAQA+ABAEAAIAQBgKAAAA","21":"b:OACAXQCAAQA8ABAEAAIAQBgKAAAA"},"packages/frontend/editor-ui/src/features/ai/mcpAccess/mcp.store.ts":{"33":"b:uACAXQCAAQA+ABAEAAIAQBgKAAAA"},"packages/frontend/editor-ui/src/features/collaboration/projects/components/ProjectCustomRolesUpgradeModal.vue":{"8":[42,3],"15":[42,3]},"packages/frontend/editor-ui/src/features/collaboration/projects/components/ProjectDeleteDialog.vue":{"62":[23,42,48,3,69,86,5,131,137]},"packages/frontend/editor-ui/src/features/collaboration/projects/components/ProjectExternalSecrets.vue":{"27":[23,42,48,3,69,86,5,131,137],"53":[23,42,48,3,69,86,5,131,137],"58":[23,42,48,3,69,86,5,131,137],"62":[86],"66":[23,42,48,3,69,86,5,131,137],"70":[23,42,48,3,69,86,5,131,137],"77":[23,42,48,3,69,86,5,131,137],"90":[23,42,48,3,69,86,5,131,137],"117":[23,42,48,3,69,86,5,131,137],"121":[23,42,48,3,69,86,5,131,137],"132":[23,42,48,3,69,86,5,131,137],"149":[86],"150":[86],"162":[86],"172":[86],"180":[23,42,48,3,69,86,5,131,137],"183":[86],"184":[86],"188":[23,42,48,3,69,86,5,131,137],"264":[23,42,48,3,69,86,5,131,137],"265":[23,42,48,3,69,86,5,131,137],"275":[23,42,48,3,69,86,5,131,137],"291":[23,42,48,3,69,86,5,131,137],"303":[23,42,48,3,69,86,5,131,137],"305":[23,42,48,3,69,86,5,131,137],"308":[23,42,48,3,69,86,5,131,137],"311":[23,42,48,3,69,86,5,131,137],"320":[23,42,48,3,69,86,5,131,137],"328":[23,42,48,3,69,86,5,131,137],"345":[86],"356":[86],"372":[86],"393":[86],"397":[86]},"packages/frontend/editor-ui/src/features/collaboration/projects/components/ProjectMembersActionsCell.vue":{"6":[23,42,48,3,69,86,5,131,137],"17":[23,42,48,3,69,86,5,131,137]},"packages/frontend/editor-ui/src/features/collaboration/projects/components/ProjectMembersRoleCell.vue":{"33":[42,3],"56":[42],"60":[42],"72":[42,3],"73":[42,3],"75":[42,3],"78":[42,3],"79":[42,3],"82":[42,3],"88":[42,3],"95":[42,3],"104":[42,3],"138":[42],"140":[42],"172":[42,3],"174":[42,3],"192":[42,3],"197":[42,3],"205":[42,3],"219":[42,3],"223":[42,3],"229":[42,3],"233":[42,3],"238":[42,3],"248":[42,3],"259":[42,3],"270":[42,3],"278":[42,3]},"packages/frontend/editor-ui/src/features/collaboration/projects/components/ProjectMembersTable.vue":{"11":[23,42,48,3,69,86,5,131,137],"37":[23,42,48,3,69,86,5,131,137],"44":[23,42,48,3,69,86,5,131,137],"58":[23,42,48,3,69,86,5,131,137],"64":[23,42,48,3,69,86,5,131,137],"67":[42],"71":[23,42,48,3,69,86,5,131,137],"73":[42,3],"74":[23,42,48,3,69,86,5,131,137],"88":[42,3],"90":[23,42,48,3,69,86,5,131,137],"95":[23,42,48,3,69,86,5,131,137],"104":[23,42,48,3,69,86,5,131,137],"107":[23,42,48,3,69,86,5,131,137]},"packages/frontend/editor-ui/src/features/collaboration/projects/components/ProjectRoleContactAdminModal.vue":{"8":[42,3],"31":[42,3]},"packages/frontend/editor-ui/src/features/collaboration/projects/components/ProjectRoleUpgradeDialog.vue":{"14":[23,42,48,3,69,86,5,131,137],"22":[23,42,48,3,69,86,5,131,137]},"packages/frontend/editor-ui/src/features/collaboration/projects/components/RoleHoverPopover.vue":{"14":[42,3],"51":[42,3]},"packages/frontend/editor-ui/src/features/collaboration/projects/views/ProjectSettings.vue":{"63":[23,42,48,3,69,86,5,131,137],"78":[23,42,48,3,69,86,5,131,137],"118":[42,48,3,69,86,5],"120":[23,42,48,3,69,86,5,131,137],"121":[42,48,3,69,86,5],"122":[42,48,3,69,86,5],"128":[42,3],"129":[42,3],"132":[23,42,48,3,69,86,5,131,137],"140":[42,3],"146":[42,3],"166":[42,3],"189":[42],"194":[42],"225":[23,48,3,69,5,131,137],"274":[23,42,48,3,69,86,5,131,137],"286":[3],"291":[23,48,3,69,5,131,137],"314":[23,48,3,69,5,131,137],"315":[23,48,3,69,5,131,137],"322":[23,48,3,69,5,131,137],"353":[23,48,3,69,5,131,137],"372":[23,48,3,69,5,131,137],"419":[23,42,48,3,69,86,5,131,137],"426":[69],"442":[23,42,48,3,69,86,5,131,137],"444":[23,42,48,3,69,86,5,131,137],"461":[23,42,48,3,69,86,5,131,137],"462":[23,42,48,3,69,86,5,131,137],"478":[23,42,48,3,69,86,5,131,137],"483":[23,42,48,3,69,86,5,131,137],"497":[23,42,48,3,69,86,5,131,137],"515":[42,3],"519":[42,48,3,69,86,5],"559":[23,42,48,3,69,86,5,131,137],"564":[23,42,48,3,69,86,5,131,137],"568":[23,42,48,3,69,86,5,131,137],"572":[23,42,48,3,69,86,5,131,137],"588":[23,42,48,3,69,86,5,131,137],"598":[23,42,48,3,69,86,5,131,137],"605":[23,42,48,3,69,86,5,131,137],"632":[23,42,48,3,69,86,5,131,137],"652":[23,42,48,3,69,86,5,131,137],"681":[23,42,48,3,69,86,5,131,137],"755":[23,42,48,3,69,86,5,131,137]},"packages/frontend/editor-ui/src/features/core/folders/composables/useFolders.ts":{"12":[65],"16":[65],"20":"b:uACAXQCAAQA+ABAEAAIAQBgKAAAA","25":[65,66,67],"29":[66,67],"63":[65],"80":[65],"86":[65,66,67],"101":[48,65,66,67,68,69,131,137],"109":[65],"130":[65,66,67]},"packages/frontend/editor-ui/src/features/integrations/secretsProviders.ee/composables/useSecretsProvidersList.ee.ts":{"21":[86],"22":[86],"24":[23,42,48,3,69,86,5,131,137],"35":[23,42,48,3,69,86,5,131,137],"64":[86],"68":[86],"72":[23,42,48,3,69,86,5,131,137],"77":[86]},"packages/frontend/editor-ui/src/features/project-roles/projectRoleScopes.ts":{"67":[23,42,48,3,69,86,5,131,137],"69":[23,42,48,3,69,86,5,131,137]},"packages/frontend/editor-ui/src/features/settings/sso/provisioning/composables/userRoleProvisioning.store.ts":{"13":[23,42,48,3,69,86,7,5,131,137],"18":[42,48,3,69,86,7,5]},"packages/frontend/editor-ui/src/features/workflows/composables/useWorkflowsEmptyState.ts":{"17":"b:uACAXQCAAQA+ABAEAAIAQBgKAAAA","26":"b:MACACQCAAQA8ABAEAAAAAAgCAAAA","27":"b:iACAXQCAAQAwABAEAAIAQBgKAAAA","28":"b:uACAXQCAAQA+ABAEAAIAQBgKAAAA","30":"b:uACAXQCAAQA+ABAEAAIAQBgKAAAA","36":[24,27,69,84,90,131],"40":"b:uACAXQCAAQA+ABAEAAIAQBgKAAAA","48":[24,27,69,84,90,131],"56":[24,27,69,84,90,131],"74":"b:MACACQCAAQA8ABAEAAAAAAgCAAAA","94":"b:MACACQCAAQA8ABAEAAAAAAgCAAAA"},"packages/frontend/editor-ui/src/features/workflows/templates/recommendations/recommendedTemplates.store.ts":{"17":"b:uACAXQCAAQA+ABAEAAIAQBgKAAAA","25":"b:uACAXQCAAQA+ABAEAAIAQBgKAAAA"},"packages/localhost-43531/assets/_plugin-vue_export-helper-Da88TEg1.js":{"2":[33,3,78,92,95,98,126,139]},"packages/localhost-43531/assets/chunk-CC9Q-vWm.js":{"8":[33,3,78,92,95,98,126,139],"9":[33,3,78,92,95,98,126,139],"10":[33,3,78,92,95,98,126,139],"19":[33,3,78,92,95,98,126,139],"23":[33,3,78,92,95,98,126,139],"29":[33,3,78,92,95,98,126,139],"33":[33,3,78,92,95,98,126,139],"34":[33,3,78,92,95,98,126,139]},"packages/@n8n/db/src/repositories/workflow-tag-mapping.repository.ts":{"8":"b:AJoQQA0wACbgQAAAAkAAEYAGAAAA","12":"b:AJoQQA0wACbgQAAAAkAAEYAGAAAA","13":"b:AJoQQA0wACbgQAAAAkAAEYAGAAAA","16":"b:AJoQQA0wACbgQAAAAkAAEYAGAAAA"},"packages/cli/src/modules/redaction/redaction-enforcement.service.ts":{"20":"b:AJoQQA0wAAbgQAAAAkAAEYCEAgEA","24":"b:AJoQQA0wAAbgQAAAAkAAEYCEAgEA","50":"b:AJoQQA0wAAbgQAAAAkAAEYCEAgEA"},"packages/@n8n/design-system/src/components/N8nIcon/custom/node-dirty.svg":{"11":"b:AAAAAAAAAACBQAAAgIAAFQEAAAAA"},"packages/@n8n/design-system/src/components/N8nIcon/custom/node-success.svg":{"11":"b:ANcbAA4gAP/BaAKAh/x/l8EAAAAA"},"packages/@n8n/design-system/src/components/N8nIcon/custom/toolbox.svg":{"10":"b:MIoZoAgwuAYh0AAgxyVvfSIAAAAA"},"packages/@n8n/design-system/src/components/N8nIcon/nodes/edit-fields.svg":{"11":"b:AMZiAAMAAJgh6wLAW+r65wkBAAAA"},"packages/@n8n/design-system/src/components/N8nIcon/nodes/loop-over-items.svg":{"11":[52,70,78,79,102,110,113,136]},"packages/@n8n/design-system/src/components/N8nIcon/nodes/no-operation.svg":{"11":"b:MAAAgAAQEAhhyAAAQAgHByAJAAAA"},"packages/@n8n/design-system/src/components/N8nNotice/Notice.vue":{"16":"b:MJ5b4A0wFEYh1VEgx82/zSMGAAAA","30":"b:MJ5b4A0wFEYh1VEgx82/zSMGAAAA","34":"b:MJ5b4A0wFEYh0UEgx82/zSAGAAAA","50":[120],"66":"b:MJ5b4A0wFEYh1VEgx82/zSMGAAAA","75":"b:MJ5b4A0wFEYh1VEgx82/zCMGAAAA"},"packages/@n8n/design-system/src/components/N8nSuggestedActions/SuggestedActions.vue":{"39":"b:cP8fwA8QAP/naQIgn///1/8OAAAA","50":"b:cP8fwA8QAP/naQIgn///1/8OAAAA","52":[93],"58":[93],"60":[93],"64":"b:cP8fwA8QAP/naQIgn///1/8OAAAA","74":[93,132],"76":"b:cP8fwA8QAP/naQIgn///1/8OAAAA","84":[93,132],"86":[93,132],"89":[93,132],"100":[93],"108":[93,132],"112":[93,132],"121":[93,132],"131":[93],"132":[93,132],"142":[93],"143":[93,132]},"packages/@n8n/design-system/src/types/binary.ts":{"24":"b:ACZKAAQAAIzBSAIAiu1/twEAAAAA"},"packages/frontend/editor-ui/src/app/components/DropArea/DropArea.vue":{"4":"b:AIIAAAEAAIAhYQIAS+hqZQgAAAAA","8":"b:AIIAAAEAAIAhYQIAS+hqZQgAAAAA","13":"b:AIIAAAEAAIAhYQIAS+hqZAgAAAAA"},"packages/frontend/editor-ui/src/app/components/WorkflowProductionChecklist.vue":{"32":"b:cP8fwA8wAP/naQIgn///1/8OAAAA","49":[33,63,65,93,132,133,137],"50":[33,63,65,93,132,133,137],"51":[33,63,65,93,132,133,137],"57":[65,93],"61":[33,63,65,93,132,133,137],"66":[33,63,65,93,132,133,137],"67":[33,63,65,93,132,133,137],"72":[33,63,65,93,132,133,137],"73":[33,63,65,93,132,133,137],"76":[33,63,65,93,132,133,137],"81":[65,93,132],"85":[63,65,93,132,133,137],"87":"b:cP8fwA8QAP/naQIgn///1/8OAAAA","91":"b:cP8fwA8wAL/naQIgj/rPV98OAAAA","92":[45,65,69,131],"94":"b:cP8fwA8wAP/naQIgn///1/8OAAAA","98":"b:cP8fwA8wAP/naQIgn///1/8OAAAA","102":"b:cP8fwA8wAL/naQIgj/rPV98OAAAA","104":"b:cP8fwA8wAP/naQIgn///1/8OAAAA","169":"b:cP8fwA8wAP/naQIgn///1n8OAAAA","215":"b:cP8fwA8wAP/naQIgn///1/8OAAAA","224":[65,93],"249":[65,93],"259":[65,93],"275":[65,93],"286":[65,93],"294":[65,93,132],"298":[65,93],"302":[65,93,132],"312":"b:cP8fwA8wAP/naQIgn///1/8OAAAA","314":[63,65,93,132,133,137],"321":[65,93,132],"328":[65],"340":"b:cP8fwA8wAP/naQIgn///1/8OAAAA","343":"b:cP8fwA8wAP/naQIgn///1/8OAAAA"},"packages/frontend/editor-ui/src/app/composables/useLoadingService.ts":{"14":"b:AAAAQAAAAAAkBBAAFmAAQMkPAAAA","26":[74,84,138,139],"32":[74,84,110,134,135,136,138,139],"39":"b:QL4dwA0wAGblYAIgl83vV+8OAAAA"},"packages/frontend/editor-ui/src/app/composables/usePushConnection/handlers/executionFinished.ts":{"62":"b:ANcLAA4gAP/DaAKAh/x/l8EAAAAA","190":"b:ANcLAA4gAP/DaAIAh/x/l8EAAAAA","196":"b:ANAKAA4AALtCYAIABvxwh8EAAAAA","217":[65],"231":"b:ANcLAA4gAP/DaAKAh/x/l8EAAAAA","261":"b:ANcLAA4gAP/DaAIAh/x/l8EAAAAA","274":"b:ANcLAA4gAP/DaAIAh/x/l8EAAAAA","300":[65],"318":[65],"335":"b:AIYBAAAgAAACAAAAAEwgAMAAAAAA","418":"b:ANEKAA4AAP/DaAKAh/x/l8EAAAAA","439":"b:ANEKAA4AAP/DaAKAh/x/l8EAAAAA","510":"b:ANcLAA4gAP/DaAIAh/x/l8EAAAAA"},"packages/frontend/editor-ui/src/app/composables/usePushConnection/handlers/executionStarted.ts":{"13":"b:ANcbAA4gAP/DaAKAh/x/l8EAAAAA"},"packages/frontend/editor-ui/src/app/composables/usePushConnection/handlers/nodeExecuteAfter.ts":{"16":"b:ANcbAA4gAP/DaAKAh/x/l8EAAAAA","49":"b:ANcbAA4gAP/DaAKAh/x/l8EAAAAA","50":"b:ANcbAA4gAP/DaAKAh/x/l8EAAAAA"},"packages/frontend/editor-ui/src/app/composables/usePushConnection/handlers/nodeExecuteAfterData.ts":{"11":"b:ANcbAA4gAP/DaAKAh/x/l8EAAAAA"},"packages/frontend/editor-ui/src/app/composables/usePushConnection/handlers/nodeExecuteBefore.ts":{"9":"b:ANcbAA4gAP/DaAKAh/x/l8EAAAAA"},"packages/frontend/editor-ui/src/app/composables/usePushConnection/handlers/trackNodeExecution.ts":{"11":"b:ANcbAA4gAP/DaAKAh/x/l8EAAAAA"},"packages/frontend/editor-ui/src/app/composables/useRunWorkflow.ts":{"92":"b:ANcbAA4gAP/BaAKAh/x/l8EIAAAA","106":"b:AAYAAAAAAACBAAAAAMhAEgAAAAAA","110":"b:ANcbAA4gAP/BaAKAh/x/l8EIAAAA","125":"b:ANcbAA4gAP/BaAKAh/x/l8EIAAAA","157":"b:ANcbAA4gAP/BaAKAh/x/l8EIAAAA","279":"b:ANcbAA4gAP/BaAKAh/x/l8EIAAAA","282":"b:ANcbAA4gAP/AaAKAh/x/l8EIAAAA","314":[14,15,17,77,95,110],"325":[9,62,64,96,107,122],"349":[9,62,64,96,107,122],"392":[64,71,111,124],"445":[20,57],"485":"b:ANcbAA4gAP/BaAKAh/x/l8EIAAAA","536":[110],"583":[110],"611":"b:AJAYAA4gALtBQAIABvxwh8EIAAAA"},"packages/frontend/editor-ui/src/app/composables/useWorkflowsCache.ts":{"27":"b:cP8fwA8wAP/naQIgn///1/8OAAAA","30":"b:cP8fwA8wAP/naQIgn///1/8OAAAA","35":"b:cP8fwA8wAP/naQIgn///1/8OAAAA","39":"b:cP8fwA8wAP/naQIgn///1/8OAAAA","46":"b:cP8fwA8wAP/naQIgn///1/8OAAAA","62":[63,65,93,132,133,137],"85":[63,65,93,132,133,137],"96":[65,93],"104":[65],"113":[65],"120":[65,93],"123":[65,93]},"packages/frontend/editor-ui/src/app/plugins/cache.ts":{"3":"b:cP8fwA8wAP/naQIgn///1/8OAAAA","8":"b:cP8fwA8wAP/naQIgn///1/8OAAAA","9":"b:cP8fwA8wAP/naQIgn///1/8OAAAA","10":"b:cP8fwA8wAP/naQIgn///1/8OAAAA","13":"b:cP8fwA8wAP/naQIgn///1/8OAAAA","25":[65],"33":"b:cP8fwA8wAP/naQIgn///1/8OAAAA","34":"b:cP8fwA8wAP/naQIgn///1/8OAAAA","36":"b:cP8fwA8wAP/naQIgn///1/8OAAAA","39":"b:cP8fwA8wAP/naQIgn///1/8OAAAA","40":[65],"44":[63,65,93,132,133,137],"49":"b:cP8fwA8wAP/naQIgn///1/8OAAAA","53":[65],"58":[65],"63":[65],"67":[65],"68":[65],"71":[65],"82":[65],"89":"b:cP8fwA8wAP/naQIgn///1/8OAAAA","99":"b:cP8fwA8wAP/naQIgn///1/8OAAAA","100":"b:cP8fwA8wAP/naQIgn///1/8OAAAA","104":[65],"111":[63,65,93,132,133,137],"112":[63,65,93,132,133,137],"117":[65],"118":[65],"123":[65],"124":[65]},"packages/frontend/editor-ui/src/app/utils/mappingUtils.ts":{"11":"b:AMZaAAQAAM7BaAIAiu1/twEAgAAA","15":"b:AMZaAAQAAM7BaAIAiu1/twEAgAAA","16":"b:AMZaAAQAAM7BaAIAiu1/twEAgAAA","29":"b:AMBaAAQAAM7BKAIAis1/lwEAgAAA","33":"b:AMBaAAQAAM6BKAIAgM1/lwEAgAAA","53":"b:AMBaAAQAAM7BKAIAiu1/twEAgAAA","70":[151],"82":[151,113],"96":[151,113]},"packages/frontend/editor-ui/src/app/utils/pairedItemUtils.ts":{"19":"b:ANdbAA4gAP/BaAIAh/1/l8EAgAAA","23":[151,113,121],"48":[151,113,121],"58":[151,113,121],"61":"b:ANcLAA4gAP/BaAIAh/x/l8EAgAAA","89":"b:ANECAAwAAD3AaAIAhvx/l8EAgAAA","95":"b:ANcLAA4gAP/BaAIAh/x/l8EAgAAA","124":"b:ANEKAAwAAL/AaAIAhvx/l8EAgAAA","138":"b:ANcLAA4gAP/BaAIAh/x/l8EAgAAA","143":"b:ANcLAA4gAP/BaAIAh/x/l8EAgAAA","152":[151,60],"168":"b:ANcbAA4gAP/BaAKAh/x/l8EIgAAA","171":"b:ANcLAA4gAP/BaAIAh/x/l8EAgAAA","172":"b:ANcLAA4gAP/BaAIAh/x/l8EAgAAA","173":"b:ANcLAA4gAP/BaAIAh/x/l8EAgAAA","188":"b:ANcbAA4gAP/BaAKAh/x/l8EIgAAA","197":"b:ANcLAA4gAP/BaAIAh/x/l8EAgAAA","209":"b:ANcbAA4gAP/BaAKAh/x/l8EIgAAA","229":"b:ANcLAA4gAP/BaAIAh/x/l8EAgAAA","230":"b:ANcLAA4gAP/BaAIAh/x/l8EAgAAA"},"packages/frontend/editor-ui/src/app/utils/workflowUtils.ts":{"11":"b:cMdzQA4gALvjaQCAnvrzw9kOgAAA","15":[151],"26":[151,94],"36":[151,94],"49":"b:YNdzQA4gALvh6wOA3vrzx9kPgAAA","60":"b:ANdzQA4gALvg6wOA3vrzx8kNgAAA","80":"b:cNdzQA4gALvj6wOA3vrzx9kPgAAA","100":"b:ANdzQA4gALvg6wOA3vrzx8kNgAAA","103":"b:ANdzQA4gALvg6wOA3vrzx8kNgAAA","138":[13,151],"145":[13,151],"146":[13,151],"158":[13,151],"167":[13,151]},"packages/frontend/editor-ui/src/features/collaboration/collaboration/components/CollaborationPane.vue":{"11":"b:cP8fwA8wAP/naQIgn///1/8OAAAA","15":"b:AAAAQAAAAAAmAAAAFiAAQAkCAAAA","24":"b:cP8fwA8wAP/naQIgn///1/8OAAAA","26":[65,131],"27":[65,131],"29":[65,131],"35":[65,131],"37":"b:cP8fwA8wAP/naQIgn///1/8OAAAA","41":[65,69,105,126,132],"44":"b:cP8fwA8wAP/naQIgn///1/8OAAAA"},"packages/frontend/editor-ui/src/features/ndv/parameters/components/AssignmentCollection/AssignmentCollection.vue":{"36":"b:AIIAAAEAAIAhYQIAS+hqZQgAAAAA","50":"b:AIIAAAEAAIAhYQIAS+hqZQgAAAAA","53":"b:AAIAAAAAAIAAIQIACMhCAQAAAAAA","69":"b:AAIAAAEAAIABIQIACMhKBQAAAAAA","74":"b:AIIAAAEAAIAhYQIAS+hqZQgAAAAA","75":[113],"76":"b:AIIAAAEAAIAhYQIAS+hqZQgAAAAA","77":"b:AIIAAAEAAIAhYQIAS+hqZQgAAAAA","92":"b:AIIAAAEAAIAhYQIAS+hqZQgAAAAA","93":[118],"101":"b:AIIAAAEAAIAhYQIAS+hqZQgAAAAA","102":[32,64,111,113,115,120,122],"104":[32,64,111,113,115,120,122],"114":[32,64,111,115,122],"135":[32,64,99,113,115,120],"143":"b:AAIAAAEAAIABIQIACMhKBQAAAAAA","153":"b:AIIAAAEAAIAhYQIAS+hqZQgAAAAA","169":"b:AIIAAAEAAIAhYQIAS+hqZQgAAAAA","203":"b:AAIAAAEAAIABIQIACMhKBQAAAAAA","212":[32,64,99,113,115,120],"226":"b:AIIAAAEAAIAhYQIAS+hqZQgAAAAA"},"packages/frontend/editor-ui/src/features/ndv/runData/components/RunDataSearch.vue":{"44":"b:AMZaAAQAAM7BaAIAis1/lwEAAAAA","50":"b:AMZaAAQAAM7BaAIAis1/lwEAAAAA","68":"b:AMZaAAQAAM7BaAIAis1/lwEAAAAA","72":"b:AAAAAAAAAACAQAAAAABfBQAAAAAA","99":[116,118],"104":[116,118],"109":[116,118],"115":[116,118],"121":[116,118],"134":"b:AAAAAAAAAACAQAAAAABfBQAAAAAA","152":"b:AMZaAAQAAM7BaAIAis1/lwEAAAAA","153":[116,118]},"packages/frontend/editor-ui/src/features/ndv/runData/components/TextWithHighlights.vue":{"11":"b:AMZaAAQAAM7BaAIAiu1/twEAAAAA","20":[116,118],"29":"b:AMZaAAQAAM7BaAIAiu1/twEAAAAA"},"packages/frontend/editor-ui/src/features/ndv/runData/components/VirtualSchema.vue":{"107":"b:AAYKAAQAAIzASAIAiu1/twEAAAAA","108":"b:AAYKAAQAAIzASAIAiu1/twEAAAAA","114":[113],"117":[113],"123":"b:AAYIAAQAAIzASAIAiu1/twEAAAAA","134":"b:AAYIAAQAAIzASAIAiu1/twEAAAAA","143":"b:AAYIAAQAAIzASAIAiu1/twEAAAAA","159":[110,117,121],"165":"b:AAYIAAQAAIzASAIAgux/lwEAAAAA","176":"b:AAYIAAQAAIzASAIAgux/lwEAAAAA","205":"b:AAYIAAQAAIzASAIAiu1/twEAAAAA","209":"b:AAYIAAQAAIzASAIAiu1/twEAAAAA","231":"b:AAYIAAQAAIzASAIAiu1/twEAAAAA","254":"b:AAYIAAQAAIzASAIAiu1/twEAAAAA","286":"b:AAYKAAQAAIzASAIAiu1/twEAAAAA","298":"b:AAYIAAQAAIzASAIAguxktgAAAAAA","320":"b:AAYKAAQAAIzASAIAiu1/twEAAAAA","366":"b:AAYIAAQAAIzASAIAiu1/twEAAAAA","384":"b:AAYIAAQAAIzASAIAiu1/twEAAAAA","388":[17,110,118],"403":"b:AAYKAAQAAIzASAIAiu1/twEAAAAA","405":"b:AAYKAAQAAIzASAIAiu1/twEAAAAA","431":"b:AAYKAAQAAIzASAIAiu1/twEAAAAA","439":"b:AAYKAAQAAIzASAIAiu1/twEAAAAA","443":"b:AAYKAAQAAIzASAIAiu1/twEAAAAA","444":[118],"456":"b:AAYKAAQAAIzASAIAiu1/twEAAAAA","461":"b:AAYIAAQAAIzASAIAiu1/twEAAAAA","463":"b:AAYIAAQAAIzASAIAiu1/twEAAAAA","466":"b:AAYKAAQAAIzASAIAiu1/twEAAAAA","473":[113],"482":[113],"484":[113],"486":[113],"523":[118],"524":[118],"543":"b:AAYKAAQAAIzASAIAiu1/twEAAAAA","564":[113],"574":[118],"579":[111,125],"602":[107],"628":[107,109,114]},"packages/frontend/editor-ui/src/features/ndv/runData/components/VirtualSchemaHeader.vue":{"22":"b:AAYIAAQAAIzASAIAiu1/twEAAAAA","24":"b:AAYIAAQAAIzASAIAiu1/twEAAAAA","70":[109],"72":[109],"77":[111,125],"79":[111,125],"82":[111,125],"84":[111,125]},"packages/frontend/editor-ui/src/features/ndv/runData/components/VirtualSchemaItem.vue":{"36":"b:AAYKAAQAAIzASAIAiu1/twEAAAAA","72":"b:AAYKAAQAAIzASAIAiu1/twEAAAAA","109":"b:AAYIAAQAAIzASAIAgu1vpwEAAAAA"},"packages/frontend/editor-ui/src/features/ndv/runData/schemaPreview.api.ts":{"13":"b:AAAAAAAAAIBAwQAAAKFEpAAAAAAA","17":[79,111,125],"27":"b:AAAAAAAAAIBAwQAAAKFEpAAAAAAA"},"packages/frontend/editor-ui/src/features/shared/nodeCreator/components/ItemTypes/ViewItem.vue":{"13":"b:MIoZoAgwuAYj0AAgxyVvfSIAAAAA"},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/buttons/CanvasRunWorkflowButton.vue":{"40":"b:cL8a4A8w/P/hzwMg3/////sPAAAA","44":"b:cL8a4A8w/P/hzwMg3/////sPAAAA","45":"b:cL8a4A8w/P/hzwMg3/////sPAAAA","49":"b:cL8a4A8w/P/hzwMg3/////sPAAAA","60":[13,63,102,107,111,122],"62":[13,63,102,107,111,122],"63":[13,63,102,107,111,122],"69":[13,63,102,107,111,122],"76":"b:cL8a4A8w/P/hzwMg3/////sPAAAA","97":"b:cL8a4A8w/P/hzwMg3/////sPAAAA","108":"b:AJAYAA4gALtBQAIABvxwh8EAAAAA","109":"b:ABAYAA4gALtBQAIABvxwh8EAAAAA","111":"b:cL8a4A8w/P/hzwMg3/////sPAAAA","118":[13,63,102,107,111,122],"136":[13,63,102,107,111,122]},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/buttons/CanvasStopCurrentExecutionButton.vue":{"6":"b:ANcbAA4gAP/BaAKAh/x/l8EIAAAA","13":"b:ANcbAA4gAP/BaAKAh/x/l8EIAAAA","18":"b:ANcbAA4gAP/BaAKAh/x/l8EIAAAA"},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/edges/CanvasEdgeToolbar.vue":{"12":"b:AAAAAAAAAAAgwAEAQUAAQAEAgAAA","27":"b:AAAAAAAAAAAgwAEAQUAAQAEAgAAA","31":"b:AAAAAAAAAAAgwAEAQUAAQAEAgAAA","41":[151,78,79,96],"45":[151,96,102],"47":"b:AAAAAAAAAAAgwAEAQUAAQAEAgAAA","55":"b:AAAAAAAAAAAgwAEAQUAAQAEAgAAA","72":"b:AAAAAAAAAAAgwAEAQUAAQAEAgAAA"},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/edges/CanvasEdgeTooltip.vue":{"9":"b:AAAAAAAAAAAgwAEAQUAAQAEAgAAA","20":"b:AAAAAAAAAAAgwAEAQUAAQAEAgAAA"},"packages/@n8n/db/src/entities/credentials-entity.ts":{"64":[149,44,92]},"packages/@n8n/db/src/repositories/shared-credentials.repository.ts":{"12":"b:sKgAwHBwAJMwEEAQEkAAAAAEJIAA","16":"b:sKgAwHBwAJMwEEAQEkAAAAAEJIAA","26":"b:sKgAwHBwAJMwEEAQEkAAAAAEJIAA","36":"b:sKgAwHBwAJMwEEAQEkAAAAAEJIAA","41":"b:sKgAwHBwAJMwEEAQEkAAAAAEJIAA","52":"b:sKgAwHBwAJMwEEAQEkAAAAAEJIAA","61":"b:sKgAwHBwAJMwEEAQEkAAAAAEJIAA","73":"b:sKgAwHBwAJMwEEAQEkAAAAAEJIAA","76":"b:sKgAwHBwAJMwEEAQEkAAAAAEJIAA","85":"b:sKgAwHBwAJMwEEAQEkAAAAAEJIAA","94":"b:sKgAwHBwAJMwEEAQEkAAAAAEJIAA","99":"b:sKgAwHBwAJMwEEAQEkAAAAAEJIAA","112":"b:sKgAwHBwAJMwEEAQEkAAAAAEJIAA","128":"b:sKgAwHBwAJMwEEAQEkAAAAAEJIAA","156":"b:sKgAwHBwAJMwEEAQEkAAAAAEJIAA","165":"b:sKgAwHBwAJMwEEAQEkAAAAAEJIAA","166":"b:sKgAwHBwAJMwEEAQEkAAAAAEJIAA","181":"b:sKgAwHBwAJMwEEAQEkAAAAAEJIAA","182":"b:sKgAwHBwAJMwEEAQEkAAAAAEJIAA","192":"b:sKgAwHBwAJMwEEAQEkAAAAAEJIAA"},"packages/cli/src/credential-types.ts":{"8":"b:MKAA4HBwAJMwAEAQAEAAAAAEJIAA","10":"b:MKAA4HBwAJMwAEAQAEAAAAAEJIAA","15":"b:MKAA4HBwAJMwAEAQAEAAAAAEJIAA","19":"b:MKAA4HBwAJMwAEAQAEAAAAAEJIAA","26":"b:MKAA4HBwAJMwAEAQAEAAAAAEJIAA"},"packages/cli/src/credentials/credentials.service.ee.ts":{"24":"b:MCAAAEA0AAAQAAAQAAAAAAAEIAAA","36":"b:MCAAAEA0AAAQAAAQAAAAAAAEIAAA","70":"b:MCAAAEA0AAAQAAAQAAAAAAAEIAAA","72":"b:MCAAAEA0AAAQAAAQAAAAAAAEIAAA","76":"b:MCAAAEA0AAAQAAAQAAAAAAAEIAAA","87":"b:MCAAAEA0AAAQAAAQAAAAAAAEIAAA","91":"b:MCAAAEA0AAAQAAAQAAAAAAAEIAAA","159":"b:MCAAAEA0AAAQAAAQAAAAAAAEIAAA","172":"b:MCAAAEA0AAAQAAAQAAAAAAAEIAAA","213":"b:MCAAAEA0AAAQAAAQAAAAAAAEIAAA"},"packages/cli/src/credentials/external-secrets.utils.ts":{"11":"b:MKAAwHBwAJMwEEAQAEAAAAAEJIAA","19":"b:MKAAwHBwAJMwEEAQAEAAAAAEJIAA","28":"b:MKAAwHBwAJMwEEAQAEAAAAAEJIAA","61":"b:MKAAwHBwAJMwEEAQAEAAAAAEJIAA"},"packages/cli/src/middlewares/list-query/dtos/credentials.filter.dto.ts":{"22":[11,31,44,45,46,68,69,86,92,5]},"packages/core/src/credentials.ts":{"11":"b:MKAAwHBwAJMwEEARAEAAAAAEJIAA","19":"b:MKAAwHBwAJMwEEARAEAAAAAEJIAA","27":"b:MKAAwHBwAJMwEEARAEAAAAAEJIAA","37":"b:MKAAwHBwAJMwEEARAEAAAAAEJIAA","48":"b:MKAAwHBwAJMwEEARAEAAAAAEJIAA","72":"b:MKAAwHBwAJMwEEARAEAAAAAEJIAA"},"packages/workflow/src/interfaces.ts":{"127":"b:MKAAwHBwAJMwEEAQAEAAAAAEJIAA"},"packages/@n8n/db/src/entities/webhook-entity.ts":{"33":"b:AAAYAAIEAIAAAAAAAAAAAKDiEK4B","39":"b:AAAYAAIEAIAAAAAAAAAAAKDiEK4B","43":"b:AAAYAAIEAIAAAAAAAAAAAKDiEK4B","44":"b:AAAYAAIEAIAAAAAAAAAAAKDiEK4B","50":"b:AAAYAAIEAIAAAAAAAAAAAKDiEK4B","51":"b:AAAYAAIEAIAAAAAAAAAAAKDiEK4B","54":"b:AAAYAAIEAIAAAAAAAAAAAKDiEK4B"},"packages/@n8n/db/src/repositories/execution.repository.ts":{"59":"b:BNMKAH4gAJXACAAABFwCEcDwEC8A","94":"b:BNMKAH4gAJXACAAABFwCEcDwEC8A","137":"b:BNMKAH4gAJXACAAABFwCEcDwEC8A","141":"b:BNMKAH4gAJXACAAABFwCEcDwEC8A","153":"b:BNMKAH4gAJXACAAABFwCEcDwEC8A","185":"b:BNMKAH4gAJXACAAABFwCEcDwEC8A","205":"b:BNMKAH4gAJXACAAABFwCEcDwEC8A","210":"b:BNMKAH4gAJXACAAABFwCEcDwEC8A","217":"b:BNMKAH4gAJXACAAABFwCEcDwEC8A","224":"b:BNMKAH4gAJXACAAABFwCEcDwEC8A","230":"b:BNMKAH4gAJXACAAABFwCEcDwEC8A","236":"b:BNMKAH4gAJXACAAABFwCEcDwEC8A","242":"b:BNMKAH4gAJXACAAABFwCEcDwEC8A","249":"b:BNMKAH4gAJXACAAABFwCEcDwEC8A","280":"b:BNMKAH4gAJXACAAABFwCEcDwEC8A","343":"b:BNMKAH4gAJXACAAABFwCEcDwEC8A","349":"b:BNMKAH4gAJXACAAABFwCEcDwEC8A","369":"b:BNMKAH4gAJXACAAABFwCEcDwEC8A","372":"b:BNMKAH4gAJXACAAABFwCEcDwEC8A","401":"b:BNMKAH4gAJXACAAABFwCEcDwEC8A","423":"b:BNMKAH4gAJXACAAABFwCEcDwEC8A","450":"b:BNMKAH4gAJXACAAABFwCEcDwEC8A","490":"b:BNMKAH4gAJXACAAABFwCEcDwEC8A","501":"b:BNMKAH4gAJXACAAABFwCEcDwEC8A","502":"b:BNMKAH4gAJXACAAABFwCEcDwEC8A","509":"b:BNMKAH4gAJXACAAABFwCEcDwEC8A","515":"b:BNMKAH4gAJXACAAABFwCEcDwEC8A","518":"b:BNMKAH4gAJXACAAABFwCEcDwEC8A","564":"b:BNMKAH4gAJXACAAABFwCEcDwEC8A","573":"b:BNMKAH4gAJXACAAABFwCEcDwEC8A","591":"b:BNMKAH4gAJXACAAABFwCEcDwEC8A","598":"b:BNMKAH4gAJXACAAABFwCEcDwEC8A","602":"b:BNMKAH4gAJXACAAABFwCEcDwEC8A","626":"b:BNMKAH4gAJXACAAABFwCEcDwEC8A","641":"b:BNMKAH4gAJXACAAABFwCEcDwEC8A","659":"b:BNMKAH4gAJXACAAABFwCEcDwEC8A","673":"b:BNMKAH4gAJXACAAABFwCEcDwEC8A","691":"b:BNMKAH4gAJXACAAABFwCEcDwEC8A","726":"b:BNMKAH4gAJXACAAABFwCEcDwEC8A","737":"b:BNMKAH4gAJXACAAABFwCEcDwEC8A","743":"b:BNMKAH4gAJXACAAABFwCEcDwEC8A","756":"b:BNMKAH4gAJXACAAABFwCEcDwEC8A","790":"b:BNMKAH4gAJXACAAABFwCEcDwEC8A","831":"b:BNMKAH4gAJXACAAABFwCEcDwEC8A","847":"b:BNMKAH4gAJXACAAABFwCEcDwEC8A","851":"b:BNMKAH4gAJXACAAABFwCEcDwEC8A","860":"b:BNMKAH4gAJXACAAABFwCEcDwEC8A","896":"b:BNMKAH4gAJXACAAABFwCEcDwEC8A","900":"b:BNMKAH4gAJXACAAABFwCEcDwEC8A","920":"b:BNMKAH4gAJXACAAABFwCEcDwEC8A","940":"b:BNMKAH4gAJXACAAABFwCEcDwEC8A","1059":"b:BNMKAH4gAJXACAAABFwCEcDwEC8A","1061":"b:BNMKAH4gAJXACAAABFwCEcDwEC8A","1069":"b:BNMKAH4gAJXACAAABFwCEcDwEC8A","1101":"b:BNMKAH4gAJXACAAABFwCEcDwEC8A","1109":"b:BNMKAH4gAJXACAAABFwCEcDwEC8A","1112":"b:BNMKAH4gAJXACAAABFwCEcDwEC8A","1115":"b:BNMKAH4gAJXACAAABFwCEcDwEC8A","1121":"b:BNMKAH4gAJXACAAABFwCEcDwEC8A","1129":"b:BNMKAH4gAJXACAAABFwCEcDwEC8A","1136":"b:BNMKAH4gAJXACAAABFwCEcDwEC8A","1144":"b:BNMKAH4gAJXACAAABFwCEcDwEC8A","1161":"b:BNMKAH4gAJXACAAABFwCEcDwEC8A"},"packages/@n8n/db/src/repositories/workflow-publish-history.repository.ts":{"8":"b:AAAYAAIEAJAAAAAAAAAAALLiEC0B","12":"b:AAAYAAIEAJAAAAAAAAAAALLiEC0B","26":"b:AAAYAAIEAJAAAAAAAAAAALLiEC0B","37":"b:AAAYAAIEAJAAAAAAAAAAALLiEC0B"},"packages/@n8n/db/src/repositories/workflow-statistics.repository.ts":{"22":"b:ANMaAA4kAJXACAAAAFACEYDwEK8B","29":"b:ANMaAA4kAJXACAAAAFACEYDwEK8B","62":"b:ANMaAA4kAJXACAAAAFACEYDwEK8B","120":"b:ANMaAA4kAJXACAAAAFACEYDwEK8B"},"packages/@n8n/decorators/src/execution-lifecycle/lifecycle-metadata.ts":{"82":"b:ANMCAH4gAJXACAAAAFACEYDwECcA","85":"b:ANMCAH4gAJXACAAAAFACEYDwECcA","89":"b:ANMCAH4gAJXACAAAAFACEYDwECcA"},"packages/@n8n/syslog-client/src/client.ts":{"78":[148],"129":[148],"147":[148],"148":[148],"162":[148],"185":[148],"197":[148],"205":[148],"214":[148],"233":[148],"253":[148],"279":[148],"293":[148],"310":[148],"322":[148],"337":[148],"342":[148],"350":[148],"365":[148],"377":[148],"391":[148],"420":[148],"438":[148],"453":[148],"468":[148],"475":[148],"483":[148],"501":[148]},"packages/@n8n/syslog-client/src/factory.ts":{"25":[148]},"packages/@n8n/syslog-client/src/index.ts":{"13":[148]},"packages/@n8n/syslog-client/src/schemas.ts":{"9":[148],"10":[148],"11":[148]},"packages/@n8n/syslog-client/src/utils.ts":{"7":[148],"15":[148],"37":[148],"69":[148]},"packages/cli/src/activation-errors.service.ts":{"9":"b:AAAYAAIEAJAAAAAAAAAAALLiEC0B","11":"b:AAAYAAIEAJAAAAAAAAAAALLiEC0B","15":"b:AAAYAAIEAJAAAAAAAAAAALLiEC0B","19":"b:AAAYAAIEAJAAAAAAAAAAALLiEC0B","27":"b:AAAYAAIEAJAAAAAAAAAAALLiEC0B","35":"b:AAAYAAIEAJAAAAAAAAAAALLiEC0B"},"packages/cli/src/active-executions.ts":{"46":"b:ANMaAH4gAJfACAAAAFACFYDwEC8B","55":"b:ANMaAH4gAJfACAAAAFACFYDwEC8B","62":"b:ANMaAH4gAJfACAAAAFACFYDwEC8B","160":"b:ANMaAH4gAJfACAAAAFACFYDwEC8B","164":"b:ANMaAH4gAJfACAAAAFACFYDwEC8B","185":"b:ANMaAH4gAJfACAAAAFACFYDwEC8B","189":"b:ANMaAH4gAJfACAAAAFACFYDwEC8B","196":"b:ANMaAH4gAJfACAAAAFACFYDwEC8B","202":"b:ANMaAH4gAJfACAAAAFACFYDwEC8B","211":"b:ANMaAH4gAJfACAAAAFACFYDwEC8B","241":"b:ANMaAH4gAJfACAAAAFACFYDwEC8B","263":"b:ANMaAH4gAJfACAAAAFACFYDwEC8B","281":"b:ANMaAH4gAJfACAAAAFACFYDwEC8B","288":"b:ANMaAH4gAJfACAAAAFACFYDwEC8B","308":"b:ANMaAH4gAJfACAAAAFACFYDwEC8B","312":"b:ANMaAH4gAJfACAAAAFACFYDwEC8B","316":"b:ANMaAH4gAJfACAAAAFACFYDwEC8B","320":"b:ANMaAH4gAJfACAAAAFACFYDwEC8B","325":"b:ANMaAH4gAJfACAAAAFACFYDwEC8B","360":"b:ANMaAH4gAJfACAAAAFACFYDwEC8B"},"packages/cli/src/active-workflow-manager.ts":{"85":"b:AAAYAAIEAJAAAAAgAAAAALLiEC0B","111":"b:AAAYAAIEAJAAAAAgAAAAALLiEC0B","122":"b:AAAYAAIEAJAAAAAgAAAAALLiEC0B","129":"b:AAAYAAIEAJAAAAAgAAAAALLiEC0B","151":"b:AAAYAAIEAJAAAAAgAAAAALLiEC0B","158":"b:AAAYAAIEAJAAAAAgAAAAALLiEC0B","169":"b:AAAYAAIEAJAAAAAgAAAAALLiEC0B","258":"b:AAAYAAIEAJAAAAAgAAAAALLiEC0B","303":"b:AAAYAAIEAJAAAAAgAAAAALLiEC0B","339":"b:AAAYAAIEAJAAAAAgAAAAALLiEC0B","350":"b:AAAYAAIEAJAAAAAgAAAAALLiEC0B","351":"b:AAAYAAIEAJAAAAAgAAAAALLiEC0B","363":"b:AAAYAAIEAJAAAAAgAAAAALLiEC0B","375":"b:AAAYAAIEAJAAAAAgAAAAALLiEC0B","382":"b:AAAYAAIEAJAAAAAgAAAAALLiEC0B","386":"b:AAAYAAIEAJAAAAAgAAAAALLiEC0B","389":"b:AAAYAAIEAJAAAAAgAAAAALLiEC0B","402":"b:AAAYAAIEAJAAAAAgAAAAALLiEC0B","413":"b:AAAYAAIEAJAAAAAgAAAAALLiEC0B","414":"b:AAAYAAIEAJAAAAAgAAAAALLiEC0B","428":"b:AAAYAAIEAJAAAAAgAAAAALLiEC0B","439":"b:AAAYAAIEAJAAAAAgAAAAALLiEC0B","453":"b:AAAYAAIEAJAAAAAgAAAAALLiEC0B","466":"b:AAAYAAIEAJAAAAAgAAAAALLiEC0B","479":"b:AAAYAAIEAJAAAAAgAAAAALLiEC0B","482":"b:AAAYAAIEAJAAAAAgAAAAALLiEC0B","508":"b:AAAYAAIEAJAAAAAgAAAAALLiEC0B","519":"b:AAAYAAIEAJAAAAAgAAAAALLiEC0B","536":"b:AAAYAAIEAJAAAAAgAAAAALLiEC0B","566":"b:AAAYAAIEAJAAAAAgAAAAALLiEC0B","589":"b:AAAYAAIEAJAAAAAgAAAAALLiEC0B","608":"b:AAAYAAIEAJAAAAAgAAAAALLiEC0B","621":"b:AAAYAAIEAJAAAAAgAAAAALLiEC0B","680":"b:AAAYAAIEAJAAAAAgAAAAALLiEC0B","687":"b:AAAYAAIEAJAAAAAgAAAAALLiEC0B","693":"b:AAAYAAIEAJAAAAAgAAAAALLiEC0B","718":"b:AAAYAAIEAJAAAAAgAAAAALLiEC0B","832":"b:AAAYAAIEAJAAAAAgAAAAALLiEC0B","833":"b:AAAYAAIEAJAAAAAgAAAAALLiEC0B","875":"b:AAAYAAIEAJAAAAAgAAAAALLiEC0B","888":"b:AAAYAAIEAJAAAAAgAAAAALLiEC0B","898":"b:AAAYAAIEAJAAAAAgAAAAALLiEC0B","932":"b:AAAYAAIEAJAAAAAgAAAAALLiEC0B","933":"b:AAAYAAIEAJAAAAAgAAAAALLiEC0B","959":"b:AAAYAAIEAJAAAAAgAAAAALLiEC0B","996":"b:AAAYAAIEAJAAAAAgAAAAALLiEC0B","1026":"b:AAAYAAIEAJAAAAAgAAAAALLiEC0B","1034":"b:AAAYAAIEAJAAAAAgAAAAALLiEC0B","1039":"b:AAAYAAIEAJAAAAAgAAAAALLiEC0B","1060":"b:AAAYAAIEAJAAAAAgAAAAALLiEC0B","1126":"b:AAAYAAIEAJAAAAAgAAAAALLiEC0B","1127":"b:AAAYAAIEAJAAAAAgAAAAALLiEC0B","1130":"b:AAAYAAIEAJAAAAAgAAAAALLiEC0B","1140":"b:AAAYAAIEAJAAAAAgAAAAALLiEC0B","1157":"b:AAAYAAIEAJAAAAAgAAAAALLiEC0B","1164":"b:AAAYAAIEAJAAAAAgAAAAALLiEC0B","1214":"b:AAAYAAIEAJAAAAAgAAAAALLiEC0B","1224":"b:AAAYAAIEAJAAAAAgAAAAALLiEC0B","1237":"b:AAAYAAIEAJAAAAAgAAAAALLiEC0B","1276":"b:AAAYAAIEAJAAAAAgAAAAALLiEC0B","1294":"b:AAAYAAIEAJAAAAAgAAAAALLiEC0B","1309":"b:AAAYAAIEAJAAAAAgAAAAALLiEC0B","1343":"b:AAAYAAIEAJAAAAAgAAAAALLiEC0B","1346":"b:AAAYAAIEAJAAAAAgAAAAALLiEC0B","1369":"b:AAAYAAIEAJAAAAAgAAAAALLiEC0B","1376":"b:AAAYAAIEAJAAAAAgAAAAALLiEC0B","1392":"b:AAAYAAIEAJAAAAAgAAAAALLiEC0B"},"packages/cli/src/chat/chat-service.ts":{"49":"b:ApsmqL44EIgwBHAEAFAAAIgEkAAA","52":"b:ApsmqL44EIgwBHAEAFAAAIgEkAAA","56":"b:ApsmqL44EIgwBHAEAFAAAIgEkAAA","68":"b:ApsmqL44EIgwBHAEAFAAAIgEkAAA","74":"b:ApsmqL44EIgwBHAEAFAAAIgEkAAA","79":"b:ApsmqL44EIgwBHAEAFAAAIgEkAAA","126":"b:ApsmqL44EIgwBHAEAFAAAIgEkAAA","128":"b:ApsmqL44EIgwBHAEAFAAAIgEkAAA","151":"b:ApsmqL44EIgwBHAEAFAAAIgEkAAA","181":"b:ApsmqL44EIgwBHAEAFAAAIgEkAAA","186":"b:ApsmqL44EIgwBHAEAFAAAIgEkAAA","195":"b:ApsmqL44EIgwBHAEAFAAAIgEkAAA","196":"b:ApsmqL44EIgwBHAEAFAAAIgEkAAA","242":"b:ApsmqL44EIgwBHAEAFAAAIgEkAAA","243":"b:ApsmqL44EIgwBHAEAFAAAIgEkAAA","271":"b:ApsmqL44EIgwBHAEAFAAAIgEkAAA","277":"b:ApsmqL44EIgwBHAEAFAAAIgEkAAA","303":"b:ApsmqL44EIgwBHAEAFAAAIgEkAAA","305":"b:ApsmqL44EIgwBHAEAFAAAIgEkAAA","312":"b:ApsmqL44EIgwBHAEAFAAAIgEkAAA","318":"b:ApsmqL44EIgwBHAEAFAAAIgEkAAA","323":"b:ApsmqL44EIgwBHAEAFAAAIgEkAAA","333":"b:ApsmqL44EIgwBHAEAFAAAIgEkAAA","340":"b:ApsmqL44EIgwBHAEAFAAAIgEkAAA","368":"b:ApsmqL44EIgwBHAEAFAAAIgEkAAA","384":"b:ApsmqL44EIgwBHAEAFAAAIgEkAAA"},"packages/cli/src/concurrency/concurrency-capacity-reservation.ts":{"21":"b:ANMCAH4gAJXACAAAAFACEYDwECcA","23":"b:ANMCAH4gAJXACAAAAFACEYDwECcA","30":"b:ANMCAH4gAJXACAAAAFACEYDwECcA"},"packages/cli/src/concurrency/concurrency-control.service.ts":{"35":"b:ANMCAH4gAJXACAAAAFACEYDwECcA","45":"b:ANMCAH4gAJXACAAAAFACEYDwECcA","90":"b:ANMCAH4gAJXACAAAAFACEYDwECcA","100":"b:ANMCAH4gAJXACAAAAFACEYDwECcA","113":"b:ANMCAH4gAJXACAAAAFACEYDwECcA","135":"b:ANMCAH4gAJXACAAAAFACEYDwECcA","136":"b:ANMCAH4gAJXACAAAAFACEYDwECcA","145":"b:ANMCAH4gAJXACAAAAFACEYDwECcA","150":"b:ANMCAH4gAJXACAAAAFACEYDwECcA","158":"b:ANMCAH4gAJXACAAAAFACEYDwECcA","173":"b:ANMCAH4gAJXACAAAAFACEYDwECcA","183":"b:ANMCAH4gAJXACAAAAFACEYDwECcA","193":"b:ANMCAH4gAJXACAAAAFACEYDwECcA","205":"b:ANMCAH4gAJXACAAAAFACEYDwECcA","208":"b:ANMCAH4gAJXACAAAAFACEYDwECcA","225":"b:ANMCAH4gAJXACAAAAFACEYDwECcA","233":"b:ANMCAH4gAJXACAAAAFACEYDwECcA","237":"b:ANMCAH4gAJXACAAAAFACEYDwECcA","244":"b:ANMCAH4gAJXACAAAAFACEYDwECcA"},"packages/cli/src/environments.ee/variables/variables.service.ee.ts":{"31":"b:ANMCAH5gAJXgCCAAAFACAYD0FCAA","39":"b:ANMCAH5gAJXgCCAAAFACAYD0FCAA","46":"b:ANMCAH5gAJXgCCAAAFACAYD0FCAA","69":"b:ANMCAH5gAJXgCCAAAFACAYD0FCAA","74":"b:ANMCAH5gAJXgCCAAAFACAYD0FCAA","78":"b:ANMCAH5gAJXgCCAAAFACAYD0FCAA","84":"b:ANMCAH5gAJXgCCAAAFACAYD0FCAA","86":"b:ANMCAH5gAJXgCCAAAFACAYD0FCAA","93":"b:ANMCAH5gAJXgCCAAAFACAYD0FCAA","99":"b:ANMCAH5gAJXgCCAAAFACAYD0FCAA","109":"b:ANMCAH5gAJXgCCAAAFACAYD0FCAA","116":"b:ANMCAH5gAJXgCCAAAFACAYD0FCAA","124":"b:ANMCAH5gAJXgCCAAAFACAYD0FCAA","128":"b:ANMCAH5gAJXgCCAAAFACAYD0FCAA","146":"b:ANMCAH5gAJXgCCAAAFACAYD0FCAA","174":"b:ANMCAH5gAJXgCCAAAFACAYD0FCAA","179":"b:ANMCAH5gAJXgCCAAAFACAYD0FCAA","184":"b:ANMCAH5gAJXgCCAAAFACAYD0FCAA","202":"b:ANMCAH5gAJXgCCAAAFACAYD0FCAA","204":"b:ANMCAH5gAJXgCCAAAFACAYD0FCAA","207":"b:ANMCAH5gAJXgCCAAAFACAYD0FCAA","214":"b:ANMCAH5gAJXgCCAAAFACAYD0FCAA","221":"b:ANMCAH5gAJXgCCAAAFACAYD0FCAA","263":"b:ANMCAH5gAJXgCCAAAFACAYD0FCAA"},"packages/cli/src/eventbus/event-message-classes/event-message-generic.ts":{"23":[148],"31":[148],"36":[148]},"packages/cli/src/eventbus/event-message-classes/event-message-node.ts":{"35":"b:ANMCAH4gAJXACAAAAFACEYDwECcA","43":"b:ANMCAH4gAJXACAAAAFACEYDwECcA","48":"b:ANMCAH4gAJXACAAAAFACEYDwECcA"},"packages/cli/src/eventbus/event-message-classes/event-message-workflow.ts":{"36":"b:ANMCAH4gAJXACAAAAFACEYDwECcA","44":"b:ANMCAH4gAJXACAAAAFACEYDwECcA","49":"b:ANMCAH4gAJXACAAAAFACEYDwECcA"},"packages/cli/src/eventbus/message-event-bus/message-event-bus.ts":{"59":"b:ANcCAH4gALXACAAAhlgCEYDwEKcA","78":"b:ANcCAH4gALXACAAAhlgCEYDwEKcA","118":"b:ANcCAH4gALXACAAAhlgCEYDwEKcA","127":"b:ANcCAH4gALXACAAAhlgCEYDwEKcA","138":"b:ANcCAH4gALXACAAAhlgCEYDwEKcA","141":"b:ANcCAH4gALXACAAAhlgCEYDwEKcA","151":"b:ANcCAH4gALXACAAAhlgCEYDwEKcA","162":"b:ANcCAH4gALXACAAAhlgCEYDwEKcA","169":"b:ANcCAH4gALXACAAAhlgCEYDwEKcA","192":"b:ANcCAH4gALXACAAAhlgCEYDwEKcA","196":"b:ANcCAH4gALXACAAAhlgCEYDwEKcA","197":"b:ANcCAH4gALXACAAAhlgCEYDwEKcA","202":"b:ANcCAH4gALXACAAAhlgCEYDwEKcA","208":"b:ANcCAH4gALXACAAAhlgCEYDwEKcA","214":"b:ANcCAH4gALXACAAAhlgCEYDwEKcA","220":"b:ANcCAH4gALXACAAAhlgCEYDwEKcA","225":"b:ANcCAH4gALXACAAAhlgCEYDwEKcA","239":"b:ANcCAH4gALXACAAAhlgCEYDwEKcA","250":"b:ANcCAH4gALXACAAAhlgCEYDwEKcA","254":"b:ANcCAH4gALXACAAAhlgCEYDwEKcA","258":"b:ANcCAH4gALXACAAAhlgCEYDwEKcA","262":"b:ANcCAH4gALXACAAAhlgCEYDwEKcA","266":"b:ANcCAH4gALXACAAAhlgCEYDwEKcA","270":"b:ANcCAH4gALXACAAAhlgCEYDwEKcA","274":"b:ANcCAH4gALXACAAAhlgCEYDwEKcA","285":"b:ANcCAH4gALXACAAAhlgCEYDwEKcA","351":"b:ANcCAH4gALXACAAAhlgCEYDwEKcA","370":"b:ANcCAH4gALXACAAAhlgCEYDwEKcA","389":"b:ANcCAH4gALXACAAAhlgCEYDwEKcA"},"packages/cli/src/execution-lifecycle/execute-error-workflow.ts":{"22":"b:AAAYIHAGAJAAAAAAAAAAgIDgEC8B","96":"b:AAAYIHAGAJAAAAAAAAAAgIDgEC8B","103":"b:AAAYIHAGAJAAAAAAAAAAgIDgEC8B","119":"b:AAAYIHAGAJAAAAAAAAAAgIDgEC8B","124":"b:AAAYIHAGAJAAAAAAAAAAgIDgEC8B"},"packages/cli/src/execution-lifecycle/execution-lifecycle-hooks.ts":{"52":"b:ANMaAH4gALfACAAAAlwCkYHwEC8B","60":"b:ANMaAH4gALfACAAAAlwCkYHwEC8B","75":"b:ANMaAH4gALfACAAAAlwCkYHwEC8B","89":"b:ANMaAH4gALfACAAAAlwCkYHwEC8B","104":"b:ANMaAH4gALfACAAAAlwCkYHwEC8B","118":"b:ANMaAH4gALfACAAAAlwCkYHwEC8B","142":"b:ANMaAH4gALfACAAAAlwCkYHwEC8B","151":"b:ANMaAH4gALfACAAAAlwCkYHwEC8B","161":"b:ANMaAH4gALfACAAAAlwCkYHwEC8B","203":"b:ANMaAH4gALfACAAAAlwCkYHwEC8B","205":"b:ANMaAH4gALfACAAAAlwCkYHwEC8B","207":"b:ANMaAH4gALfACAAAAlwCkYHwEC8B","217":"b:ANMaAH4gALfACAAAAlwCkYHwEC8B","219":"b:ANMaAH4gALfACAAAAlwCkYHwEC8B","235":"b:ANMaAH4gALfACAAAAlwCkYHwEC8B","258":"b:ANMaAH4gALfACAAAAlwCkYHwEC8B","272":"b:ANMaAH4gALfACAAAAlwCkYHwEC8B","280":"b:ANMaAH4gALfACAAAAlwCkYHwEC8B","295":"b:ANMaAH4gALfACAAAAlwCkYHwEC8B","367":"b:ANMaAH4gALfACAAAAlwCkYHwEC8B","427":"b:ANMaAH4gALfACAAAAlwCkYHwEC8B","448":"b:ANMaAH4gALfACAAAAlwCkYHwEC8B","451":"b:ANMaAH4gALfACAAAAlwCkYHwEC8B","454":"b:ANMaAH4gALfACAAAAlwCkYHwEC8B","463":"b:ANMaAH4gALfACAAAAlwCkYHwEC8B","468":"b:ANMaAH4gALfACAAAAlwCkYHwEC8B","480":"b:ANMaAH4gALfACAAAAlwCkYHwEC8B","481":"b:ANMaAH4gALfACAAAAlwCkYHwEC8B","486":"b:ANMaAH4gALfACAAAAlwCkYHwEC8B","488":"b:ANMaAH4gALfACAAAAlwCkYHwEC8B","499":"b:ANMaAH4gALfACAAAAlwCkYHwEC8B","518":"b:ANMaAH4gALfACAAAAlwCkYHwEC8B","529":"b:ANMaAH4gALfACAAAAlwCkYHwEC8B","634":"b:ANMaAH4gALfACAAAAlwCkYHwEC8B","642":"b:ANMaAH4gALfACAAAAlwCkYHwEC8B","703":"b:ANMaAH4gALfACAAAAlwCkYHwEC8B","728":"b:ANMaAH4gALfACAAAAlwCkYHwEC8B","760":"b:ANMaAH4gALfACAAAAlwCkYHwEC8B","791":"b:ANMaAH4gALfACAAAAlwCkYHwEC8B","848":"b:ANMaAH4gALfACAAAAlwCkYHwEC8B"},"packages/cli/src/execution-lifecycle/restore-binary-data-id.ts":{"30":"b:ANMaAH4kAJXACAAAAFACEYDwEC8B","64":"b:ANMaAH4kAJXACAAAAFACEYDwEC8B","78":"b:ANMaAH4kAJXACAAAAFACEYDwEC8B"},"packages/cli/src/execution-lifecycle/shared/shared-hook-functions.ts":{"12":"b:ANMCAH4gAJXACAAAAFACEYDwECcA","28":"b:ANMCAH4gAJXACAAAAFACEYDwECcA","76":"b:ANMCAH4gAJXACAAAAFACEYDwECcA","92":"b:ANMCAH4gAJXACAAAAFACEYDwECcA"},"packages/cli/src/execution-lifecycle/to-save-settings.ts":{"20":"b:ANMCAH4gAJXACAAAAFACEYDwECcA"},"packages/cli/src/executions/execution-data/db-store.ts":{"19":"b:ANMCAH4gALXAKAAABnACEYDwECcA","21":"b:ANMCAH4gALXAKAAABnACEYDwECcA","26":"b:ANMCAH4gALXAKAAABnACEYDwECcA","41":"b:ANMCAH4gALXAKAAABnACEYDwECcA","45":"b:ANMCAH4gALXAKAAABnACEYDwECcA","68":"b:ANMCAH4gALXAKAAABnACEYDwECcA","69":"b:ANMCAH4gALXAKAAABnACEYDwECcA","74":"b:ANMCAH4gALXAKAAABnACEYDwECcA"},"packages/cli/src/executions/execution-persistence.ts":{"57":"b:ANMaAH4gALfAKACABnwCEYDwEC8A","74":"b:ANMaAH4gALfAKACABnwCEYDwEC8A","83":"b:ANMaAH4gALfAKACABnwCEYDwEC8A","89":"b:ANMaAH4gALfAKACABnwCEYDwEC8A","113":"b:ANMaAH4gALfAKACABnwCEYDwEC8A","175":"b:ANMaAH4gALfAKACABnwCEYDwEC8A","257":"b:ANMaAH4gALfAKACABnwCEYDwEC8A","303":"b:ANMaAH4gALfAKACABnwCEYDwEC8A","304":"b:ANMaAH4gALfAKACABnwCEYDwEC8A","311":"b:ANMaAH4gALfAKACABnwCEYDwEC8A","316":"b:ANMaAH4gALfAKACABnwCEYDwEC8A","322":"b:ANMaAH4gALfAKACABnwCEYDwEC8A","353":"b:ANMaAH4gALfAKACABnwCEYDwEC8A","354":"b:ANMaAH4gALfAKACABnwCEYDwEC8A","361":"b:ANMaAH4gALfAKACABnwCEYDwEC8A","371":"b:ANMaAH4gALfAKACABnwCEYDwEC8A","381":"b:ANMaAH4gALfAKACABnwCEYDwEC8A","401":"b:ANMaAH4gALfAKACABnwCEYDwEC8A","411":"b:ANMaAH4gALfAKACABnwCEYDwEC8A","415":"b:ANMaAH4gALfAKACABnwCEYDwEC8A","418":"b:ANMaAH4gALfAKACABnwCEYDwEC8A","419":"b:ANMaAH4gALfAKACABnwCEYDwEC8A","424":"b:ANMaAH4gALfAKACABnwCEYDwEC8A","427":"b:ANMaAH4gALfAKACABnwCEYDwEC8A","431":"b:ANMaAH4gALfAKACABnwCEYDwEC8A","444":"b:ANMaAH4gALfAKACABnwCEYDwEC8A","454":"b:ANMaAH4gALfAKACABnwCEYDwEC8A","475":"b:ANMaAH4gALfAKACABnwCEYDwEC8A","486":"b:ANMaAH4gALfAKACABnwCEYDwEC8A","491":"b:ANMaAH4gALfAKACABnwCEYDwEC8A","522":"b:ANMaAH4gALfAKACABnwCEYDwEC8A","539":"b:ANMaAH4gALfAKACABnwCEYDwEC8A","557":"b:ANMaAH4gALfAKACABnwCEYDwEC8A","579":"b:ANMaAH4gALfAKACABnwCEYDwEC8A","597":"b:ANMaAH4gALfAKACABnwCEYDwEC8A","608":"b:ANMaAH4gALfAKACABnwCEYDwEC8A","615":"b:ANMaAH4gALfAKACABnwCEYDwEC8A","636":"b:ANMaAH4gALfAKACABnwCEYDwEC8A","643":"b:ANMaAH4gALfAKACABnwCEYDwEC8A","659":"b:ANMaAH4gALfAKACABnwCEYDwEC8A","665":"b:ANMaAH4gALfAKACABnwCEYDwEC8A","675":"b:ANMaAH4gALfAKACABnwCEYDwEC8A"},"packages/cli/src/executions/execution.service.ts":{"111":"b:RNMKAA4gAL3iCAAAHt4CkcnUEA0A","136":"b:RNMKAA4gAL3iCAAAHt4CkcnUEA0A","151":"b:RNMKAA4gAL3iCAAAHt4CkcnUEA0A","193":"b:RNMKAA4gAL3iCAAAHt4CkcnUEA0A","224":"b:RNMKAA4gAL3iCAAAHt4CkcnUEA0A","382":"b:RNMKAA4gAL3iCAAAHt4CkcnUEA0A","387":"b:RNMKAA4gAL3iCAAAHt4CkcnUEA0A","421":"b:RNMKAA4gAL3iCAAAHt4CkcnUEA0A","458":"b:RNMKAA4gAL3iCAAAHt4CkcnUEA0A","478":"b:RNMKAA4gAL3iCAAAHt4CkcnUEA0A","481":"b:RNMKAA4gAL3iCAAAHt4CkcnUEA0A","517":"b:RNMKAA4gAL3iCAAAHt4CkcnUEA0A","525":"b:RNMKAA4gAL3iCAAAHt4CkcnUEA0A","542":"b:RNMKAA4gAL3iCAAAHt4CkcnUEA0A","559":"b:RNMKAA4gAL3iCAAAHt4CkcnUEA0A","570":"b:RNMKAA4gAL3iCAAAHt4CkcnUEA0A","603":"b:RNMKAA4gAL3iCAAAHt4CkcnUEA0A","624":"b:RNMKAA4gAL3iCAAAHt4CkcnUEA0A","634":"b:RNMKAA4gAL3iCAAAHt4CkcnUEA0A","654":"b:RNMKAA4gAL3iCAAAHt4CkcnUEA0A","669":"b:RNMKAA4gAL3iCAAAHt4CkcnUEA0A","687":"b:RNMKAA4gAL3iCAAAHt4CkcnUEA0A","688":"b:RNMKAA4gAL3iCAAAHt4CkcnUEA0A","699":"b:RNMKAA4gAL3iCAAAHt4CkcnUEA0A","737":"b:RNMKAA4gAL3iCAAAHt4CkcnUEA0A","749":"b:RNMKAA4gAL3iCAAAHt4CkcnUEA0A"},"packages/cli/src/executions/executions.controller.ts":{"19":"b:BNMKAA4gALXACAAABFwCEcDQEA0A","26":"b:BNMKAA4gALXACAAABFwCEcDQEA0A","38":"b:BNMKAA4gALXACAAABFwCEcDQEA0A","82":"b:BNMKAA4gALXACAAABFwCEcDQEA0A","93":"b:BNMKAA4gALXACAAABFwCEcDQEA0A","108":"b:BNMKAA4gALXACAAABFwCEcDQEA0A","124":"b:BNMKAA4gALXACAAABFwCEcDQEA0A","135":"b:BNMKAA4gALXACAAABFwCEcDQEA0A","144":"b:BNMKAA4gALXACAAABFwCEcDQEA0A","153":"b:BNMKAA4gALXACAAABFwCEcDQEA0A"},"packages/cli/src/executions/parse-range-query.middleware.ts":{"15":"b:BIAIAAAAAJAAAAAABFwAAIDQEA0A","20":"b:BIAIAAAAAJAAAAAABFwAAIDQEA0A"},"packages/cli/src/executions/pre-execution-checks/credentials-permission-checker.ts":{"15":"b:BNMCAH4gAJXACAAAAFACEYDwECcA","26":"b:BNMCAH4gAJXACAAAAFACEYDwECcA","36":"b:BNMCAH4gAJXACAAAAFACEYDwECcA","47":"b:BNMCAH4gAJXACAAAAFACEYDwECcA","86":"b:BNMCAH4gAJXACAAAAFACEYDwECcA","100":"b:BNMCAH4gAJXACAAAAFACEYDwECcA","101":"b:BNMCAH4gAJXACAAAAFACEYDwECcA","124":"b:BNMCAH4gAJXACAAAAFACEYDwECcA"},"packages/cli/src/metrics/prometheus/workflow-execution-duration-metrics.service.ts":{"19":"b:ANMCAH4gAJXACAAAAFACEYDwECcA","24":"b:ANMCAH4gAJXACAAAAFACEYDwECcA","28":"b:ANMCAH4gAJXACAAAAFACEYDwECcA","41":"b:ANMCAH4gAJXACAAAAFACEYDwECcA"},"packages/cli/src/modules/chat-hub/chat-hub-execution-store.service.ts":{"58":"b:ANMCAH4gAJXACAAAAFACEYDwECcA","79":"b:ANMCAH4gAJXACAAAAFACEYDwECcA","93":"b:ANMCAH4gAJXACAAAAFACEYDwECcA","103":"b:ANMCAH4gAJXACAAAAFACEYDwECcA","127":"b:ANMCAH4gAJXACAAAAFACEYDwECcA","140":"b:ANMCAH4gAJXACAAAAFACEYDwECcA","154":"b:ANMCAH4gAJXACAAAAFACEYDwECcA","158":"b:ANMCAH4gAJXACAAAAFACEYDwECcA","171":"b:ANMCAH4gAJXACAAAAFACEYDwECcA","189":"b:ANMCAH4gAJXACAAAAFACEYDwECcA","199":"b:ANMCAH4gAJXACAAAAFACEYDwECcA","202":"b:ANMCAH4gAJXACAAAAFACEYDwECcA","211":"b:ANMCAH4gAJXACAAAAFACEYDwECcA"},"packages/cli/src/modules/chat-hub/chat-hub-execution-watcher.service.ts":{"32":"b:ANMaAH4gAJfACAAAAFACEYDwEC8A","54":"b:ANMaAH4gAJfACAAAAFACEYDwEC8A","117":"b:ANMaAH4gAJfACAAAAFACEYDwEC8A","160":"b:ANMaAH4gAJfACAAAAFACEYDwEC8A","203":"b:ANMaAH4gAJfACAAAAFACEYDwEC8A","235":"b:ANMaAH4gAJfACAAAAFACEYDwEC8A","257":"b:ANMaAH4gAJfACAAAAFACEYDwEC8A","280":"b:ANMaAH4gAJfACAAAAFACEYDwEC8A"},"packages/cli/src/modules/insights/database/entities/insights-raw.ts":{"13":[29,50,59,61,148,135],"27":[29,50,59,61,148,135],"38":[29,50,59,61,148,135]},"packages/cli/src/modules/insights/insights-collection.service.ts":{"65":"b:AtsyoP80FL3wDHAEAFACEYj0kD8B","95":"b:AtsyoP80FL3wDHAEAFACEYj0kD8B","105":"b:AtsyoP80FL3wDHAEAFACEYj0kD8B","113":"b:AtsyoP80FL3wDHAEAFACEYj0kD8B","119":"b:AtsyoP80FL3wDHAEAFACEYj0kD8B","124":"b:AtsyoP80FL3wDHAEAFACEYj0kD8B","131":"b:AtsyoP80FL3wDHAEAFACEYj0kD8B","136":"b:AtsyoP80FL3wDHAEAFACEYj0kD8B","152":"b:AtsyoP80FL3wDHAEAFACEYj0kD8B","217":"b:AtsyoP80FL3wDHAEAFACEYj0kD8B","232":"b:AtsyoP80FL3wDHAEAFACEYj0kD8B","255":"b:AtsyoP80FL3wDHAEAFACEYj0kD8B","283":"b:AtsyoP80FL3wDHAEAFACEYj0kD8B","305":"b:AtsyoP80FL3wDHAEAFACEYj0kD8B","328":"b:AtsyoP80FL3wDHAEAFACEYj0kD8B","345":"b:AtsyoP80FL3wDHAEAFACEYj0kD8B"},"packages/cli/src/modules/log-streaming.ee/destinations/message-event-bus-destination-syslog.ee.ts":{"19":[148],"47":[148],"79":[148],"84":[148],"101":[148],"116":[148],"121":[148],"135":[148],"149":[148],"153":[148]},"packages/cli/src/modules/log-streaming.ee/destinations/message-event-bus-destination.ee.ts":{"45":[148,88],"78":[148,88],"82":[148,88],"92":[148,88],"110":[148,88],"118":[148,88],"123":[148,88],"127":[148,88]},"packages/cli/src/modules/log-streaming.ee/log-streaming-destination.service.ts":{"37":[148,88],"49":[148,88],"69":[148,88],"84":[148,88],"91":[148,88],"116":[148,88],"136":[148,88],"155":[148,88],"182":[148,88],"187":[148,88],"188":[148,88],"195":[148,88],"203":[148,88],"214":[148,88],"215":[148,88],"223":[148,88],"232":[148,88],"257":[148,88]},"packages/cli/src/modules/log-streaming.ee/log-streaming.controller.ts":{"31":[148,87,88],"37":[148,87,88],"46":[148,87,88],"53":[148,87,88],"64":[148,87,88],"114":[148,87,88],"125":[148,87,88]},"packages/cli/src/modules/redaction/instance-redaction-enforcement.service.ts":{"16":"b:ANMCAH4gAJXACAAAAFACEYDwECcA","29":"b:ANMCAH4gAJXACAAAAFACEYDwECcA","33":"b:ANMCAH4gAJXACAAAAFACEYDwECcA","35":"b:ANMCAH4gAJXACAAAAFACEYDwECcA","42":"b:ANMCAH4gAJXACAAAAFACEYDwECcA","60":"b:ANMCAH4gAJXACAAAAFACEYDwECcA","77":"b:ANMCAH4gAJXACAAAAFACEYDwECcA","81":"b:ANMCAH4gAJXACAAAAFACEYDwECcA","90":"b:ANMCAH4gAJXACAAAAFACEYDwECcA"},"packages/cli/src/modules/redaction/redaction-context-hook.ts":{"16":"b:ANMCAH4gAJXACAAAAFACEYDwECcA","24":"b:ANMCAH4gAJXACAAAAFACEYDwECcA","36":"b:ANMCAH4gAJXACAAAAFACEYDwECcA"},"packages/cli/src/services/role-cache.service.ts":{"37":"b:QoCITWIgAJAyABQEAFIAAJgQUiEA","45":"b:QoCITWIgAJAyABQEAFIAAJgQUiEA","54":"b:QoCITWIgAJAyABQEAFIAAJgQUiEA","68":"b:QoCITWIgAJAyABQEAFIAAJgQUiEA","77":"b:QoCITWIgAJAyABQEAFIAAJgQUiEA","93":"b:QoCITWIgAJAyABQEAFIAAJgQUiEA","105":"b:QoCITWIgAJAyABQEAFIAAJgQUiEA","112":"b:QoCITWIgAJAyABQEAFIAAJgQUiEA"},"packages/cli/src/services/workflow-statistics.service.ts":{"76":"b:ANMaAH4gAJfACAAAAFACEYDwEK8B","90":"b:ANMaAH4gAJfACAAAAFACEYDwEK8B","94":"b:ANMaAH4gAJfACAAAAFACEYDwEK8B","99":"b:ANMaAH4gAJfACAAAAFACEYDwEK8B","208":"b:ANMaAH4gAJfACAAAAFACEYDwEK8B","231":"b:ANMaAH4gAJfACAAAAFACEYDwEK8B"},"packages/cli/src/task-runners/task-broker/task-broker-ws-server.ts":{"21":"b:Ap8moL84EKgwBHAEhlgAAIgUkIIA","37":"b:Ap8moL84EKgwBHAEhlgAAIgUkIIA","46":"b:Ap8moL84EKgwBHAEhlgAAIgUkIIA","50":"b:Ap8moL84EKgwBHAEhlgAAIgUkIIA","57":"b:Ap8moL84EKgwBHAEhlgAAIgUkIIA","74":"b:Ap8moL84EKgwBHAEhlgAAIgUkIIA","83":"b:Ap8moL84EKgwBHAEhlgAAIgUkIIA","87":"b:Ap8moL84EKgwBHAEhlgAAIgUkIIA","91":"b:Ap8moL84EKgwBHAEhlgAAIgUkIIA","95":"b:Ap8moL84EKgwBHAEhlgAAIgUkIIA","101":"b:Ap8moL84EKgwBHAEhlgAAIgUkIIA","146":"b:Ap8moL84EKgwBHAEhlgAAIgUkIIA","158":"b:Ap8moL84EKgwBHAEhlgAAIgUkIIA","177":"b:Ap8moL84EKgwBHAEhlgAAIgUkIIA","181":"b:Ap8moL84EKgwBHAEhlgAAIgUkIIA","186":"b:Ap8moL84EKgwBHAEhlgAAIgUkIIA","192":"b:Ap8moL84EKgwBHAEhlgAAIgUkIIA"},"packages/cli/src/utils/circuit-breaker.ts":{"15":[148,88],"147":[148,88],"172":[148,88],"176":[148,88],"180":[148,88],"184":[148,88],"191":[148,88],"197":[148,88],"206":[148,88],"234":[148,88],"269":[148,88],"270":[148,88]},"packages/cli/src/utils/sliding-window.ts":{"31":[148,88],"42":[148,88],"57":[148,88],"60":[148,88],"67":[148,88]},"packages/cli/src/webhooks/live-webhooks.ts":{"36":"b:AAAYAAAAAIAAAAAAAAAAAIDgEI4B","46":"b:AAAYAAAAAIAAAAAAAAAAAIDgEI4B","50":"b:AAAYAAAAAIAAAAAAAAAAAIDgEI4B","58":"b:AAAYAAAAAIAAAAAAAAAAAIDgEI4B","63":"b:AAAYAAAAAIAAAAAAAAAAAIDgEI4B","78":"b:AAAYAAAAAIAAAAAAAAAAAIDgEI4B","97":"b:AAAYAAAAAIAAAAAAAAAAAIDgEI4B","126":"b:AAAYAAAAAIAAAAAAAAAAAIDgEI4B","136":"b:AAAYAAAAAIAAAAAAAAAAAIDgEI4B","160":"b:AAAYAAAAAIAAAAAAAAAAAIDgEI4B","173":"b:AAAYAAAAAIAAAAAAAAAAAIDgEI4B","188":"b:AAAYAAAAAIAAAAAAAAAAAIDgEI4B","200":"b:AAAYAAAAAIAAAAAAAAAAAIDgEI4B","214":"b:AAAYAAAAAIAAAAAAAAAAAIDgEI4B","230":"b:AAAYAAAAAIAAAAAAAAAAAIDgEI4B"},"packages/cli/src/webhooks/node-type-matcher.ts":{"5":"b:AMAaAAIAAIAAAAAAAEAABIDgEI4B"},"packages/cli/src/webhooks/webhook-execution-context.ts":{"17":"b:AMAaAAIAAIIAAAAAAEAABIDgEI4B","28":"b:AMAaAAIAAIIAAAAAAEAABIDgEI4B","46":"b:AMAaAAIAAIIAAAAAAEAABIDgEI4B"},"packages/cli/src/webhooks/webhook-helpers.ts":{"89":"b:ANMaAA4kAJfACACAAFACFIDwEK8B","106":"b:ANMaAA4kAJfACACAAFACFIDwEK8B","118":"b:ANMaAA4kAJfACACAAFACFIDwEK8B","127":"b:ANMaAA4kAJfACACAAFACFIDwEK8B","137":"b:ANMaAA4kAJfACACAAFACFIDwEK8B","177":"b:ANMaAA4kAJfACACAAFACFIDwEK8B","195":"b:ANMaAA4kAJfACACAAFACFIDwEK8B","266":"b:ANMaAA4kAJfACACAAFACFIDwEK8B","302":"b:ANMaAA4kAJfACACAAFACFIDwEK8B","311":"b:ANMaAA4kAJfACACAAFACFIDwEK8B","340":"b:ANMaAA4kAJfACACAAFACFIDwEK8B","342":"b:ANMaAA4kAJfACACAAFACFIDwEK8B","352":"b:ANMaAA4kAJfACACAAFACFIDwEK8B","420":"b:ANMaAA4kAJfACACAAFACFIDwEK8B","506":"b:ANMaAA4kAJfACACAAFACFIDwEK8B","715":"b:ANMaAA4kAJfACACAAFACFIDwEK8B","817":"b:ANMaAA4kAJfACACAAFACFIDwEK8B","847":"b:ANMaAA4kAJfACACAAFACFIDwEK8B","931":"b:ANMaAA4kAJfACACAAFACFIDwEK8B","966":"b:ANMaAA4kAJfACACAAFACFIDwEK8B","1050":"b:ANMaAA4kAJfACACAAFACFIDwEK8B","1101":"b:ANMaAA4kAJfACACAAFACFIDwEK8B","1126":"b:ANMaAA4kAJfACACAAFACFIDwEK8B"},"packages/cli/src/webhooks/webhook-on-received-response-extractor.ts":{"13":"b:AAAYAAIAAIIAAAAAAEAAAIDgEA4A"},"packages/cli/src/webhooks/webhook-request-handler.ts":{"32":"b:AMAaAAIAAIIBAACAAEAABIDgEI4B","41":"b:AMAaAAIAAIIBAACAAEAABIDgEI4B","94":"b:AMAaAAIAAIIBAACAAEAABIDgEI4B","110":"b:AMAaAAIAAIIBAACAAEAABIDgEI4B","119":"b:AMAaAAIAAIIBAACAAEAABIDgEI4B","122":"b:AMAaAAIAAIIBAACAAEAABIDgEI4B","135":"b:AMAaAAIAAIIBAACAAEAABIDgEI4B","141":"b:AMAaAAIAAIIBAACAAEAABIDgEI4B","150":"b:AMAaAAIAAIIBAACAAEAABIDgEI4B","180":"b:AMAaAAIAAIIBAACAAEAABIDgEI4B","234":"b:AMAaAAIAAIIBAACAAEAABIDgEI4B","240":"b:AMAaAAIAAIIBAACAAEAABIDgEI4B"},"packages/cli/src/webhooks/webhook-request-sanitizer.ts":{"12":"b:AAAYAAIAAIABAAAAAEAABIDgEI4B","18":"b:AAAYAAIAAIABAAAAAEAABIDgEI4B","19":"b:AAAYAAIAAIABAAAAAEAABIDgEI4B","32":"b:AAAYAAIAAIABAAAAAEAABIDgEI4B","40":"b:AAAYAAIAAIABAAAAAEAABIDgEI4B"},"packages/cli/src/webhooks/webhook-response-headers.ts":{"22":"b:AMAaAAIAAIABAAAAAEAABIDgEI4B","26":"b:AMAaAAIAAIABAAAAAEAABIDgEI4B","33":"b:AMAaAAIAAIABAAAAAEAABIDgEI4B","50":"b:AMAaAAIAAIABAAAAAEAABIDgEI4B","57":"b:AMAaAAIAAIABAAAAAEAABIDgEI4B","66":"b:AMAaAAIAAIABAAAAAEAABIDgEI4B","74":"b:AMAaAAIAAIABAAAAAEAABIDgEI4B"},"packages/cli/src/webhooks/webhook-response.ts":{"37":"b:AMAaAAIAAIABAAAAAEAABIDgEI4B","41":"b:AMAaAAIAAIABAAAAAEAABIDgEI4B","45":"b:AMAaAAIAAIABAAAAAEAABIDgEI4B","49":"b:AMAaAAIAAIABAAAAAEAABIDgEI4B","53":"b:AMAaAAIAAIABAAAAAEAABIDgEI4B","59":"b:AMAaAAIAAIABAAAAAEAABIDgEI4B","72":"b:AMAaAAIAAIABAAAAAEAABIDgEI4B"},"packages/cli/src/webhooks/webhook.service.ts":{"33":"b:ANMaAA4kAJXACAAAAFACFLLyEK8B","40":"b:ANMaAA4kAJXACAAAAFACFLLyEK8B","45":"b:ANMaAA4kAJXACAAAAFACFLLyEK8B","48":"b:ANMaAA4kAJXACAAAAFACFLLyEK8B","52":"b:ANMaAA4kAJXACAAAAFACFLLyEK8B","70":"b:ANMaAA4kAJXACAAAAFACFLLyEK8B","84":"b:ANMaAA4kAJXACAAAAFACFLLyEK8B","92":"b:ANMaAA4kAJXACAAAAFACFLLyEK8B","109":"b:ANMaAA4kAJXACAAAAFACFLLyEK8B","110":"b:ANMaAA4kAJXACAAAAFACFLLyEK8B","128":"b:ANMaAA4kAJXACAAAAFACFLLyEK8B","132":"b:ANMaAA4kAJXACAAAAFACFLLyEK8B","169":"b:ANMaAA4kAJXACAAAAFACFLLyEK8B","173":"b:ANMaAA4kAJXACAAAAFACFLLyEK8B","180":"b:ANMaAA4kAJXACAAAAFACFLLyEK8B","184":"b:ANMaAA4kAJXACAAAAFACFLLyEK8B","189":"b:ANMaAA4kAJXACAAAAFACFLLyEK8B","190":"b:ANMaAA4kAJXACAAAAFACFLLyEK8B","195":"b:ANMaAA4kAJXACAAAAFACFLLyEK8B","199":"b:ANMaAA4kAJXACAAAAFACFLLyEK8B","210":"b:ANMaAA4kAJXACAAAAFACFLLyEK8B","221":"b:ANMaAA4kAJXACAAAAFACFLLyEK8B","223":"b:ANMaAA4kAJXACAAAAFACFLLyEK8B","230":"b:ANMaAA4kAJXACAAAAFACFLLyEK8B","327":"b:ANMaAA4kAJXACAAAAFACFLLyEK8B","344":"b:ANMaAA4kAJXACAAAAFACFLLyEK8B","358":"b:ANMaAA4kAJXACAAAAFACFLLyEK8B","407":"b:ANMaAA4kAJXACAAAAFACFLLyEK8B","409":"b:ANMaAA4kAJXACAAAAFACFLLyEK8B","413":"b:ANMaAA4kAJXACAAAAFACFLLyEK8B","418":"b:ANMaAA4kAJXACAAAAFACFLLyEK8B","437":"b:ANMaAA4kAJXACAAAAFACFLLyEK8B","446":"b:ANMaAA4kAJXACAAAAFACFLLyEK8B","478":"b:ANMaAA4kAJXACAAAAFACFLLyEK8B","509":"b:ANMaAA4kAJXACAAAAFACFLLyEK8B"},"packages/cli/src/workflow-execute-additional-data.ts":{"67":"b:ANcaAH5gALfgCAAAhlwCkYH0FKoB","112":"b:ANcaAH5gALfgCAAAhlwCkYH0FKoB","158":"b:ANcaAH5gALfgCAAAhlwCkYH0FKoB","176":"b:ANcaAH5gALfgCAAAhlwCkYH0FKoB","210":"b:ANcaAH5gALfgCAAAhlwCkYH0FKoB","243":"b:ANcaAH5gALfgCAAAhlwCkYH0FKoB","260":"b:ANcaAH5gALfgCAAAhlwCkYH0FKoB","316":"b:ANcaAH5gALfgCAAAhlwCkYH0FKoB","335":"b:ANcaAH5gALfgCAAAhlwCkYH0FKoB","354":"b:ANcaAH5gALfgCAAAhlwCkYH0FKoB","372":"b:ANcaAH5gALfgCAAAhlwCkYH0FKoB","373":"b:ANcaAH5gALfgCAAAhlwCkYH0FKoB","378":"b:ANcaAH5gALfgCAAAhlwCkYH0FKoB","392":"b:ANcaAH5gALfgCAAAhlwCkYH0FKoB","393":"b:ANcaAH5gALfgCAAAhlwCkYH0FKoB","407":"b:ANcaAH5gALfgCAAAhlwCkYH0FKoB","426":"b:ANcaAH5gALfgCAAAhlwCkYH0FKoB","595":"b:ANcaAH5gALfgCAAAhlwCkYH0FKoB","605":"b:ANcaAH5gALfgCAAAhlwCkYH0FKoB","634":"b:ANcaAH5gALfgCAAAhlwCkYH0FKoB","679":"b:ANcaAH5gALfgCAAAhlwCkYH0FKoB","685":"b:ANcaAH5gALfgCAAAhlwCkYH0FKoB","695":"b:ANcaAH5gALfgCAAAhlwCkYH0FKoB","732":"b:ANcaAH5gALfgCAAAhlwCkYH0FKoB","735":"b:ANcaAH5gALfgCAAAhlwCkYH0FKoB"},"packages/cli/src/workflow-hook-context.service.ts":{"9":"b:ANMCAH4gAJXACAAAAFACEYDwECcA","11":"b:ANMCAH4gAJXACAAAAFACEYDwECcA","17":"b:ANMCAH4gAJXACAAAAFACEYDwECcA"},"packages/cli/src/workflow-runner.ts":{"68":"b:ANMSAH4gAJfACAAAAFACEYDwECcB","78":"b:ANMSAH4gAJfACAAAAFACEYDwECcB","97":"b:ANMSAH4gAJfACAAAAFACEYDwECcB","165":"b:ANMSAH4gAJfACAAAAFACEYDwECcB","186":"b:ANMSAH4gAJfACAAAAFACEYDwECcB","264":"b:ANMSAH4gAJfACAAAAFACEYDwECcB","300":"b:ANMSAH4gAJfACAAAAFACEYDwECcB","319":"b:ANMSAH4gAJfACAAAAFACEYDwECcB","329":"b:ANMSAH4gAJfACAAAAFACEYDwECcB","393":"b:ANMSAH4gAJfACAAAAFACEYDwECcB","398":"b:ANMSAH4gAJfACAAAAFACEYDwECcB","453":"b:ANMSAH4gAJfACAAAAFACEYDwECcB","463":"b:ANMSAH4gAJfACAAAAFACEYDwECcB","473":"b:ANMSAH4gAJfACAAAAFACEYDwECcB","495":"b:ANMSAH4gAJfACAAAAFACEYDwECcB","521":"b:ANMSAH4gAJfACAAAAFACEYDwECcB","547":"b:ANMSAH4gAJfACAAAAFACEYDwECcB","549":"b:ANMSAH4gAJfACAAAAFACEYDwECcB","662":"b:ANMSAH4gAJfACAAAAFACEYDwECcB","682":"b:ANMSAH4gAJfACAAAAFACEYDwECcB"},"packages/cli/src/workflows/workflow-sharing.service.ts":{"22":"b:BNMKAA4gALXACAAABFwCEYDQEA0A","37":"b:BNMKAA4gALXACAAABFwCEYDQEA0A","45":"b:BNMKAA4gALXACAAABFwCEYDQEA0A","70":"b:BNMKAA4gALXACAAABFwCEYDQEA0A","73":"b:BNMKAA4gALXACAAABFwCEYDQEA0A","87":"b:BNMKAA4gALXACAAABFwCEYDQEA0A","90":"b:BNMKAA4gALXACAAABFwCEYDQEA0A","98":"b:BNMKAA4gALXACAAABFwCEYDQEA0A","101":"b:BNMKAA4gALXACAAABFwCEYDQEA0A","107":"b:BNMKAA4gALXACAAABFwCEYDQEA0A","114":"b:BNMKAA4gALXACAAABFwCEYDQEA0A","127":"b:BNMKAA4gALXACAAABFwCEYDQEA0A"},"packages/cli/src/workflows/workflow-static-data.service.ts":{"11":"b:AMAaAAIEAJAAAAAgAEAABLLiEC8B","18":"b:AMAaAAIEAJAAAAAgAEAABLLiEC8B","27":"b:AMAaAAIEAJAAAAAgAEAABLLiEC8B","48":"b:AMAaAAIEAJAAAAAgAEAABLLiEC8B","54":"b:AMAaAAIEAJAAAAAgAEAABLLiEC8B"},"packages/core/src/execution-engine/execution-context-hook-registry.service.ts":{"17":"b:ANMCAH4gAJXACAAAAFACEYDwECcA","33":"b:ANMCAH4gAJXACAAAAFACEYDwECcA","83":"b:ANMCAH4gAJXACAAAAFACEYDwECcA","92":"b:ANMCAH4gAJXACAAAAFACEYDwECcA","105":"b:ANMCAH4gAJXACAAAAFACEYDwECcA","106":"b:ANMCAH4gAJXACAAAAFACEYDwECcA","111":"b:ANMCAH4gAJXACAAAAFACEYDwECcA"},"packages/core/src/execution-engine/execution-context.service.ts":{"22":"b:ANMCAH4gALXACAAAAlwCEYDwECcA","28":"b:ANMCAH4gALXACAAAAlwCEYDwECcA","48":"b:ANMCAH4gALXACAAAAlwCEYDwECcA","57":"b:ANMCAH4gALXACAAAAlwCEYDwECcA","69":"b:ANMCAH4gALXACAAAAlwCEYDwECcA","77":"b:ANMCAH4gALXACAAAAlwCEYDwECcA"},"packages/core/src/execution-engine/execution-context.ts":{"104":"b:ANMCAH4gAJXACAAAAFACEYDwECcA"},"packages/core/src/execution-engine/execution-lifecycle-hooks.ts":{"103":"b:ANMCAH4gAJXACAAAAFACEYDwECcA","110":"b:ANMCAH4gAJXACAAAAFACEYDwECcA","118":"b:ANMCAH4gAJXACAAAAFACEYDwECcA"},"packages/core/src/execution-engine/node-execution-context/base-execute-context.ts":{"41":"b:ANcaAH4mALfACAAAhlwCkYHQEK8B","56":"b:ANcaAH4mALfACAAAhlwCkYHQEK8B","60":"b:ANcaAH4mALfACAAAhlwCkYHQEK8B","64":"b:ANcaAH4mALfACAAAhlwCkYHQEK8B","65":"b:ANcaAH4mALfACAAAhlwCkYHQEK8B","72":"b:ANcaAH4mALfACAAAhlwCkYHQEK8B","76":"b:ANcaAH4mALfACAAAhlwCkYHQEK8B","83":"b:ANcaAH4mALfACAAAhlwCkYHQEK8B","88":"b:ANcaAH4mALfACAAAhlwCkYHQEK8B","98":"b:ANcaAH4mALfACAAAhlwCkYHQEK8B","110":"b:ANcaAH4mALfACAAAhlwCkYHQEK8B","117":"b:ANcaAH4mALfACAAAhlwCkYHQEK8B","160":"b:ANcaAH4mALfACAAAhlwCkYHQEK8B","183":"b:ANcaAH4mALfACAAAhlwCkYHQEK8B","187":"b:ANcaAH4mALfACAAAhlwCkYHQEK8B","205":"b:ANcaAH4mALfACAAAhlwCkYHQEK8B","213":"b:ANcaAH4mALfACAAAhlwCkYHQEK8B","229":"b:ANcaAH4mALfACAAAhlwCkYHQEK8B","235":"b:ANcaAH4mALfACAAAhlwCkYHQEK8B","260":"b:ANcaAH4mALfACAAAhlwCkYHQEK8B","271":"b:ANcaAH4mALfACAAAhlwCkYHQEK8B","296":"b:ANcaAH4mALfACAAAhlwCkYHQEK8B"},"packages/core/src/execution-engine/node-execution-context/execute-context.ts":{"58":"b:ANMSAH4gALfBCAAAAFACEYDQECcB","105":"b:ANMSAH4gALfBCAAAAFACEYDQECcB","107":"b:ANMSAH4gALfBCAAAAFACEYDQECcB","115":"b:ANMSAH4gALfBCAAAAFACEYDQECcB","119":"b:ANMSAH4gALfBCAAAAFACEYDQECcB","129":"b:ANMSAH4gALfBCAAAAFACEYDQECcB","144":"b:ANMSAH4gALfBCAAAAFACEYDQECcB","148":"b:ANMSAH4gALfBCAAAAFACEYDQECcB","163":"b:ANMSAH4gALfBCAAAAFACEYDQECcB","188":"b:ANMSAH4gALfBCAAAAFACEYDQECcB","209":"b:ANMSAH4gALfBCAAAAFACEYDQECcB","217":"b:ANMSAH4gALfBCAAAAFACEYDQECcB","219":"b:ANMSAH4gALfBCAAAAFACEYDQECcB","231":"b:ANMSAH4gALfBCAAAAFACEYDQECcB","236":"b:ANMSAH4gALfBCAAAAFACEYDQECcB","241":"b:ANMSAH4gALfBCAAAAFACEYDQECcB","245":"b:ANMSAH4gALfBCAAAAFACEYDQECcB","249":"b:ANMSAH4gALfBCAAAAFACEYDQECcB","254":"b:ANMSAH4gALfBCAAAAFACEYDQECcB"},"packages/core/src/execution-engine/node-execution-context/index.ts":{"2":"b:ANMaIH5iAJfgCAAAAlgiHYP8FK8B","3":"b:ANMaIH5iAJfgCAAAAlgiHYP8FK8B","9":"b:ANMaIH5iAJfgCAAAAlgiHYP8FK8B","10":"b:ANMaIH5iAJfgCAAAAlgiHYP8FK8B","15":"b:ANMaIH5iAJfgCAAAAlgiHYP8FK8B","17":"b:ANMaIH5iAJfgCAAAAlgiHYP8FK8B","18":"b:ANMaIH5iAJfgCAAAAlgiHYP8FK8B"},"packages/core/src/execution-engine/node-execution-context/node-execution-context.ts":{"52":"b:ANMaIH4kAPfgCACAAtgCnZP4EK8B","64":"b:ANMaIH4kAPfgCACAAtgCnZP4EK8B","69":"b:ANMaIH4kAPfgCACAAtgCnZP4EK8B","81":"b:ANMaIH4kAPfgCACAAtgCnZP4EK8B","85":"b:ANMaIH4kAPfgCACAAtgCnZP4EK8B","89":"b:ANMaIH4kAPfgCACAAtgCnZP4EK8B","93":"b:ANMaIH4kAPfgCACAAtgCnZP4EK8B","98":"b:ANMaIH4kAPfgCACAAtgCnZP4EK8B","102":"b:ANMaIH4kAPfgCACAAtgCnZP4EK8B","106":"b:ANMaIH4kAPfgCACAAtgCnZP4EK8B","128":"b:ANMaIH4kAPfgCACAAtgCnZP4EK8B","166":"b:ANMaIH4kAPfgCACAAtgCnZP4EK8B","177":"b:ANMaIH4kAPfgCACAAtgCnZP4EK8B","181":"b:ANMaIH4kAPfgCACAAtgCnZP4EK8B","186":"b:ANMaIH4kAPfgCACAAtgCnZP4EK8B","197":"b:ANMaIH4kAPfgCACAAtgCnZP4EK8B","207":"b:ANMaIH4kAPfgCACAAtgCnZP4EK8B","212":"b:ANMaIH4kAPfgCACAAtgCnZP4EK8B","214":"b:ANMaIH4kAPfgCACAAtgCnZP4EK8B","218":"b:ANMaIH4kAPfgCACAAtgCnZP4EK8B","223":"b:ANMaIH4kAPfgCACAAtgCnZP4EK8B","225":"b:ANMaIH4kAPfgCACAAtgCnZP4EK8B","229":"b:ANMaIH4kAPfgCACAAtgCnZP4EK8B","232":"b:ANMaIH4kAPfgCACAAtgCnZP4EK8B","233":"b:ANMaIH4kAPfgCACAAtgCnZP4EK8B","234":"b:ANMaIH4kAPfgCACAAtgCnZP4EK8B","237":"b:ANMaIH4kAPfgCACAAtgCnZP4EK8B","241":"b:ANMaIH4kAPfgCACAAtgCnZP4EK8B","245":"b:ANMaIH4kAPfgCACAAtgCnZP4EK8B","249":"b:ANMaIH4kAPfgCACAAtgCnZP4EK8B","253":"b:ANMaIH4kAPfgCACAAtgCnZP4EK8B","257":"b:ANMaIH4kAPfgCACAAtgCnZP4EK8B","265":"b:ANMaIH4kAPfgCACAAtgCnZP4EK8B","269":"b:ANMaIH4kAPfgCACAAtgCnZP4EK8B","294":"b:ANMaIH4kAPfgCACAAtgCnZP4EK8B","298":"b:ANMaIH4kAPfgCACAAtgCnZP4EK8B","307":"b:ANMaIH4kAPfgCACAAtgCnZP4EK8B","318":"b:ANMaIH4kAPfgCACAAtgCnZP4EK8B","370":"b:ANMaIH4kAPfgCACAAtgCnZP4EK8B","475":"b:ANMaIH4kAPfgCACAAtgCnZP4EK8B","480":"b:ANMaIH4kAPfgCACAAtgCnZP4EK8B","490":"b:ANMaIH4kAPfgCACAAtgCnZP4EK8B","585":"b:ANMaIH4kAPfgCACAAtgCnZP4EK8B","600":"b:ANMaIH4kAPfgCACAAtgCnZP4EK8B"},"packages/core/src/execution-engine/node-execution-context/utils/binary-helper-functions.ts":{"37":"b:ANMCAH4gALXBCAAAAFQCEYDwECcA","46":"b:ANMCAH4gALXBCAAAAFQCEYDwECcA","53":"b:ANMCAH4gALXBCAAAAFQCEYDwECcA","60":"b:ANMCAH4gALXBCAAAAFQCEYDwECcA","69":"b:ANMCAH4gALXBCAAAAFQCEYDwECcA","141":"b:ANMCAH4gALXBCAAAAFQCEYDwECcA","168":"b:ANMCAH4gALXBCAAAAFQCEYDwECcA","180":"b:ANMCAH4gALXBCAAAAFQCEYDwECcA","193":"b:ANMCAH4gALXBCAAAAFQCEYDwECcA","256":"b:ANMCAH4gALXBCAAAAFQCEYDwECcA","353":"b:ANMCAH4gALXBCAAAAFQCEYDwECcA","362":"b:ANMCAH4gALXBCAAAAFQCEYDwECcA","366":"b:ANMCAH4gALXBCAAAAFQCEYDwECcA","368":"b:ANMCAH4gALXBCAAAAFQCEYDwECcA","370":"b:ANMCAH4gALXBCAAAAFQCEYDwECcA"},"packages/core/src/execution-engine/node-execution-context/utils/cleanup-parameter-data.ts":{"8":"b:ANMSAH4gANXgCAAAANBCEZHwECcA","14":"b:ANMSAH4gANXgCAAAANBCEZHwECcA","19":"b:ANMSAH4gANXgCAAAANBCEZHwECcA"},"packages/core/src/execution-engine/node-execution-context/utils/credential-check-helper-functions.ts":{"3":"b:ANMCAH4gAJXACAAAAFACEYDQECcA","9":"b:ANMCAH4gAJXACAAAAFACEYDQECcA"},"packages/core/src/execution-engine/node-execution-context/utils/custom-data.ts":{"15":"b:ANMCAH4gALXACACAAFACEYDQECYA","23":"b:ANMCAH4gALXACACAAFACEYDQECYA","34":"b:ANMCAH4gALXACACAAFACEYDQECYA","45":"b:ANMCAH4gALXACACAAFACEYDQECYA","48":"b:ANMCAH4gALXACACAAFACEYDQECYA"},"packages/core/src/execution-engine/node-execution-context/utils/data-table-helper-functions.ts":{"8":"b:ANMCAH4gAJXACAAAAFACEYDQECcA","16":"b:ANMCAH4gAJXACAAAAFACEYDQECcA","22":"b:ANMCAH4gAJXACAAAAFACEYDQECcA"},"packages/core/src/execution-engine/node-execution-context/utils/deduplication-helper-functions.ts":{"16":"b:ANMCAH4gAJXACAAAAFACEYDQECcA","30":"b:ANMCAH4gAJXACAAAAFACEYDQECcA","46":"b:ANMCAH4gAJXACAAAAFACEYDQECcA","60":"b:ANMCAH4gAJXACAAAAFACEYDQECcA","72":"b:ANMCAH4gAJXACAAAAFACEYDQECcA","84":"b:ANMCAH4gAJXACAAAAFACEYDQECcA","88":"b:ANMCAH4gAJXACAAAAFACEYDQECcA","95":"b:ANMCAH4gAJXACAAAAFACEYDQECcA","109":"b:ANMCAH4gAJXACAAAAFACEYDQECcA","116":"b:ANMCAH4gAJXACAAAAFACEYDQECcA","122":"b:ANMCAH4gAJXACAAAAFACEYDQECcA"},"packages/core/src/execution-engine/node-execution-context/utils/file-system-helper-functions.ts":{"27":"b:ANMCAH4gALXACAAAAFACEYDQECcA","33":"b:ANMCAH4gALXACAAAAFACEYDQECcA","34":"b:ANMCAH4gALXACAAAAFACEYDQECcA","35":"b:ANMCAH4gALXACAAAAFACEYDQECcA","40":"b:ANMCAH4gALXACAAAAFACEYDQECcA","57":"b:ANMCAH4gALXACAAAAFACEYDQECcA","65":"b:ANMCAH4gALXACAAAAFACEYDQECcA","66":"b:ANMCAH4gALXACAAAAFACEYDQECcA","67":"b:ANMCAH4gALXACAAAAFACEYDQECcA","76":"b:ANMCAH4gALXACAAAAFACEYDQECcA","82":"b:ANMCAH4gALXACAAAAFACEYDQECcA","92":"b:ANMCAH4gALXACAAAAFACEYDQECcA","98":"b:ANMCAH4gALXACAAAAFACEYDQECcA","99":"b:ANMCAH4gALXACAAAAFACEYDQECcA","162":"b:ANMCAH4gALXACAAAAFACEYDQECcA","166":"b:ANMCAH4gALXACAAAAFACEYDQECcA","270":"b:ANMCAH4gALXACAAAAFACEYDQECcA","287":"b:ANMCAH4gALXACAAAAFACEYDQECcA"},"packages/core/src/execution-engine/node-execution-context/utils/get-additional-keys.ts":{"13":"b:ANMCAH5gALXgCAAAAFACEYD0FCYA","20":"b:ANMCAH5gALXgCAAAAFACEYD0FCYA","56":"b:ANMCAH5gALXgCAAAAFACEYD0FCYA"},"packages/core/src/execution-engine/node-execution-context/utils/get-secrets-proxy.ts":{"4":"b:ANMCAH5gAJXgCAAAAFACEYD0FCIA","6":"b:ANMCAH5gAJXgCAAAAFACEYD0FCIA","25":"b:ANMCAH5gAJXgCAAAAFACEYD0FCIA","30":"b:ANMCAH5gAJXgCAAAAFACEYD0FCIA","50":"b:ANMCAH5gAJXgCAAAAFACEYD0FCIA","66":"b:ANMCAH5gAJXgCAAAAFACEYD0FCIA","69":"b:ANMCAH5gAJXgCAAAAFACEYD0FCIA","75":"b:ANMCAH5gAJXgCAAAAFACEYD0FCIA","78":"b:ANMCAH5gAJXgCAAAAFACEYD0FCIA"},"packages/core/src/execution-engine/node-execution-context/utils/request-helpers/factory.ts":{"27":"b:ANMCIH4gAJXACAAAAFQiGYDwECcA","34":"b:ANMCIH4gAJXACAAAAFQiGYDwECcA","69":"b:ANMCIH4gAJXACAAAAFQiGYDwECcA","89":"b:ANMCIH4gAJXACAAAAFQiGYDwECcA","109":"b:ANMCIH4gAJXACAAAAFQiGYDwECcA","127":"b:ANMCIH4gAJXACAAAAFQiGYDwECcA","141":"b:ANMCIH4gAJXACAAAAFQiGYDwECcA","166":"b:ANMCIH4gAJXACAAAAFQiGYDwECcA","186":"b:ANMCIH4gAJXACAAAAFQiGYDwECcA","205":"b:ANMCIH4gAJXACAAAAFQiGYDwECcA"},"packages/core/src/execution-engine/node-execution-context/utils/resolve-source-overwrite.ts":{"7":"b:ANMCAH4gAJXACAAAAFACEYDwECcA"},"packages/core/src/execution-engine/node-execution-context/utils/ssh-tunnel-helper-functions.ts":{"7":"b:ANMCAH4gAJXACAAAAFACEYDQECcA","10":"b:ANMCAH4gAJXACAAAAFACEYDQECcA","12":"b:ANMCAH4gAJXACAAAAFACEYDQECcA"},"packages/core/src/execution-engine/node-execution-context/utils/validate-value-against-schema.ts":{"20":"b:ANMTAH4gAPfgCAAAANACEZPwEC8B","44":"b:ANMTAH4gAPfgCAAAANACEZPwEC8B","77":"b:ANMTAH4gAPfgCAAAANACEZPwEC8B","89":"b:ANMTAH4gAPfgCAAAANACEZPwEC8B","151":"b:ANMTAH4gAPfgCAAAANACEZPwEC8B","162":"b:ANMTAH4gAPfgCAAAANACEZPwEC8B"},"packages/core/src/execution-engine/node-execution-context/utils/webhook-helper-functions.ts":{"13":"b:AAAYAAIAAIABAAAAAEAABIDgEA4B","33":"b:AAAYAAIAAIABAAAAAEAABIDgEA4B"},"packages/core/src/execution-engine/node-execution-context/webhook-context.ts":{"33":"b:AMAaAAIAAIIBAACAAEAABIDgEI4B","71":"b:AMAaAAIAAIIBAACAAEAABIDgEI4B","82":"b:AMAaAAIAAIIBAACAAEAABIDgEI4B","86":"b:AMAaAAIAAIIBAACAAEAABIDgEI4B","90":"b:AMAaAAIAAIIBAACAAEAABIDgEI4B","94":"b:AMAaAAIAAIIBAACAAEAABIDgEI4B","98":"b:AMAaAAIAAIIBAACAAEAABIDgEI4B","102":"b:AMAaAAIAAIIBAACAAEAABIDgEI4B","106":"b:AMAaAAIAAIIBAACAAEAABIDgEI4B","113":"b:AMAaAAIAAIIBAACAAEAABIDgEI4B","121":"b:AMAaAAIAAIIBAACAAEAABIDgEI4B","132":"b:AMAaAAIAAIIBAACAAEAABIDgEI4B","136":"b:AMAaAAIAAIIBAACAAEAABIDgEI4B","143":"b:AMAaAAIAAIIBAACAAEAABIDgEI4B"},"packages/core/src/execution-engine/requests-response.ts":{"31":"b:ANMCAH4gAJXACAAAAFACEYDwECcA","55":"b:ANMCAH4gAJXACAAAAFACEYDwECcA","89":"b:ANMCAH4gAJXACAAAAFACEYDwECcA","187":"b:ANMCAH4gAJXACAAAAFACEYDwECcA","203":"b:ANMCAH4gAJXACAAAAFACEYDwECcA","238":"b:ANMCAH4gAJXACAAAAFACEYDwECcA","285":"b:ANMCAH4gAJXACAAAAFACEYDwECcA","291":"b:ANMCAH4gAJXACAAAAFACEYDwECcA"},"packages/core/src/execution-engine/workflow-execute.ts":{"111":"b:ANMaAH4gAL/ACAAAgtxSEYHwEC8A","129":"b:ANMaAH4gAL/ACAAAgtxSEYHwEC8A","196":"b:ANMaAH4gAL/ACAAAgtxSEYHwEC8A","204":"b:ANMaAH4gAL/ACAAAgtxSEYHwEC8A","294":"b:ANMaAH4gAL/ACAAAgtxSEYHwEC8A","326":"b:ANMaAH4gAL/ACAAAgtxSEYHwEC8A","367":"b:ANMaAH4gAL/ACAAAgtxSEYHwEC8A","395":"b:ANMaAH4gAL/ACAAAgtxSEYHwEC8A","414":"b:ANMaAH4gAL/ACAAAgtxSEYHwEC8A","617":"b:ANMaAH4gAL/ACAAAgtxSEYHwEC8A","834":"b:ANMaAH4gAL/ACAAAgtxSEYHwEC8A","901":"b:ANMaAH4gAL/ACAAAgtxSEYHwEC8A","919":"b:ANMaAH4gAL/ACAAAgtxSEYHwEC8A","930":"b:ANMaAH4gAL/ACAAAgtxSEYHwEC8A","974":"b:ANMaAH4gAL/ACAAAgtxSEYHwEC8A","998":"b:ANMaAH4gAL/ACAAAgtxSEYHwEC8A","1003":"b:ANMaAH4gAL/ACAAAgtxSEYHwEC8A","1012":"b:ANMaAH4gAL/ACAAAgtxSEYHwEC8A","1064":"b:ANMaAH4gAL/ACAAAgtxSEYHwEC8A","1071":"b:ANMaAH4gAL/ACAAAgtxSEYHwEC8A","1073":"b:ANMaAH4gAL/ACAAAgtxSEYHwEC8A","1098":"b:ANMaAH4gAL/ACAAAgtxSEYHwEC8A","1166":"b:ANMaAH4gAL/ACAAAgtxSEYHwEC8A","1186":"b:ANMaAH4gAL/ACAAAgtxSEYHwEC8A","1239":"b:ANMaAH4gAL/ACAAAgtxSEYHwEC8A","1274":"b:ANMaAH4gAL/ACAAAgtxSEYHwEC8A","1397":"b:ANMaAH4gAL/ACAAAgtxSEYHwEC8A","1417":"b:ANMaAH4gAL/ACAAAgtxSEYHwEC8A","1443":"b:ANMaAH4gAL/ACAAAgtxSEYHwEC8A","1469":"b:ANMaAH4gAL/ACAAAgtxSEYHwEC8A","1515":"b:ANMaAH4gAL/ACAAAgtxSEYHwEC8A","1531":"b:ANMaAH4gAL/ACAAAgtxSEYHwEC8A","1536":"b:ANMaAH4gAL/ACAAAgtxSEYHwEC8A","1545":"b:ANMaAH4gAL/ACAAAgtxSEYHwEC8A","1635":"b:ANMaAH4gAL/ACAAAgtxSEYHwEC8A","1640":"b:ANMaAH4gAL/ACAAAgtxSEYHwEC8A","1719":"b:ANMaAH4gAL/ACAAAgtxSEYHwEC8A","1720":"b:ANMaAH4gAL/ACAAAgtxSEYHwEC8A","1745":"b:ANMaAH4gAL/ACAAAgtxSEYHwEC8A","1746":"b:ANMaAH4gAL/ACAAAgtxSEYHwEC8A","1864":"b:ANMaAH4gAL/ACAAAgtxSEYHwEC8A","1868":"b:ANMaAH4gAL/ACAAAgtxSEYHwEC8A","1915":"b:ANMaAH4gAL/ACAAAgtxSEYHwEC8A","2211":"b:ANMaAH4gAL/ACAAAgtxSEYHwEC8A","2307":"b:ANMaAH4gAL/ACAAAgtxSEYHwEC8A","2324":"b:ANMaAH4gAL/ACAAAgtxSEYHwEC8A","2327":"b:ANMaAH4gAL/ACAAAgtxSEYHwEC8A","2354":"b:ANMaAH4gAL/ACAAAgtxSEYHwEC8A","2359":"b:ANMaAH4gAL/ACAAAgtxSEYHwEC8A","2396":"b:ANMaAH4gAL/ACAAAgtxSEYHwEC8A","2412":"b:ANMaAH4gAL/ACAAAgtxSEYHwEC8A","2430":"b:ANMaAH4gAL/ACAAAgtxSEYHwEC8A","2451":"b:ANMaAH4gAL/ACAAAgtxSEYHwEC8A","2470":"b:ANMaAH4gAL/ACAAAgtxSEYHwEC8A","2491":"b:ANMaAH4gAL/ACAAAgtxSEYHwEC8A","2547":"b:ANMaAH4gAL/ACAAAgtxSEYHwEC8A","2628":"b:ANMaAH4gAL/ACAAAgtxSEYHwEC8A","2639":"b:ANMaAH4gAL/ACAAAgtxSEYHwEC8A","2651":"b:ANMaAH4gAL/ACAAAgtxSEYHwEC8A","2757":"b:ANMaAH4gAL/ACAAAgtxSEYHwEC8A","2817":"b:ANMaAH4gAL/ACAAAgtxSEYHwEC8A","2818":"b:ANMaAH4gAL/ACAAAgtxSEYHwEC8A","2820":"b:ANMaAH4gAL/ACAAAgtxSEYHwEC8A","2828":"b:ANMaAH4gAL/ACAAAgtxSEYHwEC8A"},"packages/core/src/html-sandbox.ts":{"4":"b:AMAaAAIAAIIAAAAAAEAABIDwEA4B","8":"b:AMAaAAIAAIIAAAAAAEAABIDwEA4B","15":"b:AMAaAAIAAIIAAAAAAEAABIDwEA4B"},"packages/core/src/storage.config.ts":{"20":"b:ANMCAH4gAJXACAAAAFACEYDwECcA","32":"b:ANMCAH4gAJXACAAAAFACEYDwECcA","38":"b:ANMCAH4gAJXACAAAAFACEYDwECcA","66":"b:ANMCAH4gAJXACAAAAFACEYDwECcA","101":"b:ANMCAH4gAJXACAAAAFACEYDwECcA"},"packages/core/src/utils/assertions.ts":{"14":"b:ANMCAH4gAJXACAAAAFACEYDwECcA","31":"b:ANMCAH4gAJXACAAAAFACEYDwECcA"},"packages/core/src/utils/convert-binary-data.ts":{"13":"b:ANMCAH4gAJXACAAAAFACEYDwECcA"},"packages/core/src/utils/deep-merge.ts":{"4":"b:ANMCAH4gAJXACAAAAFACEYDwECcA","17":"b:ANMCAH4gAJXACAAAAFACEYDwECcA"},"packages/nodes-base/nodes/Set/Set.node.ts":{"8":"b:AMISAAIAAJAgCQIACMJCgYnAECAA"},"packages/nodes-base/nodes/Set/v1/SetV1.node.ts":{"139":"b:AMISAAIAAJAgCQIACMpig4nAECAA","146":"b:AMISAAIAAJAgCQIACMpig4nAECAA","182":"b:AMISAAIAAJAgCQIACMpig4nAECAA","193":"b:AMISAAIAAJAgCQIACMpig4nAECAA","211":"b:AMISAAIAAJAgCQIACMpig4nAECAA"},"packages/nodes-base/nodes/Set/v2/SetV2.node.ts":{"302":"b:AMISAAIAAJAgCQIACMJCgYnAECIA","309":"b:AMISAAIAAJAgCQIACMJCgYnAECIA"},"packages/nodes-base/nodes/Set/v2/helpers/utils.ts":{"28":"b:AMIaAAIAAJAgCQIACMJCgYnAECIA","31":"b:AMIaAAIAAJAgCQIACMJCgYnAECIA","34":"b:AMIaAAIAAJAgCQIACMJCgYnAECIA","37":"b:AMIaAAIAAJAgCQIACMJCgYnAECIA","43":"b:AMIaAAIAAJAgCQIACMJCgYnAECIA","46":"b:AMIaAAIAAJAgCQIACMJCgYnAECIA","49":"b:AMIaAAIAAJAgCQIACMJCgYnAECIA","56":"b:AMIaAAIAAJAgCQIACMJCgYnAECIA","89":"b:AMIaAAIAAJAgCQIACMJCgYnAECIA","90":"b:AMIaAAIAAJAgCQIACMJCgYnAECIA","104":"b:AMIaAAIAAJAgCQIACMJCgYnAECIA","105":"b:AMIaAAIAAJAgCQIACMJCgYnAECIA","130":"b:AMIaAAIAAJAgCQIACMJCgYnAECIA","161":"b:AMIaAAIAAJAgCQIACMJCgYnAECIA","214":"b:AMIaAAIAAJAgCQIACMJCgYnAECIA","228":"b:AMIaAAIAAJAgCQIACMJCgYnAECIA","230":"b:AMIaAAIAAJAgCQIACMJCgYnAECIA","237":"b:AMIaAAIAAJAgCQIACMJCgYnAECIA","257":"b:AMIaAAIAAJAgCQIACMJCgYnAECIA"},"packages/nodes-base/nodes/Set/v2/manual.mode.ts":{"189":"b:AMISAAIAAJAgCQIACMJCgYnAECIA"},"packages/nodes-base/nodes/Set/v2/raw.mode.ts":{"36":"b:AMISAAIAAJAgCQIACMJCgYnAECAA"},"packages/nodes-base/nodes/Webhook/Webhook.node.ts":{"204":"b:AAAYAAMAAIBBAAAAAMAABKDgEA4B","216":"b:AAAYAAMAAIBBAAAAAMAABKDgEA4B","320":"b:AAAYAAMAAIBBAAAAAMAABKDgEA4B","324":"b:AAAYAAMAAIBBAAAAAMAABKDgEA4B"},"packages/nodes-base/nodes/Webhook/description.ts":{"19":"b:AAAYAAMAAIBBAAAAAMAABKDgEAwB","56":"b:AAAYAAMAAIBBAAAAAMAABKDgEAwB"},"packages/nodes-base/nodes/Webhook/error.ts":{"4":"b:ACgYAAMQEINABQAAAMAAAKDkEIQB"},"packages/nodes-base/nodes/Webhook/utils.ts":{"37":"b:ACgYAAMQEINBBQAAAMAABKDkEI4B","54":"b:ACgYAAMQEINBBQAAAMAABKDkEI4B","68":"b:ACgYAAMQEINBBQAAAMAABKDkEI4B","79":"b:ACgYAAMQEINBBQAAAMAABKDkEI4B","89":"b:ACgYAAMQEINBBQAAAMAABKDkEI4B","106":"b:ACgYAAMQEINBBQAAAMAABKDkEI4B","117":"b:ACgYAAMQEINBBQAAAMAABKDkEI4B","119":"b:ACgYAAMQEINBBQAAAMAABKDkEI4B","130":"b:ACgYAAMQEINBBQAAAMAABKDkEI4B","140":"b:ACgYAAMQEINBBQAAAMAABKDkEI4B","155":"b:ACgYAAMQEINBBQAAAMAABKDkEI4B","166":"b:ACgYAAMQEINBBQAAAMAABKDkEI4B","204":"b:ACgYAAMQEINBBQAAAMAABKDkEI4B","209":"b:ACgYAAMQEINBBQAAAMAABKDkEI4B","235":"b:ACgYAAMQEINBBQAAAMAABKDkEI4B","358":"b:ACgYAAMQEINBBQAAAMAABKDkEI4B","423":"b:ACgYAAMQEINBBQAAAMAABKDkEI4B","441":"b:ACgYAAMQEINBBQAAAMAABKDkEI4B"},"packages/nodes-base/utils/utilities.ts":{"40":"b:AMISAHIAALFgCQIACMhCgYnAECgB","59":"b:AMISAHIAALFgCQIACMhCgYnAECgB","71":"b:AMISAHIAALFgCQIACMhCgYnAECgB","76":"b:AMISAHIAALFgCQIACMhCgYnAECgB","92":"b:AMISAHIAALFgCQIACMhCgYnAECgB","95":"b:AMISAHIAALFgCQIACMhCgYnAECgB","119":"b:AMISAHIAALFgCQIACMhCgYnAECgB","142":"b:AMISAHIAALFgCQIACMhCgYnAECgB","146":"b:AMISAHIAALFgCQIACMhCgYnAECgB","154":"b:AMISAHIAALFgCQIACMhCgYnAECgB","173":"b:AMISAHIAALFgCQIACMhCgYnAECgB","180":"b:AMISAHIAALFgCQIACMhCgYnAECgB","189":"b:AMISAHIAALFgCQIACMhCgYnAECgB","192":"b:AMISAHIAALFgCQIACMhCgYnAECgB","195":"b:AMISAHIAALFgCQIACMhCgYnAECgB","273":"b:AMISAHIAALFgCQIACMhCgYnAECgB","277":"b:AMISAHIAALFgCQIACMhCgYnAECgB","282":"b:AMISAHIAALFgCQIACMhCgYnAECgB","284":"b:AMISAHIAALFgCQIACMhCgYnAECgB","292":"b:AMISAHIAALFgCQIACMhCgYnAECgB","317":"b:AMISAHIAALFgCQIACMhCgYnAECgB","331":"b:AMISAHIAALFgCQIACMhCgYnAECgB","332":"b:AMISAHIAALFgCQIACMhCgYnAECgB","351":"b:AMISAHIAALFgCQIACMhCgYnAECgB","373":"b:AMISAHIAALFgCQIACMhCgYnAECgB","400":"b:AMISAHIAALFgCQIACMhCgYnAECgB","409":"b:AMISAHIAALFgCQIACMhCgYnAECgB","410":"b:AMISAHIAALFgCQIACMhCgYnAECgB","420":"b:AMISAHIAALFgCQIACMhCgYnAECgB","429":"b:AMISAHIAALFgCQIACMhCgYnAECgB","451":"b:AMISAHIAALFgCQIACMhCgYnAECgB","453":"b:AMISAHIAALFgCQIACMhCgYnAECgB","477":"b:AMISAHIAALFgCQIACMhCgYnAECgB","478":"b:AMISAHIAALFgCQIACMhCgYnAECgB","481":"b:AMISAHIAALFgCQIACMhCgYnAECgB","505":"b:AMISAHIAALFgCQIACMhCgYnAECgB","511":"b:AMISAHIAALFgCQIACMhCgYnAECgB","518":"b:AMISAHIAALFgCQIACMhCgYnAECgB"},"packages/workflow/src/common/get-child-nodes.ts":{"5":"b:BNAKAH4gAJFAAAAAAPAAAYDwEC8A"},"packages/workflow/src/common/get-connected-nodes.ts":{"11":"b:ANMCAH4gAJXACAAAgFAjEYHwECcA","34":"b:ANMCAH4gAJXACAAAgFAjEYHwECcA","46":"b:ANMCAH4gAJXACAAAgFAjEYHwECcA","61":"b:ANMCAH4gAJXACAAAgFAjEYHwECcA","62":"b:ANMCAH4gAJXACAAAgFAjEYHwECcA"},"packages/workflow/src/common/map-connections-by-destination.ts":{"5":"b:ANMCAH5gAJXgCAAAAFACEYD0FCAA"},"packages/workflow/src/deferred-promise.ts":{"10":"b:ANMCAH4gAJXACAAAAFACEYDwECcA","12":"b:ANMCAH4gAJXACAAAAFACEYDwECcA"},"packages/workflow/src/execution-context-establishment-hooks.ts":{"41":"b:ANMCAH4gAJXACAAAAFACEYDwECcA"},"packages/workflow/src/expression-evaluator-proxy.ts":{"8":"b:AMMSAHIAAIBAAAIAAEACgIHiECQA","15":"b:AMMSAHIAAIBAAAIAAEACgIHiECQA","19":"b:AMMSAHIAAIBAAAIAAEACgIHiECQA"},"packages/workflow/src/expression-sandboxing.ts":{"22":"b:AMEaAHIAAIBBAAIAAEgKhoHiEK4B","25":"b:AMEaAHIAAIBBAAIAAEgKhoHiEK4B","73":"b:AMEaAHIAAIBBAAIAAEgKhoHiEK4B","74":"b:AMEaAHIAAIBBAAIAAEgKhoHiEK4B","93":"b:AMEaAHIAAIBBAAIAAEgKhoHiEK4B","137":"b:AMEaAHIAAIBBAAIAAEgKhoHiEK4B","139":"b:AMEaAHIAAIBBAAIAAEgKhoHiEK4B","171":"b:AMEaAHIAAIBBAAIAAEgKhoHiEK4B","195":"b:AMEaAHIAAIBBAAIAAEgKhoHiEK4B","211":"b:AMEaAHIAAIBBAAIAAEgKhoHiEK4B","248":"b:AMEaAHIAAIBBAAIAAEgKhoHiEK4B","250":"b:AMEaAHIAAIBBAAIAAEgKhoHiEK4B","326":"b:AMEaAHIAAIBBAAIAAEgKhoHiEK4B","356":"b:AMEaAHIAAIBBAAIAAEgKhoHiEK4B","358":"b:AMEaAHIAAIBBAAIAAEgKhoHiEK4B","367":"b:AMEaAHIAAIBBAAIAAEgKhoHiEK4B","384":"b:AMEaAHIAAIBBAAIAAEgKhoHiEK4B","393":"b:AMEaAHIAAIBBAAIAAEgKhoHiEK4B","413":"b:AMEaAHIAAIBBAAIAAEgKhoHiEK4B","433":"b:AMEaAHIAAIBBAAIAAEgKhoHiEK4B","442":"b:AMEaAHIAAIBBAAIAAEgKhoHiEK4B","451":"b:AMEaAHIAAIBBAAIAAEgKhoHiEK4B","460":"b:AMEaAHIAAIBBAAIAAEgKhoHiEK4B","469":"b:AMEaAHIAAIBBAAIAAEgKhoHiEK4B","508":"b:AMEaAHIAAIBBAAIAAEgKhoHiEK4B","533":"b:AMEaAHIAAIBBAAIAAEgKhoHiEK4B","542":"b:AMEaAHIAAIBBAAIAAEgKhoHiEK4B","551":"b:AMEaAHIAAIBBAAIAAEgKhoHiEK4B","557":"b:AMEaAHIAAIBBAAIAAEgKhoHiEK4B"},"packages/workflow/src/expression.ts":{"35":"b:ANMSAH5gAJXgCAIAAFAikYH2FCQA","38":"b:ANMSAH5gAJXgCAIAAFAikYH2FCQA","41":"b:ANMSAH5gAJXgCAIAAFAikYH2FCQA","45":"b:ANMSAH5gAJXgCAIAAFAikYH2FCQA","59":"b:ANMSAH5gAJXgCAIAAFAikYH2FCQA","112":"b:ANMSAH5gAJXgCAIAAFAikYH2FCQA","113":"b:ANMSAH5gAJXgCAIAAFAikYH2FCQA","137":"b:ANMSAH5gAJXgCAIAAFAikYH2FCQA","151":"b:ANMSAH5gAJXgCAIAAFAikYH2FCQA","183":"b:ANMSAH5gAJXgCAIAAFAikYH2FCQA","185":"b:ANMSAH5gAJXgCAIAAFAikYH2FCQA","193":"b:ANMSAH5gAJXgCAIAAFAikYH2FCQA","197":"b:ANMSAH5gAJXgCAIAAFAikYH2FCQA","208":"b:ANMSAH5gAJXgCAIAAFAikYH2FCQA","210":"b:ANMSAH5gAJXgCAIAAFAikYH2FCQA","217":"b:ANMSAH5gAJXgCAIAAFAikYH2FCQA","220":"b:ANMSAH5gAJXgCAIAAFAikYH2FCQA","231":"b:ANMSAH5gAJXgCAIAAFAikYH2FCQA","237":"b:ANMSAH5gAJXgCAIAAFAikYH2FCQA","246":"b:ANMSAH5gAJXgCAIAAFAikYH2FCQA","260":"b:ANMSAH5gAJXgCAIAAFAikYH2FCQA","262":"b:ANMSAH5gAJXgCAIAAFAikYH2FCQA","282":"b:ANMSAH5gAJXgCAIAAFAikYH2FCQA","286":"b:ANMSAH5gAJXgCAIAAFAikYH2FCQA","294":"b:ANMSAH5gAJXgCAIAAFAikYH2FCQA","305":"b:ANMSAH5gAJXgCAIAAFAikYH2FCQA","318":"b:ANMSAH5gAJXgCAIAAFAikYH2FCQA","322":"b:ANMSAH5gAJXgCAIAAFAikYH2FCQA","466":"b:ANMSAH5gAJXgCAIAAFAikYH2FCQA","475":"b:ANMSAH5gAJXgCAIAAFAikYH2FCQA","516":"b:ANMSAH5gAJXgCAIAAFAikYH2FCQA","613":"b:ANMSAH5gAJXgCAIAAFAikYH2FCQA"},"packages/workflow/src/extensions/expression-extension.ts":{"25":"b:AMMSAHIAAIJAAAIAAEAKgIHiECQA","29":"b:AMMSAHIAAIJAAAIAAEAKgIHiECQA","64":"b:AMMSAHIAAIJAAAIAAEAKgIHiECQA","66":"b:AMMSAHIAAIJAAAIAAEAKgIHiECQA","69":"b:AMMSAHIAAIJAAAIAAEAKgIHiECQA","77":"b:AMMSAHIAAIJAAAIAAEAKgIHiECQA","79":"b:AMMSAHIAAIJAAAIAAEAKgIHiECQA","95":"b:AMMSAHIAAIJAAAIAAEAKgIHiECQA","124":"b:AMMSAHIAAIJAAAIAAEAKgIHiECQA","133":"b:AMMSAHIAAIJAAAIAAEAKgIHiECQA","160":"b:AMMSAHIAAIJAAAIAAEAKgIHiECQA","174":"b:AMMSAHIAAIJAAAIAAEAKgIHiECQA","183":"b:AMMSAHIAAIJAAAIAAEAKgIHiECQA","196":"b:AMMSAHIAAIJAAAIAAEAKgIHiECQA","208":"b:AMMSAHIAAIJAAAIAAEAKgIHiECQA","387":"b:AMMSAHIAAIJAAAIAAEAKgIHiECQA","405":"b:AMMSAHIAAIJAAAIAAEAKgIHiECQA","440":"b:AMMSAHIAAIJAAAIAAEAKgIHiECQA","457":"b:AMMSAHIAAIJAAAIAAEAKgIHiECQA","519":"b:AMMSAHIAAIJAAAIAAEAKgIHiECQA","527":"b:AMMSAHIAAIJAAAIAAEAKgIHiECQA","535":"b:AMMSAHIAAIJAAAIAAEAKgIHiECQA","555":"b:AMMSAHIAAIJAAAIAAEAKgIHiECQA","571":"b:AMMSAHIAAIJAAAIAAEAKgIHiECQA","579":"b:AMMSAHIAAIJAAAIAAEAKgIHiECQA","583":"b:AMMSAHIAAIJAAAIAAEAKgIHiECQA","584":"b:AMMSAHIAAIJAAAIAAEAKgIHiECQA","598":"b:AMMSAHIAAIJAAAIAAEAKgIHiECQA"},"packages/workflow/src/extensions/expression-parser.ts":{"20":"b:AMMSAHIAAIJAAAIAAEAKgIHiECQA","24":"b:AMMSAHIAAIJAAAIAAEAKgIHiECQA","93":"b:AMMSAHIAAIJAAAIAAEAKgIHiECQA","97":"b:AMMSAHIAAIJAAAIAAEAKgIHiECQA","99":"b:AMMSAHIAAIJAAAIAAEAKgIHiECQA"},"packages/workflow/src/extensions/index.ts":{"7":"b:AMMSAHIAAIBAAAIAAEACgIHiECQA"},"packages/workflow/src/global-state.ts":{"9":"b:ANMCAH5gAJXgCAAAAFACEYD0FCAA","13":"b:ANMCAH5gAJXgCAAAAFACEYD0FCAA"},"packages/workflow/src/logger-proxy.ts":{"3":"b:AFMAAAogABXACAAAABACEYDwECcA","9":"b:AFMAAAogABXACAAAABACEYDwECcA","10":"b:AFMAAAogABXACAAAABACEYDwECcA","11":"b:AFMAAAogABXACAAAABACEYDwECcA","12":"b:AFMAAAogABXACAAAABACEYDwECcA","13":"b:AFMAAAogABXACAAAABACEYDwECcA"},"packages/workflow/src/node-validation.ts":{"19":"b:AAAYAAIEAJAAAAAAAAAAALLiEC0B","59":"b:AAAYAAIEAJAAAAAAAAAAALLiEC0B","84":"b:AAAYAAIEAJAAAAAAAAAAALLiEC0B"},"packages/workflow/src/observable-object.ts":{"9":"b:ANcCAH5gAPXgCAAAhtgCFZD0FCcA","38":"b:ANcCAH5gAPXgCAAAhtgCFZD0FCcA","48":"b:ANcCAH5gAPXgCAAAhtgCFZD0FCcA","51":"b:ANcCAH5gAPXgCAAAhtgCFZD0FCcA","54":"b:ANcCAH5gAPXgCAAAhtgCFZD0FCcA"},"packages/workflow/src/redaction-channels.ts":{"22":"b:ANMCAH4gAJXACAAAAFACEYDwECcA","36":"b:ANMCAH4gAJXACAAAAFACEYDwECcA"},"packages/workflow/src/run-execution-data-factory.ts":{"54":"b:ANMaAH5gAJXACAAAAFACHaD0FC8A","67":"b:ANMaAH5gAJXACAAAAFACHaD0FC8A","86":"b:ANMaAH5gAJXACAAAAFACHaD0FC8A","108":"b:ANMaAH5gAJXACAAAAFACHaD0FC8A","125":"b:ANMaAH5gAJXACAAAAFACHaD0FC8A"},"packages/workflow/src/type-guards.ts":{"15":"b:ANMaAH4mAL3ACAAAAlxiFaHiECwB","21":"b:ANMaAH4mAL3ACAAAAlxiFaHiECwB","25":"b:ANMaAH4mAL3ACAAAAlxiFaHiECwB","29":"b:ANMaAH4mAL3ACAAAAlxiFaHiECwB","33":"b:ANMaAH4mAL3ACAAAAlxiFaHiECwB","37":"b:ANMaAH4mAL3ACAAAAlxiFaHiECwB","41":"b:ANMaAH4mAL3ACAAAAlxiFaHiECwB","47":"b:ANMaAH4mAL3ACAAAAlxiFaHiECwB","60":"b:ANMaAH4mAL3ACAAAAlxiFaHiECwB","70":"b:ANMaAH4mAL3ACAAAAlxiFaHiECwB","83":"b:ANMaAH4mAL3ACAAAAlxiFaHiECwB","93":"b:ANMaAH4mAL3ACAAAAlxiFaHiECwB","99":"b:ANMaAH4mAL3ACAAAAlxiFaHiECwB","103":"b:ANMaAH4mAL3ACAAAAlxiFaHiECwB"},"packages/workflow/src/type-validation.ts":{"15":"b:AMMaAHKAAJkBCAIAAkhikYHAEKIA","24":"b:AMMaAHKAAJkBCAIAAkhikYHAEKIA","38":"b:AMMaAHKAAJkBCAIAAkhikYHAEKIA","48":"b:AMMaAHKAAJkBCAIAAkhikYHAEKIA","72":"b:AMMaAHKAAJkBCAIAAkhikYHAEKIA","114":"b:AMMaAHKAAJkBCAIAAkhikYHAEKIA","124":"b:AMMaAHKAAJkBCAIAAkhikYHAEKIA","146":"b:AMMaAHKAAJkBCAIAAkhikYHAEKIA","162":"b:AMMaAHKAAJkBCAIAAkhikYHAEKIA","206":"b:AMMaAHKAAJkBCAIAAkhikYHAEKIA","272":"b:AMMaAHKAAJkBCAIAAkhikYHAEKIA","284":"b:AMMaAHKAAJkBCAIAAkhikYHAEKIA","305":"b:AMMaAHKAAJkBCAIAAkhikYHAEKIA","333":"b:AMMaAHKAAJkBCAIAAkhikYHAEKIA","437":"b:AMMaAHKAAJkBCAIAAkhikYHAEKIA","438":"b:AMMaAHKAAJkBCAIAAkhikYHAEKIA"},"packages/workflow/src/workflow-data-proxy-env-provider.ts":{"13":"b:AMMSAHoAAKBAAAIAAFACgIHyECQA","41":"b:AMMSAHoAAKBAAAIAAFACgIHyECQA","49":"b:AMMSAHoAAKBAAAIAAFACgIHyECQA","53":"b:AMMSAHoAAKBAAAIAAFACgIHyECQA"},"packages/workflow/src/workflow-data-proxy.ts":{"40":"b:AMMaAHIGAIpAAAIAAEgihqHiECwB","63":"b:AMMaAHIGAIpAAAIAAEgihqHiECwB","102":"b:AMMaAHIGAIpAAAIAAEgihqHiECwB","107":"b:AMMaAHIGAIpAAAIAAEgihqHiECwB","119":"b:AMMaAHIGAIpAAAIAAEgihqHiECwB","141":"b:AMMaAHIGAIpAAAIAAEgihqHiECwB","142":"b:AMMaAHIGAIpAAAIAAEgihqHiECwB","150":"b:AMMaAHIGAIpAAAIAAEgihqHiECwB","156":"b:AMMaAHIGAIpAAAIAAEgihqHiECwB","168":"b:AMMaAHIGAIpAAAIAAEgihqHiECwB","174":"b:AMMaAHIGAIpAAAIAAEgihqHiECwB","175":"b:AMMaAHIGAIpAAAIAAEgihqHiECwB","179":"b:AMMaAHIGAIpAAAIAAEgihqHiECwB","188":"b:AMMaAHIGAIpAAAIAAEgihqHiECwB","213":"b:AMMaAHIGAIpAAAIAAEgihqHiECwB","214":"b:AMMaAHIGAIpAAAIAAEgihqHiECwB","220":"b:AMMaAHIGAIpAAAIAAEgihqHiECwB","222":"b:AMMaAHIGAIpAAAIAAEgihqHiECwB","224":"b:AMMaAHIGAIpAAAIAAEgihqHiECwB","233":"b:AMMaAHIGAIpAAAIAAEgihqHiECwB","234":"b:AMMaAHIGAIpAAAIAAEgihqHiECwB","236":"b:AMMaAHIGAIpAAAIAAEgihqHiECwB","237":"b:AMMaAHIGAIpAAAIAAEgihqHiECwB","251":"b:AMMaAHIGAIpAAAIAAEgihqHiECwB","256":"b:AMMaAHIGAIpAAAIAAEgihqHiECwB","257":"b:AMMaAHIGAIpAAAIAAEgihqHiECwB","260":"b:AMMaAHIGAIpAAAIAAEgihqHiECwB","266":"b:AMMaAHIGAIpAAAIAAEgihqHiECwB","269":"b:AMMaAHIGAIpAAAIAAEgihqHiECwB","274":"b:AMMaAHIGAIpAAAIAAEgihqHiECwB","275":"b:AMMaAHIGAIpAAAIAAEgihqHiECwB","287":"b:AMMaAHIGAIpAAAIAAEgihqHiECwB","294":"b:AMMaAHIGAIpAAAIAAEgihqHiECwB","295":"b:AMMaAHIGAIpAAAIAAEgihqHiECwB","298":"b:AMMaAHIGAIpAAAIAAEgihqHiECwB","304":"b:AMMaAHIGAIpAAAIAAEgihqHiECwB","306":"b:AMMaAHIGAIpAAAIAAEgihqHiECwB","368":"b:AMMaAHIGAIpAAAIAAEgihqHiECwB","400":"b:AMMaAHIGAIpAAAIAAEgihqHiECwB","517":"b:AMMaAHIGAIpAAAIAAEgihqHiECwB","528":"b:AMMaAHIGAIpAAAIAAEgihqHiECwB","529":"b:AMMaAHIGAIpAAAIAAEgihqHiECwB","636":"b:AMMaAHIGAIpAAAIAAEgihqHiECwB","643":"b:AMMaAHIGAIpAAAIAAEgihqHiECwB","644":"b:AMMaAHIGAIpAAAIAAEgihqHiECwB","647":"b:AMMaAHIGAIpAAAIAAEgihqHiECwB","653":"b:AMMaAHIGAIpAAAIAAEgihqHiECwB","684":"b:AMMaAHIGAIpAAAIAAEgihqHiECwB","691":"b:AMMaAHIGAIpAAAIAAEgihqHiECwB","692":"b:AMMaAHIGAIpAAAIAAEgihqHiECwB","695":"b:AMMaAHIGAIpAAAIAAEgihqHiECwB","701":"b:AMMaAHIGAIpAAAIAAEgihqHiECwB","729":"b:AMMaAHIGAIpAAAIAAEgihqHiECwB","734":"b:AMMaAHIGAIpAAAIAAEgihqHiECwB","735":"b:AMMaAHIGAIpAAAIAAEgihqHiECwB","759":"b:AMMaAHIGAIpAAAIAAEgihqHiECwB","763":"b:AMMaAHIGAIpAAAIAAEgihqHiECwB","790":"b:AMMaAHIGAIpAAAIAAEgihqHiECwB","840":"b:AMMaAHIGAIpAAAIAAEgihqHiECwB","862":"b:AMMaAHIGAIpAAAIAAEgihqHiECwB","875":"b:AMMaAHIGAIpAAAIAAEgihqHiECwB","886":"b:AMMaAHIGAIpAAAIAAEgihqHiECwB","898":"b:AMMaAHIGAIpAAAIAAEgihqHiECwB","911":"b:AMMaAHIGAIpAAAIAAEgihqHiECwB","922":"b:AMMaAHIGAIpAAAIAAEgihqHiECwB","933":"b:AMMaAHIGAIpAAAIAAEgihqHiECwB","942":"b:AMMaAHIGAIpAAAIAAEgihqHiECwB","961":"b:AMMaAHIGAIpAAAIAAEgihqHiECwB","970":"b:AMMaAHIGAIpAAAIAAEgihqHiECwB","973":"b:AMMaAHIGAIpAAAIAAEgihqHiECwB","1009":"b:AMMaAHIGAIpAAAIAAEgihqHiECwB","1031":"b:AMMaAHIGAIpAAAIAAEgihqHiECwB","1035":"b:AMMaAHIGAIpAAAIAAEgihqHiECwB","1043":"b:AMMaAHIGAIpAAAIAAEgihqHiECwB","1050":"b:AMMaAHIGAIpAAAIAAEgihqHiECwB","1102":"b:AMMaAHIGAIpAAAIAAEgihqHiECwB","1127":"b:AMMaAHIGAIpAAAIAAEgihqHiECwB","1145":"b:AMMaAHIGAIpAAAIAAEgihqHiECwB","1168":"b:AMMaAHIGAIpAAAIAAEgihqHiECwB","1169":"b:AMMaAHIGAIpAAAIAAEgihqHiECwB","1182":"b:AMMaAHIGAIpAAAIAAEgihqHiECwB","1215":"b:AMMaAHIGAIpAAAIAAEgihqHiECwB","1225":"b:AMMaAHIGAIpAAAIAAEgihqHiECwB","1323":"b:AMMaAHIGAIpAAAIAAEgihqHiECwB","1342":"b:AMMaAHIGAIpAAAIAAEgihqHiECwB","1366":"b:AMMaAHIGAIpAAAIAAEgihqHiECwB","1397":"b:AMMaAHIGAIpAAAIAAEgihqHiECwB","1398":"b:AMMaAHIGAIpAAAIAAEgihqHiECwB","1401":"b:AMMaAHIGAIpAAAIAAEgihqHiECwB","1407":"b:AMMaAHIGAIpAAAIAAEgihqHiECwB","1422":"b:AMMaAHIGAIpAAAIAAEgihqHiECwB","1437":"b:AMMaAHIGAIpAAAIAAEgihqHiECwB","1452":"b:AMMaAHIGAIpAAAIAAEgihqHiECwB","1498":"b:AMMaAHIGAIpAAAIAAEgihqHiECwB","1516":"b:AMMaAHIGAIpAAAIAAEgihqHiECwB","1540":"b:AMMaAHIGAIpAAAIAAEgihqHiECwB","1596":"b:AMMaAHIGAIpAAAIAAEgihqHiECwB","1597":"b:AMMaAHIGAIpAAAIAAEgihqHiECwB"},"packages/workflow/src/workflow-expression.ts":{"22":"b:ANMaAH5gANXgCAAAANBCHbD2FK8B","30":"b:ANMaAH5gANXgCAAAANBCHbD2FK8B","74":"b:ANMaAH5gANXgCAAAANBCHbD2FK8B","89":"b:ANMaAH5gANXgCAAAANBCHbD2FK8B","94":"b:ANMaAH5gANXgCAAAANBCHbD2FK8B","154":"b:ANMaAH5gANXgCAAAANBCHbD2FK8B","189":"b:ANMaAH5gANXgCAAAANBCHbD2FK8B","222":"b:ANMaAH5gANXgCAAAANBCHbD2FK8B","269":"b:ANMaAH5gANXgCAAAANBCHbD2FK8B","273":"b:ANMaAH5gANXgCAAAANBCHbD2FK8B","277":"b:ANMaAH5gANXgCAAAANBCHbD2FK8B"},"packages/workflow/src/workflow-validation.ts":{"16":"b:AAAYAAIEAJAAAAAAAAAAALLiEC0B"},"packages/workflow/src/workflow.ts":{"87":"b:BNMaAH5kANfgCAAAgfgiF7P2FK8B","137":"b:BNMaAH5kANfgCAAAgfgiF7P2FK8B","144":"b:BNMaAH5kANfgCAAAgfgiF7P2FK8B","149":"b:BNMaAH5kANfgCAAAgfgiF7P2FK8B","153":"b:BNMaAH5kANfgCAAAgfgiF7P2FK8B","157":"b:BNMaAH5kANfgCAAAgfgiF7P2FK8B","164":"b:BNMaAH5kANfgCAAAgfgiF7P2FK8B","217":"b:BNMaAH5kANfgCAAAgfgiF7P2FK8B","245":"b:BNMaAH5kANfgCAAAgfgiF7P2FK8B","253":"b:BNMaAH5kANfgCAAAgfgiF7P2FK8B","254":"b:BNMaAH5kANfgCAAAgfgiF7P2FK8B","261":"b:BNMaAH5kANfgCAAAgfgiF7P2FK8B","262":"b:BNMaAH5kANfgCAAAgfgiF7P2FK8B","271":"b:BNMaAH5kANfgCAAAgfgiF7P2FK8B","300":"b:BNMaAH5kANfgCAAAgfgiF7P2FK8B","309":"b:BNMaAH5kANfgCAAAgfgiF7P2FK8B","330":"b:BNMaAH5kANfgCAAAgfgiF7P2FK8B","334":"b:BNMaAH5kANfgCAAAgfgiF7P2FK8B","390":"b:BNMaAH5kANfgCAAAgfgiF7P2FK8B","409":"b:BNMaAH5kANfgCAAAgfgiF7P2FK8B","447":"b:BNMaAH5kANfgCAAAgfgiF7P2FK8B","491":"b:BNMaAH5kANfgCAAAgfgiF7P2FK8B","544":"b:BNMaAH5kANfgCAAAgfgiF7P2FK8B","563":"b:BNMaAH5kANfgCAAAgfgiF7P2FK8B","581":"b:BNMaAH5kANfgCAAAgfgiF7P2FK8B","595":"b:BNMaAH5kANfgCAAAgfgiF7P2FK8B","610":"b:BNMaAH5kANfgCAAAgfgiF7P2FK8B","625":"b:BNMaAH5kANfgCAAAgfgiF7P2FK8B","636":"b:BNMaAH5kANfgCAAAgfgiF7P2FK8B","659":"b:BNMaAH5kANfgCAAAgfgiF7P2FK8B","677":"b:BNMaAH5kANfgCAAAgfgiF7P2FK8B","678":"b:BNMaAH5kANfgCAAAgfgiF7P2FK8B","692":"b:BNMaAH5kANfgCAAAgfgiF7P2FK8B","751":"b:BNMaAH5kANfgCAAAgfgiF7P2FK8B","822":"b:BNMaAH5kANfgCAAAgfgiF7P2FK8B","852":"b:BNMaAH5kANfgCAAAgfgiF7P2FK8B","853":"b:BNMaAH5kANfgCAAAgfgiF7P2FK8B","872":"b:BNMaAH5kANfgCAAAgfgiF7P2FK8B","897":"b:BNMaAH5kANfgCAAAgfgiF7P2FK8B"},"packages/@n8n/design-system/src/components/N8nRecycleScroller/RecycleScroller.vue":{"14":[31,44,45,46,68,69,86,92,5],"30":[31,44,45,46,68,69,86,92,5],"31":[31,44,45,46,68,69,86,92,5],"48":[31,44,45,46,68,69,86,92,5],"50":[31,44,45,46,68,69,86,92,5],"60":[31,44,45,46,68,69,86,92,5],"61":[31,44,45,46,68,69,86,92,5],"72":[31,44,45,46,68,69,86,92,5],"76":[31,44,45,46,68,69,86,92,5],"77":[31,44,45,46,68,69,86,92,5],"79":[31,44,45,46,68,69,86,92,5],"81":[31,44,45,46,68,69,86,92,5],"94":[31,44,45,46,68,69,86,92,5],"102":[31,44,45,46,68,69,86,92,5],"106":[31,44,45,46,68,69,86,92,5],"116":[31,44,45,46,68,69,86,92,5],"120":[31,44,45,46,68,69,86,92,5],"132":[31,44,45,46,68,69,86,92,5],"133":[31,44,45,46,68,69,86,92,5],"141":[31,44,45,46,68,69,86,92,5],"147":[31,44,45,46,68,69,86,92,5],"148":[31,44,45,46,68,69,86,92,5],"167":[31,44,45,46,68,69,86,92,5],"170":[31,44,45,46,68,69,86,92,5],"201":[31,44,45,46,68,69,86,92,5],"208":[31,44,45,46,68,69,86,92,5],"210":[31,44,45,46,68,69,86,92,5]},"packages/frontend/editor-ui/src/app/utils/parameterUtils.ts":{"13":"b:MJQZoC1ygA6hEEEQx4WvHQMEAAAA"},"packages/frontend/editor-ui/src/features/credentials/components/CredentialCard.vue":{"68":[31,44,45,46,68,69,86,92,5],"69":[31,44,45,46,68,69,86,92,5],"72":[31,44,45,46,68,69,86,92,5],"74":[31,44,45,46,68,69,86,92,5],"82":[31,44,45,46,68,69,86,92,5],"113":[31,44,45,46,68,69,86,92,5],"122":[31,44,45,46,68,69,86,92,5],"124":[45],"151":[68],"215":[68],"224":[31,44,45,46,68,69,86,92,5],"229":[31,44,45,46,68,69,86,92,5],"232":[31,44,45,46,68,69,86,92,5],"236":[45],"263":[31,44,45,46,68,69,86,92,5],"272":[31,44,45,46,68,69,86,92,5]},"packages/frontend/editor-ui/src/features/credentials/components/CredentialsSelectModal.vue":{"14":[11,31,44,45,46,69,86,92,5],"27":[11,31,44,45,46,69,86,92,5],"34":[11,31,44,45,46,69,86,92,5],"42":[11,31,44,45,46,69,86,92,5],"43":[11,31,44,45,46,69,86,92,5],"46":[11,31,44,45,46,69,86,92,5],"50":[11,31,44,45,46,69,86,92,5],"63":[11,31,44,45,46,69,86,92,5],"76":[11,31,44,45,46,69,86,92,5],"81":[11,31,44,45,46,69,86,92,5],"96":[11,31,44,45,46,69,86,92,5],"98":[11,31,44,45,46,69,86,92,5],"100":[11,31,44,45,46,69,86,92,5],"110":[11,31,44,45,46,69,86,92,5]},"packages/frontend/editor-ui/src/features/credentials/credentials.ee.api.ts":{"6":[151,92,5],"19":[151,68]},"packages/frontend/editor-ui/src/features/credentials/views/CredentialsView.vue":{"62":[11,31,45,92,5],"79":[31,44,45,46,68,69,86,92,5],"85":[31,44,45,46,68,69,86,92,5],"88":[11,31,44,45,46,68,69,86,92,5],"89":[31,44,45,46,68,69,86,92,5],"114":[11,31,44,45,46,68,69,86,92,5],"116":[11,31,44,45,46,68,69,86,92,5],"132":[31,45,46,86],"136":[31,44,45,46,69,86,92,5],"144":[31,46,86],"153":[11,31,44,45,46,68,69,86,92,5],"164":[31,44,45,46,68,69,86,92,5],"187":[11,31,44,45,46,68,69,86,92,5],"197":[11,31,44,45,46,68,69,86,92,5],"220":[11,31,44,45,46,68,69,86,92,5],"249":[44,45,68,69,5],"253":[11,31,44,45,46,68,69,86,92,5],"255":[31,44,45,46,69,86,92,5],"268":[11,31,44,45,46,68,69,86,92,5],"270":[11,31,44,45,46,68,69,86,92,5],"271":[11,31,44,45,46,69,86,92,5],"280":[11,31,44,45,46,68,69,86,92,5],"290":[11,31,44,45,46,68,69,86,92,5],"309":[11,31,44,45,46,68,69,86,92,5],"319":[31,44,45,46,68,69,86,92,5]},"packages/@n8n/db/src/repositories/execution-metadata.repository.ts":{"8":[14,15,17,36,37,38,95,110]},"packages/cli/src/services/execution-metadata.service.ts":{"7":[14,15,17,36,37,38,95,110],"9":[14,15,17,36,37,38,95,110]},"packages/cli/src/webhooks/test-webhook-registrations.service.ts":{"28":[14,15,17,20,33,95,110,122],"40":[14,15,17,20,33,95,110,122],"47":[14,15,17,20,33,95,110,122],"76":[14,15,17,20,33,95,110,122],"85":[14,15,17,20,33,95,110,122],"90":[14,15,17,20,33,95,110,122],"98":[14,15,17,20,33,95,110,122],"106":[14,15,17,20,33,95,110,122],"116":[14,15,17,20,33,95,110,122]},"packages/cli/src/webhooks/test-webhooks.ts":{"56":"b:ANMSAA4gALXACACAAlwCFIAQAAAA","72":"b:ANMSAA4gALXACACAAlwCFIAQAAAA","102":"b:ANMSAA4gALXACACAAlwCFIAQAAAA","150":"b:ANMSAA4gALXACACAAlwCFIAQAAAA","164":"b:ANMSAA4gALXACACAAlwCFIAQAAAA","215":"b:ANMSAA4gALXACACAAlwCFIAQAAAA","238":"b:ANMSAA4gALXACACAAlwCFIAQAAAA","244":"b:ANMSAA4gALXACACAAlwCFIAQAAAA","267":"b:ANMSAA4gALXACACAAlwCFIAQAAAA","271":"b:ANMSAA4gALXACACAAlwCFIAQAAAA","278":"b:ANMSAA4gALXACACAAlwCFIAQAAAA","281":"b:ANMSAA4gALXACACAAlwCFIAQAAAA","294":"b:ANMSAA4gALXACACAAlwCFIAQAAAA","307":"b:ANMSAA4gALXACACAAlwCFIAQAAAA","353":"b:ANMSAA4gALXACACAAlwCFIAQAAAA","356":"b:ANMSAA4gALXACACAAlwCFIAQAAAA","364":"b:ANMSAA4gALXACACAAlwCFIAQAAAA","375":"b:ANMSAA4gALXACACAAlwCFIAQAAAA","458":"b:ANMSAA4gALXACACAAlwCFIAQAAAA","486":"b:ANMSAA4gALXACACAAlwCFIAQAAAA","493":"b:ANMSAA4gALXACACAAlwCFIAQAAAA","507":"b:ANMSAA4gALXACACAAlwCFIAQAAAA","515":"b:ANMSAA4gALXACACAAlwCFIAQAAAA","516":"b:ANMSAA4gALXACACAAlwCFIAQAAAA","525":"b:ANMSAA4gALXACACAAlwCFIAQAAAA","537":"b:ANMSAA4gALXACACAAlwCFIAQAAAA","544":"b:ANMSAA4gALXACACAAlwCFIAQAAAA","580":"b:ANMSAA4gALXACACAAlwCFIAQAAAA"},"packages/cli/src/webhooks/webhook-last-node-response-extractor.ts":{"29":[14,15,17,153,64,95,110,122,155],"71":[14,15,17,153,64,95,110,122,155],"116":[14,15,17,153,64,95,110,122,155],"183":[14,15,17,153,64,95,110,122,155]},"packages/core/src/execution-engine/node-execution-context/utils/execution-metadata.ts":{"8":[14,15,17,36,37,38,95,110],"46":[14,15,17,36,37,38,95,110],"51":[14,15,17,36,37,38,95,110],"63":[14,15,17,36,37,38,95,110],"70":[14,15,17,36,37,38,95,110]},"packages/nodes-base/nodes/Notion/NotionTrigger.node.ts":{"181":[95],"275":[95],"284":[95],"287":[95]},"packages/nodes-base/nodes/Notion/shared/GenericFunctions.ts":{"27":[44,69,5,95,120,133],"48":[44,69,5,95,120,133],"84":[44,69,5,95,120,133],"118":[44,69,5,95,120,133],"139":[44,69,5,95,120,133],"160":[44,69,5,95,120,133],"205":[44,69,5,95,120,133],"213":[44,69,5,95,120,133],"219":[44,69,5,95,120,133],"225":[44,69,5,95,120,133],"249":[44,69,5,95,120,133],"296":[44,69,5,95,120,133],"305":[44,69,5,95,120,133],"321":[44,69,5,95,120,133],"328":[44,69,5,95,120,133],"332":[44,69,5,95,120,133],"339":[44,69,5,95,120,133],"358":[44,69,5,95,120,133],"367":[44,69,5,95,120,133],"370":[44,69,5,95,120,133],"371":[44,69,5,95,120,133],"373":[44,69,5,95,120,133],"376":[44,69,5,95,120,133],"394":[44,69,5,95,120,133],"396":[44,69,5,95,120,133],"397":[44,69,5,95,120,133],"414":[44,69,5,95,120,133],"473":[44,69,5,95,120,133],"485":[44,69,5,95,120,133],"493":[44,69,5,95,120,133],"501":[44,69,5,95,120,133],"505":[44,69,5,95,120,133],"517":[44,69,5,95,120,133],"519":[44,69,5,95,120,133],"527":[44,69,5,95,120,133],"528":[44,69,5,95,120,133],"536":[44,69,5,95,120,133],"537":[44,69,5,95,120,133],"585":[44,69,5,95,120,133],"592":[44,69,5,95,120,133],"613":[44,69,5,95,120,133],"619":[44,69,5,95,120,133],"621":[44,69,5,95,120,133],"625":[44,69,5,95,120,133],"644":[44,69,5,95,120,133],"652":[44,69,5,95,120,133],"660":[44,69,5,95,120,133],"662":[44,69,5,95,120,133],"667":[44,69,5,95,120,133],"675":[44,69,5,95,120,133],"721":[44,69,5,95,120,133],"730":[44,69,5,95,120,133],"817":[44,69,5,95,120,133],"835":[44,69,5,95,120,133],"851":[44,69,5,95,120,133],"872":[44,69,5,95,120,133],"912":[44,69,5,95,120,133],"921":[44,69,5,95,120,133],"947":[44,69,5,95,120,133],"960":[44,69,5,95,120,133],"1080":[44,69,5,95,120,133],"1094":[44,69,5,95,120,133],"1095":[44,69,5,95,120,133],"1108":[44,69,5,95,120,133],"1125":[44,69,5,95,120,133],"1130":[44,69,5,95,120,133],"1138":[44,69,5,95,120,133],"1155":[44,69,5,95,120,133],"1167":[44,69,5,95,120,133],"1207":[44,69,5,95,120,133]},"packages/nodes-base/nodes/Notion/shared/descriptions/Filters.ts":{"1":[44,69,5,95,120,133]},"packages/nodes-base/nodes/Notion/shared/methods/listSearch.ts":{"10":[44,69,5,95,120,133],"28":[44,69,5,95,120,133]},"packages/workflow/src/highlighted-data.ts":{"3":[14,15,17,36,37,38,95,110],"7":[14,15,17,36,37,38,95,110]},"packages/workflow/src/node-parameters/parameter-type-validation.ts":{"15":[14,15,17,36,37,38,95,110],"30":[14,15,17,36,37,38,95,110],"39":[14,15,17,36,37,38,95,110],"47":[14,15,17,36,37,38,95,110],"55":[14,15,17,36,37,38,95,110],"69":[14,15,17,36,37,38,95,110],"75":[14,15,17,36,37,38,95,110],"82":[14,15,17,36,37,38,95,110],"103":[14,15,17,36,37,38,95,110],"110":[14,15,17,36,37,38,95,110],"121":[14,15,17,36,37,38,95,110],"133":[14,15,17,36,37,38,95,110],"141":[14,15,17,36,37,38,95,110],"142":[14,15,17,36,37,38,95,110],"148":[14,15,17,36,37,38,95,110],"162":[14,15,17,36,37,38,95,110],"175":[14,15,17,36,37,38,95,110],"197":[14,15,17,36,37,38,95,110],"246":[14,15,17,36,37,38,95,110],"259":[14,15,17,36,37,38,95,110]},"packages/@n8n/chat/src/api/generic.ts":{"1":[14,15,16,17,65,77,95,110],"5":[14,15,16,17,65,77,95,110],"38":[65],"49":[14,15,16,17,65,77,95,110],"56":[65]},"packages/@n8n/chat/src/api/message.ts":{"9":[65],"24":[14,15,16,17,65,77,95,110],"68":[65],"73":[65],"82":[65],"119":[65],"151":[65],"211":[65],"245":[65]},"packages/@n8n/chat/src/components/Chat.vue":{"14":[14,15,16,17,65,77,95,110],"20":[14,15,16,17,65,77,95,110],"25":[65],"27":[65],"28":[65],"31":[14,15,16,17,65,77,95,110],"36":[14,15,16,17,65,77,95,110],"41":[14,15,16,17,65,77,95,110],"46":[14,15,16,17,65,77,95,110],"51":[65],"55":[65],"106":[14,15,16,17,65,77,95,110],"108":[15,65,110],"116":[14,15,16,17,65,77,95,110],"122":[65],"127":[14,15,16,17,65,77,95,110],"131":[14,15,16,17,65,77,95,110],"149":[14,15,16,17,65,77,95,110]},"packages/@n8n/chat/src/components/GetStartedFooter.vue":{"5":[14,15,16,17,65,77,95,110]},"packages/@n8n/chat/src/components/Input.vue":{"23":[14,15,16,17,65,77,95,110],"48":[14,15,16,17,65,77,95,110],"54":[14,15,16,17,65,77,95,110],"55":[65],"58":[14,15,16,17,65,77,95,110],"59":[65],"61":[14,15,16,17,65,77,95,110],"77":[65],"93":[65],"97":[14,15,16,17,65,77,95,110],"104":[14,15,16,17,65,77,95,110],"117":[65],"129":[65],"135":[14,15,16,17,65,77,95],"141":[65],"146":[14,15,16,17,65,77,95,110],"157":[65],"170":[65],"189":[65],"202":[65],"205":[65],"208":[65],"211":[65],"218":[65],"228":[65],"249":[14,15,16,17,65,77,95,110],"279":[65,95],"288":[65],"301":[65,95],"312":[65],"317":[14,15,16,17,65,77,95,110],"325":[14,15,16,17,65,77,95,110],"336":[14,15,16,17,65,77,95,110],"364":[65]},"packages/@n8n/chat/src/components/Layout.vue":{"6":[14,15,16,17,65,77,95,110],"8":[14,15,16,17,65,77,95,110],"15":[14,15,16,17,65,77,95,110],"20":[65],"24":[14,15,16,17,65,77,95,110]},"packages/@n8n/chat/src/components/MarkdownRenderer.vue":{"16":[14,15,16,17,77,95,110],"22":[14,15,16,17,77,95,110],"42":[14,15,16,17,77,95,110]},"packages/@n8n/chat/src/components/Message.vue":{"20":[14,15,16,17,65,77,95,110],"25":[14,15,16,17,65,77,95,110],"29":[14,15,16,17,65,77,95,110],"37":[14,15,16,17,65,77,95,110],"49":[65],"50":[65],"52":[65],"57":[14,15,16,17,65,77,95,110],"69":[14,15,16,17,65,77,95,110]},"packages/@n8n/chat/src/components/MessageActions.vue":{"8":[14,15,16,17,65,77,95,110],"16":[65],"30":[65],"35":[14,15,16,17,65,77,95,110],"43":[65]},"packages/@n8n/chat/src/components/MessageTyping.vue":{"8":[14,15,16,17,65,77,95,110],"23":[14,15,16,17,65,77,95,110],"31":[14,15,16,17,65,77,95,110],"34":[14,15,16,17,65,77,95,110]},"packages/@n8n/chat/src/components/MessagesList.vue":{"19":[14,15,16,17,65,77,95,110],"23":[14,15,16,17,65,77,95,110],"24":[14,15,16,17,65,77,95,110],"32":[14,15,16,17,65,77,95,110],"41":[65],"48":[65],"53":[14,15,16,17,65,77,95,110],"55":[14,15,16,17,65,77,95,110]},"packages/@n8n/chat/src/components/PoweredBy.vue":{"2":[14,15,16,17,65,77,95,110]},"packages/@n8n/chat/src/composables/useI18n.ts":{"5":[14,15,16,17,77,95,110],"9":[14,15,16,17,77,95,110],"17":[14,15,16,17,77,95,110]},"packages/@n8n/chat/src/composables/useOptions.ts":{"6":[14,15,16,17,77,95,110]},"packages/@n8n/chat/src/plugins/chat.ts":{"26":[14,15,16,17,65,77,95,110],"41":[14,15,16,17,65,77,95,110],"69":[65],"77":[65],"100":[65],"130":[65],"143":[65],"146":[65],"149":[65],"193":[14,15,16,17,65,77,95,110],"210":[14,15,16,17,65,77,95,110],"218":[14,15,16,17,65,77,95,110],"219":[65],"226":[14,15,16,17,65,77,95,110],"235":[14,15,16,17,65,77,95,110],"295":[14,15,16,17,65,77,95,110],"302":[14,15,16,17,65,77,95,110],"318":[65],"334":[14,15,16,17,65,77,95,110]},"packages/@n8n/chat/src/utils/streaming.ts":{"22":[14,15,16,17,65,77,95,110],"24":[65],"31":[65],"46":[65],"51":[65],"57":[65],"66":[65],"82":[65],"88":[65],"89":[65],"92":[65],"96":[65],"100":[65],"102":[65],"103":[65],"106":[65],"113":[14,15,16,17,65,77,95,110],"122":[65],"127":[65]},"packages/frontend/editor-ui/src/app/composables/usePushConnection/handlers/testWebhookReceived.ts":{"8":"b:AMATAAIAAAIDIACAAEgABAAAAAAA"},"packages/frontend/editor-ui/src/app/composables/useReportWorkflowFailuresToParent.ts":{"33":[21,22,94,95,110,134,135]},"packages/frontend/editor-ui/src/app/layouts/DemoLayout.vue":{"18":[21,22,94,95,110,134,135],"61":[21,22,94,95,110,134,135],"88":[21,22,94,95,110,134,135]},"packages/frontend/editor-ui/src/app/utils/formatters/dateFormatter.ts":{"4":"b:AAYKAAQAAM6BAAIAgMx6lwEAAAAA","15":[98,106,107,108,110,134,135],"27":[14,15,16,17,77,95,110],"29":[14,15,16,17,77,95,110]},"packages/frontend/editor-ui/src/features/execution/logs/components/DemoFooter.vue":{"9":[21,22,94,95,110,134,135],"10":[21,22,94,95,110,134,135],"11":[21,22,94,95,110,134,135]},"packages/frontend/editor-ui/src/features/execution/logs/components/LogsOverviewRow.vue":{"42":[14,15,16,17,65,77,95,110],"43":[14,15,16,17,65,77,95,110],"44":[14,15,16,17,65,77,95,110],"45":[14,15,16,17,65,77,95,110],"46":[14,15,16,17,65,77,95,110],"47":[14,15,16,17,65,77,95,110],"50":[14,15,16,17,65,77,95,110],"63":[14,15,16,17,65,77,95,110],"64":[14,15,16,17,65,77,95,110],"75":[14,15,16,17,65,77,95,110],"79":[14,15,16,17,65,77,95,110],"81":[14,15,16,17,65,77,95,110],"98":[14,15,16,17,65,77,95,110],"99":[14,15,16,17,65,77,95,110],"101":[14,15,16,17,65,77,95,110],"135":[15,16,65,110],"152":[14,15,16,17,65,77,95,110],"153":[14,15,16,17,65,77,95,110],"155":[14,15,16,17,65,77,95,110],"161":[14,15,16,17,65,77,95,110],"171":[14,15,16,17,65,77,95,110],"179":[65]},"packages/frontend/editor-ui/src/features/execution/logs/components/LogsOverviewRows.vue":{"40":[14,15,16,17,65,77,95,110],"41":[14,15,16,17,65,77,95,110],"47":[14,15,16,17,65,77,95,110],"51":[65,110],"67":[14,15,16,17,65,77,95,110],"68":[14,15,16,17,65,77,95,110],"69":[14,15,16,17,65,77,95,110],"79":[14,15,16,17,65,77,95,110],"81":[14,15,16,17,65,77,95,110],"82":[14,15,16,17,65,77,95,110],"87":[14,15,16,17,65,77,110],"89":[65],"98":[14,15,16,17,65,77,95,110],"114":[65],"115":[65,110],"116":[65,110],"117":[14,65,110]},"packages/frontend/editor-ui/src/features/execution/logs/components/LogsViewExecutionSummary.vue":{"18":[14,15,16,17,65,77,95,110],"20":[14,15,16,17,65,77,95,110],"37":[14,15,16,17,65,77,95,110]},"packages/frontend/editor-ui/src/features/execution/logs/components/LogsViewNodeName.vue":{"12":[14,15,16,17,65,77,95,110],"18":[14,15,16,17,65,77,95,110]},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/background/CanvasBackgroundStripedPattern.vue":{"6":"b:ACBkAAAAAAAAAACAAEAAANgAgAAA","13":"b:ACBkAAAAAAAAAACAAEAAANgAgAAA","14":"b:ACBkAAAAAAAAAACAAEAAANgAgAAA","15":"b:ACBkAAAAAAAAAACAAEAAANgAgAAA"},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/buttons/CanvasStopWaitingForWebhookButton.vue":{"5":"b:AMATAAIAAAIBIACAAEgABAAAAAAA","9":"b:AMATAAIAAAIBIACAAEgABAAAAAAA"},"packages/cli/src/eventbus/event-message-classes/event-message-runner.ts":{"24":"b:AAUCAAgAACAAAAAAhlgAAIAQAIIA","32":"b:AAUCAAgAACAAAAAAhlgAAIAQAIIA","37":"b:AAUCAAgAACAAAAAAhlgAAIAQAIIA"},"packages/cli/src/modules/external-secrets.ee/external-secrets-manager.ee.ts":{"37":"b:EAECAAAAAAACAEAAlQgECEQBCAAA","58":"b:EAECAAAAAAACAEAAlQgECEQBCAAA","61":"b:EAECAAAAAAACAEAAlQgECEQBCAAA","81":"b:EAECAAAAAAACAEAAlQgECEQBCAAA","93":"b:EAECAAAAAAACAEAAlQgECEQBCAAA","97":"b:EAECAAAAAAACAEAAlQgECEQBCAAA","105":"b:EAECAAAAAAACAEAAlQgECEQBCAAA","109":"b:EAECAAAAAAACAEAAlQgECEQBCAAA","113":"b:EAECAAAAAAACAEAAlQgECEQBCAAA","120":"b:EAECAAAAAAACAEAAlQgECEQBCAAA","126":"b:EAECAAAAAAACAEAAlQgECEQBCAAA","139":"b:EAECAAAAAAACAEAAlQgECEQBCAAA","165":"b:EAECAAAAAAACAEAAlQgECEQBCAAA","189":"b:EAECAAAAAAACAEAAlQgECEQBCAAA","193":"b:EAECAAAAAAACAEAAlQgECEQBCAAA","197":"b:EAECAAAAAAACAEAAlQgECEQBCAAA","201":"b:EAECAAAAAAACAEAAlQgECEQBCAAA","209":"b:EAECAAAAAAACAEAAlQgECEQBCAAA","220":"b:EAECAAAAAAACAEAAlQgECEQBCAAA","226":"b:EAECAAAAAAACAEAAlQgECEQBCAAA","241":"b:EAECAAAAAAACAEAAlQgECEQBCAAA","292":"b:EAECAAAAAAACAEAAlQgECEQBCAAA","310":"b:EAECAAAAAAACAEAAlQgECEQBCAAA","342":"b:EAECAAAAAAACAEAAlQgECEQBCAAA","360":"b:EAECAAAAAAACAEAAlQgECEQBCAAA","364":"b:EAECAAAAAAACAEAAlQgECEQBCAAA","374":"b:EAECAAAAAAACAEAAlQgECEQBCAAA","385":"b:EAECAAAAAAACAEAAlQgECEQBCAAA","395":"b:EAECAAAAAAACAEAAlQgECEQBCAAA","413":"b:EAECAAAAAAACAEAAlQgECEQBCAAA","421":"b:EAECAAAAAAACAEAAlQgECEQBCAAA","423":"b:EAECAAAAAAACAEAAlQgECEQBCAAA","429":"b:EAECAAAAAAACAEAAlQgECEQBCAAA","440":"b:EAECAAAAAAACAEAAlQgECEQBCAAA","444":"b:EAECAAAAAAACAEAAlQgECEQBCAAA","463":"b:EAECAAAAAAACAEAAlQgECEQBCAAA"},"packages/cli/src/task-runners/default-task-runner-disconnect-analyzer.ts":{"18":"b:AAUCAAgAACAAAAAAhlgAAIAQAIIA","22":"b:AAUCAAgAACAAAAAAhlgAAIAQAIIA"},"packages/cli/src/task-runners/errors/task-runner-disconnected-error.ts":{"7":"b:AAUCAAgAACAAAAAAhlgAAIAQAIIA","27":"b:AAUCAAgAACAAAAAAhlgAAIAQAIIA"},"packages/cli/src/task-runners/task-broker/errors/task-deferred.error.ts":{"4":"b:AAUCAAgAACAAAAAAhlgAAIAQAIIA"},"packages/cli/src/task-runners/task-broker/errors/task-runner-accept-timeout.error.ts":{"4":"b:AAUSAAgAACAAAAAAhlAAAIAAAAIA"},"packages/cli/src/task-runners/task-broker/task-broker.service.ts":{"97":"b:AAUSAAgAACAAAAAAhlgAAMAQAIIA","108":"b:AAUSAAgAACAAAAAAhlgAAMAQAIIA","109":"b:AAUSAAgAACAAAAAAhlgAAMAQAIIA","114":"b:AAUSAAgAACAAAAAAhlgAAMAQAIIA","115":"b:AAUSAAgAACAAAAAAhlgAAMAQAIIA","131":"b:AAUSAAgAACAAAAAAhlgAAMAQAIIA","142":"b:AAUSAAgAACAAAAAAhlgAAMAQAIIA","147":"b:AAUSAAgAACAAAAAAhlgAAMAQAIIA","169":"b:AAUSAAgAACAAAAAAhlgAAMAQAIIA","173":"b:AAUSAAgAACAAAAAAhlgAAMAQAIIA","177":"b:AAUSAAgAACAAAAAAhlgAAMAQAIIA","181":"b:AAUSAAgAACAAAAAAhlgAAMAQAIIA","185":"b:AAUSAAgAACAAAAAAhlgAAMAQAIIA","233":"b:AAUSAAgAACAAAAAAhlgAAMAQAIIA","252":"b:AAUSAAgAACAAAAAAhlgAAMAQAIIA","260":"b:AAUSAAgAACAAAAAAhlgAAMAQAIIA","268":"b:AAUSAAgAACAAAAAAhlgAAMAQAIIA","276":"b:AAUSAAgAACAAAAAAhlgAAMAQAIIA","293":"b:AAUSAAgAACAAAAAAhlgAAMAQAIIA","310":"b:AAUSAAgAACAAAAAAhlgAAMAQAIIA","327":"b:AAUSAAgAACAAAAAAhlgAAMAQAIIA","364":"b:AAUSAAgAACAAAAAAhlgAAMAQAIIA","381":"b:AAUSAAgAACAAAAAAhlgAAMAQAIIA","393":"b:AAUSAAgAACAAAAAAhlgAAMAQAIIA","409":"b:AAUSAAgAACAAAAAAhlgAAMAQAIIA","420":"b:AAUSAAgAACAAAAAAhlgAAMAQAIIA","428":"b:AAUSAAgAACAAAAAAhlgAAMAQAIIA","442":"b:AAUSAAgAACAAAAAAhlgAAMAQAIIA","456":"b:AAUSAAgAACAAAAAAhlgAAMAQAIIA","472":"b:AAUSAAgAACAAAAAAhlgAAMAQAIIA","479":"b:AAUSAAgAACAAAAAAhlgAAMAQAIIA","490":"b:AAUSAAgAACAAAAAAhlgAAMAQAIIA","516":"b:AAUSAAgAACAAAAAAhlgAAMAQAIIA","530":"b:AAUSAAgAACAAAAAAhlgAAMAQAIIA","544":"b:AAUSAAgAACAAAAAAhlgAAMAQAIIA","548":"b:AAUSAAgAACAAAAAAhlgAAMAQAIIA","552":"b:AAUSAAgAACAAAAAAhlgAAMAQAIIA","594":"b:AAUSAAgAACAAAAAAhlgAAMAQAIIA","606":"b:AAUSAAgAACAAAAAAhlgAAMAQAIIA","615":"b:AAUSAAgAACAAAAAAhlgAAMAQAIIA","648":"b:AAUSAAgAACAAAAAAhlgAAMAQAIIA","655":"b:AAUSAAgAACAAAAAAhlgAAMAQAIIA","670":"b:AAUSAAgAACAAAAAAhlgAAMAQAIIA","674":"b:AAUSAAgAACAAAAAAhlgAAMAQAIIA","681":"b:AAUSAAgAACAAAAAAhlgAAMAQAIIA","695":"b:AAUSAAgAACAAAAAAhlgAAMAQAIIA","700":"b:AAUSAAgAACAAAAAAhlgAAMAQAIIA","704":"b:AAUSAAgAACAAAAAAhlgAAMAQAIIA","712":"b:AAUSAAgAACAAAAAAhlgAAMAQAIIA","716":"b:AAUSAAgAACAAAAAAhlgAAMAQAIIA","720":"b:AAUSAAgAACAAAAAAhlgAAMAQAIIA","724":"b:AAUSAAgAACAAAAAAhlgAAMAQAIIA","728":"b:AAUSAAgAACAAAAAAhlgAAMAQAIIA","732":"b:AAUSAAgAACAAAAAAhlgAAMAQAIIA","736":"b:AAUSAAgAACAAAAAAhlgAAMAQAIIA","740":"b:AAUSAAgAACAAAAAAhlgAAMAQAIIA","744":"b:AAUSAAgAACAAAAAAhlgAAMAQAIIA","748":"b:AAUSAAgAACAAAAAAhlgAAMAQAIIA","752":"b:AAUSAAgAACAAAAAAhlgAAMAQAIIA"},"packages/cli/src/task-runners/task-managers/data-request-response-builder.ts":{"17":"b:AAUCAAgAACAAAAAAhlgAAIAQAIIA","37":"b:AAUCAAgAACAAAAAAhlgAAIAQAIIA","56":"b:AAUCAAgAACAAAAAAhlgAAIAQAIIA","69":"b:AAUCAAgAACAAAAAAhlgAAIAQAIIA"},"packages/cli/src/task-runners/task-managers/data-request-response-stripper.ts":{"18":"b:AAUCAAgAACAAAAAAhlgAAIAQAIIE","32":"b:AAUCAAgAACAAAAAAhlgAAIAQAIIE","43":"b:AAUCAAgAACAAAAAAhlgAAIAQAIIE","64":"b:AAUCAAgAACAAAAAAhlgAAIAQAIIE","68":"b:AAUCAAgAACAAAAAAhlgAAIAQAIIE","72":"b:AAUCAAgAACAAAAAAhlgAAIAQAIIE","86":"b:AAUCAAgAACAAAAAAhlgAAIAQAIIE","94":"b:AAUCAAgAACAAAAAAhlgAAIAQAIIE","118":"b:AAUCAAgAACAAAAAAhlgAAIAQAIIE","138":"b:AAUCAAgAACAAAAAAhlgAAIAQAIIE"},"packages/cli/src/task-runners/task-managers/local-task-requester.ts":{"19":"b:AAUCAAgAACAAAAAAhlgAAIAQAIIA","30":"b:AAUCAAgAACAAAAAAhlgAAIAQAIIA","39":"b:AAUCAAgAACAAAAAAhlgAAIAQAIIA","40":"b:AAUCAAgAACAAAAAAhlgAAIAQAIIA"},"packages/cli/src/task-runners/task-managers/task-requester.ts":{"71":"b:AAUCAAgAACAAAAAAhlgAAMAQAIIA","79":"b:AAUCAAgAACAAAAAAhlgAAMAQAIIA","83":"b:AAUCAAgAACAAAAAAhlgAAMAQAIIA","88":"b:AAUCAAgAACAAAAAAhlgAAMAQAIIA","136":"b:AAUCAAgAACAAAAAAhlgAAMAQAIIA","172":"b:AAUCAAgAACAAAAAAhlgAAMAQAIIA","196":"b:AAUCAAgAACAAAAAAhlgAAMAQAIIA","218":"b:AAUCAAgAACAAAAAAhlgAAMAQAIIA","224":"b:AAUCAAgAACAAAAAAhlgAAMAQAIIA","228":"b:AAUCAAgAACAAAAAAhlgAAMAQAIIA","247":"b:AAUCAAgAACAAAAAAhlgAAMAQAIIA","259":"b:AAUCAAgAACAAAAAAhlgAAMAQAIIA","261":"b:AAUCAAgAACAAAAAAhlgAAMAQAIIA","287":"b:AAUCAAgAACAAAAAAhlgAAMAQAIIA","301":"b:AAUCAAgAACAAAAAAhlgAAMAQAIIA","325":"b:AAUCAAgAACAAAAAAhlgAAMAQAIIA","333":"b:AAUCAAgAACAAAAAAhlgAAMAQAIIA","341":"b:AAUCAAgAACAAAAAAhlgAAMAQAIIA","349":"b:AAUCAAgAACAAAAAAhlgAAMAQAIIA","375":"b:AAUCAAgAACAAAAAAhlgAAMAQAIIA","390":"b:AAUCAAgAACAAAAAAhlgAAMAQAIIA"},"packages/core/src/execution-engine/node-execution-context/utils/normalize-items.ts":{"10":"b:AAECAAgAACgAAAAAhlhgAoAQAAIA","17":"b:AAECAAgAACgAAAAAhlhgAoAQAAIA","20":"b:AAECAAgAACgAAAAAhlhgAoAQAAIA","24":"b:AAECAAgAACgAAAAAhlhgAoAQAAIA","26":"b:AAECAAgAACgAAAAAhlhgAoAQAAIA","27":"b:AAECAAgAACgAAAAAhlhgAoAQAAIA","40":"b:AAECAAgAACgAAAAAhlhgAoAQAAIA","44":"b:AAECAAgAACgAAAAAhlhgAoAQAAIA"},"packages/nodes-base/nodes/Code/Code.node.ts":{"24":"b:AAcCAAgAACAAAAAAh1ggAIAQAAIA","187":"b:AAcCAAgAACAAAAAAh1ggAIAQAAIA"},"packages/nodes-base/nodes/Code/JsCodeValidator.ts":{"8":"b:AIMCAAgAACAAAAAAh1gAAIAUAIAE","15":"b:AIMCAAgAACAAAAAAh1gAAIAUAIAE","42":"b:AIMCAAgAACAAAAAAh1gAAIAUAIAE","54":"b:AIMCAAgAACAAAAAAh1gAAIAUAIAE"},"packages/nodes-base/nodes/Code/JsTaskRunnerSandbox.ts":{"20":"b:AIcCAAgAACAAAAAAh1ggAIAQAIIE","30":"b:AIcCAAgAACAAAAAAh1ggAIAQAIIE","56":"b:AIcCAAgAACAAAAAAh1ggAIAQAIIE","78":"b:AIcCAAgAACAAAAAAh1ggAIAQAIIE","123":"b:AIcCAAgAACAAAAAAh1ggAIAQAIIE","145":"b:AIcCAAgAACAAAAAAh1ggAIAQAIIE"},"packages/nodes-base/nodes/Code/PythonTaskRunnerSandbox.ts":{"18":"b:AIMCAAgAACAAAAAAh1gAAIAQAIAA","26":"b:AIMCAAgAACAAAAAAh1gAAIAQAIAA","42":"b:AIMCAAgAACAAAAAAh1gAAIAQAIAA","80":"b:AIMCAAgAACAAAAAAh1gAAIAQAIAA","98":"b:AIMCAAgAACAAAAAAh1gAAIAQAIAA"},"packages/nodes-base/nodes/Code/ValidationError.ts":{"12":"b:AIMCAAgAACAAAAAAh1gAAIAUAIAA"},"packages/nodes-base/nodes/Code/errors/WrappedExecutionError.ts":{"13":"b:AIcCAAgAACAAAAAAh1gAAMAQAIAA","22":"b:AIcCAAgAACAAAAAAh1gAAMAQAIAA","29":"b:AIcCAAgAACAAAAAAh1gAAMAQAIAA"},"packages/nodes-base/nodes/Code/python-runner-unavailable.error.ts":{"11":"b:AAMCAAgAACAAAAAAh1ggAIAQAAAA"},"packages/nodes-base/nodes/Code/reserved-key-found-error.ts":{"4":"b:AIMCAAgAACAAAAAAh1gAAIAUAIAA"},"packages/nodes-base/nodes/Code/result-validation.ts":{"16":"b:AIMCAAgAACAAAAAAh1ggAIAUAIIE","25":"b:AIMCAAgAACAAAAAAh1ggAIAUAIIE","31":"b:AIMCAAgAACAAAAAAh1ggAIAUAIIE","61":"b:AIMCAAgAACAAAAAAh1ggAIAUAIIE","86":"b:AIMCAAgAACAAAAAAh1ggAIAUAIIE","126":"b:AIMCAAgAACAAAAAAh1ggAIAUAIIE","159":"b:AIMCAAgAACAAAAAAh1ggAIAUAIIE","160":"b:AIMCAAgAACAAAAAAh1ggAIAUAIIE","172":"b:AIMCAAgAACAAAAAAh1ggAIAUAIIE"},"packages/nodes-base/nodes/Code/throw-execution-error.ts":{"5":"b:AIcCAAgAACAAAAAAh1gAAMAQAIAA"},"packages/nodes-base/nodes/Code/utils.ts":{"3":"b:AIMCAAgAACAAAAAAh1ggAIAUAIIA","9":"b:AIMCAAgAACAAAAAAh1ggAIAUAIIA","16":"b:AIMCAAgAACAAAAAAh1ggAIAUAIIA","17":"b:AIMCAAgAACAAAAAAh1ggAIAUAIIA","40":"b:AIMCAAgAACAAAAAAh1ggAIAUAIIA","47":"b:AIMCAAgAACAAAAAAh1ggAIAUAIIA"},"packages/nodes-base/nodes/N8n/GenericFunctions.ts":{"21":[98],"56":[98],"93":[98],"94":[98],"107":[98],"111":[98],"146":[98],"150":[98],"186":[98],"210":[98]},"packages/nodes-base/nodes/N8n/WorkflowLocator.ts":{"18":[98],"32":[98],"37":[98],"42":[98]},"packages/workflow/src/errors/base/operational.error.ts":{"16":"b:AAUSAAgGACAAAAAAhlAAAIAAAAIA"},"packages/workflow/src/errors/base/unexpected.error.ts":{"16":"b:AAUCAAgEACAAABAAhFgAAIBQAIIA"},"packages/workflow/src/errors/base/user.error.ts":{"19":"b:AANiAAgQACAAAAAABlgAAIAQACIA"},"packages/@n8n/design-system/src/components/N8nIcon/nodes/ai-transform.svg":{"11":"b:AAAAIAgAAAgAAAAAxwAgAQAAAAAA"},"packages/@n8n/design-system/src/components/N8nIcon/nodes/code.svg":{"11":"b:AAcCIAgAACgAgAFAx1pgQsAAAAAA"},"packages/@n8n/design-system/src/components/N8nIcon/nodes/compare-datasets.svg":{"11":[29,35,96,97,98,102,103,117]},"packages/@n8n/design-system/src/components/N8nIcon/nodes/convert-to-file.svg":{"11":"b:AAAAIAgAAAABAAAAxwEgAAAAAAAA"},"packages/@n8n/design-system/src/components/N8nIcon/nodes/extract-from-file.svg":{"11":"b:AAAAIAgAACAAAAAAxwEgAAAAAAAA"},"packages/@n8n/design-system/src/components/N8nIcon/nodes/n8n.svg":{"11":[54,98]},"packages/@n8n/design-system/src/components/N8nInfoAccordion/InfoAccordion.vue":{"29":"b:AIAAIAEAAAIBAAAABNwgBMACAAAA","40":"b:AIAAIAEAAAIBAAAABNwgBMACAAAA","54":"b:AIAAIAEAAAIBAAAABNwgBMACAAAA","61":"b:AIAAIAEAAAIBAAAABNwgBMACAAAA"},"packages/@n8n/design-system/src/components/N8nKeyboardShortcut/N8nKeyboardShortcut.vue":{"7":"b:AIAAAAAAAAAAIAEAdgAABAEAAAAA","10":"b:AIAAAAAAAAAAIAEAdgAABAEAAAAA","25":"b:AIAAAAAAAAAAIAEAdgAABAEAAAAA","29":"b:AIAAAAAAAAAAIAEAdgAABAEAAAAA","33":"b:AIAAAAAAAAAAIAEAdgAABAEAAAAA"},"packages/@n8n/design-system/src/v2/components/Checkbox/Checkbox.vue":{"12":"b:AIAAAAAAAIAgABhgBFwAAPAKAAAA","15":"b:AIAAAAAAAIAgABhgBFwAAPAKAAAA","20":"b:AIAAAAAAAIAgABhgBFwAAPAKAAAA","23":"b:AIAAAAAAAIAgABhgBFwAAPAKAAAA","24":"b:AIAAAAAAAIAgABhgBFwAAPAKAAAA","26":[83,84,93,110,137,139],"30":"b:AIAAAAAAAIAgABhgBFwAAPAKAAAA","38":"b:AIAAAAAAAIAgABhgBFwAAHAKAAAA","47":"b:AIAAAAAAAIAgABhgBFwAAPAKAAAA","49":"b:AIAAAAAAAAAAABhgBFwAAEAKAAAA","58":"b:AIAAAAAAAIAgABhgBFwAAPAKAAAA","59":"b:AIAAAAAAAAAAAABABFwAAEAKAAAA"},"packages/frontend/editor-ui/src/app/components/WorkflowPreview.vue":{"63":[98,106,107,108,110,134,135,139],"79":[98,106,107,108,110,134,135,139],"126":[110,134,135],"163":[134],"173":[110,134,135],"193":[110,134,135],"197":[110,134,135],"209":[110,134,135],"223":[98,106,107,108,110,134,135,139],"228":[98,106,107,135,139],"233":[98,106,107,108,110,134,135,139],"234":[110,134,135],"246":[98,106,107,108,110,134,135,139],"269":[98,106,107,108,110,134,135,139],"278":[98,106,107,108,110,134,135,139],"279":[139]},"packages/frontend/editor-ui/src/app/composables/useIntersectionObserver.ts":{"45":[15,98,105,106,108,135],"56":[108,135],"62":[108,135],"82":[15,98,105,106,135]},"packages/frontend/editor-ui/src/features/execution/executions/components/ExecutionStopAllText.vue":{"10":[15,98,106,107,108,110,134,135],"17":[15,98,106,107,108,110,134,135],"18":[98,106,107,108,110,134,135],"26":[15,98,106,107,108,110,134,135]},"packages/frontend/editor-ui/src/features/execution/executions/components/ExecutionsFilter.vue":{"41":[15,98,106,107,108,110,134,135],"63":[134],"66":[134],"67":[134],"69":[15,98,106,107,108,110,134,135],"87":[134],"104":[134],"113":[134],"120":[134],"127":[134],"139":[134],"155":[15,98,106,107,108,110,134,135],"205":[134],"219":[15,98,106,107,108,110,134,135],"222":[15,98,106,107,108,110,134,135],"233":[15,98,106,107,108,110,134,135],"249":[134],"256":[134],"300":[134],"352":[134],"364":[134],"373":[134],"375":[134],"378":[134],"410":[134],"429":[134],"455":[134],"477":[134],"501":[134]},"packages/frontend/editor-ui/src/features/execution/executions/components/workflow/WorkflowExecutionsCard.vue":{"41":[98,106,107,108,110,134,135],"44":[98,106,107,108,110,134,135],"47":[106,134,135],"57":[98,106,107,108,110,134,135],"60":[98,106,107,108,110,134,135],"61":[98,106,107,108,110,134,135],"63":[98,106,107,108,110,134,135],"69":[98,106,107,108,110,134,135],"104":[98,106,107,108,110,134,135],"119":[135],"137":[98,106,107,108,110,134,135],"175":[98,106,107,108,110,134,135]},"packages/frontend/editor-ui/src/features/execution/executions/components/workflow/WorkflowExecutionsInfoAccordion.vue":{"58":[15,98,106,107,108,110,134,135],"78":[15,98,106,107,108,110,134,135],"88":[15,98,106,107,108,110,134,135],"96":[15,98,106,107,108,110,134,135],"109":[15,98,106,107,108,110,134,135],"110":[15,98,106,107,108,110,134,135],"119":[107,110],"123":[15,98,106,107,108,110,134,135],"130":[15,98,106,107,108,110,134,135]},"packages/frontend/editor-ui/src/features/execution/executions/components/workflow/WorkflowExecutionsLandingPage.vue":{"22":[15,98,106,107,108,110,134,135],"23":[15,98,106,107,108,110,134,135],"25":[135],"43":[135],"46":[135],"54":[15,98,106,107,108,110,134,135]},"packages/frontend/editor-ui/src/features/execution/executions/components/workflow/WorkflowExecutionsList.vue":{"12":[15,98,106,107,108,110,134,135],"42":[15,98,106,107,108,110,134,135],"43":[98,106,107,108,110,134,135],"48":[15,98,106,107,108,110,134,135],"52":[107],"73":[15,98,106,135],"81":[15,98,106,107,108,110,134,135],"92":[110],"94":[134]},"packages/frontend/editor-ui/src/features/execution/executions/components/workflow/WorkflowExecutionsPreview.vue":{"51":[98,106,107,108,110,134,135],"55":[98,106,107,108,110,134,135],"56":[98,106,107,108,110,134,135],"57":[98,106,107,108,110,134,135],"60":[98,106,107,108,110,134,135],"71":[98,106,107,108,110,134,135],"75":[98,106,107,108,110,134,135],"79":[107],"90":[98,106,107,108,110,134,135],"96":[106,107,108,110,134,135],"106":[106,107,108,110,134,135],"118":[98,106,107,108,110,134,135],"140":[98,106,107,108,110,134,135],"142":[98,106,107,108,110,134,135],"169":[107],"239":[135],"247":[135],"260":[98,106,107,108,110,134,135],"280":[98,106,107,108,110,134,135],"310":[98,106,107,108,110,134,135],"321":[106,107,108,110,134,135],"355":[98,106,107,108,110,134,135],"367":[98,106,107,108,110,134,135],"370":[106],"395":[106,134],"398":[106,134],"401":[106,134]},"packages/frontend/editor-ui/src/features/execution/executions/components/workflow/WorkflowExecutionsSidebar.vue":{"26":[15,98,106,107,108,110,134,135],"63":[108,135],"70":[15,98,106,107,108,110,134,135],"79":[98,106,107,108,110,134,135],"83":[15,98,106,107,108,110,134,135],"87":[15,98,106,107,108,110,134,135],"97":[15,98,106,107,108,110,134,135],"98":[98,106,107,108,110,134,135],"107":[98,106,107,108,110,134,135],"116":[98,106,107,108,110,134,135],"125":[98,106,107,108,110,134,135],"136":[134],"143":[110],"147":[98,106,134],"169":[15,98,106,107,108,110,134,135],"176":[15,98,106,107,108,110,134,135],"216":[15,98,106,107,108,110,134,135],"221":[107,134],"229":[15,98,106,107,108,110,134,135],"232":[98,106,107,108,110,134,135]},"packages/frontend/editor-ui/src/features/execution/executions/composables/useExecutionHelpers.ts":{"24":[98,106,107,108,110,134,135],"69":[98,106,107,108,110,134,135],"74":[98,106,107,108,110,134,135],"87":[127,128]},"packages/frontend/editor-ui/src/features/execution/executions/views/WorkflowExecutionsView.vue":{"37":[15,98,106,107,108,110,134,135],"42":[15,98,106,107,108,110,134,135],"51":[15,98,106,107,108,110,134,135],"52":[98,106,107,108,110,134,135],"70":[15,98,106,107,108,110,134,135],"74":[15,98,106,107,108,110,134,135],"81":[15,98,106,107,108,110,134,135],"83":[98,106,107,108,110,134,135],"88":[15,98,106,107,108,110,134,135],"99":[15,98,106,135],"104":[15,98,106,107,108,110,134,135],"137":[15,98,106,107,108,110,134,135],"149":[15,98,106,107,108,110,134,135],"161":[110],"196":[134],"223":[107],"229":[107],"300":[108,135],"306":[15,98,106,107,108,110,134,135],"312":[108,135]},"packages/frontend/editor-ui/src/features/shared/editors/components/CodeNodeEditor/AskAI/AskAI.vue":{"28":"b:AAQAIAgAAAAAAAEAxwAgAAAAAAAA","57":"b:AAQAIAgAAAAAAAEAxwAgAAAAAAAA","64":[103],"67":[103],"70":"b:AAQAIAgAAAAAAAEAxwAgAAAAAAAA","76":[103],"93":"b:AAQAIAgAAAAAAAEAxwAgAAAAAAAA","100":"b:AAQAIAgAAAAAAAEAxwAgAAAAAAAA","101":"b:AAQAIAgAAAAAAAEAxwAgAAAAAAAA","103":"b:AAQAIAgAAAAAAAEAxwAgAAAAAAAA","104":"b:AAQAIAgAAAAAAAEAxwAgAAAAAAAA","107":[103],"108":[103],"110":[103],"118":[103],"133":[103],"141":[103],"150":[103],"216":[103],"221":[103],"243":"b:AAQAIAgAAAAAAAEAxwAgAAAAAAAA","250":[103],"254":"b:AAQAIAgAAAAAAAEAxwAgAAAAAAAA","259":"b:AAQAIAgAAAAAAAEAxwAgAAAAAAAA","293":[103],"304":"b:AAQAIAgAAAAAAAEAxwAgAAAAAAAA","308":[103]},"packages/frontend/editor-ui/src/features/shared/editors/components/CodeNodeEditor/CodeNodeEditor.vue":{"43":"b:AAQAIAgAAAAAAAEAxwAgAAAAAAAA","71":[96,103,117],"72":"b:AAQAIAgAAAAAAAEAxwAgAAAAAAAA","73":[10,96,103,117],"76":"b:AAQAIAgAAAAAAAEAxwAgAAAAAAAA","77":[29,35,96,97,98,102,103,117],"78":"b:AAQAIAgAAAAAAAEAxwAgAAAAAAAA","85":"b:AAQAIAgAAAAAAAEAxwAgAAAAAAAA","86":"b:AAQAIAgAAAAAAAEAxwAgAAAAAAAA","87":"b:AAQAIAgAAAAAAAEAxwAgAAAAAAAA","90":"b:AAQAIAgAAAAAAAEAxwAgAAAAAAAA","97":"b:AAQAIAgAAAAAAAEAxwAgAAAAAAAA","100":"b:AAQAIAgAAAAAAAEAxwAgAAAAAAAA","109":[29,35,80,96,97,98,102,103,117],"114":"b:AAQAIAgAAAAAAAEAxwAgAAAAAAAA","118":"b:AAQAIAgAAAAAAAEAxwAgAAAAAAAA","124":[103],"140":[103],"152":[10,80,103,117],"158":[10],"160":[10],"165":[10,80,103,117],"166":[10,80,103,117],"199":[103],"203":[103],"225":"b:AAQAIAgAAAAAAAEAxwAgAAAAAAAA","239":"b:AAQAIAgAAAAAAAEAxwAgAAAAAAAA","245":"b:AAQAIAgAAAAAAAEAxwAgAAAAAAAA","252":"b:AAQAIAgAAAAAAAEAxwAgAAAAAAAA","271":"b:AAQAIAgAAAAAAAEAxwAgAAAAAAAA","291":[35]},"packages/frontend/editor-ui/src/features/shared/editors/components/CodeNodeEditor/linter.ts":{"23":"b:AAQAIAgAAAAAAAEAxwAgAAAAAAAA","29":"b:AAQAIAgAAAAAAAEAxwAgAAAAAAAA","38":[10,96,103,117],"62":[103],"68":[103],"95":[96,103,117],"136":[96,103,117],"138":[96,103,117],"142":[96,103,117],"144":[96,103,117],"146":[96,103,117],"151":[103],"180":[103],"222":[103],"230":[103],"257":[96,103,117],"264":[103],"288":[96,103,117],"298":[103],"321":[96,103,117],"328":[103],"329":[103],"346":[103],"352":[103],"377":[96,103,117],"399":[96,103,117],"415":[96,103,117],"422":[103],"466":[103],"513":[96,103,117],"554":[96,103,117],"588":[96,103,117],"599":[103],"626":[103],"632":[103],"633":[103]},"packages/frontend/editor-ui/src/features/shared/editors/components/CodeNodeEditor/theme.ts":{"91":"b:AIQCYAgAQAAAAAEAxyEvhwAAAAAA"},"packages/frontend/editor-ui/src/features/shared/editors/components/JsonEditor/JsonEditor.vue":{"33":"b:AAACQAAAQAAAAAAABCEPhwAAAAAA","43":"b:AAACQAAAQAAAAAAABCEPhwAAAAAA","71":"b:AAACQAAAQAAAAAAABCEPhwAAAAAA","80":"b:AAACQAAAQAAAAAAABCEPhwAAAAAA","84":"b:AAACAAAAQAAAAAAAAAEPBwAAAAAA","89":"b:AAACQAAAQAAAAAAABCEPhwAAAAAA","90":[104,112,113,114,115,121,122],"102":"b:AAACQAAAQAAAAAAABCEPhwAAAAAA","124":"b:AAACQAAAQAAAAAAABCEPhwAAAAAA"},"packages/frontend/editor-ui/src/features/shared/editors/composables/useCodeEditor.ts":{"70":"b:AAQAIAgAAAAAAAEAxwAgAAAAAAAA","113":"b:AAQAIAgAAAAAAAEAxwAgAAAAAAAA","114":"b:AAQAIAgAAAAAAAEAxwAgAAAAAAAA","125":"b:AAQAIAgAAAAAAAEAxwAgAAAAAAAA","134":"b:AAQAIAgAAAAAAAEAxwAgAAAAAAAA","166":"b:AAQAIAgAAAAAAAEAxwAgAAAAAAAA","170":"b:AAQAIAgAAAAAAAEAxwAgAAAAAAAA","181":"b:AAQAIAgAAAAAAAEAxwAgAAAAAAAA","185":[10,35,80,96,103,117],"195":"b:AAQAIAgAAAAAAAEAxwAgAAAAAAAA","203":"b:AAQAIAgAAAAAAAEAxwAgAAAAAAAA","224":"b:AAQAIAgAAAAAAAEAxwAgAAAAAAAA","239":"b:AAQAIAgAAAAAAAEAxwAgAAAAAAAA","253":[10,80,103,117],"262":[117],"267":[117],"275":"b:AAQAIAgAAAAAAAEAxwAgAAAAAAAA","370":[10,29,35,96,97,98,102,103,117],"382":"b:AAQAIAgAAAAAAAEAxwAgAAAAAAAA","386":[29,35,80,96,97,98,102,103,117],"417":[10,103,117],"443":[10,103,117]},"packages/frontend/editor-ui/src/features/shared/editors/plugins/codemirror/typescript/client/useTypescript.ts":{"28":"b:AAQAIAgAAAAAAAEAxwAgAAAAAAAA","44":"b:AAQAIAgAAAAAAAEAxwAgAAAAAAAA","68":[10,103],"116":[10,103],"124":[10,103],"134":"b:AAQAIAgAAAAAAAEAxwAgAAAAAAAA","138":[103],"146":[29,35,80,96,97,98,102,103,117]},"packages/frontend/editor-ui/src/features/shared/nodeCreator/components/ItemTypes/ActionItem.vue":{"19":"b:MAgRoAgQZAIjAAAgxwFlPSIAAAAA","35":"b:MAgRoAgQZAIjAAAgxwFlPSIAAAAA","40":[65],"42":"b:MAgRoAgQZAIjAAAgxwFlPSIAAAAA","45":[65],"75":[65],"88":[65],"94":[65],"99":"b:MAgRoAgQZAIjAAAgxwFlPSIAAAAA","111":"b:MAgRoAgQZAIjAAAgxwFlPSIAAAAA","117":"b:MAgRoAgQZAIjAAAgxwFlPSIAAAAA"},"packages/frontend/editor-ui/src/features/shared/nodeCreator/components/Modes/ActionsMode.vue":{"41":"b:MAgRoAgQZAIjAAAgxwFlPSIAAAAA","63":"b:MAgRoAAQRAIiAAAAAAEgPSIAAAAA","66":"b:MAgRoAgQZAIjAAAgxwFlPSIAAAAA","69":"b:MAgQoAgQIAIjAAAgxwFlPSIAAAAA","76":"b:AAABIAAQRAACAAAAAAAgOQAAAAAA","86":"b:MAgRoAAQRAIiAAAAAAEgPSIAAAAA","92":"b:MAgRoAgQZAIjAAAgxwFlPSIAAAAA","93":"b:MAgRoAgQZAIjAAAgxwFlPSIAAAAA","98":"b:MAgRoAgQZAIjAAAgxwFlPSIAAAAA","100":"b:MAgRoAgQZAIjAAAgxwFlPSIAAAAA","102":"b:MAgRoAgQZAIjAAAgxwFlPSIAAAAA","104":"b:MAgRoAgQZAIjAAAgxwFlPSIAAAAA","109":"b:MAgRoAgQZAIjAAAgxwFlPSIAAAAA","118":"b:MAgRoAAQRAIiAAAAAAEgPSIAAAAA","127":"b:MAgRoAgQZAIjAAAgxwFlPSIAAAAA","130":"b:MAgRoAgQZAIjAAAgxwFlPSIAAAAA","137":"b:MAgRoAgQZAIjAAAgxwFlPSIAAAAA","139":"b:MAgRoAgQZAIjAAAgxwFlPSIAAAAA","151":[65],"157":[65],"161":"b:MAgRoAgQZAIjAAAgxwFlPSIAAAAA","165":[65],"169":[65],"171":[65],"176":"b:MAgRoAgQRAIjAAAgxwElPSIAAAAA","189":"b:MAgRoAgQRAIjAAAgxwElPSIAAAAA","212":"b:MAgRoAgQZAIjAAAgxwFlPSIAAAAA","215":"b:MAgRoAgQZAIjAAAgxwFlPSIAAAAA","223":"b:MAgRoAgQZAIjAAAgxwFlPSIAAAAA","234":[65],"238":[65],"258":"b:MAgRoAgQZAIjAAAgxwFlPSIAAAAA","262":"b:MAgRoAgQZAIjAAAgxwFlPSIAAAAA","263":"b:MAgRoAgQZAIjAAAgxwFlPSIAAAAA","280":"b:MAgRoAAQRAIiAAAAAAEgPSIAAAAA","293":[50,65,117,120,123,124],"299":[50,65,117,120,123,124],"311":[65],"320":"b:MAgRoAgQZAIjAAAgxwFlPSIAAAAA","335":[54,65,120,123,124],"339":[65],"341":[65]},"packages/frontend/editor-ui/src/features/shared/nodeCreator/components/OrderSwitcher.vue":{"11":"b:MAgRoAgQZAIjAAAgxwFlPSIAAAAA"},"packages/frontend/editor-ui/src/features/shared/nodeCreator/components/Panel/NoResults.vue":{"20":[51,65,98,102],"41":[51,65,98,102],"46":[51,65,98,102],"56":[51,65,98,102]},"packages/frontend/editor-ui/src/features/shared/nodeCreator/components/Panel/NoResultsIcon.vue":{"8":[51,65,98,102]},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/nodes/render-types/parts/CanvasNodeDisabledStrikeThrough.vue":{"6":"b:AAAAAAAAAAAAAAAgRVAAAOAAgAAA","10":"b:AAAAAAAAAAAAAAAgRVAAAOAAgAAA","19":"b:AAAAAAAAAAAAAAAgRVAAAOAAgAAA"},"packages/localhost-43531/assets/shield-alt-B7h2cjjC.js":{"8":[98]},"packages/@n8n/db/src/repositories/tag.repository.ts":{"11":[108,126,130,134,135],"15":[108,126,130,134,135],"26":[108,126,130,134,135],"35":[108,126,130,134,135],"47":[108,126,130,134,135],"64":[108,126,130,134,135],"76":[108,126,130,134,135]},"packages/nodes-base/nodes/Schedule/GenericFunctions.ts":{"7":"b:ACoAAAAAAEAAAQAASMgDRRAAACAA","40":"b:ACoAAAAAAEAAAQAASMgDRRAAACAA","105":"b:ACoAAAAAAEAAAQAASMgDRRAAACAA","110":"b:ACoAAAAAAEAAAQAASMgDRRAAACAA","142":"b:ACoAAAAAAEAAAQAASMgDRRAAACAA"},"packages/nodes-base/nodes/Schedule/ScheduleTrigger.node.ts":{"429":"b:ACoAAAAAAEAAAQAASMgDRRAAACAA","455":"b:ACoAAAAAAEAAAQAASMgDRRAAACAA","494":"b:ACoAAAAAAEAAAQAASMgDRRAAACAA","507":"b:ACoAAAAAAEAAAQAASMgDRRAAACAA","522":"b:ACoAAAAAAEAAAQAASMgDRRAAACAA"},"packages/frontend/editor-ui/src/app/components/DependencyPill.vue":{"37":[45,69,5,126,137,139],"39":[45,69,5,126,137,139],"45":[45,69,5,126,137,139],"47":[45,69,5,126,137,139],"53":[45,69,5,126,137,139],"95":[45,69,5,126,137,139],"219":[45,69,5,126,137,139],"222":[45,69,5,126,137,139]},"packages/frontend/editor-ui/src/app/components/IntersectionObserved.vue":{"6":[65,80,126,130,136],"19":[65,80,126,130,136],"29":[65,130],"34":[65,80,126,130,136]},"packages/frontend/editor-ui/src/app/components/IntersectionObserver.vue":{"6":"b:AAAAAAAAAAACAAEAAAAAQBwNAAAA","26":[65,130,132],"32":"b:AAAAAAAAAAACAAEAAAAAQBwNAAAA","43":[65,80,126,130,136],"44":[65,80,126,130,136],"54":[65,80,126,130,136],"60":[65,130],"64":"b:AAAAAAAAAAACAAEAAAAAQBwNAAAA"},"packages/frontend/editor-ui/src/features/ndv/panel/components/WireMeUp.vue":{"8":"b:IAABIAAQAAAhEAAAAgAgRQAAAAAA"},"packages/frontend/editor-ui/src/features/ndv/parameters/components/FixedCollection/FixedCollectionParameterLegacy.vue":{"66":"b:MJIZwAUQFEIgAQAgQoD/ZyAAAAAA","71":"b:AJIYQAUABEIBAQAgQoBvZyAAAAAA","73":"b:AJIYQAUABEIBAQAgQoBvZyAAAAAA","76":"b:AJIYQAUABEIBAQAgQoBvZyAAAAAA","80":"b:MJIZwAUQFEIhAQAgQoD/ZyAAAAAA","81":"b:MAAZgAAQEAIgAAAAAADyAyAAAAAA","82":"b:AJIYQAUABEIAAQAgQoBvZyAAAAAA","83":"b:AJIYQAUABEIBAQAgQoBvZyAAAAAA","85":"b:MJIZwAUQFEIgAQAgQoD/ZyAAAAAA","92":"b:MJIZwAUQFEIhAQAgQoD/ZyAAAAAA","94":"b:MJIZwAUQFEIhAQAgQoD/ZyAAAAAA","105":"b:MJIZwAUQFEIhAQAgQoD/ZyAAAAAA","108":[52,57,64],"111":"b:MJIZwAUQFEIhAQAgQoD/ZyAAAAAA","115":[20,57],"122":[20,57],"126":[20,57],"140":"b:MJIZwAUQFEIhAQAgQoD/ZyAAAAAA","155":[20,57],"160":[20,57],"191":[20,57],"196":"b:AJIYQAUABEIBAQAgQoBvZyAAAAAA","207":[20,57],"232":"b:AJIYQAUABEIBAQAgQoBvZyAAAAAA","242":[20,57],"263":[57],"276":[57],"299":"b:MJIZwAUQFEIhAQAgQoD/ZyAAAAAA","300":"b:ABAYgAQQAAIhAAAAAgCDAQAAAAAA","307":"b:MJIZwAUQFEIhAQAgQoD/ZyAAAAAA","339":[19,20,57,97,113,120],"362":[19,20,57,97,113,120],"368":[19,20,57,97,113,120],"382":[19,20,57,97,113,120],"389":[19,20,57,64,97,112,113],"421":"b:AJIYQAUABEIAAQAgQoBvZyAAAAAA","423":"b:MJIZwAUQFEIhAQAgQoD/ZyAAAAAA","439":"b:AJIYQAUABEIBAQAgQoBvZyAAAAAA","461":"b:AJIYQAUABEIAAQAgQoBvZyAAAAAA","531":[57],"532":[20,57],"636":[19,20,57,97,113,120],"644":[113,117,118,121]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/ParameterInputHint.vue":{"13":"b:AIIBAAAABMABEUIgQsmvXyAAAAAA","21":"b:AIIBAAAABMABEUIgQsmvXyAAAAAA","23":[72],"27":"b:AAIAAAAAAIAAAUIAAEgPHwAAAAAA","39":"b:AIIBAAAABMABEUIgQsmvXyAAAAAA","43":"b:AIIBAAAABMABEUIgQsmvXyAAAAAA"},"packages/frontend/editor-ui/src/features/shared/tags/components/TagsContainer.vue":{"20":"b:AAAAAAAAAAACAAEAAAAAQBwNAAAA","37":"b:AAAAAAAAAAACAAEAAAAAQBwNAAAA","41":"b:AAAAAAAAAAACAAEAAAAAQBwNAAAA","42":[65,80,126,130,136],"48":[65,80,126,130,136],"55":[65,80,126,130,136],"63":[65,80,126,130,136],"81":"b:AAAAAAAAAAACAAEAAAAAQBwNAAAA","87":"b:AAAAAAAAAAACAAEAAAAAQBwNAAAA","95":[65,80,126,130,136],"101":[65,130],"112":"b:AAAAAAAAAAACAAEAAAAAQBwNAAAA","117":[65,130,132],"120":"b:AAAAAAAAAAACAAEAAAAAQBwNAAAA","131":"b:AAAAAAAAAAACAAEAAAAAQBwNAAAA","134":[65,80,126,130,136],"137":[65,130],"152":[65,80,126,130,136]},"packages/frontend/editor-ui/src/features/shared/tags/components/WorkflowTagsContainer.vue":{"16":"b:AAAAAAAAAAACAAEAAAAAQBwNAAAA","22":"b:AAAAAAAAAAACAAEAAAAAQBwNAAAA","24":[65,130],"26":"b:AAAAAAAAAAACAAEAAAAAQBwNAAAA"},"packages/core/src/errors/error-reporter.ts":{"70":[142,48,91,117,120,123,138,139],"87":[142,48,91,117,120,123,138,139],"95":[142,48,91,117,120,123,138,139],"123":[142,48,91,117,120,123,138,139],"125":[142,48,91,117,120,123,138,139],"129":[142,48,91,117,120,123,138,139],"147":[142,48,91,117,120,123,138,139],"153":[142,48,91,117,120,123,138,139],"158":[142,48,91,117,120,123,138,139],"176":[142,48,91,117,120,123,138,139],"200":[142,48,91,117,120,123,138,139],"201":[142,48,91,117,120,123,138,139],"237":[142,48,91,117,120,123,138,139],"238":[142,48,91,117,120,123,138,139],"241":[142,48,91,117,120,123,138,139],"268":[142,48,91,117,120,123,138,139],"272":[142,48,91,117,120,123,138,139],"278":[142,48,91,117,120,123,138,139],"325":[142,48,91,117,120,123,138,139],"331":[142,48,91,117,120,123,138,139],"335":[142,48,91,117,120,123,138,139],"339":[142,48,91,117,120,123,138,139],"346":[142,48,91,117,120,123,138,139],"351":[142,48,91,117,120,123,138,139],"355":[142,48,91,117,120,123,138,139],"359":[142,48,91,117,120,123,138,139],"369":[142,48,91,117,120,123,138,139],"375":[142,48,91,117,120,123,138,139],"391":[142,48,91,117,120,123,138,139],"393":[142,48,91,117,120,123,138,139]},"packages/core/src/execution-engine/node-execution-context/hook-context.ts":{"21":[139],"34":[139],"38":[139],"42":[139],"54":[139],"61":[139]},"packages/nodes-base/nodes/Google/GenericFunctions.ts":{"70":[11,44,121,123,139],"125":[11,44,121,123,139]},"packages/nodes-base/nodes/Google/Sheet/GoogleSheets.node.ts":{"8":[123,139]},"packages/nodes-base/nodes/Google/Sheet/v1/GenericFunctions.ts":{"20":[123,139],"72":[123,139],"96":[123,139],"99":[123,139]},"packages/nodes-base/nodes/Google/Sheet/v1/GoogleSheet.ts":{"48":[123,139],"66":[123,139],"78":[123,139],"97":[123,139],"119":[123,139],"138":[123,139],"156":[123,139],"175":[123,139],"194":[123,139],"218":[123,139],"250":[123,139],"270":[123,139],"286":[123,139],"300":[123,139],"386":[123,139],"470":[123,139],"542":[123,139],"574":[123,139],"576":[123,139]},"packages/nodes-base/nodes/Google/Sheet/v1/GoogleSheetsV1.node.ts":{"32":[123,139],"42":[123,139],"68":[123,139],"96":[123,139],"125":[123,139],"227":[123,139],"299":[123,139],"413":[123,139]},"packages/nodes-base/nodes/Google/Sheet/v2/GoogleSheetsV2.node.ts":{"15":[123,139],"29":[123,139]},"packages/nodes-base/nodes/Google/Sheet/v2/actions/router.ts":{"9":[123,139]},"packages/nodes-base/nodes/Google/Sheet/v2/actions/sheet/append.operation.ts":{"213":[123,139],"326":[123,139]},"packages/nodes-base/nodes/Google/Sheet/v2/actions/sheet/appendOrUpdate.operation.ts":{"264":[123,139],"365":[123,139],"374":[123,139],"392":[123,139],"424":[123,139],"447":[123,139],"521":[123,139]},"packages/nodes-base/nodes/Google/Sheet/v2/actions/sheet/clear.operation.ts":{"160":[123,139]},"packages/nodes-base/nodes/Google/Sheet/v2/actions/sheet/create.operation.ts":{"77":[123,139]},"packages/nodes-base/nodes/Google/Sheet/v2/actions/sheet/delete.operation.ts":{"114":[123,139]},"packages/nodes-base/nodes/Google/Sheet/v2/actions/sheet/read.operation.ts":{"170":[123,139]},"packages/nodes-base/nodes/Google/Sheet/v2/actions/sheet/remove.operation.ts":{"7":[123,139]},"packages/nodes-base/nodes/Google/Sheet/v2/actions/sheet/update.operation.ts":{"253":[123,139],"345":[123,139],"354":[123,139],"371":[123,139],"403":[123,139],"430":[123,139],"496":[123,139]},"packages/nodes-base/nodes/Google/Sheet/v2/actions/spreadsheet/create.operation.ts":{"118":[123,139]},"packages/nodes-base/nodes/Google/Sheet/v2/actions/spreadsheet/delete.operation.ts":{"68":[123,139]},"packages/nodes-base/nodes/Google/Sheet/v2/actions/utils/readOperation.ts":{"12":[123,139],"110":[123,139]},"packages/nodes-base/nodes/Google/Sheet/v2/helpers/GoogleSheet.ts":{"39":[123,139],"47":[123,139],"58":[123,139],"74":[123,139],"93":[123,139],"117":[123,139],"136":[123,139],"149":[123,139],"165":[123,139],"178":[123,139],"186":[123,139],"204":[123,139],"220":[123,139],"262":[123,139],"285":[123,139],"331":[123,139],"365":[123,139],"378":[123,139],"392":[123,139],"409":[123,139],"439":[123,139],"444":[123,139],"459":[123,139],"478":[123,139],"492":[123,139],"543":[123,139],"625":[123,139],"673":[123,139],"801":[123,139],"831":[123,139],"833":[123,139],"855":[123,139],"878":[123,139]},"packages/nodes-base/nodes/Google/Sheet/v2/helpers/GoogleSheets.utils.ts":{"24":[123,139],"50":[123,139],"56":[123,139],"69":[123,139],"79":[123,139],"82":[123,139],"99":[123,139],"101":[123,139],"106":[123,139],"108":[123,139],"115":[123,139],"117":[123,139],"120":[123,139],"128":[123,139],"134":[123,139],"135":[123,139],"146":[123,139],"149":[123,139],"151":[123,139],"156":[123,139],"161":[123,139],"162":[123,139],"166":[123,139],"199":[123,139],"206":[123,139],"208":[123,139],"211":[123,139],"238":[123,139],"272":[123,139],"281":[123,139],"282":[123,139],"305":[123,139],"310":[123,139],"311":[123,139],"326":[123,139],"334":[123,139],"336":[123,139],"351":[123,139],"358":[123,139],"364":[123,139],"368":[123,139],"369":[123,139],"371":[123,139]},"packages/nodes-base/nodes/Google/Sheet/v2/methods/credentialTest.ts":{"9":[123,139]},"packages/nodes-base/nodes/Google/Sheet/v2/methods/listSearch.ts":{"13":[123,139],"42":[123,139],"51":[123,139]},"packages/nodes-base/nodes/Google/Sheet/v2/methods/loadOptions.ts":{"8":[123,139],"39":[123,139],"83":[123,139],"92":[123,139],"95":[123,139],"99":[123,139],"109":[123,139],"113":[123,139]},"packages/nodes-base/nodes/Google/Sheet/v2/methods/resourceMapping.ts":{"12":[123,139],"52":[123,139],"54":[123,139]},"packages/nodes-base/nodes/Google/Sheet/v2/transport/index.ts":{"15":[123,139],"82":[123,139]},"packages/nodes-base/nodes/Hubspot/HubspotTrigger.node.ts":{"16":[139],"326":[139],"329":[139],"332":[139],"335":[139],"343":[139],"390":[139],"424":[139],"453":[139]},"packages/nodes-base/nodes/Hubspot/V1/GenericFunctions.ts":{"15":[139],"78":[139],"114":[139],"125":[139],"1923":[139],"1925":[139],"1930":[139],"1933":[139],"1948":[139],"1957":[139],"1967":[139],"1978":[139],"1994":[139]},"packages/nodes-base/nodes/If/If.node.ts":{"8":[13,59,105,107,110,116,118,139]},"packages/nodes-base/nodes/If/V1/IfV1.node.ts":{"16":"b:ACAAAAAAAAgAAAAAAEpQAgAIAAAA","310":"b:ACAAAAAAAAgAAAAAAEpQAgAIAAAA","319":"b:ACAAAAAAAAgAAAAAAEpQAgAIAAAA","321":"b:ACAAAAAAAAgAAAAAAEpQAgAIAAAA","327":"b:ACAAAAAAAAgAAAAAAEpQAgAIAAAA","329":"b:ACAAAAAAAAgAAAAAAEpQAgAIAAAA","331":"b:ACAAAAAAAAgAAAAAAEpQAgAIAAAA","333":"b:ACAAAAAAAAgAAAAAAEpQAgAIAAAA","335":"b:ACAAAAAAAAgAAAAAAEpQAgAIAAAA","337":"b:ACAAAAAAAAgAAAAAAEpQAgAIAAAA","339":"b:ACAAAAAAAAgAAAAAAEpQAgAIAAAA","340":"b:ACAAAAAAAAgAAAAAAEpQAgAIAAAA","341":"b:ACAAAAAAAAgAAAAAAEpQAgAIAAAA","343":"b:ACAAAAAAAAgAAAAAAEpQAgAIAAAA","345":"b:ACAAAAAAAAgAAAAAAEpQAgAIAAAA","347":"b:ACAAAAAAAAgAAAAAAEpQAgAIAAAA","349":"b:ACAAAAAAAAgAAAAAAEpQAgAIAAAA","351":"b:ACAAAAAAAAgAAAAAAEpQAgAIAAAA","353":"b:ACAAAAAAAAgAAAAAAEpQAgAIAAAA","359":"b:ACAAAAAAAAgAAAAAAEpQAgAIAAAA","367":"b:ACAAAAAAAAgAAAAAAEpQAgAIAAAA","381":"b:ACAAAAAAAAgAAAAAAEpQAgAIAAAA","398":"b:ACAAAAAAAAgAAAAAAEpQAgAIAAAA"},"packages/nodes-base/nodes/If/V2/IfV2.node.ts":{"21":"b:ACAAAAAAAAgAAAAAAEpwAAAIAAAA","96":"b:ACAAAAAAAAgAAAAAAEpwAAAIAAAA","100":"b:ACAAAAAAAAgAAAAAAEpwAAAIAAAA"},"packages/nodes-base/nodes/If/V2/utils.ts":{"3":"b:ACAAAAAAAAhAAAAAAkhSAAAIAAAA","7":"b:ACAAAAAAAAhAAAAAAkhSAAAIAAAA","8":"b:ACAAAAAAAAhAAAAAAkhSAAAIAAAA"},"packages/nodes-base/nodes/NoOp/NoOp.node.ts":{"26":"b:AAAAAAAAABhhCAAAAAgGAgAIAAEA"},"packages/nodes-base/nodes/StickyNote/StickyNote.node.ts":{"57":[70,101,107,127,139]},"packages/workflow/src/errors/abstract/execution-base.error.ts":{"25":"b:AIIAAAAmAAAAAAAAAEwACQBIAAAA","41":"b:AIIAAAAmAAAAAAAAAEwACQBIAAAA"},"packages/workflow/src/errors/abstract/node.error.ts":{"40":"b:AIIAIAAmAAAAAAAAAAwACQBIAAAA","78":"b:AIIAIAAmAAAAAAAAAAwACQBIAAAA","98":"b:AIIAIAAmAAAAAAAAAAwACQBIAAAA","106":"b:AIIAIAAmAAAAAAAAAAwACQBIAAAA","138":"b:AIIAIAAmAAAAAAAAAAwACQBIAAAA","148":"b:AIIAIAAmAAAAAAAAAAwACQBIAAAA"},"packages/workflow/src/errors/node-operation.error.ts":{"12":[9,15,142,41,42,107,117,139],"28":[9,15,142,41,42,107,117,139]},"packages/@n8n/design-system/src/components/N8nIcon/custom/node-pin.svg":{"11":"b:AABAAAAAAABAAAAASI1/BwEJAAAA"},"packages/@n8n/design-system/src/components/N8nIcon/nodes/edit-image.svg":{"11":[50,51,139]},"packages/@n8n/design-system/src/components/N8nIcon/nodes/if.svg":{"11":"b:ACAAAAAAAAgAAAAAAEpwAgAJAAAA"},"packages/@n8n/design-system/src/components/N8nMarkdown/Markdown.vue":{"37":[70,79,101,107,127,136,138,139],"82":[70,79,101,107,127,136,138,139],"89":[139],"110":[101,136,139],"143":[70,79,101,107,127,136,138,139],"200":[101],"218":[70,79,101,107,127,136,138,139],"236":[138,139]},"packages/@n8n/design-system/src/components/N8nMarkdown/youtube.ts":{"34":[70,79,101,107,127,136,138,139],"42":[70,101,107,127,136,139]},"packages/@n8n/design-system/src/components/N8nSticky/Sticky.vue":{"16":[70,79,101,107,127,136,139],"28":[70,79,101,107,127,136,139],"32":[70,79,101,107,127,136,139],"36":[70,79,101,107,127,136,139],"38":[70,79,101,107,127,136,139],"43":[70,79,101,107,127,136,139],"58":[70,79,101,107,127,136,139],"65":[70,79,101,107,127,136,139],"99":[70,79,101,107,127,136,139]},"packages/@n8n/design-system/src/utils/markdown.ts":{"36":[139]},"packages/frontend/editor-ui/src/app/components/CollectionWorkflowCard.vue":{"12":[139],"13":[139],"17":[139]},"packages/frontend/editor-ui/src/app/components/NodeList.vue":{"19":[138,139],"23":[139],"27":[138,139],"31":[138,139],"36":[138,139],"42":[138,139]},"packages/frontend/editor-ui/src/app/views/WorkflowOnboardingView.vue":{"17":[139],"55":[139]},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/nodes/render-types/CanvasNodeStickyNote.vue":{"15":[151,70,79,101,107,127,136,139],"27":[151,70,79,101,107,127,136,139],"29":[151,70,79,101,107,127,136,139],"39":[151],"57":[151],"63":[151],"75":[151],"83":[151,101],"91":[151,70,79,101,107,127,136,139],"95":[151],"98":[151,70,79,101,107,127,136,139]},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/nodes/toolbar/CanvasNodeStickyColorSelector.vue":{"10":[151,70,79,101,107,127,136,139],"17":[151,101],"21":[151,101],"27":[151],"31":[151,101],"35":[151],"40":[151],"44":[151],"49":[151],"53":[151,101],"60":[151],"61":[151],"66":[151,70,79,101,107,127,136,139],"70":[151],"73":[151,70,79,101,107,127,136,139],"86":[151,70,79,101,107,127,136,139],"95":[151,101],"98":[151,101],"135":[151]},"packages/frontend/editor-ui/src/features/workflows/templates/components/TemplateCard.vue":{"12":[138,139],"37":[138],"41":[139],"43":[138,139],"65":[138,139],"71":[138,139],"75":[138,139]},"packages/frontend/editor-ui/src/features/workflows/templates/components/TemplateFilters.vue":{"15":[139],"34":[139],"38":[139],"43":[139],"44":[139],"52":[139],"60":[139],"68":[139],"69":[139],"80":[139],"81":[139],"91":[139],"108":[139],"118":[139]},"packages/frontend/editor-ui/src/features/workflows/templates/components/TemplateList.vue":{"38":[138,139],"47":[138,139],"71":[139],"74":[138],"83":[138,139],"90":[138,139],"97":[139],"98":[138]},"packages/frontend/editor-ui/src/features/workflows/templates/components/TemplatesInfoCard.vue":{"21":[139],"29":[139]},"packages/frontend/editor-ui/src/features/workflows/templates/components/TemplatesInfoCarousel.vue":{"11":[139],"37":[139],"64":[139],"65":[139],"67":[139],"73":[139],"74":[139],"76":[139],"82":[139],"95":[139],"101":[139],"112":[139],"113":[139],"115":[139]},"packages/frontend/editor-ui/src/features/workflows/templates/recommendations/components/RecommendedTemplateCard.vue":{"35":[139],"38":[139],"43":[139],"46":[139],"71":[139],"82":[139],"101":[139],"109":[139],"121":[139],"137":[139],"148":[139],"177":[139],"187":[139]},"packages/frontend/editor-ui/src/features/workflows/templates/utils/templateActions.ts":{"30":[138],"72":[138],"100":[139],"128":[138,139],"132":[138,139],"137":[138,139]},"packages/frontend/editor-ui/src/features/workflows/templates/views/TemplatesSearchView.vue":{"51":[139],"54":[139],"61":[139],"65":[139],"69":[139],"73":[139],"87":[139],"105":[139],"106":[139],"110":[139],"115":[139],"125":[139],"129":[139],"137":[139],"149":[139],"156":[139],"166":[139],"173":[139],"178":[139],"192":[139],"196":[139],"206":[139],"220":[139],"258":[139],"277":[139],"285":[139],"297":[139],"310":[139],"319":[139],"330":[139],"379":[139],"386":[139],"410":[139]},"packages/frontend/editor-ui/src/features/workflows/templates/views/TemplatesWorkflowView.vue":{"35":[139],"39":[139],"41":[139],"58":[139],"68":[139],"69":[139],"80":[139],"102":[139],"119":[139],"126":[139],"160":[139],"165":[139]},"packages/@n8n/backend-common/src/index.ts":{"5":"b:APsCGX5wALXxGFQEAFACEZjUJKIA","6":"b:APsCGX5wALXxGFQEAFACEZjUJKIA","7":"b:APsCGX5wALXxGFQEAFACEZjUJKIA","9":"b:APsCGX5wALXxGFQEAFACEZjUJKIA","10":"b:APsCGX5wALXxGFQEAFACEZjUJKIA","14":"b:APsCGX5wALXxGFQEAFACEZjUJKIA"},"packages/@n8n/db/src/index.ts":{"15":"b:INsCXX6gAbXyCHQEAFoCEYjSBDAA","17":"b:INsCXX6gAbXyCHQEAFoCEYjSBDAA","18":"b:INsCXX6gAbXyCHQEAFoCEYjSBDAA","19":"b:INsCXX6gAbXyCHQEAFoCEYjSBDAA","34":"b:INsCXX6gAbXyCHQEAFoCEYjSBDAA","42":"b:INsCXX6gAbXyCHQEAFoCEYjSBDAA","44":"b:INsCXX6gAbXyCHQEAFoCEYjSBDAA"},"packages/@n8n/db/src/utils/sql.ts":{"4":"b:IAgAXQIgAAAyAHQEAAIAAAgAAAAA"},"packages/cli/src/middlewares/list-query/dtos/base.filter.dto.ts":{"7":"b:YAgAXQJwAAAwAFQEAAIAABgAAAAA","23":"b:YAgAXQJwAAAwAFQEAAIAABgAAAAA"},"packages/cli/src/modules/insights/database/repositories/insights-by-period-query.helper.ts":{"23":"b:IAgAXQIgAAAyAHQEAAIAAAgAAAAA","55":"b:IAgAXQIgAAAyAHQEAAIAAAgAAAAA"},"packages/cli/src/modules/insights/database/repositories/insights-by-period.repository.ts":{"38":"b:IAgAXQIgAAAyAHQEAAIAAAgAAAAA","39":"b:IAgAXQIgAAAyAHQEAAIAAAgAAAAA","40":"b:IAgAXQIgAAAyAHQEAAIAAAgAAAAA","41":"b:IAgAXQIgAAAyAHQEAAIAAAgAAAAA","42":"b:IAgAXQIgAAAyAHQEAAIAAAgAAAAA","43":"b:IAgAXQIgAAAyAHQEAAIAAAgAAAAA","44":"b:IAgAXQIgAAAyAHQEAAIAAAgAAAAA","51":"b:IAgAXQIgAAAyAHQEAAIAAAgAAAAA","55":"b:IAgAXQIgAAAyAHQEAAIAAAgAAAAA","79":"b:IAgAXQIgAAAyAHQEAAIAAAgAAAAA","83":"b:IAgAXQIgAAAyAHQEAAIAAAgAAAAA","87":"b:IAgAXQIgAAAyAHQEAAIAAAgAAAAA","97":"b:IAgAXQIgAAAyAHQEAAIAAAgAAAAA","111":"b:IAgAXQIgAAAyAHQEAAIAAAgAAAAA","119":"b:IAgAXQIgAAAyAHQEAAIAAAgAAAAA","137":"b:IAgAXQIgAAAyAHQEAAIAAAgAAAAA","160":"b:IAgAXQIgAAAyAHQEAAIAAAgAAAAA","204":"b:IAgAXQIgAAAyAHQEAAIAAAgAAAAA","240":"b:IAgAXQIgAAAyAHQEAAIAAAgAAAAA","259":"b:IAgAXQIgAAAyAHQEAAIAAAgAAAAA","305":"b:IAgAXQIgAAAyAHQEAAIAAAgAAAAA","310":"b:IAgAXQIgAAAyAHQEAAIAAAgAAAAA","323":"b:IAgAXQIgAAAyAHQEAAIAAAgAAAAA","392":"b:IAgAXQIgAAAyAHQEAAIAAAgAAAAA","407":"b:IAgAXQIgAAAyAHQEAAIAAAgAAAAA","431":"b:IAgAXQIgAAAyAHQEAAIAAAgAAAAA"},"packages/cli/src/modules/insights/insights.controller.ts":{"22":"b:IAgAXQIgAAAyAHQEAAIAAAgAAAAA","26":"b:IAgAXQIgAAAyAHQEAAIAAAgAAAAA","43":"b:IAgAXQIgAAAyAHQEAAIAAAgAAAAA","63":"b:IAgAXQIgAAAyAHQEAAIAAAgAAAAA","85":"b:IAgAXQIgAAAyAHQEAAIAAAgAAAAA","102":"b:IAgAXQIgAAAyAHQEAAIAAAgAAAAA","109":"b:IAgAXQIgAAAyAHQEAAIAAAgAAAAA","123":"b:IAgAXQIgAAAyAHQEAAIAAAgAAAAA","127":"b:IAgAXQIgAAAyAHQEAAIAAAgAAAAA","141":"b:IAgAXQIgAAAyAHQEAAIAAAgAAAAA","157":"b:IAgAXQIgAAAyAHQEAAIAAAgAAAAA"},"packages/cli/src/modules/insights/insights.service.ts":{"17":"b:IAgAXQIgAAAyAHQEAAIAAAgAAAAA","28":"b:IAgAXQIgAAAyAHQEAAIAAAgAAAAA","37":"b:IAgAXQIgAAAyAHQEAAIAAAgAAAAA","46":"b:IAgAXQIgAAAyAHQEAAIAAAgAAAAA","53":"b:IAgAXQIgAAAyAHQEAAIAAAgAAAAA","59":"b:IAgAXQIgAAAyAHQEAAIAAAgAAAAA","64":"b:IAgAXQIgAAAyAHQEAAIAAAgAAAAA","69":"b:IAgAXQIgAAAyAHQEAAIAAAgAAAAA","91":"b:IAgAXQIgAAAyAHQEAAIAAAgAAAAA","99":"b:IAgAXQIgAAAyAHQEAAIAAAgAAAAA","128":"b:IAgAXQIgAAAyAHQEAAIAAAgAAAAA","163":"b:IAgAXQIgAAAyAHQEAAIAAAgAAAAA","193":"b:IAgAXQIgAAAyAHQEAAIAAAgAAAAA","214":"b:IAgAXQIgAAAyAHQEAAIAAAgAAAAA","247":"b:IAgAXQIgAAAyAHQEAAIAAAgAAAAA","272":"b:IAgAXQIgAAAyAHQEAAIAAAgAAAAA"},"packages/nodes-base/nodes/Form/Form.node.ts":{"354":"b:ACgQAAAQEIMABQAAAAAAAAAEAAAA","437":"b:ACgQAAAQEIMABQAAAAAAAAAEAAAA","445":"b:ACgQAAAQEIMABQAAAAAAAAAEAAAA","455":"b:ACgQAAAQEIMABQAAAAAAAAAEAAAA"},"packages/nodes-base/nodes/Form/utils/formCompletionUtils.ts":{"21":"b:ACgQAAAQEIMABQAAAAAAAAAEAAAA","25":"b:ACgQAAAQEIMABQAAAAAAAAAEAAAA","32":"b:ACgQAAAQEIMABQAAAAAAAAAEAAAA","51":"b:ACgQAAAQEIMABQAAAAAAAAAEAAAA"},"packages/nodes-base/nodes/Form/utils/formNodeUtils.ts":{"14":"b:ACgQAAAQEIMABQAAAAAAAAAEAAAA","84":"b:ACgQAAAQEIMABQAAAAAAAAAEAAAA","87":"b:ACgQAAAQEIMABQAAAAAAAAAEAAAA"},"packages/nodes-base/nodes/Form/utils/utils.ts":{"58":"b:ACgYAAAQEINABQAAAEAAAKAkAAAA","71":"b:ACgYAAAQEINABQAAAEAAAKAkAAAA","149":"b:ACgYAAAQEINABQAAAEAAAKAkAAAA","150":"b:ACgYAAAQEINABQAAAEAAAKAkAAAA","153":"b:ACgYAAAQEINABQAAAEAAAKAkAAAA","154":"b:ACgYAAAQEINABQAAAEAAAKAkAAAA","166":"b:ACgYAAAQEINABQAAAEAAAKAkAAAA","186":"b:ACgYAAAQEINABQAAAEAAAKAkAAAA","198":"b:ACgYAAAQEINABQAAAEAAAKAkAAAA","209":"b:ACgYAAAQEINABQAAAEAAAKAkAAAA","217":"b:ACgYAAAQEINABQAAAEAAAKAkAAAA","296":"b:ACgYAAAQEINABQAAAEAAAKAkAAAA","316":"b:ACgYAAAQEINABQAAAEAAAKAkAAAA","338":"b:ACgYAAAQEINABQAAAEAAAKAkAAAA","344":"b:ACgYAAAQEINABQAAAEAAAKAkAAAA","383":"b:ACgYAAAQEINABQAAAEAAAKAkAAAA","434":"b:ACgYAAAQEINABQAAAEAAAKAkAAAA","463":"b:ACgYAAAQEINABQAAAEAAAKAkAAAA","541":"b:ACgYAAAQEINABQAAAEAAAKAkAAAA","581":"b:ACgYAAAQEINABQAAAEAAAKAkAAAA","633":"b:ACgYAAAQEINABQAAAEAAAKAkAAAA","634":"b:ACgYAAAQEINABQAAAEAAAKAkAAAA","643":"b:ACgYAAAQEINABQAAAEAAAKAkAAAA","645":"b:ACgYAAAQEINABQAAAEAAAKAkAAAA","661":"b:ACgYAAAQEINABQAAAEAAAKAkAAAA","682":"b:ACgYAAAQEINABQAAAEAAAKAkAAAA","711":"b:ACgYAAAQEINABQAAAEAAAKAkAAAA","749":"b:ACgYAAAQEINABQAAAEAAAKAkAAAA","758":"b:ACgYAAAQEINABQAAAEAAAKAkAAAA","932":"b:ACgYAAAQEINABQAAAEAAAKAkAAAA","961":"b:ACgYAAAQEINABQAAAEAAAKAkAAAA"},"packages/nodes-base/nodes/Google/Gmail/GenericFunctions.ts":{"30":[11,44,121],"146":[11,44,121],"209":[11,44,121],"233":[11,44,121],"255":[11,44,121],"278":[11,44,121],"286":[11,44,121],"340":[11,44,121],"397":[11,44,121],"405":[11,44,121],"425":[11,44,121],"465":[11,44,121],"498":[11,44,121],"499":[11,44,121],"509":[11,44,121],"514":[11,44,121],"518":[11,44,121],"520":[11,44,121],"527":[11,44,121],"539":[11,44,121],"556":[11,44,121]},"packages/nodes-base/nodes/Google/Gmail/Gmail.node.ts":{"8":[11,44,121]},"packages/nodes-base/nodes/Google/Gmail/utils/replyToEmail.ts":{"15":[11,44,121],"70":[11,44,121],"75":[11,44,121],"92":[11,44,121],"102":[11,44,121]},"packages/nodes-base/nodes/Google/Gmail/v1/GmailV1.node.ts":{"134":[11,44,121],"147":[11,44,121],"260":[11,44,121],"267":[11,44,121],"275":[11,44,121],"347":[11,44,121],"354":[11,44,121],"362":[11,44,121],"417":[11,44,121],"421":[11,44,121],"587":[11,44,121],"595":[11,44,121],"603":[11,44,121]},"packages/nodes-base/nodes/Google/Gmail/v2/GmailV2.node.ts":{"157":[11,44,121],"174":[11,44,121]},"packages/nodes-base/nodes/Google/Gmail/v2/loadOptions.ts":{"5":[11,44,121],"29":[11,44,121]},"packages/nodes-base/nodes/Google/Gmail/v2/utils/draft.ts":{"7":[11,44,121],"14":[11,44,121],"21":[11,44,121],"32":[11,44,121]},"packages/nodes-base/nodes/ManualTrigger/ManualTrigger.node.ts":{"40":"b:AJsCoA4wELXgCAAAElwAEIgQAgAA","41":"b:AJsCoA4wELXgCAAAElwAEIgQAgAA"},"packages/nodes-base/nodes/Slack/Slack.node.ts":{"8":[11,13,44,52,63,72]},"packages/nodes-base/nodes/Slack/V1/GenericFunctions.ts":{"16":[11,13,44,52,63,72],"19":[11,13,44,52,63,72],"20":[11,13,44,52,63,72],"26":[11,13,44,52,63,72],"27":[11,13,44,52,63,72],"33":[11,13,44,52,63,72],"104":[11,13,44,52,63,72],"140":[11,13,44,52,63,72]},"packages/nodes-base/nodes/Slack/V1/SlackV1.node.ts":{"76":[11,13,44,52,63,72],"190":[11,13,44,52,63,72],"202":[11,13,44,52,63,72],"216":[11,13,44,52,63,72],"236":[11,13,44,52,63,72],"250":[11,13,44,52,63,72],"268":[11,13,44,52,63,72],"476":[11,13,44,52,63,72],"486":[11,13,44,52,63,72]},"packages/nodes-base/nodes/Slack/V2/GenericFunctions.ts":{"34":[11,13,44,52,63,72],"41":[11,13,44,52,63,72],"44":[11,13,44,52,63,72],"45":[11,13,44,52,63,72],"51":[11,13,44,52,63,72],"52":[11,13,44,52,63,72],"58":[11,13,44,52,63,72],"153":[11,13,44,52,63,72],"166":[11,13,44,52,63,72],"202":[11,13,44,52,63,72],"264":[11,13,44,52,63,72],"296":[11,13,44,52,63,72],"371":[11,13,44,52,63,72],"381":[11,13,44,52,63,72],"408":[11,13,44,52,63,72],"424":[11,13,44,52,63,72],"456":[11,13,44,52,63,72]},"packages/nodes-base/nodes/Slack/V2/SlackV2.node.ts":{"59":[11,13,44,52,63,72],"174":[11,13,44,52,63,72],"191":[11,13,44,52,63,72],"211":[11,13,44,52,63,72],"216":[11,13,44,52,63,72],"221":[11,13,44,52,63,72],"228":[11,13,44,52,63,72],"236":[11,13,44,52,63,72],"241":[11,13,44,52,63,72],"246":[11,13,44,52,63,72],"257":[11,13,44,52,63,72],"269":[11,13,44,52,63,72],"283":[11,13,44,52,63,72],"303":[11,13,44,52,63,72],"317":[11,13,44,52,63,72],"336":[11,13,44,52,63,72],"350":[11,13,44,52,63,72],"370":[11,13,44,52,63,72],"594":[11,13,44,52,63,72],"657":[11,13,44,52,63,72],"667":[11,13,44,52,63,72],"1459":[11,13,44,52,63,72],"1504":[11,13,44,52,63,72],"1532":[11,13,44,52,63,72]},"packages/nodes-base/utils/sendAndWait/configureWaitTillDate.util.ts":{"4":"b:ACgQAAAQEIMABQAAAAAAAAAEAAAA"},"packages/nodes-base/utils/sendAndWait/email-templates.ts":{"82":"b:ACgAAAAQEIEABQAAAAgAAAAEAAAA","147":"b:ACgAAAAQEIEABQAAAAgAAAAEAAAA"},"packages/nodes-base/utils/sendAndWait/utils.ts":{"58":"b:ACgAAAAQEIEABQAAAAgAAAAEAAAA","154":"b:ACgAAAAQEIEABQAAAAgAAAAEAAAA","309":"b:ACgAAAAQEIEABQAAAAgAAAAEAAAA","339":"b:ACgAAAAQEIEABQAAAAgAAAAEAAAA","349":"b:ACgAAAAQEIEABQAAAAgAAAAEAAAA","352":"b:ACgAAAAQEIEABQAAAAgAAAAEAAAA","482":"b:ACgAAAAQEIEABQAAAAgAAAAEAAAA","545":"b:ACgAAAAQEIEABQAAAAgAAAAEAAAA","553":"b:ACgAAAAQEIEABQAAAAgAAAAEAAAA","587":"b:ACgAAAAQEIEABQAAAAgAAAAEAAAA"},"packages/@n8n/design-system/src/components/AskAssistantButton/AskAssistantButton.vue":{"8":[9,10,11],"26":[9,10,11]},"packages/@n8n/design-system/src/components/AskAssistantChat/messages/BaseMessage.vue":{"16":[9,10,11,12,13,18],"26":[9,10,11,12,13,18]},"packages/@n8n/design-system/src/components/AskAssistantChat/messages/MessageWrapper.vue":{"22":[9,10,11,12,13,18],"30":[9,10,11,12,13,18],"33":[9,10,11,12,13,18],"47":[10],"48":[10]},"packages/@n8n/design-system/src/components/AskAssistantChat/messages/TextMessage.vue":{"31":[12],"40":[9,10,11,12,13,18],"42":[9,10,11,12,13,18],"52":[9,10,11,12,13,18],"53":[9,10,11,12,13,18],"58":[9,10,11,12,13,18],"80":[9,10,11,12,13,18],"89":[9,10,11,12,13,18],"137":[12]},"packages/@n8n/design-system/src/components/AskAssistantChat/messages/ThinkingMessage.vue":{"14":[9,10,11,12,13,18],"21":[9,10,11,12,13,18],"23":[9,10,11,12,13,18],"32":[9,10,11,12,13,18],"38":[9,10,11,12,13,18],"48":[9,10,11,12,13,18],"64":[9,10,11,12,13,18],"65":[9,10,11,12,13,18]},"packages/@n8n/design-system/src/components/AskAssistantChat/messages/helpers.ts":{"10":[9,10,11,12,13,18]},"packages/@n8n/design-system/src/components/AskAssistantChat/messages/useMarkdown.ts":{"6":[9,10,11,12,13,18],"20":[9,10,11,12,13,18]},"packages/@n8n/design-system/src/components/BlinkingCursor/BlinkingCursor.vue":{"2":[9,10,11,12,13]},"packages/@n8n/design-system/src/components/InlineAskAssistantButton/InlineAskAssistantButton.vue":{"8":[9,10,11,12],"37":[9,10,11,12],"39":[9,10,11],"42":[9,10,11,12]},"packages/@n8n/design-system/src/types/assistant.ts":{"165":[9,10,11,12,13,18],"221":[9,10,11,12,13,18],"227":[9,10,11,12,13,18],"239":[9,10,11,12,13,18]},"packages/frontend/editor-ui/src/app/components/CopyInput.vue":{"37":[107],"54":[11,44,46,64,84,107,123,138]},"packages/frontend/editor-ui/src/features/ai/assistant/assistant.api.ts":{"15":[13,151,18],"42":[9,10,11,12,151],"71":[10,151],"83":[151,103],"95":[151],"105":[151],"125":[13,151,18],"132":[151],"136":[151],"143":[151],"151":[151],"160":[151]},"packages/frontend/editor-ui/src/features/ai/assistant/components/Chat/AskAssistantChat.vue":{"13":[9,10,11,12],"27":[9,10,11,12],"32":[9,10,11,12],"34":[9,10,11,12],"39":[9,12],"50":[9,12],"65":[10],"72":[10],"80":[9,10,11,12],"84":[9,10,11,12],"87":[9,12],"96":[9],"108":[9,10,11,12]},"packages/frontend/editor-ui/src/features/ai/assistant/components/Chat/AskAssistantFloatingButton.vue":{"13":[9,10,11,65],"21":[9,10,11,65],"35":[65],"39":[65],"59":[9,10,11,65],"71":[65],"76":[9,10,11,65]},"packages/frontend/editor-ui/src/features/ai/assistant/components/Chat/AskModeEmptyState.vue":{"5":[9,10,11,12],"6":[9,10,11,12]},"packages/frontend/editor-ui/src/features/credentials/components/CredentialEdit/GoogleAuthButton.vue":{"2":[11,44,46,123]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/ResourceLocator/ResourceLocator.vue":{"76":"b:MIgBgAAQFAAgEAAgAECgCSAAAAAA","166":[120,123],"175":"b:MIgBgAAQFAAgEAAgAECgCSAAAAAA","188":"b:MIgBgAAQFAAgEAAgAECgCSAAAAAA","195":[117,123],"198":[117,123],"207":[117,123],"220":"b:MIgBgAAQFAAgEAAgAECgCSAAAAAA","233":"b:MIgBgAAQFAAgEAAgAECgCSAAAAAA","237":"b:MIgBgAAQFAAgEAAgAECgCSAAAAAA","241":"b:MIgBgAAQFAAgEAAgAECgCSAAAAAA","242":"b:MIgBgAAQFAAgEAAgAECgCSAAAAAA","254":"b:MIgBgAAQFAAgEAAgAECgCSAAAAAA","290":"b:MIgBgAAQFAAgEAAgAECgCSAAAAAA","300":"b:MIgBgAAQFAAgEAAgAECgCSAAAAAA","302":"b:MIgBgAAQFAAgEAAgAECgCSAAAAAA","315":"b:MIgBgAAQFAAgEAAgAECgCSAAAAAA","317":"b:MIgBgAAQFAAgEAAgAECgCSAAAAAA","320":[123],"328":"b:MIgBgAAQFAAgEAAgAECgCSAAAAAA","330":"b:MIgBgAAQFAAgEAAgAECgCSAAAAAA","337":"b:MIgBgAAQFAAgEAAgAECgCSAAAAAA","341":"b:MIgBgAAQFAAgEAAgAECgCSAAAAAA","342":"b:MIgBgAAQFAAgEAAgAECgCSAAAAAA","343":"b:MIgBgAAQFAAgEAAgAECgCSAAAAAA","346":[117,123],"350":"b:MIgBgAAQFAAgEAAgAECgCSAAAAAA","364":"b:MIgBgAAQFAAgEAAgAECgCSAAAAAA","370":"b:MIgBgAAQFAAgEAAgAECgCSAAAAAA","376":"b:MIgBgAAQFAAgEAAgAECgCSAAAAAA","380":"b:MIgBgAAQFAAgEAAgAECgCSAAAAAA","467":"b:MIgBgAAQFAAgEAAgAECgCSAAAAAA","473":[117,123],"481":"b:MIgBgAAQFAAgEAAgAECgCSAAAAAA","492":[120,123],"502":[117,123],"522":"b:MIgBgAAQFAAgEAAgAECgCSAAAAAA","523":[117,120,123],"543":"b:MIgBgAAQFAAgEAAgAECgCSAAAAAA","544":[15,16,31,44,69,76,120,123],"565":"b:MIgBgAAQFAAgEAAgAECgCSAAAAAA","569":"b:MIgBgAAQFAAgEAAgAECgCSAAAAAA","574":"b:MIgBgAAQFAAgEAAgAECgCSAAAAAA","579":"b:AIABAAAAFAAgEAAgAECgASAAAAAA","589":"b:MIgBgAAQFAAgEAAgAECgCSAAAAAA","595":[120,123],"622":"b:MIgBgAAQFAAgEAAgAECgCSAAAAAA","645":[123],"665":"b:MIgBgAAQFAAgEAAgAECgCSAAAAAA","667":"b:MIgBgAAQFAAgEAAgAECgCSAAAAAA","672":"b:MIgBgAAQFAAgEAAgAECgCSAAAAAA","680":[120,123],"697":[123],"703":[123],"709":[120,123],"728":[120,123],"750":[117,123],"757":[123],"769":[117,123],"780":[117,123],"897":[123],"910":[123],"918":[117,120,123],"943":"b:MIgBgAAQEAAgEAAgAECgCSAAAAAA","951":[117,123],"957":[117,123],"970":[117,120,123],"1013":"b:MIgBgAAQFAAgEAAgAECgCSAAAAAA","1043":[117,123],"1050":[117,123],"1055":[123],"1083":"b:MIgBgAAQFAAgEAAgAECgCSAAAAAA","1103":"b:MIgBgAAQFAAgEAAgAECgCSAAAAAA","1105":"b:MIgBgAAQFAAgEAAgAECgCCAAAAAA","1112":"b:MIgBgAAQFAAgEAAgAECgCCAAAAAA","1134":"b:MIgBgAAQFAAgEAAgAECgCSAAAAAA","1186":"b:AIgBAAAQFAAAEAAgAECgCQAAAAAA","1210":[120,123]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/ResourceLocator/ResourceLocatorDropdown.vue":{"13":"b:MIgBgAAQFAAgEAAgAECgCSMAAAAA","58":[123],"74":[69,123,129],"76":[123,129],"116":"b:MIgBgAAQFAAgEAAgAECgCSMAAAAA","117":[69,117,123,129],"123":[69,117,123,129],"132":"b:MIgBgAAQFAAgEAAgAECgCSMAAAAA","136":"b:AIABAAAAFAAgEAAgAECgASMAAAAA","196":[129],"200":[129],"213":[69,129],"216":[69,129],"227":[129],"242":[120,123],"248":"b:MIgBgAAQFAAgEAAgAECgCSMAAAAA","250":"b:MIgBgAAQFAAgEAAgAECgCSMAAAAA","264":"b:MIgBgAAQFAAgEAAgAECgCSMAAAAA","276":"b:MIgBgAAQFAAgEAAgAECgCSMAAAAA","279":[69,117,123,129],"301":[69,123,129],"338":[69,129],"340":[69,129],"348":[123,129],"359":[129],"360":[129],"387":[123,129]},"packages/frontend/editor-ui/src/features/shared/nodeCreator/components/ItemTypes/LabelItem.vue":{"11":"b:MAgAoAAQQAAiAAAgAAAlLSAAAAAA"},"packages/localhost-37381/assets/_plugin-vue_export-helper-Da88TEg1.js":{"2":[11,23,48,75,4,109,129,135]},"packages/localhost-37381/assets/chunk-CC9Q-vWm.js":{"8":[11,23,48,75,4,109,129,135],"9":[11,23,48,75,4,109,129,135],"10":[11,23,48,75,4,109,129,135],"19":[11,23,48,75,4,109,129,135],"23":[11,23,48,75,4,109,129,135],"29":[11,23,48,75,4,109,129,135],"33":[11,23,48,75,4,109,129,135],"34":[11,23,48,75,4,109,129,135]},"packages/localhost-37381/assets/shield-alt-B7h2cjjC.js":{"8":[11,4]},"packages/@n8n/db/src/repositories/folder.repository.ts":{"11":"b:4ACAXQIAAAA+ABQEAAIAABgAAAAA","15":"b:4ACAXQIAAAA+ABQEAAIAABgAAAAA","23":"b:4ACAXQIAAAA+ABQEAAIAABgAAAAA","28":"b:4ACAXQIAAAA+ABQEAAIAABgAAAAA","39":"b:4ACAXQIAAAA+ABQEAAIAABgAAAAA","51":"b:4ACAXQIAAAA+ABQEAAIAABgAAAAA","56":"b:4ACAXQIAAAA+ABQEAAIAABgAAAAA","66":"b:4ACAXQIAAAA+ABQEAAIAABgAAAAA","85":"b:4ACAXQIAAAA+ABQEAAIAABgAAAAA","98":"b:4ACAXQIAAAA+ABQEAAIAABgAAAAA","104":"b:4ACAXQIAAAA+ABQEAAIAABgAAAAA","136":"b:4ACAXQIAAAA+ABQEAAIAABgAAAAA","140":"b:4ACAXQIAAAA+ABQEAAIAABgAAAAA","144":"b:4ACAXQIAAAA+ABQEAAIAABgAAAAA","148":"b:4ACAXQIAAAA+ABQEAAIAABgAAAAA","165":"b:4ACAXQIAAAA+ABQEAAIAABgAAAAA","198":"b:4ACAXQIAAAA+ABQEAAIAABgAAAAA","209":"b:4ACAXQIAAAA+ABQEAAIAABgAAAAA","225":"b:4ACAXQIAAAA+ABQEAAIAABgAAAAA","235":"b:4ACAXQIAAAA+ABQEAAIAABgAAAAA","240":"b:4ACAXQIAAAA+ABQEAAIAABgAAAAA","254":"b:4ACAXQIAAAA+ABQEAAIAABgAAAAA","260":"b:4ACAXQIAAAA+ABQEAAIAABgAAAAA","276":"b:4ACAXQIAAAA+ABQEAAIAABgAAAAA","295":"b:4ACAXQIAAAA+ABQEAAIAABgAAAAA","312":"b:4ACAXQIAAAA+ABQEAAIAABgAAAAA","352":"b:4ACAXQIAAAA+ABQEAAIAABgAAAAA","386":"b:4ACAXQIAAAA+ABQEAAIAABgAAAAA","389":"b:4ACAXQIAAAA+ABQEAAIAABgAAAAA"},"packages/@n8n/db/src/utils/is-string-array.ts":{"1":"b:YACAXQIEAAA2ABQEAAIAABgCQCAA","2":"b:YACAXQIEAAA2ABQEAAIAABgCQCAA"},"packages/@n8n/decorators/src/timed.ts":{"16":"b:YACAXQIAAAA2ABQEAAIAABgAAAAA","17":"b:YACAXQIAAAA2ABQEAAIAABgAAAAA","18":"b:YACAXQIAAAA2ABQEAAIAABgAAAAA","23":"b:YACAXQIAAAA2ABQEAAIAABgAAAAA"},"packages/cli/src/middlewares/list-query/dtos/pagination.dto.ts":{"6":"b:YACAXQIAAAA2ABQEAAIAABgAAAAA","15":"b:YACAXQIAAAA2ABQEAAIAABgAAAAA"},"packages/cli/src/middlewares/list-query/dtos/workflow.filter.dto.ts":{"55":"b:YACAXQIAAAA2ABQEAAIAABgAAAAA"},"packages/cli/src/middlewares/list-query/dtos/workflow.sort-by.dto.ts":{"6":"b:YACAXQIAAAA2ABQEAAIAABgAAAAA","13":"b:YACAXQIAAAA2ABQEAAIAABgAAAAA"},"packages/frontend/editor-ui/src/app/components/Badge.vue":{"8":[23],"17":[23]},"packages/frontend/editor-ui/src/app/components/VersionCard.vue":{"13":[23],"17":[23]},"packages/@n8n/api-types/src/dto/data-table/list-data-table-content-query.dto.ts":{"12":[47,48],"39":[47,48]},"packages/@n8n/db/src/utils/transaction.ts":{"8":[36,37,38,47,48,156]},"packages/cli/src/modules/data-table/data-table-aggregate.service.ts":{"13":[48,137],"20":[48,137],"21":[48,137],"23":[48,137],"30":[48,137],"33":[48,137]},"packages/cli/src/modules/data-table/data-table-column.repository.ts":{"21":[47,48],"31":[47,48],"43":[47,48],"62":[47,48],"72":[47,48],"76":[47,48],"88":[47,48],"98":[47,48],"99":[47,48],"124":[47,48],"125":[47,48],"138":[47,48],"144":[47,48],"163":[47,48],"169":[47,48],"189":[47,48],"190":[47,48],"195":[47,48]},"packages/cli/src/modules/data-table/data-table-ddl.service.ts":{"21":[47,48],"23":[47,48],"28":[47,48],"42":[47,48],"43":[47,48],"51":[47,48],"57":[47,48],"62":[47,48],"68":[47,48],"73":[47,48],"80":[47,48]},"packages/cli/src/modules/data-table/data-table-rows.repository.ts":{"56":[47,48],"138":[47,48],"140":[47,48],"146":[47,48],"167":[47,48],"208":[47,48],"215":[47,48],"221":[47,48],"222":[47,48],"261":[47,48],"273":[47,48],"294":[47,48],"302":[47,48],"307":[47,48],"308":[47,48],"342":[47,48],"347":[47,48],"366":[47,48],"372":[47,48],"409":[47,48],"417":[47,48],"449":[47,48],"455":[47,48],"456":[47,48],"477":[47,48],"484":[47,48],"499":[47,48],"513":[47,48],"534":[47,48],"546":[47,48],"564":[47,48],"573":[47,48],"574":[47,48],"593":[47,48],"618":[47,48],"629":[47,48],"655":[47,48],"664":[47,48],"683":[47,48],"692":[47,48],"700":[47,48]},"packages/cli/src/modules/data-table/data-table.controller.ts":{"51":[47,48],"57":[47,48],"77":[47,48],"87":[47,48],"104":[47,48],"129":[47,48],"143":[47,48],"167":[47,48],"188":[47,48],"208":[47,48],"224":[47,48],"240":[47,48],"262":[47,48],"284":[47,48],"309":[47,48],"350":[47,48],"379":[47,48],"409":[47,48],"462":[47,48],"515":[47,48]},"packages/cli/src/modules/favorites/favorites.event-relay.ts":{"10":[36,37,39,42,48,67,132,137],"17":[36,37,39,42,48,67,132,137],"19":[36,37,39,42,48,67,132,137],"21":[36,37,39,42,48,67,132,137],"23":[36,37,39,42,48,67,132,137],"25":[36,37,39,42,48,67,132,137]},"packages/@n8n/design-system/src/components/N8nBreadcrumbs/Breadcrumbs.vue":{"34":[47,48,65,66,67],"59":[47,48,65,66,67],"65":[47,48,65,66,67],"69":[66],"73":[66],"74":[66],"81":[66],"107":[47,48,65,66,67],"108":[66],"114":[66],"123":[66],"124":[66],"142":[66],"143":[66],"158":[66],"172":[47,48,65,66,67],"211":[66],"212":[66],"238":[66],"245":[47,48,65,66,67],"257":[66],"258":[66],"259":[66],"261":[47,48,65,66,67]},"packages/frontend/editor-ui/src/features/core/dataTable/DataTableDetailsView.vue":{"49":[47,48],"51":[47,48],"69":[47,48],"88":[47],"96":[47],"103":[47],"111":[47],"143":[47,48],"150":[47,48],"157":[48],"200":[47,48],"203":[47,48],"207":[47,48],"218":[47,48]},"packages/frontend/editor-ui/src/features/core/dataTable/DataTableView.vue":{"64":[47,48],"65":[47,48],"73":[47,48],"75":[48],"82":[47,48],"100":[47,48],"120":[47,48],"125":[47,48],"142":[48],"161":[47,48],"165":[47,48],"166":[47,48],"201":[47,48],"211":[47,48]},"packages/frontend/editor-ui/src/features/core/dataTable/components/AddDataTableModal.vue":{"120":[47,48],"140":[47,48],"141":[47,48],"149":[47,48],"188":[47,48],"267":[47,48],"334":[47,48],"339":[47,48],"345":[47,48],"357":[47,48],"358":[47,48],"361":[47,48]},"packages/frontend/editor-ui/src/features/core/dataTable/components/DataTableActions.vue":{"53":[47,48],"54":[47,48],"56":[47,48],"91":[48],"153":[48]},"packages/frontend/editor-ui/src/features/core/dataTable/components/DataTableBreadcrumbs.vue":{"16":[47,48],"38":[47,48],"42":[47,48],"46":[47,48],"81":[47],"103":[47,48],"109":[47,48],"119":[47,48],"122":[47,48]},"packages/frontend/editor-ui/src/features/core/dataTable/components/DataTableCard.vue":{"34":[47,48],"44":[47,48],"49":[47,48],"50":[47,48],"55":[47,48],"64":[47,48],"67":[47,48],"74":[47,48],"81":[47,48],"93":[47,48],"105":[47,48],"114":[47,48],"120":[47,48]},"packages/frontend/editor-ui/src/features/core/dataTable/components/DownloadDataTableModal.vue":{"25":[47,48]},"packages/frontend/editor-ui/src/features/core/dataTable/components/ImportCsvModal.vue":{"21":[47,48],"143":[47,48],"154":[47,48]},"packages/frontend/editor-ui/src/features/core/dataTable/components/dataGrid/AddColumnButton.vue":{"31":[47,48],"48":[47,48],"67":[47,48],"69":[47],"72":[47],"78":[47],"114":[47],"123":[47],"129":[47],"142":[47,48],"154":[47,48],"160":[47,48],"174":[47],"184":[47],"217":[47],"221":[47],"222":[47],"243":[47]},"packages/frontend/editor-ui/src/features/core/dataTable/components/dataGrid/AddRowButton.vue":{"5":[47,48]},"packages/frontend/editor-ui/src/features/core/dataTable/components/dataGrid/ColumnHeader.vue":{"31":[47,48],"32":[47,48],"34":[47,48],"55":[47],"64":[47],"68":[47],"72":[47],"76":[47,48],"86":[47,48],"90":[47,48],"97":[47,48],"102":[47,48],"113":[47,48],"122":[47,48],"124":[47],"130":[47,48],"150":[47,48],"154":[47,48],"172":[47],"182":[47,48],"194":[47,48],"200":[47,48],"253":[47]},"packages/frontend/editor-ui/src/features/core/dataTable/components/dataGrid/DataTableTable.vue":{"49":[47,48],"51":[47,48],"69":[47,48],"90":[47,48],"117":[47,48],"120":[47],"128":[47],"132":[47],"136":[47],"140":[47,48],"157":[47],"162":[47,48],"163":[47],"193":[47,48]},"packages/frontend/editor-ui/src/features/core/dataTable/components/dataGrid/registerAgGridModulesOnce.ts":{"27":[47,48]},"packages/frontend/editor-ui/src/features/core/dataTable/composables/useAgGrid.ts":{"23":[47,48],"34":[47,48],"81":[47,48],"93":[47,48],"113":[47],"119":[47],"128":[47],"130":[47],"140":[47],"148":[47],"168":[47],"207":[47,48],"226":[47,48]},"packages/frontend/editor-ui/src/features/core/dataTable/composables/useDataTableColumnFilters.ts":{"19":[47,48]},"packages/frontend/editor-ui/src/features/core/dataTable/composables/useDataTableColumns.ts":{"40":[47,48],"59":[47,48],"66":[47],"97":[47],"123":[47,48],"132":[47,48],"159":[47,48],"161":[47,48],"214":[47,48],"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":{"57":[47,48],"113":[47],"114":[47],"132":[47],"135":[47],"204":[47],"228":[47],"238":[47],"254":[47],"277":[47],"330":[47,48],"354":[47],"390":[47]},"packages/frontend/editor-ui/src/features/core/dataTable/composables/useDataTablePagination.ts":{"11":[47,48],"17":[47,48],"21":[47],"32":[47]},"packages/frontend/editor-ui/src/features/core/dataTable/composables/useDataTableSelection.ts":{"5":[47,48],"13":[47,48],"18":[47],"19":[47,48],"23":[47],"27":[47],"36":[47,48]},"packages/frontend/editor-ui/src/features/core/dataTable/composables/useDataTableTypes.ts":{"8":[47,48],"9":[47,48],"18":[47,48],"25":[47,48]},"packages/frontend/editor-ui/src/features/core/dataTable/module.descriptor.ts":{"13":[47,48],"14":[47,48],"15":[47,48],"25":[47,48],"37":[48]},"packages/frontend/editor-ui/src/features/core/dataTable/typeGuards.ts":{"11":[47],"21":[47,48]},"packages/frontend/editor-ui/src/features/core/dataTable/utils/columnUtils.ts":{"26":[47],"29":[47],"35":[47,48],"36":[47,48],"51":[47,48],"52":[47,48],"65":[47,48],"66":[47,48],"94":[47,48],"95":[47],"119":[47],"126":[47,48],"135":[47],"141":[47],"149":[47,48],"156":[47,48],"163":[47,48],"170":[47,48],"177":[47],"184":[47,48],"191":[47,48],"198":[47,48],"205":[47,48],"212":[47,48],"219":[47,48],"229":[47,48],"241":[47],"253":[47]},"packages/@n8n/backend-common/src/utils/parse-flatted.ts":{"15":"b:ANMCAH4gALXACAAAAFACEYDQACAA"},"packages/@n8n/nodes-langchain/nodes/agents/Agent/AgentTool.node.ts":{"8":[75]},"packages/@n8n/nodes-langchain/nodes/agents/Agent/V2/AgentToolV2.node.ts":{"19":[75],"99":[75]},"packages/@n8n/nodes-langchain/nodes/agents/Agent/V2/utils.ts":{"11":[75],"23":[75],"26":[75],"86":[75],"89":[75]},"packages/@n8n/nodes-langchain/nodes/agents/Agent/V3/AgentToolV3.node.ts":{"22":[75],"101":[75]},"packages/@n8n/nodes-langchain/nodes/llms/LMChatOpenAi/LmChatOpenAi.node.ts":{"73":[15,75,119],"742":[15,75,119]},"packages/@n8n/nodes-langchain/nodes/llms/LMChatOpenAi/common.ts":{"15":[15,75,119],"18":[15,75,119],"21":[15,75,119],"24":[15,75,119],"27":[15,75,119],"30":[15,75,119],"86":[15,75,119]},"packages/@n8n/nodes-langchain/nodes/llms/LMChatOpenAi/methods/loadModels.ts":{"10":[15,75,119],"35":[15,75,119],"43":[15,75,119],"46":[15,75,119]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/helpers/error-handling.ts":{"11":[15,16,75,93,119],"15":[15,16,75,93,119],"19":[15,16,75,93,119],"36":[15,16,75,93,119]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/helpers/modelFiltering.ts":{"9":[15,75,93,119]},"packages/cli/src/executions/execution-redaction-proxy.service.ts":{"13":"b:ANMCAA4gALXACAAAAFQCEYDQAAAA","17":"b:ANMCAA4gALXACAAAAFQCEYDQAAAA","27":"b:ANMCAA4gALXACAAAAFQCEYDQAAAA"},"packages/cli/src/executions/execution.service.ee.ts":{"13":"b:ANMCAA4gALXACAAAAlQCEYAQAAAA","19":"b:ANMCAA4gALXACAAAAlQCEYAQAAAA"},"packages/cli/src/manual-execution.service.ts":{"27":"b:AJMCAA4gAPXACAAAg1wjEYAQAAAA","29":"b:AJMCAA4gAPXACAAAg1wjEYAQAAAA","49":"b:AJMCAA4gAPXACAAAg1wjEYAQAAAA","61":"b:AJMCAA4gAPXACAAAg1wjEYAQAAAA"},"packages/cli/src/modules/redaction/executions/execution-redaction.service.ts":{"37":"b:ANMCAA4gALXACAAAAFQCEYDQAAAA","45":"b:ANMCAA4gALXACAAAAFQCEYDQAAAA","57":"b:ANMCAA4gALXACAAAAFQCEYDQAAAA","74":"b:ANMCAA4gALXACAAAAFQCEYDQAAAA","89":"b:ANMCAA4gALXACAAAAFQCEYDQAAAA","96":"b:ANMCAA4gALXACAAAAFQCEYDQAAAA","99":"b:ANMCAA4gALXACAAAAFQCEYDQAAAA","191":"b:ANMCAA4gALXACAAAAFQCEYDQAAAA","239":"b:ANMCAA4gALXACAAAAFQCEYDQAAAA","272":"b:ANMCAA4gALXACAAAAFQCEYDQAAAA","273":"b:ANMCAA4gALXACAAAAFQCEYDQAAAA","274":"b:ANMCAA4gALXACAAAAFQCEYDQAAAA","291":"b:ANMCAA4gALXACAAAAFQCEYDQAAAA","306":"b:ANMCAA4gALXACAAAAFQCEYDQAAAA","325":"b:ANMCAA4gALXACAAAAFQCEYDQAAAA"},"packages/cli/src/tool-generation/index.ts":{"7":[41,44,75,119]},"packages/cli/src/utils/get-item-count-by-connection-type.ts":{"4":"b:ANMSAA4gALXACAAAAlQCEYAAAAAA","15":"b:ANMSAA4gALXACAAAAlQCEYAAAAAA"},"packages/cli/src/workflows/workflow-execution.service.ts":{"47":"b:BNMKAH4gAPfBCAAAg/xnE4AQAAEA","63":"b:BNMKAH4gAPfBCAAAg/xnE4AQAAEA","100":"b:BNMKAH4gAPfBCAAAg/xnE4AQAAEA","101":"b:BNMKAH4gAPfBCAAAg/xnE4AQAAEA","112":"b:BNMKAH4gAPfBCAAAg/xnE4AQAAEA","276":"b:BNMKAH4gAPfBCAAAg/xnE4AQAAEA","315":"b:BNMKAH4gAPfBCAAAg/xnE4AQAAEA","499":"b:BNMKAH4gAPfBCAAAg/xnE4AQAAEA","517":"b:BNMKAH4gAPfBCAAAg/xnE4AQAAEA","522":"b:BNMKAH4gAPfBCAAAg/xnE4AQAAEA","525":"b:BNMKAH4gAPfBCAAAg/xnE4AQAAEA","528":"b:BNMKAH4gAPfBCAAAg/xnE4AQAAEA","531":"b:BNMKAH4gAPfBCAAAg/xnE4AQAAEA","539":"b:BNMKAH4gAPfBCAAAg/xnE4AQAAEA","564":"b:BNMKAH4gAPfBCAAAg/xnE4AQAAEA","576":"b:BNMKAH4gAPfBCAAAg/xnE4AQAAEA","588":"b:BNMKAH4gAPfBCAAAg/xnE4AQAAEA","597":"b:BNMKAH4gAPfBCAAAg/xnE4AQAAEA","604":"b:BNMKAH4gAPfBCAAAg/xnE4AQAAEA"},"packages/cli/src/workflows/workflow-history/workflow-history.controller.ts":{"20":"b:AOM2AA4gALWiCAAAGlIAAYgEAAAA","23":"b:AOM2AA4gALWiCAAAGlIAAYgEAAAA","40":"b:AOM2AA4gALWiCAAAGlIAAYgEAAAA","58":"b:AOM2AA4gALWiCAAAGlIAAYgEAAAA","79":"b:AOM2AA4gALWiCAAAGlIAAYgEAAAA","92":"b:AOM2AA4gALWiCAAAGlIAAYgEAAAA"},"packages/core/src/execution-engine/node-execution-context/trigger-context.ts":{"19":"b:AJMCAA4gAJXACAAAAlgCEIAQACEA","23":"b:AJMCAA4gAJXACAAAAlgCEIAQACEA","27":"b:AJMCAA4gAJXACAAAAlgCEIAQACEA","34":"b:AJMCAA4gAJXACAAAAlgCEIAQACEA","56":"b:AJMCAA4gAJXACAAAAlgCEIAQACEA","60":"b:AJMCAA4gAJXACAAAAlgCEIAQACEA"},"packages/core/src/execution-engine/node-execution-context/utils/return-json-array.ts":{"8":"b:ANMCAA4gAJXACAAAAlQCEIAQAAEA","15":"b:ANMCAA4gAJXACAAAAlQCEIAQAAEA"},"packages/core/src/execution-engine/node-execution-context/utils/scheduling-helper-functions.ts":{"6":"b:AJMCAA4gAJXACAAgAlgCELAQACEA","13":"b:AJMCAA4gAJXACAAgAlgCELAQACEA"},"packages/core/src/execution-engine/triggers-and-pollers.ts":{"26":"b:AJMCAA4gALXACAAAAlwCEIAQACEA","51":"b:AJMCAA4gALXACAAAAlwCEIAQACEA","55":"b:AJMCAA4gALXACAAAAlwCEIAQACEA","61":"b:AJMCAA4gALXACAAAAlwCEIAQACEA","65":"b:AJMCAA4gALXACAAAAlwCEIAQACEA","71":"b:AJMCAA4gALXACAAAAlwCEIAQACEA","76":"b:AJMCAA4gALXACAAAAlwCEIAQACEA","81":"b:AJMCAA4gALXACAAAAlwCEIAQACEA","95":"b:AJMCAA4gALXACAAAAlwCEIAQACEA"},"packages/core/src/node-execute-functions.ts":{"17":"b:AJMCAA4gALXACAAAAlwCEIAQAAAA","31":"b:AJMCAA4gALXACAAAAlwCEIAQAAAA"},"packages/nodes-base/nodes/HackerNews/GenericFunctions.ts":{"16":[75,111,112,114],"42":[75,111,112,114]},"packages/nodes-base/nodes/HackerNews/HackerNews.node.ts":{"264":[75,111,112,114]},"packages/workflow/src/common/get-parent-nodes.ts":{"11":"b:AMMSAHQAAESACAAAgUACEAEAAIIA"},"packages/workflow/src/execution-context.ts":{"12":"b:AJMCAA4gALXACAAAAlwCEYAQAAQA","294":"b:AJMCAA4gALXACAAAAlwCEYAQAAQA","316":"b:AJMCAA4gALXACAAAAlwCEYAQAAQA","329":"b:AJMCAA4gALXACAAAAlwCEYAQAAQA","334":"b:AJMCAA4gALXACAAAAlwCEYAQAAQA"},"packages/workflow/src/run-execution-data/run-execution-data.ts":{"29":"b:ANMCAH4gALXACAAAAFACEYDQACAA"},"packages/@n8n/design-system/src/components/N8nSelectableList/SelectableList.vue":{"7":[41,75],"37":[41,75],"39":[41,75],"43":[41,75],"63":[41,75],"70":[41,75],"76":[41,75]},"packages/frontend/editor-ui/src/app/components/AiStarsIcon.vue":{"11":[41,44,75,119],"17":[41,44,75,119]},"packages/frontend/editor-ui/src/features/ndv/panel/components/InputNodeSelect.vue":{"18":"b:AAABAAAQAAAAGAAAAEByAwAAAAAA","29":"b:AAABAAAQAAAAGAAAAEByAwAAAAAA","33":"b:AAABAAAQAAAAGAAAAEByAwAAAAAA","40":"b:AAABAAAQAAAAGAAAAEByAwAAAAAA","43":[75,110,113,116,117,118,121],"56":[75,110,113,116,117,118,121],"58":[75,110,113,116,117,118,121],"65":[75,110,113,116,117,118,121],"70":[75,110,113,116,117,118,121],"79":[75,110,113,116,117,118,121],"106":[75,110,113,116,117,118,121],"110":[75,110,113,116,117,118,121],"116":[113,121],"118":"b:AAABAAAQAAAAGAAAAEByAwAAAAAA","133":"b:AAABAAAQAAAAGAAAAEByAwAAAAAA","139":"b:AAABAAAQAAAAGAAAAEByAwAAAAAA","143":[75,110,113,116,117,118,121],"149":[75,110,113,116,117,118,121]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/ParameterInputOverrides/FromAiOverrideButton.vue":{"6":[41,44,75,119],"16":[41,44,75,119],"24":[41,44,75,119],"29":[41]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/ParameterInputOverrides/FromAiOverrideField.vue":{"10":[41,75],"11":[41,75]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/ParameterInputOverrides/ParameterOverrideSelectableList.vue":{"16":[41,75],"22":[41,75],"23":[41,75],"47":[41,75]},"packages/frontend/editor-ui/src/features/ndv/runData/components/RunDataItemCount.vue":{"16":"b:AMZbAAQAAM6BKAIAgM1/lwEAAAAA","17":"b:AMZbAAQAAM6BKAIAgM1/lgEAAAAA","21":[116,118],"29":"b:AMZbAAQAAM6BKAIAgM1/lwEAAAAA"},"packages/frontend/editor-ui/src/features/ndv/runData/components/RunDataJson.vue":{"22":[75,107,110,113,118],"59":[75,107,110,113,118],"61":[75,107,110,113,118],"63":[113],"71":[75,107,110,113,118],"82":[75,107,110,113,118],"83":[75,107,110,113,118],"85":[113],"98":[113],"122":[75,107,110,113,118],"126":[75,107,110,113,118],"130":[75,107,110,113,118],"166":[75,107,110,113,118],"181":[75,107,110,113,118]},"packages/frontend/editor-ui/src/features/ndv/runData/components/RunDataJsonActions.vue":{"63":[75,107,110,113,118]},"packages/@n8n/design-system/src/components/N8nIcon/nodes/data-table.svg":{"11":"b:MIAAgAASAAAgAAAAAAEgASAAAAAA"},"packages/@n8n/design-system/src/components/N8nIcon/nodes/information-extractor.svg":{"11":[31,44,59,69,4,5,120,133]},"packages/frontend/editor-ui/src/app/components/WorkflowShareModal.ee.vue":{"42":[4,6,137],"60":[4,6,137],"63":[4,6,137],"64":[4,6,137],"65":[6,137],"68":[4,6,137],"71":[4,6,137],"74":[4,6,137],"86":[4,6,137],"90":[4,6,137],"92":[4,6,137],"111":[4,6,137],"115":[4,6,137],"127":[6,137],"130":[4],"132":[4,6,137],"137":[4,6,137],"138":[4,6,137],"154":[6],"161":[6],"175":[6],"182":[6],"217":[6],"241":[4,6,137],"256":[4,6,137],"261":[6],"267":[4,6,137],"279":[4,6,137],"323":[4],"324":[4],"327":[4],"360":[4,6,137],"372":[4,6,137],"374":[4,6,137],"377":[4],"386":[6,137]},"packages/frontend/editor-ui/src/app/stores/workflows.ee.store.ts":{"13":[4,6,93,137],"18":[93],"19":[93],"34":[6],"43":[6],"49":[6]},"packages/nodes-base/nodes/DebugHelper/DebugHelper.node.ts":{"255":[71,107,109,117,127],"346":[71,107,109,117,127]},"packages/nodes-base/nodes/DebugHelper/functions.ts":{"4":[71,107,109,117,127],"14":[71,107,109,117,127]},"packages/nodes-base/nodes/DebugHelper/randomData.ts":{"26":[71,107,109,117,127],"36":[71,107,109,117,127],"48":[71,107,109,117,127],"55":[71,107,109,117,127],"59":[71,107,109,117,127],"63":[71,107,109,117,127],"79":[71,107,109,117,127],"83":[71,107,109,117,127],"87":[71,107,109,117,127],"91":[71,107,109,117,127],"95":[71,107,109,117,127],"99":[71,107,109,117,127]},"packages/frontend/editor-ui/src/features/integrations/logStreaming.ee/components/EventDestinationCard.vue":{"44":[87,88],"52":[87,88],"56":[87,88],"72":[87,88],"76":[87,88],"87":[88],"110":[88],"135":[87,88],"141":[87,88],"144":[87,88],"148":[87,88],"153":[87,88],"157":[87,88],"160":[87,88]},"packages/frontend/editor-ui/src/features/integrations/logStreaming.ee/components/EventDestinationSettingsModal.vue":{"80":[87,88],"107":[87,88],"121":[87,88],"125":[87,88],"129":[87],"133":[87],"137":[87,88],"139":[87,88],"143":[87,88],"161":[87,88],"165":[87,88],"185":[87,88],"189":[87,88],"204":[87,88],"208":[87,88],"217":[87,88],"223":[87,88],"231":[87,88],"235":[87,88],"261":[87,88],"300":[87],"305":[88],"329":[88],"341":[87,88],"361":[87,88],"391":[87,88],"399":[87,88],"415":[87,88],"432":[87,88],"474":[87,88],"484":[87,88],"492":[87,88],"494":[87,88],"506":[87,88],"515":[87,88]},"packages/frontend/editor-ui/src/features/integrations/logStreaming.ee/logStreaming.store.ts":{"44":[87,88],"53":[87,88],"81":[87,88],"99":[87,88],"105":[87,88],"128":[87,88],"136":[87,88],"151":[87,88],"155":[87,88],"163":[87,88],"220":[87,88],"226":[88],"231":[87,88],"248":[87,88],"265":[87],"276":[87,88],"280":[87,88],"284":[88]},"packages/frontend/editor-ui/src/features/integrations/logStreaming.ee/logStreaming.utils.ts":{"8":[87,88]},"packages/frontend/editor-ui/src/features/integrations/logStreaming.ee/views/SettingsLogStreamingView.vue":{"37":[87,88],"45":[87,88],"50":[87,88],"54":[87,88],"58":[87,88],"60":[87,88],"73":[87,88],"75":[88],"88":[87,88],"94":[87,88],"98":[87,88],"103":[88],"108":[87,88],"133":[87,88],"137":[87,88],"152":[88],"161":[88],"182":[87,88],"204":[87,88],"208":[87,88],"214":[88],"215":[88],"230":[87,88],"248":[88]},"packages/localhost-41381/assets/_plugin-vue_export-helper-Da88TEg1.js":{"2":[87]},"packages/localhost-41381/assets/chunk-CC9Q-vWm.js":{"8":[87],"9":[87],"10":[87],"19":[87],"23":[87],"29":[87],"33":[87],"34":[87]},"packages/@n8n/ai-utilities/src/guards.ts":{"7":[8,15,17,36,37,38,110],"9":[8,15,17,36,37,38,110],"17":[8,15,17,36,37,38,110],"21":[8,15,17,36,37,38,110],"25":[8,15,17,36,37,38,110],"31":[8,15,17,36,37,38,110]},"packages/@n8n/ai-utilities/src/utils/failed-attempt-handler/n8nLlmFailedAttemptHandler.ts":{"13":[15,36,37,38,41,42,110],"17":[15,36,37,38,41,42,110]},"packages/@n8n/ai-utilities/src/utils/helpers.ts":{"3":[8,15,17,36,37,38,110],"17":[8,15,17,36,37,38,110],"37":[8,15,17,36,37,38,110]},"packages/@n8n/ai-utilities/src/utils/http-proxy-agent.ts":{"31":[15,36,37,38,110],"50":[15,36,37,38,110],"79":[15,36,37,38,110],"101":[15,36,37,38,110]},"packages/@n8n/ai-utilities/src/utils/log-ai-event.ts":{"4":[8,15,17,36,37,38,110]},"packages/@n8n/ai-utilities/src/utils/n8n-llm-tracing.ts":{"55":[15,36,37,38,41,42,110],"92":[15,36,37,38,41,42,110],"107":[15,36,37,38,41,42,110],"110":[15,36,37,38,41,42,110],"121":[15,36,37,38,41,42,110],"122":[15,36,37,38,41,42,110],"126":[15,36,37,38,41,42,110],"131":[15,36,37,38,41,42,110],"136":[15,36,37,38,41,42,110],"137":[15,36,37,38,41,42,110],"187":[15,36,37,38,41,42,110],"212":[15,36,37,38,41,42,110],"245":[15,36,37,38,41,42,110],"253":[15,36,37,38,41,42,110],"286":[15,36,37,38,41,42,110],"290":[15,36,37,38,41,42,110]},"packages/@n8n/ai-utilities/src/utils/tokenizer/tiktoken.ts":{"9":[15,36,37,38,110],"15":[15,36,37,38,110],"18":[15,36,37,38,110],"34":[15,36,37,38,110],"43":[15,36,37,38,110]},"packages/@n8n/ai-utilities/src/utils/tokenizer/token-estimator.ts":{"33":[15,36,37,38,110],"70":[15,36,37,38,110],"129":[15,36,37,38,110],"141":[15,36,37,38,110],"169":[15,36,37,38,110]},"packages/@n8n/nodes-langchain/nodes/llms/LMChatAnthropic/LmChatAnthropic.node.ts":{"82":[36,37,38,110,119],"150":[36,37,38,110,119],"450":[36,37,38,110,119],"529":[36,37,38,110,119],"566":[36,37,38,110,119]},"packages/@n8n/nodes-langchain/nodes/llms/LMChatAnthropic/methods/searchModels.ts":{"14":[36,37,38,110,119],"41":[36,37,38,110,119],"48":[36,37,38,110,119],"49":[36,37,38,110,119],"50":[36,37,38,110,119]},"packages/cli/src/credentials-overwrites.ts":{"22":"b:AIAAAHBgAJMAAAAAAEAACQAEBIAA","30":"b:AIAAAHBgAJMAAAAAAEAACQAEBIAA","52":"b:AIAAAHBgAJMAAAAAAEAACQAEBIAA","56":"b:AIAAAHBgAJMAAAAAAEAACQAEBIAA","78":"b:AIAAAHBgAJMAAAAAAEAACQAEBIAA","79":"b:AIAAAHBgAJMAAAAAAEAACQAEBIAA","83":"b:AIAAAHBgAJMAAAAAAEAACQAEBIAA","97":"b:AIAAAHBgAJMAAAAAAEAACQAEBIAA","102":"b:AIAAAHBgAJMAAAAAAEAACQAEBIAA","117":"b:AIAAAHBgAJMAAAAAAEAACQAEBIAA","132":"b:AIAAAHBgAJMAAAAAAEAACQAEBIAA","135":"b:AIAAAHBgAJMAAAAAAEAACQAEBIAA","139":"b:AIAAAHBgAJMAAAAAAEAACQAEBIAA","151":"b:AIAAAHBgAJMAAAAAAEAACQAEBIAA","177":"b:AIAAAHBgAJMAAAAAAEAACQAEBIAA","209":"b:AIAAAHBgAJMAAAAAAEAACQAEBIAA","213":"b:AIAAAHBgAJMAAAAAAEAACQAEBIAA","214":"b:AIAAAHBgAJMAAAAAAEAACQAEBIAA","219":"b:AIAAAHBgAJMAAAAAAEAACQAEBIAA","224":"b:AIAAAHBgAJMAAAAAAEAACQAEBIAA"},"packages/cli/src/eventbus/event-message-classes/event-message-ai-node.ts":{"34":[8,15,17,36,37,38,110],"42":[8,15,17,36,37,38,110],"47":[8,15,17,36,37,38,110]},"packages/cli/src/executions/execution.utils.ts":{"13":"b:AAAYAAAAAIIAAAAAAEAAgIEAAAgB","26":"b:AAAYAAAAAIIAAAAAAEAAgIEAAAgB"},"packages/cli/src/task-runners/task-runner-module.ts":{"44":[110],"53":[110],"61":[110],"69":[110],"70":[110],"77":[110],"84":[110],"94":[110],"95":[110],"96":[110],"103":[110],"106":[110],"113":[110],"116":[110],"123":[110],"135":[110],"159":[110]},"packages/cli/src/utils/cors.util.ts":{"3":[19,20,57,63,110,155,135]},"packages/cli/src/webhooks/waiting-webhooks.ts":{"44":[19,20,57,63,110,155,135],"55":[19,20,57,63,110,155,135],"63":[19,20,57,63,110,155,135],"67":[19,20,57,63,110,155,135],"71":[19,20,57,63,110,155,135],"75":[19,20,57,63,110,155,135],"82":[19,20,57,63,110,155,135],"95":[19,20,57,63,110,155,135],"106":[19,20,57,63,110,155,135],"132":[19,20,57,63,110,155,135],"153":[19,20,57,63,110,155,135],"174":[19,20,57,63,110,155,135],"256":[19,20,57,63,110,155,135],"265":[19,20,57,63,110,155,135],"316":[19,20,57,63,110,155,135],"344":[19,20,57,63,110,155,135],"357":[19,20,57,63,110,155,135]},"packages/core/src/execution-engine/node-execution-context/supply-data-context.ts":{"52":[8,15,17,36,37,38,159,110],"97":[8,15,17,36,37,38,159,110],"99":[8,15,17,36,37,38,159,110],"107":[8,15,17,36,37,38,159,110],"114":[8,15,17,36,37,38,159,110],"129":[8,15,17,36,37,38,159,110],"152":[8,15,17,36,37,38,159,110],"173":[8,15,17,36,37,38,159,110],"181":[8,15,17,36,37,38,159,110],"187":[8,15,17,36,37,38,159,110],"192":[8,15,17,36,37,38,159,110],"208":[8,15,17,36,37,38,159,110],"221":[8,15,17,36,37,38,159,110],"237":[8,15,17,36,37,38,159,110],"247":[8,15,17,36,37,38,159,110],"367":[8,15,17,36,37,38,159,110],"369":[8,15,17,36,37,38,159,110],"381":[8,15,17,36,37,38,159,110]},"packages/core/src/execution-engine/node-execution-context/utils/extract-value.ts":{"19":[59,63,107,110,117,118,120,123],"29":[59,63,107,110,117,118,120,123],"34":[59,63,107,110,117,118,120,123],"70":[59,63,107,110,117,118,120,123],"90":[59,63,107,110,117,118,120,123],"99":[59,63,107,110,117,118,120,123],"133":[59,63,107,110,117,118,120,123],"153":[59,63,107,110,117,118,120,123],"187":[59,63,107,110,117,118,120,123]},"packages/core/src/execution-engine/node-execution-context/utils/get-input-connection-data.ts":{"46":[8,15,17,36,37,38,41,159,110],"51":[8,15,17,36,37,38,41,159,110],"55":[8,15,17,36,37,38,41,159,110],"65":[8,15,17,36,37,38,41,159,110],"78":[8,15,17,36,37,38,41,159,110],"103":[8,15,17,36,37,38,41,159,110],"143":[8,15,17,36,37,38,41,159,110],"147":[8,15,17,36,37,38,41,159,110],"156":[8,15,17,36,37,38,41,159,110],"159":[8,15,17,36,37,38,41,159,110],"168":[8,15,17,36,37,38,41,159,110],"169":[8,15,17,36,37,38,41,159,110],"177":[8,15,17,36,37,38,41,159,110],"208":[8,15,17,36,37,38,41,159,110],"220":[8,15,17,36,37,38,41,159,110],"234":[8,15,17,36,37,38,41,159,110],"328":[8,15,17,36,37,38,41,159,110],"348":[8,15,17,36,37,38,41,159,110],"351":[8,15,17,36,37,38,41,159,110],"365":[8,15,17,36,37,38,41,159,110],"380":[8,15,17,36,37,38,41,159,110],"396":[8,15,17,36,37,38,41,159,110],"405":[8,15,17,36,37,38,41,159,110],"458":[8,15,17,36,37,38,41,159,110],"481":[8,15,17,36,37,38,41,159,110],"552":[8,15,17,36,37,38,41,159,110]},"packages/core/src/execution-engine/partial-execution-utils/clean-run-data.ts":{"12":[9,71,103,107,110,111,118,124]},"packages/core/src/execution-engine/partial-execution-utils/directed-graph.ts":{"40":[9,71,103,107,110,111,118,124],"45":[9,71,103,107,110,111,118,124],"49":[9,71,103,107,110,111,118,124],"58":[9,71,103,107,110,111,118,124],"72":[9,71,103,107,110,111,118,124],"86":[9,71,103,107,110,111,118,124],"91":[9,71,103,107,110,111,118,124],"116":[9,71,103,107,110,111,118,124],"172":[9,71,103,107,110,111,118,124],"198":[9,71,103,107,110,111,118,124],"213":[9,71,103,107,110,111,118,124],"230":[9,71,103,107,110,111,118,124],"252":[9,71,103,107,110,111,118,124],"256":[9,71,103,107,110,111,118,124],"273":[9,71,103,107,110,111,118,124],"290":[9,71,103,107,110,111,118,124],"294":[9,71,103,107,110,111,118,124],"344":[9,71,103,107,110,111,118,124],"352":[9,71,103,107,110,111,118,124],"363":[9,71,103,107,110,111,118,124],"411":[9,71,103,107,110,111,118,124],"451":[9,71,103,107,110,111,118,124],"455":[9,71,103,107,110,111,118,124],"463":[9,71,103,107,110,111,118,124],"496":[9,71,103,107,110,111,118,124],"534":[9,71,103,107,110,111,118,124],"540":[9,71,103,107,110,111,118,124],"563":[9,71,103,107,110,111,118,124]},"packages/core/src/execution-engine/partial-execution-utils/filter-disabled-nodes.ts":{"5":[9,71,103,107,110,111,118,124],"12":[9,71,103,107,110,111,118,124]},"packages/core/src/execution-engine/partial-execution-utils/find-start-nodes.ts":{"13":[9,71,103,107,110,111,118,124],"29":[9,71,103,107,110,111,118,124],"50":[9,71,103,107,110,111,118,124],"137":[9,71,103,107,110,111,118,124],"159":[9,71,103,107,110,111,118,124]},"packages/core/src/execution-engine/partial-execution-utils/find-subgraph.ts":{"6":"b:AAIAAAAAAACAAAAAgMhAEgAAAAAA","39":"b:AAIAAAAAAACAAAAAgMhAEgAAAAAA","45":"b:AAIAAAAAAACAAAAAgMhAEgAAAAAA","88":"b:AAIAAAAAAACAAAAAgMhAEgAAAAAA"},"packages/core/src/execution-engine/partial-execution-utils/find-trigger-for-partial-execution.ts":{"12":"b:AAIAAAAAAACAAAAAgMhAEgAAAAAA","14":"b:AAIAAAAAAACAAAAAgMhAEgAAAAAA","17":"b:AAIAAAAAAACAAAAAgMhAEgAAAAAA","29":"b:AAIAAAAAAACAAAAAgMhAEgAAAAAA","30":"b:AAIAAAAAAACAAAAAgMhAEgAAAAAA","31":"b:AAIAAAAAAACAAAAAgMhAEgAAAAAA","36":"b:AAIAAAAAAACAAAAAgMhAEgAAAAAA","61":"b:AAIAAAAAAACAAAAAgMhAEgAAAAAA","78":"b:AAIAAAAAAACAAAAAgMhAEgAAAAAA","98":"b:AAIAAAAAAACAAAAAgMhAEgAAAAAA","112":"b:AAIAAAAAAACAAAAAgMhAEgAAAAAA","115":"b:AAIAAAAAAACAAAAAgMhAEgAAAAAA","121":"b:AAIAAAAAAACAAAAAgMhAEgAAAAAA"},"packages/core/src/execution-engine/partial-execution-utils/get-incoming-data.ts":{"3":[9,71,103,107,110,111,118,124],"13":[9,71,103,107,110,111,118,124],"17":[9,71,103,107,110,111,118,124]},"packages/core/src/execution-engine/partial-execution-utils/get-source-data-groups.ts":{"5":"b:AAIAAAAAAACAAAAAgMhAEgAAAAAA","28":"b:AAIAAAAAAACAAAAAgMhAEgAAAAAA","86":"b:AAIAAAAAAACAAAAAgMhAEgAAAAAA","118":"b:AAIAAAAAAACAAAAAgMhAEgAAAAAA","119":"b:AAIAAAAAAACAAAAAgMhAEgAAAAAA","126":"b:AAIAAAAAAACAAAAAgMhAEgAAAAAA","139":"b:AAIAAAAAAACAAAAAgMhAEgAAAAAA","156":"b:AAIAAAAAAACAAAAAgMhAEgAAAAAA","157":"b:AAIAAAAAAACAAAAAgMhAEgAAAAAA"},"packages/core/src/execution-engine/partial-execution-utils/handle-cycles.ts":{"15":[9,71,103,107,110,111,118,124],"26":[9,71,103,107,110,111,118,124],"41":[9,71,103,107,110,111,118,124]},"packages/core/src/execution-engine/partial-execution-utils/index.ts":{"1":[9,71,103,107,110,111,118,124],"7":[9,71,103,107,110,111,118,124],"8":[9,71,103,107,110,111,118,124],"9":[9,71,103,107,110,111,118,124],"10":[9,71,103,107,110,111,118,124],"11":[9,71,103,107,110,111,118,124],"13":[9,71,103,107,110,111,118,124]},"packages/core/src/execution-engine/partial-execution-utils/recreate-node-execution-stack.ts":{"20":[9,71,103,107,110,111,118,124],"39":[9,71,103,107,110,111,118,124],"72":[9,71,103,107,110,111,118,124],"103":[9,71,103,107,110,111,118,124]},"packages/core/src/execution-engine/partial-execution-utils/run-data-utils.ts":{"11":[9,71,103,107,110,111,118,124],"17":[9,71,103,107,110,111,118,124],"20":[9,71,103,107,110,111,118,124]},"packages/core/src/instance-settings/instance-settings.ts":{"66":[14,15,17,20,33,110,122],"88":[14,15,17,20,33,110,122],"101":[14,15,17,20,33,110,122],"102":[14,15,17,20,33,110,122],"110":[14,15,17,20,33,110,122],"111":[14,15,17,20,33,110,122],"117":[14,15,17,20,33,110,122],"170":[14,15,17,20,33,110,122],"174":[14,15,17,20,33,110,122],"179":[14,15,17,20,33,110,122],"184":[14,15,17,20,33,110,122],"188":[14,15,17,20,33,110,122],"192":[14,15,17,20,33,110,122],"196":[14,15,17,20,33,110,122],"200":[14,15,17,20,33,110,122],"204":[14,15,17,20,33,110,122],"208":[14,15,17,20,33,110,122],"212":[14,15,17,20,33,110,122],"216":[14,15,17,20,33,110,122],"220":[14,15,17,20,33,110,122],"228":[14,15,17,20,33,110,122],"251":[14,15,17,20,33,110,122],"259":[14,15,17,20,33,110,122],"306":[14,15,17,20,33,110,122],"313":[14,15,17,20,33,110,122],"321":[14,15,17,20,33,110,122],"329":[14,15,17,20,33,110,122],"357":[14,15,17,20,33,110,122],"362":[14,15,17,20,33,110,122],"383":[14,15,17,20,33,110,122],"395":[14,15,17,20,33,110,122]},"packages/nodes-base/nodes/SplitInBatches/SplitInBatches.node.ts":{"9":[70,110,113]},"packages/nodes-base/nodes/SplitInBatches/v1/SplitInBatchesV1.node.ts":{"62":[70,110,113],"97":[70,110,113],"111":[70,110,113],"128":[70,110,113]},"packages/nodes-base/nodes/SplitInBatches/v2/SplitInBatchesV2.node.ts":{"64":[70,110,113],"102":[70,110,113],"116":[70,110,113],"135":[70,110,113],"147":[70,110,113]},"packages/nodes-base/nodes/SplitInBatches/v3/SplitInBatchesV3.node.ts":{"88":[70,110,113],"126":[70,110,113],"140":[70,110,113],"159":[70,110,113],"171":[70,110,113]},"packages/nodes-base/nodes/Wait/Wait.node.ts":{"229":[19,20,70,107,110,155,133,135],"501":[19,20,70,107,110,155,133,135],"507":[19,20,70,107,110,155,133,135],"522":[19,20,70,107,110,155,133,135],"599":[19,20,70,107,110,155,133,135],"600":[19,20,70,107,110,155,133,135],"601":[19,20,70,107,110,155,133,135],"612":[19,20,70,107,110,155,133,135],"643":[19,20,70,107,110,155,133,135]},"packages/nodes-base/nodes/Wait/validation.ts":{"1":[19,20,70,107,110,155,133,135],"6":[19,20,70,107,110,155,133,135]},"packages/workflow/src/errors/execution-cancelled.error.ts":{"9":[110],"19":[110],"26":[110],"33":[110]},"packages/workflow/src/node-parameters/filter-parameter.ts":{"24":[59,107,110,117,118],"32":[59,107,110,117,118],"66":[59,107,110,117,118],"71":[59,107,110,117,118],"106":[59,107,110,117,118],"118":[59,107,110,117,118],"124":[59,107,110,117,118],"196":[59,107,110,117,118],"209":[59,107,110,117,118],"211":[59,107,110,117,118],"222":[59,107,110,117,118],"419":[59,107,110,117,118],"423":[59,107,110,117,118],"437":[59,107,110,117,118],"442":[59,107,110,117,118]},"packages/workflow/src/result.ts":{"7":[10,110,134,135],"12":[10,110,134,135],"23":[10,110,134,135]},"packages/@n8n/design-system/src/components/N8nIcon/custom/node-execution-error.svg":{"11":"b:AIYBAAAgAAAAAAAAAEwgAMAAAAAA"},"packages/@n8n/design-system/src/components/N8nIcon/custom/schema.svg":{"8":[14,15,16,17,69,77,110]},"packages/@n8n/design-system/src/components/N8nIcon/custom/status-waiting.svg":{"8":[69,110]},"packages/@n8n/design-system/src/components/N8nIcon/custom/text.svg":{"8":[15,69,110]},"packages/@n8n/design-system/src/components/N8nIcon/nodes/wait.svg":{"11":[19,21,22,70,107,110]},"packages/@n8n/design-system/src/components/N8nTree/Tree.vue":{"20":"b:AABCAAAAAAgBAAAAAERaAgAAAAAA","28":"b:AABCAAAAAAgBAAAAAERaAgAAAAAA","32":"b:AABCAAAAAAgBAAAAAERaAgAAAAAA","36":"b:AABCAAAAAAgBAAAAAERaAgAAAAAA","52":"b:AABCAAAAAAgBAAAAAERaAgAAAAAA","61":"b:AABCAAAAAAgBAAAAAERaAgAAAAAA","68":"b:AABCAAAAAAgBAAAAAERaAgAAAAAA","87":[110,113,116,121],"95":[110,113,116,121]},"packages/frontend/editor-ui/src/features/agents/composables/useMessageAgentSessionLink.ts":{"19":[65],"32":[14,15,16,17,65,77,110],"60":[14,15,16,17,65,77,110],"65":[14,15,16,17,65,77,110],"89":[65]},"packages/frontend/editor-ui/src/features/execution/executions/components/ViewSubExecution.vue":{"9":[17,19,110,127,128],"23":[17,19,110,127,128],"27":[127,128],"41":[17,19,110,127,128]},"packages/frontend/editor-ui/src/features/execution/logs/components/LogDetailsPanel.vue":{"32":[14,15,16,17,65,77,110],"70":[14,15,16,17,65,77,110],"71":[14,15,16,17,65,77,110],"72":[14,15,16,17,65,77,110],"73":[14,15,16,17,65,77,110],"77":[15,65,110],"79":[65],"83":[15,65,110],"84":[14,15,16,17,65,77,110],"92":[65],"102":[14,15,16,17,65,77,110],"113":[14,15,16,17,65,77,110],"130":[14,15,16,17,65,77,110],"138":[65],"145":[14,15,16,17,65,77,110],"151":[14,15,16,17,65,77,110],"158":[14,15,16,17,65,77,110],"164":[14,15,16,17,65,77,110],"175":[65],"193":[15,65,110],"202":[65],"215":[65],"226":[65]},"packages/frontend/editor-ui/src/features/execution/logs/components/LogsViewConsumedTokenCountText.vue":{"8":[65,110],"20":[65]},"packages/frontend/editor-ui/src/features/execution/logs/components/LogsViewRunData.vue":{"37":[14,15,16,17,65,77,110],"49":[14,15,16,17,65,77,110],"52":[14,15,16,17,65,77,110],"75":[14,15,16,17,65,77,110],"82":[65],"86":[15,65,110],"88":[14,15,16,17,65,77,110],"116":[65],"118":[14,15,16,17,65,77,110],"120":[14,15,16,17,65,77,110],"124":[14,15,16,17,65,77,110],"131":[15,65,110],"135":[65,110],"137":[65,110],"146":[65],"154":[65],"160":[65],"164":[65],"167":[65]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/AssignmentCollection/Assignment.vue":{"32":"b:AAIAAAEAAIABIQIACMhKBQAAAAAA","36":"b:AAIAAAEAAIABIQIACMhKBQAAAAAA","54":"b:AAIAAAEAAIABIQIACMhKBQAAAAAA","78":"b:AAIAAAEAAIABIQIACMhKBQAAAAAA","87":"b:AAIAAAEAAIABIQIACMhKBQAAAAAA","101":"b:AAIAAAEAAIABIQIACMhKBQAAAAAA","103":"b:AAIAAAEAAIABIQIACMhKBQAAAAAA","112":"b:AAIAAAEAAIABIQIACMhKBQAAAAAA","114":"b:AAIAAAAAAIAAAQIAAEgKBQAAAAAA","116":[32,64,113],"120":[32,64],"128":[32,64,113,115,120,122],"136":[32,64,99,113,115,120],"140":[113],"153":"b:AAIAAAEAAIABIQIACMhKBQAAAAAA","185":"b:AAIAAAEAAIABIQIACMhKBQAAAAAA","201":"b:AAIAAAEAAIABIQIACMhKBQAAAAAA","205":"b:AAIAAAEAAIABIQIACMhKBQAAAAAA","215":"b:AAIAAAEAAIABIQIACMhKBQAAAAAA"},"packages/frontend/editor-ui/src/features/ndv/parameters/components/AssignmentCollection/TypeSelect.vue":{"17":"b:AAIAAAEAAIABIQIACMhKBQAAAAAA","30":"b:AAIAAAEAAIABIQIACMhKBQAAAAAA","32":"b:AAIAAAEAAIABIQIACMhKBQAAAAAA","33":"b:AAIAAAEAAIABIQIACMhKBQAAAAAA","43":[32,64],"45":"b:AAIAAAEAAIABIQIACMhKBQAAAAAA","58":"b:AAIAAAEAAIABIQIACMhKBAAAAAAA","60":"b:AAIAAAEAAIABIQIACMhKBAAAAAAA"},"packages/frontend/editor-ui/src/features/ndv/parameters/components/InputTriple/InputTriple.vue":{"10":"b:AAIAAAEAAIgBIQIACshKBQAAAAAA","13":"b:AAIAAAEAAIgBIQIACshKBQAAAAAA","21":"b:AAIAAAEAAIgBIQIACshKBQAAAAAA","22":"b:AAIAAAEAAIgBIQIACshKBQAAAAAA"},"packages/frontend/editor-ui/src/features/ndv/runData/components/RunDataParsedAiContent.vue":{"31":[110],"33":[110],"54":[110],"63":[110],"72":[110],"76":[110]},"packages/frontend/editor-ui/src/features/ndv/runData/components/RunDataPinButton.vue":{"6":"b:AABYAAQAAM6BAAIAgM1/lwEAAAAA","24":"b:AABYAAQAAM6BAAIAgM1/lwEAAAAA","27":"b:AABYAAQAAM6BAAIAgM1/lwEAAAAA","31":[57,64],"49":"b:AABYAAQAAM6BAAIAgM1/lwEAAAAA","66":[106,122]},"packages/frontend/editor-ui/src/features/ndv/runData/components/RunDataTable.vue":{"87":"b:AABaAAQAAM6BAAIAgM1/lwEAAAAA","88":"b:AMBaAAQAAM6BIAIAgM1/lwEAAAAA","89":"b:AMBaAAQAAM6BIAIAgM1/lwEAAAAA","91":"b:AMBaAAQAAM6BIAIAgM1/lwEAAAAA","92":"b:AMBaAAQAAM6BIAIAgM1/lwEAAAAA","93":[113,116,118,121],"94":"b:AMBaAAQAAM6BIAIAgM1/lwEAAAAA","95":"b:AMBaAAQAAM6BIAIAgM1/lwEAAAAA","103":"b:AMBaAAQAAM6BIAIAgM1/lwEAAAAA","114":"b:AMBaAAQAAM6BIAIAgM1/lwEAAAAA","151":[127],"163":[113,116,118,121],"185":[113,118,121],"192":[113],"196":[113],"200":[113,116],"206":"b:AMBaAAQAAM6BIAIAgM1/lwEAAAAA","219":"b:AMBaAAQAAM6BIAIAgM1/lwEAAAAA","226":"b:AABCAAAAAAgBAAAAAERaAgAAAAAA","239":"b:AABCAAAAAAgBAAAAAERaAgAAAAAA","252":"b:AMBaAAQAAM6BIAIAgM1/lwEAAAAA","262":"b:AMBaAAQAAM6BIAIAgM1/lwEAAAAA","284":[113],"294":[113],"302":[113],"308":"b:AABCAAAAAAgBAAAAAERaAgAAAAAA","316":[113],"318":[113],"340":"b:AMBaAAQAAM6BIAIAgM1/lwEAAAAA","349":"b:AABCAAAAAAgBAAAAAERaAgAAAAAA","353":"b:AMBaAAQAAM6BIAIAgM1/lwEAAAAA","357":"b:AMBaAAQAAM6BIAIAgM1/lwEAAAAA","369":"b:AMBaAAQAAM6BIAIAgM1/lwEAAAAA","394":"b:AAAAAAAAAAiAAAAAAEhyhwAAAAAA","412":"b:AMBaAAQAAM6BIAIAgM1/lwEAAAAA","428":"b:AMBaAAQAAM6BIAIAgM1/lwEAAAAA","456":[64,71,113,120,121,122],"457":[64,71,113,120,121,122],"466":"b:AMBaAAQAAM6BIAIAgM1/lwEAAAAA","511":[110,117,118,122],"568":"b:AMBaAAQAAM6BIAIAgM1/lwEAAAAA","580":"b:AMBaAAQAAM6BIAIAgM1/lwEAAAAA","589":[113],"591":"b:AMBaAAQAAM6BIAIAgM1/lwEAAAAA","594":"b:AMBaAAQAAM6BIAIAgM1/lwEAAAAA","611":"b:AMBaAAQAAM6BIAIAgM1/lwEAAAAA","667":"b:AMBaAAQAAM6BIAIAgM1/lwEAAAAA","697":[127],"711":"b:AMBaAAQAAM6BIAIAgM1/lwEAAAAA","729":"b:AABCAAAAAAgBAAAAAERaAgAAAAAA","743":[113],"752":"b:AABCAAAAAAgBAAAAAERaAgAAAAAA"},"packages/frontend/editor-ui/src/features/ndv/runData/components/RunInfo.vue":{"7":"b:AAYKAAQAAM6BAAIAgMx6lwEAAAAA","15":"b:AAYKAAQAAM6BAAIAgMx6lwEAAAAA","19":"b:AAYKAAQAAM6BAAIAgMx6lwEAAAAA","23":"b:AAYKAAQAAM6BAAIAgMx6lwEAAAAA","33":"b:AAYKAAQAAM6BAAIAgMx6lwEAAAAA"},"packages/frontend/editor-ui/src/features/ndv/runData/components/ai/utils.ts":{"38":[110],"51":[110],"52":[110],"53":[110]},"packages/frontend/editor-ui/src/features/ndv/runData/components/error/NodeErrorView.vue":{"46":[9,10,15,16,106,110,117],"69":[9,10,15,16,106,110,117],"73":[117],"86":[9,10,15,16,106,110,117],"97":[9,10,15,16,106,110,117],"101":[16,106],"110":[9,10,15,16,106,110,117],"117":[16,106],"140":[9,10,15,16,106,110,117],"151":[9,10],"158":[9,10,15,16,106,110,117],"165":[9,16,106,117],"181":[9,10,15,16,117],"185":[9,10,15,16,117],"210":[9,10,15,16,106,110,117],"222":[9,10,15,16,106,110,117],"225":[9,10,15,16,106,110,117],"250":[117],"260":[117],"266":[117],"280":[117],"402":[9,10,16,106,117],"436":[9,10],"463":[9,10,15,16,106,110,117],"509":[9,10,15,16,106,110,117],"548":[16,106]},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/nodes/render-types/parts/CanvasNodeTooltip.vue":{"11":"b:AMATAAIAAAIBIAAAAEgABAAAgAAA","13":"b:AMATAAIAAAIBIAAAAEgABAAAgAAA","14":"b:AMATAAIAAAIBIAAAAEgABAAAgAAA","26":"b:AMATAAIAAAIBIAAAAEgABAAAgAAA","28":"b:AMATAAIAAAIBIAAAAEgABAAAgAAA"},"packages/localhost-38255/assets/_plugin-vue_export-helper-Da88TEg1.js":{"2":[110]},"packages/localhost-38255/assets/chunk-CC9Q-vWm.js":{"8":[110],"9":[110],"10":[110],"19":[110],"23":[110],"29":[110],"33":[110],"34":[110]},"packages/@n8n/api-types/src/schemas/node-version.schema.ts":{"7":[29,69,117,120,123,124,128,129]},"packages/cli/src/controllers/dynamic-node-parameters.controller.ts":{"16":[29,69,117,120,123,124,128,129],"19":[29,69,117,120,123,124,128,129],"68":[29,69,117,120,123,124,128,129],"106":[29,69,117,120,123,124,128,129],"134":[29,69,117,120,123,124,128,129],"158":[29,69,117,120,123,124,128,129]},"packages/cli/src/services/dynamic-node-parameters.service.ts":{"60":"b:AAAAIHAAAAAgAAAAAAAgGQMAAAAA","68":"b:AAAAIHAAAAAgAAAAAAAgGQMAAAAA","108":"b:AAAAIHAAAAAgAAAAAAAgGQMAAAAA","109":"b:AAAAIHAAAAAgAAAAAAAgGQMAAAAA","118":"b:AAAAIHAAAAAgAAAAAAAgGQMAAAAA","127":"b:AAAAIHAAAAAgAAAAAAAgGQMAAAAA","139":"b:AAAAIHAAAAAgAAAAAAAgGQMAAAAA","147":"b:AAAAIHAAAAAgAAAAAAAgGQMAAAAA","215":"b:AAAAIHAAAAAgAAAAAAAgGQMAAAAA","226":"b:AAAAIHAAAAAgAAAAAAAgGQMAAAAA","230":"b:AAAAIHAAAAAgAAAAAAAgGQMAAAAA","244":"b:AAAAIHAAAAAgAAAAAAAgGQMAAAAA","250":"b:AAAAIHAAAAAgAAAAAAAgGQMAAAAA","262":"b:AAAAIHAAAAAgAAAAAAAgGQMAAAAA","268":"b:AAAAIHAAAAAgAAAAAAAgGQMAAAAA","281":"b:AAAAIHAAAAAgAAAAAAAgGQMAAAAA","294":"b:AAAAIHAAAAAgAAAAAAAgGQMAAAAA","320":"b:AAAAIHAAAAAgAAAAAAAgGQMAAAAA","363":"b:AAAAIHAAAAAgAAAAAAAgGQMAAAAA","367":"b:AAAAIHAAAAAgAAAAAAAgGQMAAAAA","393":"b:AAAAIHAAAAAgAAAAAAAgGQMAAAAA","402":"b:AAAAIHAAAAAgAAAAAAAgGQMAAAAA","414":"b:AAAAIHAAAAAgAAAAAAAgGQMAAAAA","418":"b:AAAAIHAAAAAgAAAAAAAgGQMAAAAA"},"packages/cli/src/services/workflow-loader.service.ts":{"7":[69,128,129],"9":[69,128,129]},"packages/cli/src/workflows/workflow.formatter.ts":{"6":"b:AAAAAAAAAJAAAAAgAAAAADIAACkB"},"packages/core/src/execution-engine/active-workflow-triggers.ts":{"38":"b:AAAAAAAEAJAAAAAgAAAAALIiAC0B","51":"b:AAAAAAAEAJAAAAAgAAAAALIiAC0B","58":"b:AAAAAAAEAJAAAAAgAAAAALIiAC0B","65":"b:AAAAAAAEAJAAAAAgAAAAALIiAC0B","76":"b:AAAAAAAEAJAAAAAgAAAAALIiAC0B","89":"b:AAAAAAAEAJAAAAAgAAAAALIiAC0B","109":"b:AAAAAAAEAJAAAAAgAAAAALIiAC0B","127":"b:AAAAAAAEAJAAAAAgAAAAALIiAC0B","167":"b:AAAAAAAEAJAAAAAgAAAAALIiAC0B","211":"b:AAAAAAAEAJAAAAAgAAAAALIiAC0B","242":"b:AAAAAAAEAJAAAAAgAAAAALIiAC0B","269":"b:AAAAAAAEAJAAAAAgAAAAALIiAC0B","312":"b:AAAAAAAEAJAAAAAgAAAAALIiAC0B","321":"b:AAAAAAAEAJAAAAAgAAAAALIiAC0B","347":"b:AAAAAAAEAJAAAAAgAAAAALIiAC0B","368":"b:AAAAAAAEAJAAAAAgAAAAALIiAC0B","395":"b:AAAAAAAEAJAAAAAgAAAAALIiAC0B","406":"b:AAAAAAAEAJAAAAAgAAAAALIiAC0B","408":"b:AAAAAAAEAJAAAAAgAAAAALIiAC0B","418":"b:AAAAAAAEAJAAAAAgAAAAALIiAC0B"},"packages/core/src/execution-engine/node-execution-context/local-load-options-context.ts":{"16":[69,128,129],"23":[69,128,129],"42":[69,128,129],"69":[69,128,129]},"packages/core/src/execution-engine/node-execution-context/workflow-node-context.ts":{"16":[69,128,129],"22":[69,128,129]},"packages/core/src/execution-engine/workflow-active-triggers-state.ts":{"7":"b:AAAAAAAAAJAAAAAgAAAAADIAACkB","11":"b:AAAAAAAAAJAAAAAgAAAAADIAACkB","16":"b:AAAAAAAAAJAAAAAgAAAAADIAACkB","21":"b:AAAAAAAAAJAAAAAgAAAAADIAACkB","26":"b:AAAAAAAAAJAAAAAgAAAAADIAACkB","31":"b:AAAAAAAAAJAAAAAgAAAAADIAACkB","36":"b:AAAAAAAAAJAAAAAgAAAAADIAACkB"},"packages/nodes-base/nodes/ExecuteWorkflow/ExecuteWorkflow/ExecuteWorkflow.node.ts":{"290":[69,127,128,160,155,129]},"packages/nodes-base/nodes/ExecuteWorkflow/ExecuteWorkflow/GenericFunctions.ts":{"10":[69,127,128,160,155,129],"29":[69,127,128,160,155,129]},"packages/nodes-base/nodes/ExecuteWorkflow/ExecuteWorkflow/methods/localResourceMapping.ts":{"5":[69,127,128,160,155,129]},"packages/nodes-base/nodes/ExecuteWorkflow/ExecuteWorkflowTrigger/ExecuteWorkflowTrigger.node.ts":{"223":[69,127,128,160,155,129],"229":[69,127,128,160,155,129],"248":[69,127,128,160,155,129],"249":[69,127,128,160,155,129],"251":[69,127,128,160,155,129],"254":[69,127,128,160,155,129]},"packages/nodes-base/utils/workflow-backtracking.ts":{"24":[69,127,128,160,155,129],"44":[69,127,128,160,155,129]},"packages/nodes-base/utils/workflowInputsResourceMapping/GenericFunctions.ts":{"27":[69,127,128,160,155,129],"29":[69,127,128,160,155,129],"74":[69,127,128,160,155,129],"81":[69,127,128,160,155,129],"121":[69,127,128,160,155,129],"126":[69,127,128,160,155,129],"147":[69,127,128,160,155,129],"155":[69,127,128,160,155,129],"157":[69,127,128,160,155,129],"160":[69,127,128,160,155,129],"168":[69,127,128,160,155,129],"184":[69,127,128,160,155,129]},"packages/workflow/src/node-parameters/path-utils.ts":{"10":[69,128,129]},"packages/@n8n/design-system/src/components/N8nIcon/nodes/execute-sub-workflow.svg":{"11":[54,127,128,129]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/ParameterIssues.vue":{"9":"b:ABAYQAAyAAIgAQAAAAGiCQIAAAAA","10":"b:ABAYQAAyAAIgAQAAAAGiCAIAAAAA","17":"b:ABAYAAACAAIgAQAAAAGiCQIAAAAA"},"packages/frontend/editor-ui/src/features/ndv/parameters/components/ResourceMapper/ResourceMapper.vue":{"50":[69,123,124,128,129],"90":[124],"110":[69,123,124,128,129],"112":[124],"130":[124],"142":[69,123,124,128,129],"144":[124],"156":[69,123,124,128,129],"192":[124],"222":[124],"226":[69,123,124,128,129],"233":[69,123,124,128,129],"237":[69,123,124,128,129],"241":[69,123,124,128,129],"245":[69,123,124,128,129],"253":[69,123,124,128,129],"263":[124],"273":[124],"289":[69,123,124,128,129],"292":[124],"300":[69,128,129],"307":[69,123,124,128,129],"332":[69,123,124,128,129],"357":[69,123,124,128,129],"380":[69,123,124,128,129],"388":[124],"389":[124],"416":[69,123,124,128,129],"419":[124],"439":[69,123,124,128,129],"452":[69,123,124,128,129],"458":[124],"469":[124],"489":[124],"495":[124],"503":[124],"504":[124],"521":[124],"568":[69,123,124,128,129],"580":[69,123,124,128,129],"586":[124],"597":[69,123,124,128,129],"630":[124],"633":[69,128,129],"666":[69,128,129]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/WorkflowSelectorParameterInput/WorkflowSelectorParameterInput.vue":{"59":[69,128,129],"96":[69,128,129],"120":[69,128,129],"130":[69,128,129],"144":[69,128,129],"156":[69,128,129],"164":[69,128,129],"168":[69,128,129],"175":[128,129],"193":[129],"203":[69,129],"208":[69,129],"216":[129],"229":[69,128,129],"245":[69,128,129],"252":[128,129],"256":[69,128,129],"257":[129],"266":[69,128,129],"267":[69,128,129],"279":[69,128,129],"283":[69,129],"288":[69,129],"321":[69,128,129],"359":[129],"367":[69,128,129],"385":[69,128,129],"387":[69,128,129],"393":[69,128,129],"410":[69,128,129],"446":[69,128,129],"470":[69,128,129]},"packages/frontend/editor-ui/src/features/ndv/parameters/composables/useWorkflowResourceLocatorDropdown.ts":{"4":[69,128,129],"11":[69,129],"19":[69,129],"23":[69,129]},"packages/frontend/editor-ui/src/features/ndv/parameters/composables/useWorkflowResourceLocatorModes.ts":{"12":[69,128,129],"19":[69,128,129],"32":[69,128,129],"33":[69,128,129],"35":[129],"52":[69,128,129]},"packages/frontend/editor-ui/src/features/ndv/parameters/composables/useWorkflowResourcesLocator.ts":{"11":[69,128,129],"25":[69,128,129],"27":[69,128,129],"36":[128,129],"44":[69,129],"52":[69,128,129],"57":[69,128,129],"67":[69,128,129],"92":[69,128,129],"98":[129],"103":[69,129]},"packages/core/src/execution-engine/scheduled-task-manager.ts":{"22":"b:AAAAAAAEAAAAAAAgAAAAALAiACUB","27":"b:AAAAAAAEAAAAAAAgAAAAALAiACUB","34":"b:AAAAAAAEAAAAAAAgAAAAALAiACUB","44":"b:AAAAAAAEAAAAAAAgAAAAALAiACUB","53":"b:AAAAAAAEAAAAAAAgAAAAALAiACUB","82":"b:AAAAAAAEAAAAAAAgAAAAALAiACUB","85":"b:AAAAAAAEAAAAAAAgAAAAALAiACUB","127":"b:AAAAAAAEAAAAAAAgAAAAALAiACUB","151":"b:AAAAAAAEAAAAAAAgAAAAALAiACUB","156":"b:AAAAAAAEAAAAAAAgAAAAALAiACUB","183":"b:AAAAAAAEAAAAAAAgAAAAALAiACUB","188":"b:AAAAAAAEAAAAAAAgAAAAALAiACUB","197":"b:AAAAAAAEAAAAAAAgAAAAALAiACUB","213":"b:AAAAAAAEAAAAAAAgAAAAALAiACUB"},"packages/frontend/editor-ui/src/features/execution/executions/components/ExecutionsTime.vue":{"14":[135],"22":[135],"24":[135],"29":[135],"36":[135]},"packages/localhost-45211/assets/_plugin-vue_export-helper-Da88TEg1.js":{"2":[135]},"packages/localhost-45211/assets/chunk-CC9Q-vWm.js":{"8":[135],"9":[135],"10":[135],"19":[135],"23":[135],"29":[135],"33":[135],"34":[135]},"packages/@n8n/design-system/src/components/N8nIcon/nodes/respond-to-webhook.svg":{"11":[29,32,64,117,122,137]},"packages/frontend/editor-ui/src/features/ndv/panel/components/TriggerPanel.vue":{"60":"b:AAAQIAEAAAIBAAAAAIggBAACAAAA","74":"b:AAAQIAEQBAIBAAAAAIggLAACAAAA","78":"b:AAAQIAEQBAIBAAAAAIggLAACAAAA","86":"b:AAAQIAEAAAIBAAAAAIggBAACAAAA","94":"b:AAAQIAEAAAIBAAAAAIggBAACAAAA","113":"b:AAAQIAEQBAIBAAAAAIggLAACAAAA","119":[29,32,64,111,117,122,137],"127":[20,57],"135":[20,57,64,107],"139":"b:AAAQIAEQBAIBAAAAAIggLAACAAAA","157":"b:AAAQIAEQBAIBAAAAAIggLAACAAAA","165":"b:AAAQIAEAAAIBAAAAAIggBAACAAAA","169":[20,57,64,111],"173":"b:AAAQIAEAAAIBAAAAAIggBAACAAAA","191":[20,29,32,57,64,111,117,122,137],"193":[20,29,32,57,64,111,117,122,137],"199":[20,29,32,57,64,111,117,122,137],"201":[20,57],"207":[20,57],"220":[20,29,32,57,64,111,117,122,137],"238":[20,29,32,57,64,111,117,122,137],"248":[20,29,32,57,64,111,117,122,137],"288":[20,29,32,57,64,111,117,122,137],"378":[107],"435":[20,57],"439":[20,57],"465":[29,32,57,64,111,117,122,137],"482":[29,32,57,64,111,117,122,137],"488":[29,32,57,64,111,117,122,137]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/ImportCurlParameter.vue":{"11":"b:ABAAQAUwAAQBgAAAAQSABAAAAAAA","16":"b:ABAAQAUwAAQBgAAAAQSABAAAAAAA"},"packages/frontend/editor-ui/src/features/shared/editors/components/InlineExpressionEditor/InlineExpressionTip.vue":{"21":"b:ABAYAAUgAA4BAEAAAAUPHwAAAAAA","33":"b:AAAAAAAAAAAAAEAAAAEPHwAAAAAA","37":[112,113,114,115,120,121,122],"39":"b:ABAYAAUgAA4BAEAAAAUPHwAAAAAA","57":"b:AAAAAAAAAAAAAEAAAAAPHwAAAAAA","83":"b:ABAYAAUgAA4BAEAAAAUPGQAAAAAA","88":"b:ABAYAAUgAA4BAEAAAAUPHwAAAAAA","96":"b:ABAYAAUgAA4BAEAAAAUPHwAAAAAA","97":"b:AAAAAAAAAAAAAEAAAAAPHwAAAAAA","106":"b:ABAYAAUgAA4BAEAAAAUPHwAAAAAA","110":"b:ABAYAAUgAA4BAEAAAAUPHwAAAAAA","114":[113,115,120,122],"120":[113,115,120,122]},"packages/localhost-45867/assets/_plugin-vue_export-helper-Da88TEg1.js":{"2":[32,50,83,100,104,106,116,117]},"packages/localhost-45867/assets/chunk-CC9Q-vWm.js":{"8":[32,50,83,100,104,106,116,117],"9":[32,50,83,100,104,106,116,117],"10":[32,50,83,100,104,106,116,117],"19":[32,50,83,100,104,106,116,117],"23":[32,50,83,100,104,106,116,117],"29":[32,50,83,100,104,106,116,117],"33":[32,50,83,100,104,106,116,117],"34":[32,50,83,100,104,106,116,117]},"packages/localhost-45867/assets/shield-alt-B7h2cjjC.js":{"8":[32,50,104,117]},"packages/@n8n/ai-utilities/src/node-catalog/discriminator-utils.ts":{"44":[156,157],"55":[156,157],"70":[156,157],"81":[156,157],"117":[156,157],"128":[156,157],"139":[156,157],"151":[156,157],"161":[156,157],"178":[156,157]},"packages/@n8n/ai-utilities/src/node-catalog/index.ts":{"14":[156,157],"31":[156,157]},"packages/@n8n/ai-utilities/src/node-catalog/lean-node-type.ts":{"62":[156,157],"66":[156,157],"88":[156,157]},"packages/@n8n/ai-utilities/src/node-catalog/node-type-parser.ts":{"39":[156,157],"48":[156,157],"64":[156,157],"80":[156,157],"87":[156,157],"109":[156,157],"118":[156,157],"126":[156,157],"145":[156,157]},"packages/@n8n/ai-utilities/src/node-catalog/resource-operation-extractor.ts":{"56":[156,157],"82":[156,157],"87":[156,157],"98":[156,157],"122":[156,157],"127":[156,157],"152":[156,157],"171":[156,157],"198":[156,157],"216":[156,157],"250":[156,157],"288":[156,157],"295":[156,157],"305":[156,157]},"packages/@n8n/ai-utilities/src/node-catalog/search-engine.ts":{"20":[156,157],"27":[156,157],"58":[156,157],"72":[156,157],"79":[156,157],"82":[156,157],"89":[156,157],"91":[156,157],"120":[156,157],"121":[156,157],"132":[156,157],"138":[156,157],"149":[156,157],"153":[156,157],"157":[156,157],"161":[156,157],"173":[156,157],"203":[156,157],"210":[156,157],"214":[156,157],"221":[156,157],"223":[156,157],"242":[156,157],"248":[156,157],"250":[156,157],"276":[156,157],"324":[156,157],"337":[156,157],"351":[156,157],"378":[156,157],"379":[156,157],"388":[156,157],"414":[156,157],"422":[156,157],"424":[156,157]},"packages/@n8n/ai-workflow-builder.ee/src/code-builder/index.ts":{"14":[156,157],"21":[156,157],"22":[156,157],"24":[156,157]},"packages/@n8n/ai-workflow-builder.ee/src/index.ts":{"7":[18,156,157],"42":[18,156,157]},"packages/@n8n/workflow-sdk/src/index.ts":{"113":[156,157],"126":[156,157],"164":[156,157]},"packages/@n8n/workflow-sdk/src/validation/index.ts":{"64":[156,157],"91":[156,157],"139":[156,157],"204":[156,157],"267":[156,157],"287":[156,157],"305":[156,157],"370":[156,157],"382":[156,157],"473":[156,157],"539":[156,157],"596":[156,157],"629":[156,157],"692":[156,157],"700":[156,157],"701":[156,157],"723":[156,157],"736":[156,157],"750":[156,157],"772":[156,157],"857":[156,157],"898":[156,157],"933":[156,157],"945":[156,157],"969":[156,157],"1001":[156,157],"1031":[156,157],"1035":[156,157],"1048":[156,157],"1055":[156,157],"1063":[156,157],"1068":[156,157],"1075":[156,157],"1100":[156,157],"1158":[156,157],"1195":[156,157]},"packages/@n8n/workflow-sdk/src/validation/schema-validator.ts":{"38":[156,157],"46":[156,157],"59":[156,157],"75":[156,157],"94":[156,157],"120":[156,157],"138":[156,157],"151":[156,157],"183":[156,157],"192":[156,157],"212":[156,157],"256":[156,157],"284":[156,157],"300":[156,157],"313":[156,157],"335":[156,157],"357":[156,157],"389":[156,157],"412":[156,157],"420":[156,157],"422":[156,157],"469":[156,157],"479":[156,157],"482":[156,157],"503":[156,157],"515":[156,157],"518":[156,157],"520":[156,157],"539":[156,157],"548":[156,157],"550":[156,157],"558":[156,157],"573":[156,157],"588":[156,157],"590":[156,157],"611":[156,157],"626":[156,157],"627":[156,157],"636":[156,157],"653":[156,157],"679":[156,157],"680":[156,157]},"packages/cli/src/modules/data-table/data-table-proxy.service.ts":{"44":[156,157],"50":[156,157],"60":[156,157],"69":[156,157],"75":[156,157],"80":[156,157],"91":[156,157],"103":[156,157],"110":[156,157],"113":[156,157],"115":[156,157],"119":[156,157],"124":[156,157],"131":[156,157],"137":[156,157],"147":[156,157],"153":[156,157],"159":[156,157],"171":[156,157],"178":[156,157],"188":[156,157],"199":[156,157],"211":[156,157],"229":[156,157],"232":[156,157],"236":[156,157],"244":[156,157],"248":[156,157],"254":[156,157],"262":[156,157],"266":[156,157],"271":[156,157],"275":[156,157],"279":[156,157],"283":[156,157],"288":[156,157],"292":[156,157],"299":[156,157],"309":[156,157],"319":[156,157]},"packages/cli/src/modules/mcp/mcp-api-key.service.ts":{"25":[157],"33":[157],"56":[157],"71":[157],"105":[157],"124":[157],"133":[157],"146":[157],"162":[157],"163":[157]},"packages/cli/src/modules/mcp/mcp-server-middleware.service.ts":{"23":[156,157],"34":[156,157],"61":[156,157],"62":[156,157],"103":[156,157],"116":[156,157],"125":[156,157]},"packages/cli/src/modules/mcp/mcp.controller.ts":{"24":[156,157],"28":[156,157],"37":[156,157],"64":[156,157],"80":[156,157],"113":[156,157],"191":[156,157],"197":[156,157],"204":[156,157],"212":[156,157]},"packages/cli/src/modules/mcp/mcp.errors.ts":{"9":[156,157],"21":[156,157],"35":[156,157],"46":[156,157],"53":[156,157],"66":[156,157]},"packages/cli/src/modules/mcp/mcp.service.ts":{"107":[156,157],"135":[156,157],"154":[156,157],"193":[156,157],"194":[156,157],"400":[156,157],"453":[156,157],"533":[156,157],"555":[156,157],"563":[156,157],"578":[156,157],"592":[156,157],"603":[156,157],"626":[156,157],"641":[156,157]},"packages/cli/src/modules/mcp/mcp.settings.controller.ts":{"19":[156,157],"30":[156,157],"52":[156,157],"58":[156,157],"63":[156,157],"87":[156,157]},"packages/cli/src/modules/mcp/mcp.settings.service.ts":{"45":[156,157],"55":[156,157],"71":[156,157],"80":[156,157],"120":[156,157],"180":[156,157],"204":[156,157],"209":[156,157],"225":[156,157],"228":[156,157],"248":[156,157],"263":[156,157]},"packages/cli/src/modules/mcp/mcp.typeguards.ts":{"15":[156,157],"24":[156,157],"47":[156,157],"58":[156,157],"76":[156,157]},"packages/cli/src/modules/mcp/mcp.utils.ts":{"11":[156,157],"24":[156,157],"41":[156,157],"63":[156,157],"71":[156,157]},"packages/cli/src/modules/mcp/tools/data-table/add-data-table-column.tool.ts":{"29":[156,157],"47":[156,157]},"packages/cli/src/modules/mcp/tools/data-table/add-data-table-rows.tool.ts":{"30":[156,157],"49":[156,157]},"packages/cli/src/modules/mcp/tools/data-table/create-data-table.tool.ts":{"35":[156,157],"54":[156,157],"72":[156,157]},"packages/cli/src/modules/mcp/tools/data-table/delete-data-table-column.tool.ts":{"19":[156,157],"38":[156,157]},"packages/cli/src/modules/mcp/tools/data-table/index.ts":{"1":[156,157],"2":[156,157],"3":[156,157],"5":[156,157],"6":[156,157]},"packages/cli/src/modules/mcp/tools/data-table/rename-data-table-column.tool.ts":{"28":[156,157],"46":[156,157]},"packages/cli/src/modules/mcp/tools/data-table/rename-data-table.tool.ts":{"19":[156,157],"37":[156,157]},"packages/cli/src/modules/mcp/tools/data-table/search-data-tables.tool.ts":{"28":[156,157],"47":[156,157],"73":[156,157],"79":[156,157]},"packages/cli/src/modules/mcp/tools/execute-workflow.tool.ts":{"96":[156,157],"117":[156,157],"191":[156,157],"224":[156,157],"246":[156,157],"316":[156,157],"334":[156,157],"387":[156,157],"414":[156,157],"425":[156,157],"449":[156,157]},"packages/cli/src/modules/mcp/tools/get-execution.tool.ts":{"64":[156,157],"84":[156,157],"206":[156,157],"239":[156,157],"243":[156,157]},"packages/cli/src/modules/mcp/tools/get-workflow-details.tool.ts":{"31":[156,157],"55":[156,157],"104":[156,157],"134":[156,157],"142":[156,157],"165":[156,157],"167":[156,157]},"packages/cli/src/modules/mcp/tools/list-credentials.tool.ts":{"90":[156,157],"109":[156,157],"163":[156,157],"193":[156,157]},"packages/cli/src/modules/mcp/tools/prepare-workflow-pin-data.tool.ts":{"57":[156,157],"79":[156,157],"137":[156,157],"147":[156,157],"150":[156,157],"223":[156,157]},"packages/cli/src/modules/mcp/tools/publish-workflow.tool.ts":{"39":[156,157],"60":[156,157],"77":[156,157]},"packages/cli/src/modules/mcp/tools/schemas.ts":{"14":[156,157],"18":[156,157],"43":[156,157]},"packages/cli/src/modules/mcp/tools/search-executions.tool.ts":{"64":[156,157],"84":[156,157],"134":[156,157]},"packages/cli/src/modules/mcp/tools/search-folders.tool.ts":{"35":[156,157],"55":[156,157],"93":[156,157]},"packages/cli/src/modules/mcp/tools/search-projects.tool.ts":{"62":[156,157],"82":[156,157],"114":[156,157],"115":[156,157],"119":[156,157],"127":[156,157],"135":[156,157],"142":[156,157]},"packages/cli/src/modules/mcp/tools/search-workflows.tool.ts":{"73":[156,157],"93":[156,157],"151":[156,157],"187":[156,157]},"packages/cli/src/modules/mcp/tools/test-workflow.tool.ts":{"58":[156,157],"81":[156,157],"150":[156,157],"183":[156,157],"184":[156,157],"254":[156,157]},"packages/cli/src/modules/mcp/tools/unpublish-workflow.tool.ts":{"31":[156,157],"52":[156,157],"68":[156,157]},"packages/cli/src/modules/mcp/tools/webhook-utils.ts":{"41":[157],"49":[157],"108":[157],"114":[157],"123":[157],"129":[157],"139":[157],"145":[157],"159":[157],"168":[157],"176":[157],"198":[157],"201":[157],"206":[157],"217":[157],"233":[157],"263":[157],"278":[157],"298":[157]},"packages/cli/src/modules/mcp/tools/workflow-builder/create-workflow-from-code.tool.ts":{"25":[156,157],"113":[156,157],"137":[156,157],"180":[156,157],"195":[156,157],"269":[156,157]},"packages/cli/src/modules/mcp/tools/workflow-builder/delete-workflow.tool.ts":{"28":[156,157],"48":[156,157],"66":[156,157]},"packages/cli/src/modules/mcp/tools/workflow-builder/get-workflow-best-practices.tool.ts":{"49":[156,157],"50":[156,157],"56":[156,157],"63":[156,157],"79":[156,157],"104":[156,157],"122":[156,157]},"packages/cli/src/modules/mcp/tools/workflow-builder/get-workflow-node-types.tool.ts":{"39":[156,157],"58":[156,157]},"packages/cli/src/modules/mcp/tools/workflow-builder/get-workflow-sdk-reference.tool.ts":{"41":[156,157],"59":[156,157]},"packages/cli/src/modules/mcp/tools/workflow-builder/mcp-instructions.ts":{"21":[156,157]},"packages/cli/src/modules/mcp/tools/workflow-builder/search-workflow-nodes.tool.ts":{"31":[156,157],"50":[156,157]},"packages/cli/src/modules/mcp/tools/workflow-builder/update-workflow.tool.ts":{"121":[156,157],"126":[156,157],"140":[156,157],"142":[156,157],"220":[156,157],"246":[156,157],"263":[156,157],"298":[156,157],"345":[156,157],"358":[156,157],"371":[156,157]},"packages/cli/src/modules/mcp/tools/workflow-builder/validate-node.tool.ts":{"81":[156,157],"99":[156,157],"107":[156,157],"109":[156,157],"126":[156,157],"127":[156,157],"128":[156,157]},"packages/cli/src/modules/mcp/tools/workflow-builder/validate-workflow-code.tool.ts":{"53":[156,157],"72":[156,157],"80":[156,157],"90":[156,157]},"packages/cli/src/modules/mcp/tools/workflow-validation.utils.ts":{"20":[157],"50":[157]},"packages/cli/src/node-catalog/node-catalog.service.ts":{"67":[156,157],"71":[156,157],"74":[156,157],"79":[156,157],"86":[156,157],"100":[156,157],"118":[156,157],"120":[156,157],"132":[156,157],"134":[156,157],"161":[156,157],"171":[156,157],"176":[156,157],"182":[156,157],"183":[156,157],"184":[156,157],"201":[156,157],"204":[156,157],"219":[156,157],"229":[156,157]},"packages/cli/src/telemetry/index.ts":{"86":[156,157],"97":[156,157],"142":[156,157],"154":[156,157],"156":[156,157],"165":[156,157],"174":[156,157],"176":[156,157],"183":[156,157],"226":[156,157],"227":[156,157],"251":[156,157],"255":[156,157],"256":[156,157],"276":[156,157],"323":[156,157],"336":[156,157],"362":[156,157],"386":[156,157],"393":[156,157],"423":[156,157],"449":[156,157],"491":[156,157],"495":[156,157],"499":[156,157]},"packages/nodes-base/nodes/OpenWeatherMap/OpenWeatherMap.node.ts":{"195":[50]},"packages/@n8n/design-system/src/components/N8nIcon/nodes/ftp.svg":{"11":[50]},"packages/@n8n/nodes-langchain/nodes/mcp/McpTrigger/McpServer.ts":{"59":[159],"68":[159],"76":[159],"89":[159],"98":[159],"99":[159],"102":[159],"117":[159],"130":[159],"185":[159],"206":[159],"230":[159],"234":[159],"244":[159],"260":[159],"278":[159],"327":[159],"332":[159],"337":[159],"341":[159],"345":[159],"349":[159],"353":[159],"357":[159],"361":[159],"365":[159],"369":[159],"380":[159],"389":[159],"405":[159],"422":[159],"432":[159],"435":[159],"442":[159],"454":[159],"470":[159],"516":[159],"519":[159]},"packages/@n8n/nodes-langchain/nodes/mcp/McpTrigger/McpTrigger.node.ts":{"13":[159],"144":[159]},"packages/@n8n/nodes-langchain/nodes/mcp/McpTrigger/execution/DirectExecutionStrategy.ts":{"6":[159]},"packages/@n8n/nodes-langchain/nodes/mcp/McpTrigger/execution/ExecutionCoordinator.ts":{"10":[159],"14":[159],"22":[159],"26":[159],"30":[159]},"packages/@n8n/nodes-langchain/nodes/mcp/McpTrigger/execution/PendingCallsManager.ts":{"9":[159],"12":[159],"18":[159],"19":[159],"35":[159],"46":[159],"57":[159],"61":[159],"65":[159],"69":[159]},"packages/@n8n/nodes-langchain/nodes/mcp/McpTrigger/protocol/MessageFormatter.ts":{"4":[159],"25":[159]},"packages/@n8n/nodes-langchain/nodes/mcp/McpTrigger/protocol/MessageParser.ts":{"11":[159],"20":[159],"30":[159],"40":[159],"49":[159]},"packages/@n8n/nodes-langchain/nodes/mcp/McpTrigger/session/InMemorySessionStore.ts":{"5":[159],"11":[159],"16":[159],"21":[159],"26":[159],"30":[159],"34":[159]},"packages/@n8n/nodes-langchain/nodes/mcp/McpTrigger/session/SessionManager.ts":{"16":[159],"18":[159],"32":[159],"37":[159],"41":[159],"45":[159],"49":[159],"53":[159],"57":[159],"61":[159],"65":[159]},"packages/@n8n/nodes-langchain/nodes/mcp/McpTrigger/transport/SSETransport.ts":{"10":[159],"17":[159],"22":[159]},"packages/@n8n/nodes-langchain/nodes/mcp/McpTrigger/transport/StreamableHttpTransport.ts":{"17":[159],"32":[159],"37":[159],"49":[159],"54":[159]},"packages/@n8n/nodes-langchain/nodes/mcp/McpTrigger/transport/TransportFactory.ts":{"13":[159],"17":[159],"23":[159],"30":[159],"35":[159]},"packages/@n8n/nodes-langchain/nodes/tools/ToolCode/ToolCode.node.ts":{"46":[15,159],"72":[15,159],"92":[15,159],"176":[15,159],"329":[15,159],"334":[15,159]},"packages/@n8n/nodes-langchain/utils/schemaParsing.ts":{"9":[159],"10":[159],"36":[159],"51":[159],"55":[159]},"packages/cli/src/credentials/dynamic-credentials-proxy.ts":{"30":"b:AAAAAHAgAJEAAAAAAAAAAAAABIQA","32":"b:AAAAAHAgAJEAAAAAAAAAAAAABIQA","36":"b:AAAAAHAgAJEAAAAAAAAAAAAABIQA","46":"b:AAAAAHAgAJEAAAAAAAAAAAAABIQA","58":"b:AAAAAHAgAJEAAAAAAAAAAAAABIQA","64":"b:AAAAAHAgAJEAAAAAAAAAAAAABIQA","87":"b:AAAAAHAgAJEAAAAAAAAAAAAABIQA","115":"b:AAAAAHAgAJEAAAAAAAAAAAAABIQA"},"packages/cli/src/errors/response-errors/webhook-not-found.error.ts":{"3":[141,159],"36":[141,159]},"packages/workflow/src/tool-helpers.ts":{"10":[41,159]},"packages/@n8n/db/src/utils/build-workflows-by-nodes-query.ts":{"4":[36,37,38,83],"20":[36,37,38,83],"27":[36,37,38,83]},"packages/frontend/editor-ui/src/features/settings/communityNodes/components/CommunityPackageCard.vue":{"43":[83],"47":[83],"55":[83],"63":[83],"80":[83],"98":[83],"103":[83],"105":[83],"108":[83],"120":[83],"135":[83],"142":[83],"151":[83],"168":[83],"176":[83]},"packages/frontend/editor-ui/src/features/settings/communityNodes/components/CommunityPackageInstallModal.vue":{"32":[83],"39":[83],"47":[83],"54":[83],"78":[83],"82":[83],"86":[83],"98":[83],"111":[83],"119":[83],"134":[83],"167":[83],"172":[83],"178":[83]},"packages/frontend/editor-ui/src/features/settings/communityNodes/components/CommunityPackageManageConfirmModal.vue":{"32":[83],"54":[83],"57":[83],"68":[83],"69":[83],"72":[83],"108":[83],"112":[83],"120":[83],"124":[83],"147":[83],"151":[83],"190":[83],"192":[83],"203":[83],"216":[83],"226":[83],"232":[83],"240":[83],"252":[83],"253":[83],"261":[83],"270":[83]},"packages/frontend/editor-ui/src/features/settings/communityNodes/composables/useInstallNode.ts":{"38":[55,83],"60":[83]},"packages/frontend/editor-ui/src/features/settings/communityNodes/views/SettingsCommunityNodesView.vue":{"40":[83],"44":[83],"48":[83],"56":[83],"77":[83],"82":[83],"94":[83],"104":[83],"110":[83],"117":[83],"122":[83],"126":[83],"130":[83],"178":[83]},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/groups/CanvasNodeGroupTitleBar.vue":{"18":[151,100],"47":[151,100],"48":[151,100],"52":[151,100],"59":[151,100],"68":[151,100],"70":[151,100],"77":[151,100],"81":[151,100],"85":[151,100],"93":[151,100],"97":[151,100],"98":[151,100],"108":[151,100],"115":[151,100],"154":[151,100],"175":[151,100]},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/selection/CanvasSelectionToolbar.vue":{"14":[151,100],"30":[151,100],"31":[151,100],"39":[151,100],"41":[151,100],"45":[151,100],"49":[151,100],"53":[151,100],"61":[151,100],"66":[151],"68":[151,100],"80":[151,100],"87":[151,100],"103":[151,100]},"packages/frontend/editor-ui/src/features/workflows/canvas/composables/useVueFlowTransformPaneTeleport.ts":{"9":[151,100],"14":[151,100],"16":[151,100]},"packages/nodes-base/nodes/Html/Html.node.ts":{"19":[104],"23":[104],"24":[104],"383":[104],"429":[104],"435":[104],"451":[104],"474":[104],"579":[104]},"packages/nodes-base/nodes/Html/utils.ts":{"10":[104],"12":[104],"13":[104],"21":[104],"29":[104],"35":[104]},"packages/nodes-base/nodes/Postgres/Postgres.node.ts":{"8":[104]},"packages/nodes-base/nodes/Postgres/transport/index.ts":{"26":[104],"44":[104],"79":[104],"80":[104],"84":[104],"88":[104],"94":[104],"102":[104],"109":[104],"116":[104],"124":[104],"125":[104],"152":[104],"153":[104],"158":[104],"164":[104],"182":[104],"204":[104]},"packages/nodes-base/nodes/Postgres/v1/PostgresV1.node.ts":{"288":[104],"297":[104],"331":[104]},"packages/nodes-base/nodes/Postgres/v1/genericFunctions.ts":{"13":[104],"27":[104],"33":[104],"36":[104],"55":[104],"62":[104],"78":[104],"83":[104],"88":[104],"92":[104],"105":[104],"119":[104],"121":[104],"136":[104],"157":[104],"182":[104],"198":[104],"200":[104],"224":[104],"231":[104],"255":[104],"291":[104],"307":[104],"308":[104],"314":[104],"327":[104],"346":[104],"383":[104],"398":[104],"399":[104],"405":[104],"418":[104],"425":[104],"450":[104],"494":[104],"510":[104],"511":[104],"517":[104],"520":[104],"537":[104],"546":[104],"558":[104],"561":[104],"587":[104],"626":[104],"641":[104],"642":[104],"648":[104],"651":[104],"668":[104],"677":[104],"690":[104],"693":[104],"721":[104]},"packages/nodes-base/nodes/Postgres/v2/PostgresV2.node.ts":{"16":[104],"25":[104]},"packages/nodes-base/nodes/Postgres/v2/actions/database/deleteTable.operation.ts":{"88":[104]},"packages/nodes-base/nodes/Postgres/v2/actions/database/executeQuery.operation.ts":{"55":[104],"65":[104],"119":[104],"120":[104]},"packages/nodes-base/nodes/Postgres/v2/actions/database/insert.operation.ts":{"161":[104]},"packages/nodes-base/nodes/Postgres/v2/actions/database/select.operation.ts":{"79":[104]},"packages/nodes-base/nodes/Postgres/v2/actions/database/update.operation.ts":{"195":[104],"279":[104],"286":[104],"333":[104]},"packages/nodes-base/nodes/Postgres/v2/actions/database/upsert.operation.ts":{"194":[104],"286":[104],"298":[104]},"packages/nodes-base/nodes/Postgres/v2/actions/router.ts":{"11":[104]},"packages/nodes-base/nodes/Postgres/v2/helpers/utils.ts":{"27":[104],"36":[104],"46":[104],"50":[104],"51":[104],"54":[104],"58":[104],"63":[104],"70":[104],"79":[104],"87":[104],"130":[104],"151":[104],"180":[104],"192":[104],"207":[104],"226":[104],"234":[104],"311":[104],"314":[104],"315":[104],"322":[104],"353":[104],"356":[104],"359":[104],"366":[104],"376":[104],"392":[104],"413":[104],"453":[104],"495":[104],"501":[104],"517":[104],"518":[104],"526":[104],"527":[104],"530":[104],"537":[104],"540":[104],"547":[104],"562":[104],"592":[104],"608":[104],"613":[104],"620":[104],"625":[104],"628":[104],"645":[104],"652":[104],"673":[104],"676":[104],"694":[104],"711":[104],"752":[104],"754":[104],"766":[104],"772":[104],"781":[104]},"packages/nodes-base/nodes/Postgres/v2/methods/credentialTest.ts":{"10":[104]},"packages/nodes-base/nodes/Postgres/v2/methods/listSearch.ts":{"6":[104],"17":[104],"24":[104],"40":[104]},"packages/nodes-base/nodes/Postgres/v2/methods/loadOptions.ts":{"7":[104],"23":[104],"30":[104],"38":[104],"43":[104]},"packages/nodes-base/nodes/Postgres/v2/methods/resourceMapping.ts":{"61":[104],"76":[104],"98":[104],"100":[104]},"packages/nodes-base/utils/connection-pool-manager.ts":{"48":[104],"61":[104],"63":[104],"69":[104],"76":[104],"99":[104],"126":[104],"134":[104],"147":[104],"161":[104]},"packages/@n8n/codemirror-lang-sql/src/complete.ts":{"192":[104],"193":[104]},"packages/@n8n/design-system/src/components/N8nIcon/nodes/html.svg":{"11":[104]},"packages/frontend/editor-ui/src/features/shared/editors/components/HtmlEditor/HtmlEditor.vue":{"51":[104],"63":[104],"68":[104],"97":[104],"100":[104],"237":[104],"243":[104],"247":[104],"260":[104],"265":[104]},"packages/frontend/editor-ui/src/features/shared/editors/components/HtmlEditor/utils.ts":{"44":[104]},"packages/frontend/editor-ui/src/features/shared/editors/components/InlineExpressionEditor/ExpressionOutput.vue":{"20":"b:AAAAAAAAAAAAAEAAAAEPHwAAAAAA","30":"b:AAAAAAAAAAAAAEAAAAEPHwAAAAAA","35":"b:AAAAAAAAAAAAAEAAAAEPFwAAAAAA","49":"b:AAAAAAAAAAAAAEAAAAEPHwAAAAAA","50":"b:AAAAAAAAAAAAAEAAAAEPFwAAAAAA","53":"b:AAAAAAAAAAAAAEAAAAEPHwAAAAAA","71":"b:AAAAAAAAAAAAAEAAAAEPFwAAAAAA","82":"b:AAAAAAAAAAAAAEAAAAEPFwAAAAAA","85":"b:AAAAAAAAAAAAAEAAAAEPHwAAAAAA","95":[114],"105":"b:AAAAAAAAAAAAAEAAAAEPHwAAAAAA","106":"b:AAAAAAAAAAAAAEAAAAEPFwAAAAAA","119":"b:AAAAAAAAAAAAAEAAAAEPHwAAAAAA","132":"b:AAAAAAAAAAAAAEAAAAEPHwAAAAAA","137":"b:AAAAAAAAAAAAAEAAAAEPGQAAAAAA","141":[114],"142":"b:AAAAAAAAAAAAAEAAAAEPHwAAAAAA"},"packages/frontend/editor-ui/src/features/shared/editors/components/InlineExpressionEditor/OutputItemSelect.vue":{"7":"b:AAAAAAAAAAAAAEAAAAEPHwAAAAAA","10":"b:AAAAAAAAAAAAAEAAAAEPHwAAAAAA","11":"b:AAAAAAAAAAAAAEAAAAEPHwAAAAAA","12":"b:AAAAAAAAAAAAAEAAAAEPHwAAAAAA","13":"b:AAAAAAAAAAAAAEAAAAEPHwAAAAAA","14":"b:AAAAAAAAAAAAAEAAAAEPHwAAAAAA","17":"b:AAAAAAAAAAAAAEAAAAEPHwAAAAAA","18":"b:AAAAAAAAAAAAAEAAAAEPHwAAAAAA","19":"b:AAAAAAAAAAAAAEAAAAEPHwAAAAAA","20":"b:AAAAAAAAAAAAAEAAAAEPHwAAAAAA","21":"b:AAAAAAAAAAAAAEAAAAEPHwAAAAAA","25":"b:AAAAAAAAAAAAAEAAAAEPHwAAAAAA","31":[120,121],"35":[120],"37":"b:AAAAAAAAAAAAAEAAAAEPHwAAAAAA","43":"b:AAAAAAAAAAAAAEAAAAEPHwAAAAAA","70":"b:AAAAAAAAAAAAAEAAAAEPHwAAAAAA"},"packages/frontend/editor-ui/src/features/shared/editors/components/SqlEditor/SqlEditor.vue":{"42":[104],"80":[104],"82":[104],"88":[104],"130":[104],"135":[104],"140":[104],"146":[104],"154":[104],"158":[104],"160":[104],"163":[104],"208":[104],"213":[104]},"packages/frontend/editor-ui/src/features/shared/editors/plugins/codemirror/completions/blank.completions.ts":{"8":"b:AAAAAAAAAAAAAEAAAAEPHQAAAAAA"},"packages/frontend/editor-ui/src/features/shared/editors/plugins/codemirror/completions/bracketAccess.completions.ts":{"17":"b:AAAAAAAAAAAAAEAAAAEPHQAAAAAA","53":[112,113,114,120],"62":[113],"70":[112,113,114,120],"74":[112,113,114,120],"75":[112,113,114,120]},"packages/frontend/editor-ui/src/features/shared/editors/plugins/codemirror/completions/dollar.completions.ts":{"29":"b:AAAAAAAAAAAAAEAAAAEPHQAAAAAA","43":"b:AAAAAAAAAAAAAEAAAAEPFQAAAAAA","60":"b:AAAAAAAAAAAAAEAAAAEPFQAAAAAA","138":"b:AAAAAAAAAAAAAAAAAAEPFQAAAAAA","153":"b:AAAAAAAAAAAAAAAAAAEPFQAAAAAA","155":"b:AAAAAAAAAAAAAAAAAAEPFQAAAAAA"},"packages/frontend/editor-ui/src/features/shared/editors/plugins/codemirror/completions/nonDollar.completions.ts":{"9":"b:AAAAAAAAAAAAAEAAAAEPHQAAAAAA"},"packages/core/src/binary-data/utils.ts":{"6":"b:ABEAABQEACQBAAAAAAQAgAEQAA4B","10":"b:ABEAABQEACQBAAAAAAQAgAEQAA4B","15":"b:ABEAABQEACQBAAAAAAQAgAEQAA4B","16":"b:ABEAABQEACQBAAAAAAQAgAEQAA4B","18":"b:ABEAABQEACQBAAAAAAQAgAEQAA4B","19":"b:ABEAABQEACQBAAAAAAQAgAEQAA4B","20":"b:ABEAABQEACQBAAAAAAQAgAEQAA4B","29":"b:ABEAABQEACQBAAAAAAQAgAEQAA4B","46":"b:ABEAABQEACQBAAAAAAQAgAEQAA4B","54":"b:ABEAABQEACQBAAAAAAQAgAEQAA4B","75":"b:ABEAABQEACQBAAAAAAQAgAEQAA4B","83":"b:ABEAABQEACQBAAAAAAQAgAEQAA4B","89":"b:ABEAABQEACQBAAAAAAQAgAEQAA4B","98":"b:ABEAABQEACQBAAAAAAQAgAEQAA4B","108":"b:ABEAABQEACQBAAAAAAQAgAEQAA4B"},"packages/core/src/execution-engine/node-execution-context/utils/request-helpers/axios-utils.ts":{"18":"b:ABAAAHQgAIQAAAAAAIQAAQAAAAQA","27":"b:ABAAAHQgAIQAAAAAAIQAAQAAAAQA","36":"b:ABAAAHQgAIQAAAAAAIQAAQAAAAQA","48":"b:ABAAAHQgAIQAAAAAAIQAAQAAAAQA","55":"b:ABAAAHQgAIQAAAAAAIQAAQAAAAQA","59":"b:ABAAAHQgAIQAAAAAAIQAAQAAAAQA","78":"b:ABAAAHQgAIQAAAAAAIQAAQAAAAQA","86":"b:ABAAAHQgAIQAAAAAAIQAAQAAAAQA","133":"b:ABAAAHQgAIQAAAAAAIQAAQAAAAQA","140":"b:ABAAAHQgAIQAAAAAAIQAAQAAAAQA","145":"b:ABAAAHQgAIQAAAAAAIQAAQAAAAQA","148":"b:ABAAAHQgAIQAAAAAAIQAAQAAAAQA","151":"b:ABAAAHQgAIQAAAAAAIQAAQAAAAQA","184":"b:ABAAAHQgAIQAAAAAAIQAAQAAAAQA","194":"b:ABAAAHQgAIQAAAAAAIQAAQAAAAQA","197":"b:ABAAAHQgAIQAAAAAAIQAAQAAAAQA","201":"b:ABAAAHQgAIQAAAAAAIQAAQAAAAQA","217":"b:ABAAAHQgAIQAAAAAAIQAAQAAAAQA","230":"b:ABAAAHQgAIQAAAAAAIQAAQAAAAQA","236":"b:ABAAAHQgAIQAAAAAAIQAAQAAAAQA","238":"b:ABAAAHQgAIQAAAAAAIQAAQAAAAQA","253":"b:ABAAAHQgAIQAAAAAAIQAAQAAAAQA","280":"b:ABAAAHQgAIQAAAAAAIQAAQAAAAQA","291":"b:ABAAAHQgAIQAAAAAAIQAAQAAAAQA","316":"b:ABAAAHQgAIQAAAAAAIQAAQAAAAQA","331":"b:ABAAAHQgAIQAAAAAAIQAAQAAAAQA"},"packages/core/src/execution-engine/node-execution-context/utils/request-helpers/http-request.ts":{"32":"b:ABAAIHQgAIQAAAAAAAQgCQAAAAQA","52":"b:ABAAIHQgAIQAAAAAAAQgCQAAAAQA","108":"b:ABAAIHQgAIQAAAAAAAQgCQAAAAQA","159":"b:ABAAIHQgAIQAAAAAAAQgCQAAAAQA","163":"b:ABAAIHQgAIQAAAAAAAQgCQAAAAQA","173":"b:ABAAIHQgAIQAAAAAAAQgCQAAAAQA","180":"b:ABAAIHQgAIQAAAAAAAQgCQAAAAQA"},"packages/core/src/execution-engine/node-execution-context/utils/request-helpers/legacy-request-adapter.ts":{"55":[12,34,45,154,58,63,106,120],"73":[12,34,45,154,58,63,106,120],"138":[12,34,45,154,58,63,106,120],"187":[12,34,45,154,58,63,106,120],"207":[12,34,45,154,58,63,106,120],"211":[12,34,45,154,58,63,106,120],"220":[12,34,45,154,58,63,106,120],"250":[12,34,45,154,58,63,106,120],"261":[12,34,45,154,58,63,106,120],"314":[12,34,45,154,58,63,106,120],"322":[12,34,45,154,58,63,106,120],"335":[12,34,45,154,58,63,106,120],"352":[12,34,45,154,58,63,106,120]},"packages/core/src/execution-engine/node-execution-context/utils/request-helpers/outbound-user-agent.ts":{"11":"b:ABAAAHQgAIQAAAAAAAQAAQAAAAQA","28":"b:ABAAAHQgAIQAAAAAAAQAAQAAAAQA","40":"b:ABAAAHQgAIQAAAAAAAQAAQAAAAQA","54":"b:ABAAAHQgAIQAAAAAAAQAAQAAAAQA"},"packages/nodes-base/nodes/HttpRequest/GenericFunctions.ts":{"31":"b:ABAAQAQwAAQBAAAAAQSAAAAABAQA","40":"b:ABAAQAQwAAQBAAAAAQSAAAAABAQA","44":"b:ABAAQAQwAAQBAAAAAQSAAAAABAQA","45":"b:ABAAQAQwAAQBAAAAAQSAAAAABAQA","48":"b:ABAAQAQwAAQBAAAAAQSAAAAABAQA","54":"b:ABAAQAQwAAQBAAAAAQSAAAAABAQA","67":"b:ABAAQAQwAAQBAAAAAQSAAAAABAQA","94":"b:ABAAQAQwAAQBAAAAAQSAAAAABAQA","129":"b:ABAAQAQwAAQBAAAAAQSAAAAABAQA","131":"b:ABAAQAQwAAQBAAAAAQSAAAAABAQA","142":"b:ABAAQAQwAAQBAAAAAQSAAAAABAQA","238":"b:ABAAQAQwAAQBAAAAAQSAAAAABAQA","243":"b:ABAAQAQwAAQBAAAAAQSAAAAABAQA","248":"b:ABAAQAQwAAQBAAAAAQSAAAAABAQA","255":"b:ABAAQAQwAAQBAAAAAQSAAAAABAQA","281":"b:ABAAQAQwAAQBAAAAAQSAAAAABAQA","296":"b:ABAAQAQwAAQBAAAAAQSAAAAABAQA","298":"b:ABAAQAQwAAQBAAAAAQSAAAAABAQA","300":"b:ABAAQAQwAAQBAAAAAQSAAAAABAQA","312":"b:ABAAQAQwAAQBAAAAAQSAAAAABAQA"},"packages/nodes-base/nodes/HttpRequest/HttpRequest.node.ts":{"9":"b:ABAAQAQwAAQBAAAAAQSAAAAABAAA"},"packages/nodes-base/nodes/HttpRequest/V1/HttpRequestV1.node.ts":{"42":"b:ABAAQAQwAAQBAAAAAQSAAAAABAAA","616":"b:ABAAQAQwAAQBAAAAAQSAAAAABAAA","812":"b:ABAAQAQwAAQBAAAAAQSAAAAABAAA","889":"b:ABAAQAQwAAQBAAAAAQSAAAAABAAA","1003":"b:ABAAQAQwAAQBAAAAAQSAAAAABAAA","1010":"b:ABAAQAQwAAQBAAAAAQSAAAAABAAA","1015":"b:ABAAQAQwAAQBAAAAAQSAAAAABAAA","1159":"b:ABAAQAQwAAQBAAAAAQSAAAAABAAA"},"packages/nodes-base/nodes/HttpRequest/V2/HttpRequestV2.node.ts":{"44":"b:ABAAQAQwAAQBAAAAAQSAAAAABAAA","629":"b:ABAAQAQwAAQBAAAAAQSAAAAABAAA","874":"b:ABAAQAQwAAQBAAAAAQSAAAAABAAA","951":"b:ABAAQAQwAAQBAAAAAQSAAAAABAAA","1068":"b:ABAAQAQwAAQBAAAAAQSAAAAABAAA","1074":"b:ABAAQAQwAAQBAAAAAQSAAAAABAAA","1079":"b:ABAAQAQwAAQBAAAAAQSAAAAABAAA","1092":"b:ABAAQAQwAAQBAAAAAQSAAAAABAAA","1235":"b:ABAAQAQwAAQBAAAAAQSAAAAABAAA"},"packages/nodes-base/nodes/HttpRequest/V3/Description.ts":{"1223":"b:ABAAQAQwAAQBAAAAAQSAAAAABAAA"},"packages/nodes-base/nodes/HttpRequest/V3/HttpRequestV3.node.ts":{"53":"b:ABAAQAQwAAQBAAAAAQSAAAAABAQA","60":"b:ABAAQAQwAAQBAAAAAQSAAAAABAQA","64":"b:ABAAQAQwAAQBAAAAAQSAAAAABAQA","71":"b:ABAAQAQwAAQBAAAAAQSAAAAABAQA","106":"b:ABAAQAQwAAQBAAAAAQSAAAAABAQA","389":"b:ABAAQAQwAAQBAAAAAQSAAAAABAQA","506":"b:ABAAQAQwAAQBAAAAAQSAAAAABAQA","630":"b:ABAAQAQwAAQBAAAAAQSAAAAABAQA","672":"b:ABAAQAQwAAQBAAAAAQSAAAAABAQA","728":"b:ABAAQAQwAAQBAAAAAQSAAAAABAQA","747":"b:ABAAQAQwAAQBAAAAAQSAAAAABAQA","758":"b:ABAAQAQwAAQBAAAAAQSAAAAABAQA","763":"b:ABAAQAQwAAQBAAAAAQSAAAAABAQA","778":"b:ABAAQAQwAAQBAAAAAQSAAAAABAQA","784":"b:ABAAQAQwAAQBAAAAAQSAAAAABAQA","807":"b:ABAAQAQwAAQBAAAAAQSAAAAABAQA","809":"b:ABAAQAQwAAQBAAAAAQSAAAAABAQA","810":"b:ABAAQAQwAAQBAAAAAQSAAAAABAQA","945":"b:ABAAQAQwAAQBAAAAAQSAAAAABAQA","1107":"b:ABAAQAQwAAQBAAAAAQSAAAAABAQA","1170":"b:ABAAQAQwAAQBAAAAAQSAAAAABAQA"},"packages/nodes-base/nodes/HttpRequest/V3/utils/binaryData.ts":{"3":"b:ABAAQAQwAAQBAAAAAQSAAAAABAAA"},"packages/nodes-base/nodes/HttpRequest/V3/utils/buffer-decoding.ts":{"13":"b:ABAAQAQwAAQBAAAAAQSAAAAABAQA","36":"b:ABAAQAQwAAQBAAAAAQSAAAAABAQA"},"packages/nodes-base/nodes/HttpRequest/V3/utils/parse.ts":{"1":"b:ABAAQAQwAAQBAAAAAQSAAAAABAAA"},"packages/nodes-base/nodes/HttpRequest/shared/optimizeResponse.ts":{"20":"b:ABAAQAQwAAQBAAAAAQSAAAAABAQA","37":"b:ABAAQAQwAAQBAAAAAQSAAAAABAQA","38":"b:ABAAQAQwAAQBAAAAAQSAAAAABAQA","42":"b:ABAAQAQwAAQBAAAAAQSAAAAABAQA","55":"b:ABAAQAQwAAQBAAAAAQSAAAAABAQA","63":"b:ABAAQAQwAAQBAAAAAQSAAAAABAQA","92":"b:ABAAQAQwAAQBAAAAAQSAAAAABAQA","97":"b:ABAAQAQwAAQBAAAAAQSAAAAABAQA","127":"b:ABAAQAQwAAQBAAAAAQSAAAAABAQA","128":"b:ABAAQAQwAAQBAAAAAQSAAAAABAQA","179":"b:ABAAQAQwAAQBAAAAAQSAAAAABAQA","194":"b:ABAAQAQwAAQBAAAAAQSAAAAABAQA","226":"b:ABAAQAQwAAQBAAAAAQSAAAAABAQA","255":"b:ABAAQAQwAAQBAAAAAQSAAAAABAQA"},"packages/workflow/src/credential-domain-restrictions.ts":{"54":"b:ABAAAHQgAIQAAAAAAAQAAQAAAAQA","58":"b:ABAAAHQgAIQAAAAAAAQAAQAAAAQA","65":"b:ABAAAHQgAIQAAAAAAAQAAQAAAAQA","74":"b:ABAAAHQgAIQAAAAAAAQAAQAAAAQA","86":"b:ABAAAHQgAIQAAAAAAAQAAQAAAAQA","91":"b:ABAAAHQgAIQAAAAAAAQAAQAAAAQA","98":"b:ABAAAHQgAIQAAAAAAAQAAQAAAAQA","116":"b:ABAAAHQgAIQAAAAAAAQAAQAAAAQA","133":"b:ABAAAHQgAIQAAAAAAAQAAQAAAAQA","147":"b:ABAAAHQgAIQAAAAAAAQAAQAAAAQA","181":"b:ABAAAHQgAIQAAAAAAAQAAQAAAAQA"},"packages/workflow/src/errors/node-api.error.ts":{"124":[15,29,41,42,45,106,120,123],"277":[15,29,41,42,45,106,120,123],"285":[15,29,41,42,45,106,120,123],"301":[15,29,41,42,45,106,120,123]},"packages/frontend/editor-ui/src/app/components/FocusPanel.vue":{"57":[80,99],"89":[80,99],"93":[80,99],"113":[80,99],"129":[80,99],"137":[80,99],"140":[80,99],"142":[80,99],"196":[80,99],"202":[80,99],"213":[80,99],"215":[80,99],"233":[80,99],"235":[99],"241":[99],"369":[80,99],"373":[80,99],"374":[80,99],"395":[80,99],"601":[99],"604":[99]},"packages/frontend/editor-ui/src/features/workflows/canvas/experimental/components/ExperimentalCanvasNodeSettings.vue":{"21":[151,80,99],"31":[151,80,99],"32":[151,80,99],"35":[151,80,99],"36":[151,80,99],"41":[151,80,99],"43":[151],"49":[151],"70":[151,80,99],"92":[151],"94":[151]},"packages/frontend/editor-ui/src/features/workflows/canvas/experimental/components/ExperimentalEmbeddedNdvMapper.vue":{"19":[13,80,99],"39":[13,80,99],"43":[13,80,99],"45":[99],"54":[99],"80":[13,80,99],"87":[80,99],"96":[13,80,99],"111":[99]},"packages/frontend/editor-ui/src/features/workflows/canvas/experimental/components/ExperimentalFocusPanelHeader.vue":{"18":[80,99],"27":[80,99],"28":[80,99],"32":[80,99]},"packages/frontend/editor-ui/src/features/workflows/canvas/experimental/components/ExperimentalNodeDetailsDrawer.vue":{"21":[80,99],"26":[80,99],"27":[80],"33":[80,99],"36":[80,99],"37":[80],"46":[80,99],"51":[80],"53":[80],"58":[80]},"packages/frontend/editor-ui/src/features/workflows/canvas/experimental/composables/useExpressionResolveCtx.ts":{"7":[13,151,80,99],"12":[13,151,80,99],"21":[13,151,80,99]},"packages/@n8n/design-system/src/components/N8nIcon/custom/triangle.svg":{"8":"b:AAQAAAAAAAChAAAAgIQAFQEAAAAA"},"packages/frontend/editor-ui/src/app/composables/usePushConnection/handlers/sendConsoleMessage.ts":{"7":[12,34,45,58,65,106]},"packages/frontend/editor-ui/src/app/utils/rbac/checks/isEnterpriseFeatureEnabled.ts":{"4":[106],"15":[106]},"packages/frontend/editor-ui/src/app/utils/rbac/middleware/enterprise.ts":{"6":[106]},"packages/frontend/editor-ui/src/features/execution/executions/composables/useExecutionDebugging.ts":{"39":[106],"43":[106],"54":[106],"55":[106],"61":[106],"71":[106],"88":[106],"107":[106],"113":[106],"117":[106],"161":[106]},"packages/frontend/editor-ui/src/app/utils/stringUtils.ts":{"8":[116,118],"16":[116,118],"21":[116,118],"22":[116,118]},"packages/frontend/editor-ui/src/features/ndv/runData/components/RunDataPaginationBar.vue":{"12":[71,116,118],"16":[71,116,118],"28":[71],"39":[71,116,118],"40":[71,116,118]},"packages/core/src/execution-engine/node-execution-context/load-options-context.ts":{"21":[29,36,37,38,117,120,123,124],"36":[29,36,37,38,117,120,123,124],"40":[29,36,37,38,117,120,123,124],"69":[29,36,37,38,117,120,123,124]},"packages/core/src/execution-engine/node-execution-context/utils/request-helpers/authentication.ts":{"22":[29,36,37,38,154,63,117,120],"150":[29,36,37,38,154,63,117,120]},"packages/nodes-base/nodes/Airtable/Airtable.node.ts":{"8":[117]},"packages/nodes-base/nodes/Airtable/v1/AirtableV1.node.ts":{"558":[117],"565":[117],"833":[117],"834":[117],"838":[117],"839":[117]},"packages/nodes-base/nodes/Airtable/v1/GenericFunctions.ts":{"29":[117],"72":[117],"100":[117]},"packages/nodes-base/nodes/Airtable/v2/AirtableV2.node.ts":{"15":[117],"29":[117]},"packages/nodes-base/nodes/Airtable/v2/actions/base/getMany.operation.ts":{"88":[117],"112":[117]},"packages/nodes-base/nodes/Airtable/v2/actions/base/getSchema.operation.ts":{"30":[117]},"packages/nodes-base/nodes/Airtable/v2/actions/record/create.operation.ts":{"51":[117]},"packages/nodes-base/nodes/Airtable/v2/actions/record/deleteRecord.operation.ts":{"36":[117]},"packages/nodes-base/nodes/Airtable/v2/actions/record/get.operation.ts":{"60":[117],"85":[117]},"packages/nodes-base/nodes/Airtable/v2/actions/record/search.operation.ts":{"147":[117],"183":[117],"214":[117],"224":[117]},"packages/nodes-base/nodes/Airtable/v2/actions/record/update.operation.ts":{"57":[117]},"packages/nodes-base/nodes/Airtable/v2/actions/record/upsert.operation.ts":{"52":[117],"120":[117],"125":[117],"142":[117]},"packages/nodes-base/nodes/Airtable/v2/actions/router.ts":{"8":[117]},"packages/nodes-base/nodes/Airtable/v2/helpers/utils.ts":{"11":[117],"16":[117],"35":[117],"42":[117],"57":[117],"76":[117],"91":[117],"100":[117],"110":[117]},"packages/nodes-base/nodes/Airtable/v2/methods/listSearch.ts":{"11":[117],"44":[117],"54":[117],"91":[117],"101":[117],"117":[117],"145":[117]},"packages/nodes-base/nodes/Airtable/v2/methods/loadOptions.ts":{"6":[117],"19":[117],"42":[117],"57":[117],"62":[117],"65":[117],"80":[117]},"packages/nodes-base/nodes/Airtable/v2/methods/resourceMapping.ts":{"48":[117],"63":[117],"76":[117],"88":[117],"90":[117],"120":[117]},"packages/nodes-base/nodes/Airtable/v2/transport/index.ts":{"20":[117],"59":[117],"87":[117],"94":[117],"131":[117]},"packages/nodes-base/nodes/Code/ExecutionError.ts":{"14":[8,17,117,138],"30":[8,17,117,138],"38":[8,17,117,138],"39":[8,17,117,138],"59":[8,17,117,138],"75":[8,17,117,138]},"packages/nodes-base/nodes/Code/JavaScriptSandbox.ts":{"30":[8,17,117,138],"52":[8,17,117,138],"55":[8,17,117,138],"65":[8,17,117,138],"85":[8,17,117,138],"93":[8,17,117,138],"103":[8,17,117,138]},"packages/nodes-base/nodes/Code/Sandbox.ts":{"24":[8,17,117,138],"46":[8,17,117,138],"59":[8,17,117,138],"71":[8,17,117,138]},"packages/nodes-base/nodes/Function/Function.node.ts":{"67":[117,138],"79":[117,138],"80":[117,138],"101":[117,138],"102":[117,138],"115":[117,138],"215":[117,138]},"packages/nodes-base/nodes/Typeform/GenericFunctions.ts":{"40":[117],"77":[117],"113":[117]},"packages/nodes-base/nodes/Typeform/TypeformTrigger.node.ts":{"122":[117],"160":[117],"179":[117],"205":[117],"230":[117],"305":[117]},"packages/nodes-base/nodes/Typeform/TypeformTriggerHelpers.ts":{"18":[117],"24":[117],"36":[117]},"packages/nodes-base/utils/webhook-signature-verification.ts":{"64":[117],"106":[117]},"packages/workflow/src/errors/expression.error.ts":{"32":[117],"56":[117]},"packages/workflow/src/workflow-data-proxy-helpers.ts":{"3":[117]},"packages/@n8n/design-system/src/components/N8nIcon/custom/empty-output.svg":{"9":[117]},"packages/frontend/editor-ui/src/features/shared/editors/components/CodeNodeEditor/utils.ts":{"10":[96,103,117],"19":[96,103,117],"30":[96,103,117]},"packages/frontend/editor-ui/src/features/shared/editors/components/JsEditor/JsEditor.vue":{"31":[15,117],"36":[15,117],"40":[15,117],"57":[15,117],"73":[15,117],"77":[15,117],"102":[15,117],"121":[15,117]},"packages/core/src/execution-engine/node-execution-context/utils/parse-incoming-message.ts":{"3":[19,20,34,57,63],"5":[19,20,34,57,63],"55":[19,20,34,57,63],"77":[19,20,34,57,63],"108":[19,20,34,57,63]},"packages/localhost-33901/assets/_plugin-vue_export-helper-Da88TEg1.js":{"2":[34]},"packages/localhost-33901/assets/chunk-CC9Q-vWm.js":{"8":[34],"9":[34],"10":[34],"19":[34],"23":[34],"29":[34],"33":[34],"34":[34]},"packages/@n8n/ai-utilities/src/utils/log-wrapper.ts":{"38":[8,17,36,37,38],"80":[8,17,36,37,38],"109":[8,17,36,37,38],"127":[8,17,36,37,38],"132":[8,17,36,37,38],"155":[8,17,36,37,38],"184":[8,17,36,37,38],"205":[8,17,36,37,38],"227":[8,17,36,37,38],"271":[8,17,36,37,38],"298":[8,17,36,37,38],"325":[8,17,36,37,38],"355":[8,17,36,37,38],"374":[8,17,36,37,38],"398":[8,17,36,37,38],"422":[8,17,36,37,38],"456":[8,17,36,37,38]},"packages/@n8n/api-types/src/schemas/timezone.schema.ts":{"3":[36,37,38]},"packages/@n8n/db/src/repositories/project-secrets-provider-access.repository.ee.ts":{"9":[36,37,39,86],"12":[36,37,39,86],"21":[36,37,39,86],"28":[36,37,39,86],"35":[36,37,39,86],"43":[36,37,39,86],"54":[36,37,39,86]},"packages/@n8n/nodes-langchain/credentials/AnthropicApi.credentials.ts":{"9":[36,37,38],"76":[36,37,38]},"packages/@n8n/nodes-langchain/nodes/memory/MemoryBufferWindow/MemoryBufferWindow.node.ts":{"30":[36,37,38],"34":[36,37,38],"41":[36,37,38],"63":[36,37,38],"75":[36,37,38],"158":[36,37,38]},"packages/@n8n/nodes-langchain/nodes/memory/MemoryManager/MemoryManager.node.ts":{"20":[36,37,38],"47":[36,37,38],"50":[36,37,38],"53":[36,37,38],"63":[36,37,38],"73":[36,37,38],"302":[36,37,38],"400":[36,37,38]},"packages/@n8n/nodes-langchain/nodes/memory/descriptions.ts":{"28":[15,36,37,38,119,120],"63":[15,36,37,38,119,120]},"packages/cli/src/credentials/credential-connection-status-proxy.ts":{"17":[36,37,39],"21":[36,37,39],"26":[36,37,39],"31":[36,37,39],"36":[36,37,39]},"packages/cli/src/modules/chat-hub/chat-hub-agent.repository.ts":{"8":[36,37,38,39],"12":[36,37,38,39],"23":[36,37,38,39],"31":[36,37,38,39],"36":[36,37,38,39],"43":[36,37,38,39],"52":[36,37,38,39]},"packages/cli/src/modules/chat-hub/chat-hub-agent.service.ts":{"37":[36,37,38,39,7],"52":[36,37,38,39,7],"55":[36,37,38,39,7],"58":[36,37,38,39,7],"59":[36,37,38,39,7],"78":[36,37,38,39,7],"82":[36,37,38,39,7],"90":[36,37,38,39,7],"97":[36,37,38,39,7],"125":[36,37,38,39,7],"165":[36,37,38,39,7],"184":[36,37,38,39,7],"205":[36,37,38,39,7],"217":[36,37,38,39,7],"231":[36,37,38,39,7],"265":[36,37,38,39,7],"288":[36,37,38,39,7],"310":[36,37,38,39,7],"335":[36,37,38,39,7],"350":[36,37,38,39,7],"361":[36,37,38,39,7],"376":[36,37,38,39,7],"385":[36,37,38,39,7],"395":[36,37,38,39,7],"401":[36,37,38,39,7],"404":[36,37,38,39,7],"419":[36,37,38,39,7],"427":[36,37,38,39,7],"452":[36,37,38,39,7]},"packages/cli/src/modules/chat-hub/chat-hub-credentials.service.ts":{"18":[36,37,38,39,42],"25":[36,37,38,39,42],"38":[36,37,38,39,42],"49":[36,37,38,39,42],"62":[36,37,38,39,42],"71":[36,37,38,39,42],"91":[36,37,38,39,42]},"packages/cli/src/modules/chat-hub/chat-hub-execution.service.ts":{"51":[36,37,38,41,42],"68":[36,37,38,41,42],"79":[36,37,38,41,42],"91":[36,37,38,41,42],"156":[36,37,38,41,42],"207":[36,37,38,41,42],"228":[36,37,38,41,42],"251":[36,37,38,41,42],"254":[36,37,38,41,42],"264":[36,37,38,41,42],"274":[36,37,38,41,42],"303":[36,37,38,41,42],"368":[36,37,38,41,42],"447":[36,37,38,41,42],"489":[36,37,38,41,42],"497":[36,37,38,41,42],"498":[36,37,38,41,42],"499":[36,37,38,41,42],"541":[36,37,38,41,42],"570":[36,37,38,41,42],"610":[36,37,38,41,42],"624":[36,37,38,41,42],"629":[36,37,38,41,42],"631":[36,37,38,41,42],"635":[36,37,38,41,42],"641":[36,37,38,41,42],"653":[36,37,38,41,42],"659":[36,37,38,41,42],"661":[36,37,38,41,42],"662":[36,37,38,41,42],"663":[36,37,38,41,42],"666":[36,37,38,41,42],"673":[36,37,38,41,42],"692":[36,37,38,41,42],"713":[36,37,38,41,42],"733":[36,37,38,41,42],"746":[36,37,38,41,42]},"packages/cli/src/modules/chat-hub/chat-hub-extractor.ts":{"31":[36,37,38],"51":[36,37,38],"64":[36,37,38],"70":[36,37,38]},"packages/cli/src/modules/chat-hub/chat-hub-title.service.ts":{"39":[36,37,38,39,42],"53":[36,37,38,39,42],"80":[36,37,38,39,42],"88":[36,37,38,39,42],"124":[36,37,38,39,42],"152":[36,37,38,39,42],"186":[36,37,38,39,42],"259":[36,37,38,39,42],"260":[36,37,38,39,42],"262":[36,37,38,39,42],"272":[36,37,38,39,42]},"packages/cli/src/modules/chat-hub/chat-hub-tool.repository.ts":{"10":[36,37,38,39,41],"14":[36,37,38,39,41],"22":[36,37,38,39,41],"30":[36,37,38,39,41],"35":[36,37,38,39,41],"42":[36,37,38,39,41],"50":[36,37,38,39,41],"57":[36,37,38,39,41],"68":[36,37,38,39,41],"79":[36,37,38,39,41],"90":[36,37,38,39,41],"98":[36,37,38,39,41],"101":[36,37,38,39,41],"109":[36,37,38,39,41],"112":[36,37,38,39,41],"122":[36,37,38,39,41]},"packages/cli/src/modules/chat-hub/chat-hub-tool.service.ts":{"21":[36,37,38,39,41],"29":[36,37,38,39,41],"33":[36,37,38,39,41],"37":[36,37,38,39,41],"39":[36,37,38,39,41],"42":[36,37,38,39,41],"44":[36,37,38,39,41],"47":[36,37,38,39,41],"51":[36,37,38,39,41],"55":[36,37,38,39,41],"59":[36,37,38,39,41],"63":[36,37,38,39,41],"79":[36,37,38,39,41],"86":[36,37,38,39,41],"104":[36,37,38,39,41],"110":[36,37,38,39,41],"136":[36,37,38,39,41],"137":[36,37,38,39,41],"149":[36,37,38,39,41]},"packages/cli/src/modules/chat-hub/chat-hub-workflow.service.ts":{"85":[36,37,38,39,41,42],"100":[36,37,38,39,41,42],"106":[36,37,38,39,41,42],"127":[36,37,38,39,41,42],"181":[36,37,38,39,41,42],"192":[36,37,38,39,41,42],"247":[36,37,38,39,41,42],"262":[36,37,38,39,41,42],"276":[36,37,38,39,41,42],"296":[36,37,38,39,41,42],"297":[36,37,38,39,41,42],"311":[36,37,38,39,41,42],"358":[36,37,38,39,41,42],"374":[36,37,38,39,41,42],"424":[36,37,38,39,41,42],"425":[36,37,38,39,41,42],"488":[36,37,38,39,41,42],"558":[36,37,38,39,41,42],"623":[36,37,38,39,41,42],"635":[36,37,38,39,41,42],"716":[36,37,38,39,41,42],"724":[36,37,38,39,41,42],"750":[36,37,38,39,41,42],"912":[36,37,38,39,41,42],"927":[36,37,38,39,41,42],"949":[36,37,38,39,41,42],"1019":[36,37,38,39,41,42],"1079":[36,37,38,39,41,42],"1090":[36,37,38,39,41,42],"1104":[36,37,38,39,41,42],"1120":[36,37,38,39,41,42],"1121":[36,37,38,39,41,42],"1128":[36,37,38,39,41,42],"1153":[36,37,38,39,41,42],"1166":[36,37,38,39,41,42],"1201":[36,37,38,39,41,42],"1204":[36,37,38,39,41,42],"1215":[36,37,38,39,41,42],"1226":[36,37,38,39,41,42],"1284":[36,37,38,39,41,42],"1326":[36,37,38,39,41,42],"1396":[36,37,38,39,41,42],"1426":[36,37,38,39,41,42],"1456":[36,37,38,39,41,42],"1464":[36,37,38,39,41,42],"1467":[36,37,38,39,41,42],"1521":[36,37,38,39,41,42],"1530":[36,37,38,39,41,42],"1534":[36,37,38,39,41,42],"1539":[36,37,38,39,41,42],"1552":[36,37,38,39,41,42],"1561":[36,37,38,39,41,42],"1579":[36,37,38,39,41,42],"1586":[36,37,38,39,41,42],"1615":[36,37,38,39,41,42],"1641":[36,37,38,39,41,42],"1762":[36,37,38,39,41,42],"1785":[36,37,38,39,41,42]},"packages/cli/src/modules/chat-hub/chat-hub.attachment.service.ts":{"19":[36,37,38],"28":[36,37,38],"55":[36,37,38],"85":[36,37,38],"129":[36,37,38],"132":[36,37,38],"138":[36,37,38],"146":[36,37,38],"152":[36,37,38],"154":[36,37,38],"158":[36,37,38],"170":[36,37,38],"174":[36,37,38],"196":[36,37,38],"197":[36,37,38],"211":[36,37,38]},"packages/cli/src/modules/chat-hub/chat-hub.constants.ts":{"694":[36,37,38],"719":[36,37,38]},"packages/cli/src/modules/chat-hub/chat-hub.controller.ts":{"59":[36,37,38,39,41],"69":[36,37,38,39,41],"79":[36,37,38,39,41],"94":[36,37,38,39,41],"104":[36,37,38,39,41],"142":[36,37,38,39,41],"151":[36,37,38,39,41],"177":[36,37,38,39,41],"207":[36,37,38,39,41],"232":[36,37,38,39,41],"266":[36,37,38,39,41],"291":[36,37,38,39,41],"325":[36,37,38,39,41],"341":[36,37,38,39,41],"357":[36,37,38,39,41],"372":[36,37,38,39,41],"384":[36,37,38,39,41],"386":[36,37,38,39,41],"391":[36,37,38,39,41],"403":[36,37,38,39,41],"418":[36,37,38,39,41],"429":[36,37,38,39,41],"435":[36,37,38,39,41],"445":[36,37,38,39,41],"456":[36,37,38,39,41],"470":[36,37,38,39,41],"493":[36,37,38,39,41],"503":[36,37,38,39,41]},"packages/cli/src/modules/chat-hub/chat-hub.models.service.ts":{"32":[36,37,38,42],"41":[36,37,38,42],"54":[36,37,38,42],"64":[36,37,38,42],"90":[36,37,38,42],"98":[36,37,38,42],"172":[36,37,38,42],"188":[36,37,38,42],"204":[36,37,38,42],"256":[36,37,38,42],"301":[36,37,38,42],"311":[36,37,38,42],"318":[36,37,38,42],"412":[36,37,38,42],"461":[36,37,38,42],"510":[36,37,38,42],"554":[36,37,38,42],"597":[36,37,38,42],"640":[36,37,38,42],"683":[36,37,38,42],"726":[36,37,38,42],"769":[36,37,38,42],"781":[36,37,38,42],"783":[36,37,38,42],"803":[36,37,38,42],"812":[36,37,38,42],"813":[36,37,38,42],"820":[36,37,38,42],"828":[36,37,38,42],"874":[36,37,38,42],"879":[36,37,38,42],"880":[36,37,38,42],"884":[36,37,38,42],"885":[36,37,38,42],"894":[36,37,38,42],"900":[36,37,38,42]},"packages/cli/src/modules/chat-hub/chat-hub.service.ts":{"56":[36,37,38,39,41,42],"76":[36,37,38,39,41,42],"87":[36,37,38,39,41,42],"113":[36,37,38,39,41,42],"163":[36,37,38,39,41,42],"187":[36,37,38,39,41,42],"194":[36,37,38,39,41,42],"198":[36,37,38,39,41,42],"225":[36,37,38,39,41,42],"233":[36,37,38,39,41,42],"249":[36,37,38,39,41,42],"262":[36,37,38,39,41,42],"271":[36,37,38,39,41,42],"281":[36,37,38,39,41,42],"293":[36,37,38,39,41,42],"301":[36,37,38,39,41,42],"318":[36,37,38,39,41,42],"322":[36,37,38,39,41,42],"331":[36,37,38,39,41,42],"375":[36,37,38,39,41,42],"376":[36,37,38,39,41,42],"383":[36,37,38,39,41,42],"422":[36,37,38,39,41,42],"436":[36,37,38,39,41,42],"460":[36,37,38,39,41,42],"474":[36,37,38,39,41,42],"506":[36,37,38,39,41,42],"550":[36,37,38,39,41,42],"587":[36,37,38,39,41,42],"615":[36,37,38,39,41,42],"628":[36,37,38,39,41,42],"707":[36,37,38,39,41,42],"745":[36,37,38,39,41,42],"760":[36,37,38,39,41,42],"773":[36,37,38,39,41,42],"779":[36,37,38,39,41,42],"852":[36,37,38,39,41,42],"878":[36,37,38,39,41,42],"898":[36,37,38,39,41,42],"911":[36,37,38,39,41,42],"917":[36,37,38,39,41,42],"1006":[36,37,38,39,41,42],"1033":[36,37,38,39,41,42],"1042":[36,37,38,39,41,42],"1054":[36,37,38,39,41,42],"1057":[36,37,38,39,41,42],"1113":[36,37,38,39,41,42],"1127":[36,37,38,39,41,42],"1139":[36,37,38,39,41,42],"1142":[36,37,38,39,41,42],"1201":[36,37,38,39,41,42],"1228":[36,37,38,39,41,42],"1271":[36,37,38,39,41,42],"1291":[36,37,38,39,41,42],"1298":[36,37,38,39,41,42]},"packages/cli/src/modules/chat-hub/chat-message.repository.ts":{"19":[36,37,38],"26":[36,37,38],"38":[36,37,38],"48":[36,37,38],"74":[36,37,38],"108":[36,37,38],"117":[36,37,38],"122":[36,37,38],"130":[36,37,38]},"packages/cli/src/modules/chat-hub/chat-session.repository.ts":{"10":[36,37,38],"14":[36,37,38],"26":[36,37,38],"31":[36,37,38],"36":[36,37,38],"72":[36,37,38],"77":[36,37,38],"91":[36,37,38]},"packages/cli/src/modules/chat-hub/chat-stream-state.service.ts":{"68":[36,37,38],"89":[36,37,38],"115":[36,37,38],"131":[36,37,38],"151":[36,37,38],"177":[36,37,38],"187":[36,37,38],"205":[36,37,38],"233":[36,37,38],"245":[36,37,38],"251":[36,37,38],"268":[36,37,38],"283":[36,37,38],"287":[36,37,38],"291":[36,37,38],"304":[36,37,38],"319":[36,37,38],"329":[36,37,38],"342":[36,37,38],"357":[36,37,38],"367":[36,37,38],"370":[36,37,38],"380":[36,37,38]},"packages/cli/src/modules/chat-hub/chat-stream.service.ts":{"52":[36,37,38,41,42],"66":[36,37,38,41,42],"100":[36,37,38,41,42],"137":[36,37,38,41,42],"162":[36,37,38,41,42],"198":[36,37,38,41,42],"235":[36,37,38,41,42],"272":[36,37,38,41,42],"308":[36,37,38,41,42],"318":[36,37,38,41,42],"326":[36,37,38,41,42],"335":[36,37,38,41,42],"435":[36,37,38,41,42],"454":[36,37,38,41,42],"461":[36,37,38,41,42],"501":[36,37,38,41,42],"531":[36,37,38,41,42],"561":[36,37,38,41,42],"588":[36,37,38,41,42],"616":[36,37,38,41,42],"643":[36,37,38,41,42]},"packages/cli/src/modules/chat-hub/context-limits.ts":{"223":[36,37,38]},"packages/cli/src/modules/chat-hub/stream-capturer.ts":{"13":[36,37,38],"23":[36,37,38],"32":[36,37,38],"43":[36,37,38],"44":[36,37,38],"53":[36,37,38],"67":[36,37,38],"72":[36,37,38],"96":[36,37,38],"112":[36,37,38],"124":[36,37,38],"142":[36,37,38],"151":[36,37,38],"204":[36,37,38]},"packages/nodes-base/nodes/Merge/Merge.node.ts":{"9":[36,37,38,97,107,119]},"packages/nodes-base/nodes/Merge/v1/MergeV1.node.ts":{"20":[36,37,38,97,107,119],"205":[36,37,38,97,107,119]},"packages/nodes-base/nodes/Merge/v2/MergeV2.node.ts":{"35":[36,37,38,97,107,119],"293":[36,37,38,97,107,119],"459":[36,37,38,97,107,119],"467":[36,37,38,97,107,119],"520":[36,37,38,97,107,119],"603":[36,37,38,97,107,119],"604":[36,37,38,97,107,119]},"packages/nodes-base/nodes/Merge/v2/utils.ts":{"31":[36,37,38,97,107,119],"32":[36,37,38,97,107,119],"34":[36,37,38,97,107,119],"41":[36,37,38,97,107,119],"47":[36,37,38,97,107,119],"72":[36,37,38,97,107,119],"78":[36,37,38,97,107,119],"103":[36,37,38,97,107,119],"128":[36,37,38,97,107,119],"150":[36,37,38,97,107,119],"151":[36,37,38,97,107,119],"159":[36,37,38,97,107,119],"176":[36,37,38,97,107,119],"187":[36,37,38,97,107,119],"191":[36,37,38,97,107,119],"197":[36,37,38,97,107,119],"203":[36,37,38,97,107,119],"210":[36,37,38,97,107,119],"213":[36,37,38,97,107,119],"216":[36,37,38,97,107,119],"219":[36,37,38,97,107,119],"243":[36,37,38,97,107,119],"246":[36,37,38,97,107,119],"250":[36,37,38,97,107,119],"268":[36,37,38,97,107,119],"273":[36,37,38,97,107,119],"279":[36,37,38,97,107,119],"285":[36,37,38,97,107,119],"288":[36,37,38,97,107,119],"292":[36,37,38,97,107,119],"307":[36,37,38,97,107,119],"327":[36,37,38,97,107,119],"334":[36,37,38,97,107,119],"350":[36,37,38,97,107,119],"351":[36,37,38,97,107,119]},"packages/nodes-base/nodes/Merge/v3/MergeV3.node.ts":{"15":[36,37,38,97,107,119],"26":[36,37,38,97,107,119]},"packages/nodes-base/nodes/Merge/v3/actions/mode/append.ts":{"21":[36,37,38,97,107,119]},"packages/nodes-base/nodes/Merge/v3/actions/mode/chooseBranch.ts":{"73":[36,37,38,97,107,119],"98":[36,37,38,97,107,119],"99":[36,37,38,97,107,119]},"packages/nodes-base/nodes/Merge/v3/actions/mode/combineAll.ts":{"35":[36,37,38,97,107,119]},"packages/nodes-base/nodes/Merge/v3/actions/mode/combineByFields.ts":{"261":[36,37,38,97,107,119],"274":[36,37,38,97,107,119],"297":[36,37,38,97,107,119],"305":[36,37,38,97,107,119],"358":[36,37,38,97,107,119]},"packages/nodes-base/nodes/Merge/v3/actions/mode/combineByPosition.ts":{"49":[36,37,38,97,107,119],"80":[36,37,38,97,107,119],"82":[36,37,38,97,107,119],"95":[36,37,38,97,107,119],"100":[36,37,38,97,107,119],"106":[36,37,38,97,107,119],"110":[36,37,38,97,107,119],"112":[36,37,38,97,107,119]},"packages/nodes-base/nodes/Merge/v3/actions/mode/combineBySql.ts":{"84":[36,37,38,97,107,119],"105":[36,37,38,97,107,119],"113":[36,37,38,97,107,119],"114":[36,37,38,97,107,119],"138":[36,37,38,97,107,119],"181":[36,37,38,97,107,119],"196":[36,37,38,97,107,119],"197":[36,37,38,97,107,119],"198":[36,37,38,97,107,119],"215":[36,37,38,97,107,119],"216":[36,37,38,97,107,119],"226":[36,37,38,97,107,119]},"packages/nodes-base/nodes/Merge/v3/actions/router.ts":{"7":[36,37,38,97,107,119]},"packages/nodes-base/nodes/Merge/v3/helpers/sandbox-utils.ts":{"12":[36,37,38,97,107,119],"14":[36,37,38,97,107,119],"30":[36,37,38,97,107,119],"42":[36,37,38,97,107,119],"50":[36,37,38,97,107,119],"102":[36,37,38,97,107,119],"121":[36,37,38,97,107,119],"136":[36,37,38,97,107,119],"156":[36,37,38,97,107,119],"177":[36,37,38,97,107,119]},"packages/nodes-base/nodes/Merge/v3/helpers/utils.ts":{"33":[36,37,38,97,107,119],"34":[36,37,38,97,107,119],"36":[36,37,38,97,107,119],"43":[36,37,38,97,107,119],"49":[36,37,38,97,107,119],"74":[36,37,38,97,107,119],"80":[36,37,38,97,107,119],"105":[36,37,38,97,107,119],"130":[36,37,38,97,107,119],"152":[36,37,38,97,107,119],"153":[36,37,38,97,107,119],"161":[36,37,38,97,107,119],"178":[36,37,38,97,107,119],"189":[36,37,38,97,107,119],"193":[36,37,38,97,107,119],"199":[36,37,38,97,107,119],"205":[36,37,38,97,107,119],"212":[36,37,38,97,107,119],"215":[36,37,38,97,107,119],"218":[36,37,38,97,107,119],"221":[36,37,38,97,107,119],"245":[36,37,38,97,107,119],"248":[36,37,38,97,107,119],"252":[36,37,38,97,107,119],"270":[36,37,38,97,107,119],"275":[36,37,38,97,107,119],"281":[36,37,38,97,107,119],"287":[36,37,38,97,107,119],"290":[36,37,38,97,107,119],"294":[36,37,38,97,107,119],"309":[36,37,38,97,107,119],"329":[36,37,38,97,107,119],"336":[36,37,38,97,107,119],"352":[36,37,38,97,107,119],"353":[36,37,38,97,107,119],"365":[36,37,38,97,107,119],"366":[36,37,38,97,107,119],"372":[36,37,38,97,107,119],"376":[36,37,38,97,107,119],"390":[36,37,38,97,107,119],"407":[36,37,38,97,107,119]},"packages/nodes-base/nodes/Merge/v3/methods/loadOptions.ts":{"3":[36,37,38,97,107,119],"36":[36,37,38,97,107,119]},"packages/frontend/editor-ui/src/features/ai/chatHub/chat.types.ts":{"114":[36,37]},"packages/localhost-43315/assets/_plugin-vue_export-helper-Da88TEg1.js":{"2":[37,42]},"packages/localhost-43315/assets/chunk-CC9Q-vWm.js":{"8":[37,42],"9":[37,42],"10":[37,42],"19":[37,42],"23":[37,42],"29":[37,42],"33":[37,42],"34":[37,42]},"packages/@n8n/ai-utilities/src/utils/failed-attempt-handler/n8nDefaultFailedAttemptHandler.ts":{"20":[15,41,42]},"packages/cli/src/events/relays/workflow-failure-notification.event-relay.ts":{"15":[29,42],"24":[29,42],"26":[29,42],"35":[29,42]},"packages/cli/src/modules/provisioning.ee/provisioning.service.ee.ts":{"37":[27,42,7],"54":[27,42,7],"58":[27,42,7],"66":[27,42,7],"141":[27,42,7],"207":[27,42,7],"220":[27,42,7],"250":[27,42,7],"252":[27,42,7],"255":[27,42,7],"272":[27,42,7],"330":[27,42,7],"363":[27,42,7],"367":[27,42,7],"386":[27,42,7],"401":[27,42,7],"409":[27,42,7],"417":[27,42,7],"425":[27,42,7],"430":[27,42,7],"435":[27,42,7],"440":[27,42,7],"446":[27,42,7],"452":[27,42,7],"485":[27,42,7],"495":[27,42,7],"502":[27,42,7],"510":[27,42,7],"556":[27,42,7],"583":[27,42,7],"593":[27,42,7],"605":[27,42,7],"607":[27,42,7],"612":[27,42,7],"628":[27,42,7],"646":[27,42,7],"652":[27,42,7],"657":[27,42,7]},"packages/core/src/binary-data/binary-data.service.ts":{"24":"b:AAEAABAEACABAAAAAAgAgBESAAoB","30":"b:AAEAABAEACABAAAAAAgAgBESAAoB","34":"b:AAEAABAEACABAAAAAAgAgBESAAoB","39":"b:AAEAABAEACABAAAAAAgAgBESAAoB","47":"b:AAEAABAEACABAAAAAAgAgBESAAoB","60":"b:AAEAABAEACABAAAAAAgAgBESAAoB","66":"b:AAEAABAEACABAAAAAAgAgBESAAoB","97":"b:AAEAABAEACABAAAAAAgAgBESAAoB","128":"b:AAEAABAEACABAAAAAAgAgBESAAoB","134":"b:AAEAABAEACABAAAAAAgAgBESAAoB","144":"b:AAEAABAEACABAAAAAAgAgBESAAoB","150":"b:AAEAABAEACABAAAAAAgAgBESAAoB","156":"b:AAEAABAEACABAAAAAAgAgBESAAoB","164":"b:AAEAABAEACABAAAAAAgAgBESAAoB","193":"b:AAEAABAEACABAAAAAAgAgBESAAoB","199":"b:AAEAABAEACABAAAAAAgAgBESAAoB","202":"b:AAEAABAEACABAAAAAAgAgBESAAoB","222":"b:AAEAABAEACABAAAAAAgAgBESAAoB","234":"b:AAEAABAEACABAAAAAAgAgBESAAoB","238":"b:AAEAABAEACABAAAAAAgAgBESAAoB","246":"b:AAEAABAEACABAAAAAAgAgBESAAoB","258":"b:AAEAABAEACABAAAAAAgAgBESAAoB","264":"b:AAEAABAEACABAAAAAAgAgBESAAoB","265":"b:AAEAABAEACABAAAAAAgAgBESAAoB","278":"b:AAEAABAEACABAAAAAAgAgBESAAoB"},"packages/core/src/binary-data/file-system.manager.ts":{"18":"b:AAEAABAEACABAAAAAAgAABASAAIA","23":"b:AAEAABAEACABAAAAAAgAABASAAIA","27":"b:AAEAABAEACABAAAAAAgAABASAAIA","46":"b:AAEAABAEACABAAAAAAgAABASAAIA","50":"b:AAEAABAEACABAAAAAAgAABASAAIA","60":"b:AAEAABAEACABAAAAAAgAABASAAIA","70":"b:AAEAABAEACABAAAAAAgAABASAAIA","76":"b:AAEAABAEACABAAAAAAgAABASAAIA","79":"b:AAEAABAEACABAAAAAAgAABASAAIA","84":"b:AAEAABAEACABAAAAAAgAABASAAIA","90":"b:AAEAABAEACABAAAAAAgAABASAAIA","109":"b:AAEAABAEACABAAAAAAgAABASAAIA","124":"b:AAEAABAEACABAAAAAAgAABASAAIA","136":"b:AAEAABAEACABAAAAAAgAABASAAIA","137":"b:AAEAABAEACABAAAAAAgAABASAAIA","155":"b:AAEAABAEACABAAAAAAgAABASAAIA","159":"b:AAEAABAEACABAAAAAAgAABASAAIA","170":"b:AAEAABAEACABAAAAAAgAABASAAIA","186":"b:AAEAABAEACABAAAAAAgAABASAAIA","196":"b:AAEAABAEACABAAAAAAgAABASAAIA","202":"b:AAEAABAEACABAAAAAAgAABASAAIA"},"packages/core/src/binary-data/index.ts":{"4":[140,36,42,127,128,160,155]},"packages/nodes-base/nodes/E2eTest/E2eTest.node.ts":{"175":[123,124],"180":[123,124],"188":[123,124],"201":[123,124],"207":[123,124]},"packages/nodes-base/nodes/E2eTest/mock.ts":{"66":[123,124]},"packages/frontend/editor-ui/src/features/ai/chatHub/ChatWorkflowAgentsView.vue":{"30":[42],"31":[42],"32":[42],"49":[42],"68":[42],"76":[42]},"packages/@n8n/client-oauth2/src/client-oauth2.ts":{"41":[46,146,123],"61":[46,146,123],"69":[46,146,123],"82":[46,146,123],"95":[46,146,123],"98":[46,146,123],"129":[46,146,123]},"packages/@n8n/client-oauth2/src/code-flow.ts":{"21":[46,146,123],"26":[46,146,123],"56":[46,146,123]},"packages/@n8n/client-oauth2/src/credentials-flow.ts":{"20":[46,146,123],"25":[46,146,123]},"packages/@n8n/client-oauth2/src/index.ts":{"2":[46,146,123],"5":[46,146,123]},"packages/@n8n/client-oauth2/src/utils.ts":{"8":[46,146,123],"22":[46,146,123],"34":[46,146,123],"51":[46,146,123],"58":[46,146,123],"65":[46,146,123]},"packages/cli/src/controllers/oauth/oauth2-credential.controller.ts":{"20":[46,146,123],"30":[46,146,123],"38":[46,146,123],"158":[46,146,123]},"packages/cli/src/oauth/oauth-browser-binding.service.ts":{"16":[46,146,123,138],"19":[46,146,123,138],"31":[46,146,123,138],"48":[46,146,123,138],"58":[46,146,123,138],"72":[46,146,123,138]},"packages/cli/src/oauth/oauth.service.ts":{"76":[46,146,123,138],"87":[46,146,123,138],"104":[46,146,123,138],"108":[46,146,123,138],"117":[46,146,123,138],"122":[46,146,123,138],"148":[46,146,123,138],"175":[46,146,123,138],"182":[46,146,123,138],"192":[46,146,123,138],"199":[46,146,123,138],"214":[46,146,123,138],"229":[46,146,123,138],"251":[46,146,123,138],"287":[46,146,123,138],"293":[46,146,123,138],"313":[46,146,123,138],"321":[46,146,123,138],"329":[46,146,123,138],"409":[46,146,123,138],"422":[46,146,123,138],"460":[46,146,123,138],"464":[46,146,123,138],"499":[46,146,123,138],"510":[46,146,123,138],"519":[46,146,123,138],"571":[46,146,123,138],"574":[46,146,123,138],"587":[46,146,123,138],"598":[46,146,123,138],"689":[46,146,123,138],"709":[46,146,123,138],"764":[46,146,123,138],"824":[46,146,123,138],"850":[46,146,123,138],"925":[46,146,123,138],"937":[46,146,123,138],"975":[46,146,123,138],"1007":[46,146,123,138],"1035":[46,146,123,138],"1056":[46,146,123,138],"1088":[46,146,123,138],"1114":[46,146,123,138]},"packages/cli/src/oauth/validate-oauth-url.ts":{"12":[46,146,123,138]},"packages/localhost-40353/assets/_plugin-vue_export-helper-Da88TEg1.js":{"2":[46,52,61,66,7,128]},"packages/localhost-40353/assets/chunk-CC9Q-vWm.js":{"8":[46,52,61,66,7,128],"9":[46,52,61,66,7,128],"10":[46,52,61,66,7,128],"19":[46,52,61,66,7,128],"23":[46,52,61,66,7,128],"29":[46,52,61,66,7,128],"33":[46,52,61,66,7,128],"34":[46,52,61,66,7,128]},"packages/@n8n/design-system/src/components/N8nIcon/nodes/send-mail.svg":{"11":[15,19,41,52,56]},"packages/nodes-base/nodes/N8nTrigger/N8nTrigger.node.ts":{"63":[152],"86":[152]},"packages/@n8n/backend-common/src/utils/fs.ts":{"3":[8,140,153,36,61,64],"13":[8,140,153,36,61,64]},"packages/core/src/utils/serialized-buffer.ts":{"10":[8,140,153,61],"14":[8,140,153,61]},"packages/nodes-base/nodes/Files/ExtractFromFile/ExtractFromFile.node.ts":{"117":[61]},"packages/nodes-base/nodes/Files/ExtractFromFile/actions/moveTo.operation.ts":{"105":[61]},"packages/nodes-base/nodes/Files/ExtractFromFile/actions/pdf.operation.ts":{"83":[61]},"packages/nodes-base/nodes/Files/ExtractFromFile/actions/spreadsheet.operation.ts":{"8":[61],"9":[61],"18":[61],"58":[61]},"packages/nodes-base/nodes/Files/ReadWriteFile/ReadWriteFile.node.ts":{"60":[61]},"packages/nodes-base/nodes/Files/ReadWriteFile/actions/read.operation.ts":{"78":[61]},"packages/nodes-base/nodes/Files/ReadWriteFile/actions/write.operation.ts":{"62":[61]},"packages/nodes-base/nodes/Files/ReadWriteFile/helpers/utils.ts":{"5":[61],"37":[61],"44":[61]},"packages/nodes-base/nodes/SpreadsheetFile/v2/fromFile.operation.ts":{"85":[61],"126":[61],"129":[61],"136":[61],"144":[61],"154":[61]},"packages/nodes-base/utils/binary.ts":{"32":[56,61,64],"82":[56,61,64],"134":[56,61,64],"150":[56,61,64],"170":[56,61,64],"174":[56,61,64],"184":[56,61,64],"213":[56,61,64],"216":[56,61,64]},"packages/@n8n/design-system/src/components/N8nIcon/nodes/read-write-files-from-disk.svg":{"11":[59,61]},"packages/@n8n/api-types/src/schemas/folder.schema.ts":{"10":[65,66]},"packages/cli/src/controllers/folder.controller.ts":{"36":[65,66,67,68,69],"43":[65,66,67,68,69],"61":[65,66,67,68,69],"82":[65,66,67,68,69],"102":[65,66,67,68,69],"126":[65,66,67,68,69],"148":[65,66,67,68,69],"170":[65,66,67,68,69],"185":[65,66,67,68,69],"207":[65,66,67,68,69]},"packages/cli/src/services/folder.service.ts":{"33":[65,66,67,68,69,7],"41":[65,66,67,68,69,7],"58":[65,66,67,68,69,7],"97":[65,66,67,68,69,7],"105":[65,66,67,68,69,7],"134":[65,66,67,68,69,7],"153":[65,66,67,68,69,7],"166":[65,66,67,68,69,7],"189":[65,66,67,68,69,7],"197":[65,66,67,68,69,7],"205":[65,66,67,68,69,7],"213":[65,66,67,68,69,7],"224":[65,66,67,68,69,7],"238":[65,66,67,68,69,7],"239":[65,66,67,68,69,7],"247":[65,66,67,68,69,7],"272":[65,66,67,68,69,7],"285":[65,66,67,68,69,7],"311":[65,66,67,68,69,7],"321":[65,66,67,68,69,7],"324":[65,66,67,68,69,7],"329":[65,66,67,68,69,7]},"packages/frontend/editor-ui/src/features/core/folders/components/FolderCard.vue":{"68":[65,66,67],"72":[66],"74":[65,66,67],"98":[65,66,67],"106":[65,66,67],"119":[65,66,67],"130":[65,66,67],"134":[65,66,67],"145":[66],"165":[66],"169":[65,66,67],"180":[65,66,67],"213":[65,66,67],"220":[65,66,67],"221":[65,66,67],"230":[65,66,67],"233":[65,66,67],"240":[65,66,67],"248":[65,67],"259":[65,66,67],"271":[65,66,67],"280":[65,66,67],"286":[65,66,67],"287":[65,66,67],"299":[66],"329":[65,66,67],"339":[65,66,67],"360":[65,66,67]},"packages/frontend/editor-ui/src/features/core/folders/folders.api.ts":{"11":[66,67],"23":[65,66,67],"35":[67],"46":[67],"57":[67,68,69],"87":[67],"100":[65,67],"111":[67]},"packages/frontend/editor-ui/src/app/utils/telemetryUtils.ts":{"5":[86,112,113,114,115,120,123,124],"13":[86,112,113,114,115,120,124],"14":[86,112,113,114,115,124],"21":[86,112,113,114,115,124],"27":[112,114,124],"28":[112,114,124],"71":[86,112,113,114,115,124]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/ResourceMapper/MappingFields.vue":{"49":[124],"74":[124],"83":[124],"85":[124],"86":[124],"101":[124],"104":[124],"117":[124],"118":[124],"121":[124],"122":[124],"131":[124],"132":[124],"134":[124],"161":[124],"164":[124],"178":[124],"182":[124],"186":[124],"196":[124],"204":[124],"214":[124],"238":[124],"252":[124],"267":[124],"279":[124],"283":[124],"287":[124],"295":[124],"314":[124],"327":[124],"365":[124],"396":[124],"441":[124]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/ResourceMapper/MappingModeSelect.vue":{"20":[123,124],"54":[123,124],"61":[123,124],"103":[123,124],"113":[123,124],"121":[123,124],"123":[123,124],"128":[123,124],"140":[123,124],"150":[123,124],"153":[123,124]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/ResourceMapper/MatchingColumnsSelect.vue":{"27":[124],"39":[124],"50":[124],"51":[124],"62":[124],"63":[124],"69":[124],"84":[124],"103":[124],"117":[124],"130":[124],"156":[124],"169":[124],"182":[124],"191":[124],"200":[124],"202":[124],"206":[124],"211":[124]},"packages/frontend/editor-ui/src/features/ndv/parameters/composables/useNodeSpecificationValues.ts":{"5":[123,124],"6":[123,124],"10":[123,124],"16":[124],"20":[123,124],"24":[124]},"packages/@n8n/api-types/src/dto/user/role-change-request.dto.ts":{"9":[7]},"packages/cli/src/modules/chat-hub/chat-hub-event-relay.service.ts":{"10":[7],"19":[7],"27":[7]},"packages/frontend/editor-ui/src/app/utils/rbac/checks/isDefaultUser.ts":{"4":[7]},"packages/frontend/editor-ui/src/features/settings/users/components/DeleteUserModal.vue":{"15":[7],"32":[7],"35":[7],"38":[7],"40":[7],"49":[7],"65":[7],"71":[7],"105":[7],"118":[7],"122":[7],"128":[7],"132":[7],"134":[7],"137":[7],"142":[7],"154":[7],"155":[7],"156":[7],"165":[7],"174":[7]},"packages/frontend/editor-ui/src/features/settings/users/components/SettingsUsersActionsCell.vue":{"7":[7],"16":[7],"21":[7]},"packages/frontend/editor-ui/src/features/settings/users/components/SettingsUsersLastActiveCell.vue":{"7":[7],"10":[7],"13":[7]},"packages/frontend/editor-ui/src/features/settings/users/components/SettingsUsersProjectsCell.vue":{"6":[7],"13":[7],"19":[7],"22":[7],"26":[7],"30":[7]},"packages/frontend/editor-ui/src/features/settings/users/components/SettingsUsersRoleCell.vue":{"20":[7],"21":[7],"22":[7],"24":[7],"29":[7],"42":[7],"49":[7],"54":[7]},"packages/frontend/editor-ui/src/features/settings/users/components/SettingsUsersTable.vue":{"24":[7],"45":[7],"51":[7],"66":[7],"77":[7],"88":[7],"99":[7],"105":[7],"124":[7],"143":[7],"151":[7],"154":[7],"159":[7],"161":[7],"176":[7],"181":[7],"192":[7],"195":[7],"198":[7],"202":[7]},"packages/frontend/editor-ui/src/features/settings/users/views/SettingsUsersView.vue":{"73":[7],"75":[7],"79":[7],"83":[7],"85":[7],"95":[7],"100":[7],"109":[7],"115":[7],"122":[7],"131":[7],"136":[7],"140":[7],"144":[7],"163":[7],"198":[7],"203":[7],"318":[7],"319":[7],"328":[7],"340":[7],"363":[7],"368":[7],"415":[7],"418":[7],"423":[7],"432":[7],"492":[7],"499":[7]},"packages/cli/src/executions/pre-execution-checks/subworkflow-policy-checker.ts":{"17":[127,128,160,155],"28":[127,128,160,155],"61":[127,128,160,155],"79":[127,128,160,155],"88":[127,128,160,155],"106":[127,128,160,155],"110":[127,128,160,155],"111":[127,128,160,155],"122":[127,128,160,155]},"packages/frontend/editor-ui/src/app/components/WorkflowExtractionNameModal.vue":{"21":[128],"31":[128],"37":[128],"57":[128],"59":[128],"64":[128],"79":[128],"90":[128]},"packages/@n8n/config/src/configs/ai.config.ts":{"6":[15],"26":[15]},"packages/@n8n/nodes-langchain/nodes/memory/MemoryRedisChat/MemoryRedisChat.node.ts":{"26":[15,119],"114":[15,119],"148":[15,119],"178":[15,119]},"packages/@n8n/nodes-langchain/nodes/tools/ToolCalculator/ToolCalculator.node.ts":{"15":[15],"21":[15],"55":[15],"61":[15]},"packages/@n8n/nodes-langchain/nodes/tools/ToolWikipedia/ToolWikipedia.node.ts":{"15":[15,120],"23":[15,120],"56":[15,120],"62":[15,120]},"packages/@n8n/design-system/src/components/N8nIcon/nodes/calculator.svg":{"11":[15,41]},"packages/@n8n/design-system/src/components/N8nIcon/nodes/compression.svg":{"11":[15,41]},"packages/@n8n/design-system/src/components/N8nIcon/nodes/date-and-time.svg":{"11":[15,41]},"packages/@n8n/design-system/src/components/N8nIcon/nodes/item-list-output-parser.svg":{"11":[15]},"packages/@n8n/design-system/src/components/N8nIcon/nodes/model-selector.svg":{"11":[15,16,119]},"packages/@n8n/design-system/src/components/N8nIcon/nodes/rss-read.svg":{"11":[15,41]},"packages/@n8n/design-system/src/components/N8nIcon/nodes/simple-memory.svg":{"11":[15,119]},"packages/@n8n/design-system/src/components/N8nIcon/nodes/structured-output-parser.svg":{"11":[15,120]},"packages/@n8n/design-system/src/components/N8nIcon/nodes/think-tool.svg":{"11":[15,41]},"packages/@n8n/design-system/src/components/N8nIcon/nodes/totp.svg":{"11":[15,41]},"packages/@n8n/design-system/src/components/N8nIcon/nodes/vector-store-question-answer-tool.svg":{"11":[15]},"packages/localhost-46493/assets/_plugin-vue_export-helper-Da88TEg1.js":{"2":[15,16]},"packages/localhost-46493/assets/chunk-CC9Q-vWm.js":{"8":[15,16],"9":[15,16],"10":[15,16],"19":[15,16],"23":[15,16],"29":[15,16],"33":[15,16],"34":[15,16]},"packages/localhost-46493/assets/shield-alt-B7h2cjjC.js":{"8":[15,16]},"packages/@n8n/nodes-langchain/nodes/chains/ChainLLM/ChainLlm.node.ts":{"23":[16,119],"67":[16,119],"87":[16,119],"93":[16,119],"119":[16,119],"137":[16,119]},"packages/@n8n/nodes-langchain/nodes/chains/ChainLLM/methods/chainExecutor.ts":{"19":[16,119],"34":[16,119],"45":[16,119],"60":[16,119],"69":[16,119],"95":[16,119],"118":[16,119],"126":[16,119],"140":[16,119]},"packages/@n8n/nodes-langchain/nodes/chains/ChainLLM/methods/config.ts":{"21":[16,119]},"packages/@n8n/nodes-langchain/nodes/chains/ChainLLM/methods/imageUtils.ts":{"15":[16,119],"27":[16,119],"82":[16,119]},"packages/@n8n/nodes-langchain/nodes/chains/ChainLLM/methods/index.ts":{"1":[16,119]},"packages/@n8n/nodes-langchain/nodes/chains/ChainLLM/methods/processItem.ts":{"11":[16,119],"33":[16,119]},"packages/@n8n/nodes-langchain/nodes/chains/ChainLLM/methods/promptUtils.ts":{"23":[16,119],"34":[16,119],"44":[16,119],"50":[16,119],"66":[16,119],"75":[16,119],"120":[16,119],"149":[16,119],"153":[16,119],"158":[16,119],"159":[16,119],"168":[16,119]},"packages/@n8n/nodes-langchain/nodes/chains/ChainLLM/methods/responseFormatter.ts":{"6":[16,119]},"packages/@n8n/design-system/src/components/N8nIcon/nodes/basic-llm-chain.svg":{"11":[16,119,120]},"packages/@n8n/design-system/src/components/N8nIcon/nodes/chat-memory-manager.svg":{"11":[16,97]},"packages/frontend/editor-ui/src/features/shared/editors/components/CodeNodeEditor/completer.ts":{"23":[35],"27":[35]},"packages/localhost-34739/assets/_plugin-vue_export-helper-Da88TEg1.js":{"2":[35,62,91,127,133]},"packages/localhost-34739/assets/chunk-CC9Q-vWm.js":{"8":[35,62,91,127,133],"9":[35,62,91,127,133],"10":[35,62,91,127,133],"19":[35,62,91,127,133],"23":[35,62,91,127,133],"29":[35,62,91,127,133],"33":[35,62,91,127,133],"34":[35,62,91,127,133]},"packages/localhost-34739/assets/shield-alt-B7h2cjjC.js":{"8":[35,133]},"packages/@n8n/design-system/src/components/N8nAlertDialog/AlertDialog.vue":{"74":[43],"94":[43],"99":[43]},"packages/@n8n/design-system/src/components/N8nDialog/Dialog.vue":{"95":[43,93],"99":[43,93],"108":[43,93]},"packages/@n8n/design-system/src/components/N8nDialog/DialogContent.vue":{"59":[43,93],"81":[43,93],"101":[43,93]},"packages/@n8n/design-system/src/components/N8nDialog/DialogOverlay.vue":{"15":[43,93]},"packages/frontend/editor-ui/src/app/utils/rbac/checks/isInstanceOwner.ts":{"4":[1,43,89,90]},"packages/frontend/editor-ui/src/features/settings/apiKeys/apiKeys.store.ts":{"17":[43],"23":[43]},"packages/frontend/editor-ui/src/features/settings/apiKeys/components/ApiKeyScopesModal.vue":{"7":[43],"18":[43],"27":[43]},"packages/frontend/editor-ui/src/features/settings/apiKeys/components/RevokeApiKeyConfirmModal.vue":{"7":[43],"23":[43],"31":[43],"43":[43]},"packages/frontend/editor-ui/src/features/settings/apiKeys/views/SettingsApiView.vue":{"150":[43],"226":[43]},"packages/frontend/editor-ui/src/features/shared/banners/components/banners/BaseBanner.vue":{"18":[43],"34":[43],"44":[43],"59":[43]},"packages/frontend/editor-ui/src/features/shared/banners/components/banners/TrialBanner.vue":{"73":[43],"80":[43],"81":[43],"82":[43],"90":[43],"93":[43],"99":[43],"104":[43],"106":[43],"120":[43],"130":[43],"135":[43],"143":[43],"148":[43],"166":[43],"178":[43],"194":[43],"198":[43],"204":[43],"212":[43]},"packages/localhost-34695/assets/_plugin-vue_export-helper-Da88TEg1.js":{"2":[43]},"packages/localhost-34695/assets/chunk-CC9Q-vWm.js":{"8":[43],"9":[43],"10":[43],"19":[43],"23":[43],"29":[43],"33":[43],"34":[43]},"packages/cli/src/errors/response-errors/auth.error.ts":{"4":[145,156,90]},"packages/cli/src/modules/mcp/mcp-oauth-authorization-code.service.ts":{"17":[156],"23":[156],"53":[156],"81":[156],"109":[156],"136":[156],"150":[156]},"packages/cli/src/modules/mcp/mcp-oauth-consent.service.ts":{"17":[156],"29":[156],"58":[156]},"packages/cli/src/modules/mcp/mcp-oauth-service.ts":{"43":[156],"53":[156],"55":[156],"77":[156],"100":[156],"105":[156],"123":[156],"136":[156],"162":[156],"202":[156],"212":[156],"272":[156],"286":[156],"290":[156],"296":[156],"310":[156],"338":[156],"345":[156],"355":[156],"386":[156]},"packages/cli/src/modules/mcp/mcp-oauth-token.service.ts":{"35":[156],"51":[156],"56":[156],"60":[156],"84":[156],"90":[156],"106":[156],"111":[156],"171":[156],"205":[156],"246":[156],"261":[156],"276":[156],"285":[156],"304":[156]},"packages/cli/src/modules/mcp/mcp-oauth.helpers.ts":{"9":[156],"22":[156]},"packages/cli/src/modules/mcp/mcp.auth.consent.controller.ts":{"12":[156],"19":[156],"45":[156],"76":[156],"83":[156],"90":[156]},"packages/cli/src/modules/mcp/mcp.oauth.controller.ts":{"28":[156],"49":[156],"66":[156],"69":[156],"112":[156],"122":[156],"147":[156],"157":[156]},"packages/cli/src/modules/mcp/oauth-session.service.ts":{"24":[156],"29":[156],"45":[156],"52":[156],"59":[156]},"packages/cli/src/controllers/orchestration.controller.ts":{"9":[91],"20":[91]},"packages/cli/src/scaling/worker-status.service.ee.ts":{"16":[91],"23":[91],"33":[91],"48":[91],"59":[91],"91":[91],"92":[91],"102":[91]},"packages/frontend/editor-ui/src/features/settings/orchestration.ee/components/WorkerList.vue":{"25":[91],"35":[91],"39":[91],"41":[91],"49":[91],"60":[91]},"packages/frontend/editor-ui/src/features/settings/orchestration.ee/orchestration.store.ts":{"26":[65,91],"34":[65],"47":[65],"56":[65,91],"59":[65],"65":[65],"71":[65],"74":[65],"77":[65]},"packages/frontend/editor-ui/src/features/settings/orchestration.ee/views/WorkerView.vue":{"30":[91],"33":[91]},"packages/cli/src/errors/response-errors/bad-request.error.ts":{"4":[141,44,84,160,133]},"packages/cli/src/errors/response-errors/conflict.error.ts":{"4":[133]},"packages/nodes-base/nodes/Form/FormTrigger.node.ts":{"8":[141,20,57,133]},"packages/nodes-base/nodes/Form/v1/FormTriggerV1.node.ts":{"91":[141,20,57,133],"98":[141,20,57,133]},"packages/nodes-base/nodes/Form/v2/FormTriggerV2.node.ts":{"154":[141,20,57,133],"269":[141,20,57,133],"276":[141,20,57,133]},"packages/nodes-base/nodes/Notion/Notion.node.ts":{"8":[44,69,5,120,133]},"packages/nodes-base/nodes/Notion/shared/descriptions/Blocks.ts":{"377":[44,69,5,120,133],"426":[44,69,5,120,133],"442":[44,69,5,120,133],"458":[44,69,5,120,133],"468":[44,69,5,120,133],"478":[44,69,5,120,133],"493":[44,69,5,120,133],"557":[44,69,5,120,133]},"packages/nodes-base/nodes/Notion/v1/NotionV1.node.ts":{"34":[44,69,5,120,133],"44":[44,69,5,120,133],"69":[44,69,5,120,133],"80":[44,69,5,120,133],"92":[44,69,5,120,133],"103":[44,69,5,120,133],"106":[44,69,5,120,133],"116":[44,69,5,120,133],"121":[44,69,5,120,133],"127":[44,69,5,120,133],"132":[44,69,5,120,133],"145":[44,69,5,120,133],"172":[44,69,5,120,133],"184":[44,69,5,120,133],"195":[44,69,5,120,133],"203":[44,69,5,120,133],"223":[44,69,5,120,133],"404":[44,69,5,120,133],"409":[44,69,5,120,133]},"packages/nodes-base/nodes/Notion/v2/NotionV2.node.ts":{"38":[44,69,5,120,133],"47":[44,69,5,120,133],"140":[44,69,5,120,133],"453":[44,69,5,120,133],"457":[44,69,5,120,133]},"packages/nodes-base/nodes/Notion/v2/methods/loadOptions.ts":{"11":[44,69,5,120,133],"37":[44,69,5,120,133],"49":[44,69,5,120,133],"63":[44,69,5,120,133],"75":[44,69,5,120,133],"79":[44,69,5,120,133],"91":[44,69,5,120,133],"99":[44,69,5,120,133],"105":[44,69,5,120,133],"111":[44,69,5,120,133],"125":[44,69,5,120,133],"154":[44,69,5,120,133],"166":[44,69,5,120,133],"177":[44,69,5,120,133],"185":[44,69,5,120,133]},"packages/nodes-base/nodes/RespondToWebhook/RespondToWebhook.node.ts":{"358":[142,153,64,160,133],"366":[142,153,64,160,133],"390":[142,153,64,160,133],"470":[142,153,64,160,133],"536":[142,153,64,160,133]},"packages/nodes-base/nodes/RespondToWebhook/utils/binary.ts":{"5":[142,64,160,133],"16":[142,64,160,133]},"packages/nodes-base/nodes/RespondToWebhook/utils/outputs.ts":{"1":[142,64,160,133]},"packages/frontend/editor-ui/src/app/components/ActivationModal.vue":{"22":[63,93,132,133,137],"31":[63,93,132,133,137],"33":[63,93,132,133,137],"94":[93],"98":[63,93,132,133,137],"103":[63,93,132,133,137],"105":[63,93,132,133,137],"110":[63,93,132,133,137],"122":[63,93,132,133,137],"125":[63,93,132,133,137]},"packages/frontend/editor-ui/src/app/components/MainHeader/WorkflowPublishModal.vue":{"32":[63,93,132,133,137],"48":[63,93,132,133,137],"52":[63,93,132,133,137],"56":[63,93,132,133,137],"66":[63,93,132,133,137],"68":[63,93,132,133,137],"74":[63,93,132,133,137],"80":[63,93,132,133,137],"96":[63,93,132,133,137],"100":[63,93,132,133,137],"118":[63,93,132,133,137],"122":[63,93,132,133,137],"125":[63],"147":[63,93,132,133,137],"160":[63,93,132,133,137],"203":[63,93,132,133,137],"251":[63,93,132,133,137],"264":[63,93,132,133,137],"265":[63,93,132,133,137],"267":[63,93,132,133,137],"309":[63,93,132,133,137]},"packages/frontend/editor-ui/src/app/components/WorkflowVersionForm.vue":{"16":[63,93,132,133,137],"26":[63,93,132,133,137],"38":[63,93,132,133,137],"47":[63,93,132,133,137],"62":[63,93,132,133,137]},"packages/frontend/editor-ui/src/app/composables/useWorkflowActivate.ts":{"85":[63,93,132,133,137],"178":[137]},"packages/frontend/editor-ui/src/features/workflows/workflowHistory/utils.ts":{"9":[105],"15":[63,93,132,133,137],"19":[105],"37":[105],"69":[105],"74":[105]},"packages/@n8n/ai-utilities/src/utils/n8n-json-loader.ts":{"15":[17],"21":[17],"35":[17],"45":[17],"81":[17]},"packages/@n8n/ai-utilities/src/utils/vector-store/MemoryManager/MemoryCalculator.ts":{"21":[8,17],"61":[8,17]},"packages/@n8n/ai-utilities/src/utils/vector-store/MemoryManager/MemoryVectorStoreManager.ts":{"40":[8,17],"69":[8,17],"80":[8,17],"91":[8,17],"106":[8,17],"114":[8,17],"131":[8,17],"138":[8,17],"163":[8,17],"175":[8,17],"182":[8,17],"190":[8,17],"211":[8,17],"268":[8,17]},"packages/@n8n/ai-utilities/src/utils/vector-store/MemoryManager/StoreCleanupService.ts":{"16":[8,17],"31":[8,17],"45":[8,17],"79":[8,17],"117":[8,17],"120":[8,17],"153":[8,17]},"packages/@n8n/ai-utilities/src/utils/vector-store/MemoryManager/config.ts":{"10":[8,17],"38":[8,17],"47":[8,17]},"packages/@n8n/ai-utilities/src/utils/vector-store/createVectorStoreNode/createVectorStoreNode.ts":{"46":[8,17,120],"49":[8,17,120],"413":[8,17,120],"471":[8,17,120]},"packages/@n8n/ai-utilities/src/utils/vector-store/createVectorStoreNode/operations/insertOperation.ts":{"17":[8,17]},"packages/@n8n/ai-utilities/src/utils/vector-store/createVectorStoreNode/utils.ts":{"11":[8,17,120],"15":[8,17,120],"25":[8,17,120],"35":[8,17,120],"40":[8,17,120]},"packages/@n8n/ai-utilities/src/utils/vector-store/processDocuments.ts":{"7":[8,17],"19":[8,17],"28":[8,17],"41":[8,17]},"packages/@n8n/nodes-langchain/nodes/chains/ChainRetrievalQA/ChainRetrievalQa.node.ts":{"20":[17],"185":[17],"201":[17],"207":[17]},"packages/@n8n/nodes-langchain/nodes/chains/ChainRetrievalQA/processItem.ts":{"19":[17]},"packages/@n8n/nodes-langchain/nodes/code/Code.node.ts":{"67":[8,17],"122":[8,17],"126":[8,17],"136":[8,17],"146":[8,17],"150":[8,17],"151":[8,17],"152":[8,17]},"packages/@n8n/nodes-langchain/nodes/document_loaders/DocumentDefaultDataLoader/DocumentDefaultDataLoader.node.ts":{"21":[8,17],"38":[8,17],"329":[8,17]},"packages/@n8n/nodes-langchain/nodes/retrievers/RetrieverVectorStore/RetrieverVectorStore.node.ts":{"14":[17],"73":[17]},"packages/@n8n/nodes-langchain/nodes/text_splitters/TextSplitterCharacterTextSplitter/TextSplitterCharacterTextSplitter.node.ts":{"13":[8,17],"68":[8,17]},"packages/@n8n/nodes-langchain/nodes/vector_store/VectorStoreInMemory/VectorStoreInMemory.node.ts":{"37":[8,17],"132":[8,17],"143":[8,17],"152":[8,17],"161":[8,17],"186":[8,17],"192":[8,17]},"packages/core/src/execution-engine/external-secrets-proxy.ts":{"15":[8,17],"19":[8,17],"23":[8,17],"27":[8,17],"31":[8,17],"35":[8,17]},"packages/@n8n/design-system/src/components/N8nIcon/nodes/character-text-splitter.svg":{"11":[8,17]},"packages/@n8n/design-system/src/components/N8nIcon/nodes/default-data-loader.svg":{"11":[8,17,120]},"packages/@n8n/design-system/src/components/N8nIcon/nodes/question-and-answer-chain.svg":{"11":[17,120]},"packages/@n8n/design-system/src/components/N8nIcon/nodes/simple-vector-store.svg":{"11":[8,17,53,113,120]},"packages/@n8n/design-system/src/components/N8nIcon/nodes/vector-store-retriever.svg":{"11":[17,120]},"packages/localhost-44479/assets/_plugin-vue_export-helper-Da88TEg1.js":{"2":[17]},"packages/localhost-44479/assets/chunk-CC9Q-vWm.js":{"8":[17],"9":[17],"10":[17],"19":[17],"23":[17],"29":[17],"33":[17],"34":[17]},"packages/@n8n/ai-workflow-builder.ee/src/agents/planner.agent.ts":{"62":[18],"64":[18],"109":[18],"136":[18]},"packages/@n8n/ai-workflow-builder.ee/src/agents/responder.agent.ts":{"78":[18],"104":[18],"108":[18],"112":[18],"121":[18],"186":[18],"231":[18],"269":[18]},"packages/@n8n/ai-workflow-builder.ee/src/agents/supervisor.agent.ts":{"23":[18],"66":[18],"74":[18],"122":[18]},"packages/@n8n/ai-workflow-builder.ee/src/ai-workflow-builder-agent.service.ts":{"38":[18],"61":[18],"66":[18],"86":[18],"102":[18],"159":[18],"167":[18],"171":[18],"180":[18],"186":[18],"196":[18],"233":[18],"244":[18],"267":[18],"326":[18],"363":[18],"365":[18],"372":[18],"374":[18],"379":[18],"380":[18],"385":[18],"400":[18],"423":[18],"429":[18],"447":[18],"466":[18],"482":[18],"501":[18],"541":[18]},"packages/@n8n/ai-workflow-builder.ee/src/chains/workflow-name.ts":{"7":[18]},"packages/@n8n/ai-workflow-builder.ee/src/llm-config.ts":{"17":[18],"18":[18],"34":[18],"35":[18],"55":[18],"56":[18],"81":[18],"82":[18],"103":[18],"104":[18],"135":[18],"136":[18],"137":[18],"234":[18]},"packages/@n8n/ai-workflow-builder.ee/src/multi-agent-workflow-subgraphs.ts":{"56":[18],"73":[18],"113":[18],"118":[18],"187":[18],"194":[18],"211":[18],"252":[18],"275":[18],"286":[18],"353":[18],"379":[18],"391":[18],"392":[18],"402":[18],"403":[18],"406":[18],"433":[18],"444":[18],"452":[18],"506":[18],"525":[18],"527":[18],"536":[18],"544":[18]},"packages/@n8n/ai-workflow-builder.ee/src/parent-graph-state.ts":{"23":[18],"28":[18],"29":[18],"34":[18],"39":[18],"40":[18],"45":[18],"46":[18],"51":[18],"52":[18],"57":[18],"58":[18],"63":[18],"64":[18],"70":[18],"77":[18],"82":[18],"83":[18],"88":[18],"89":[18],"94":[18],"95":[18],"100":[18],"101":[18],"106":[18],"107":[18],"113":[18],"114":[18],"118":[18],"119":[18],"124":[18],"125":[18],"130":[18],"131":[18],"136":[18],"137":[18]},"packages/@n8n/ai-workflow-builder.ee/src/prompts/agents/discovery.prompt.ts":{"30":[18],"32":[18],"36":[18],"38":[18],"347":[18],"358":[18],"368":[18],"372":[18]},"packages/@n8n/ai-workflow-builder.ee/src/prompts/agents/planner.prompt.ts":{"73":[18],"98":[18],"109":[18],"122":[18],"129":[18],"130":[18]},"packages/@n8n/ai-workflow-builder.ee/src/prompts/agents/responder.prompt.ts":{"168":[18],"178":[18],"188":[18],"200":[18],"205":[18],"226":[18],"232":[18],"244":[18]},"packages/@n8n/ai-workflow-builder.ee/src/prompts/builder/prompt-builder.ts":{"17":[18],"30":[18],"44":[18],"55":[18],"79":[18],"116":[18],"129":[18],"149":[18],"175":[18],"197":[18],"228":[18],"252":[18],"268":[18],"282":[18],"302":[18],"330":[18],"357":[18]},"packages/@n8n/ai-workflow-builder.ee/src/prompts/index.ts":{"31":[18],"45":[18],"47":[18]},"packages/@n8n/ai-workflow-builder.ee/src/session-manager.service.ts":{"36":[18],"54":[18],"62":[18],"72":[18],"83":[18],"87":[18],"96":[18],"104":[18],"118":[18],"132":[18],"160":[18],"166":[18],"174":[18],"180":[18],"185":[18],"200":[18],"222":[18],"270":[18],"275":[18],"279":[18],"283":[18],"300":[18],"312":[18],"335":[18],"363":[18],"378":[18],"427":[18],"440":[18],"532":[18],"564":[18],"583":[18],"666":[18],"674":[18]},"packages/@n8n/ai-workflow-builder.ee/src/subgraphs/discovery.subgraph.ts":{"103":[18],"104":[18],"109":[18],"110":[18],"115":[18],"116":[18],"121":[18],"122":[18],"127":[18],"128":[18],"133":[18],"134":[18],"139":[18],"140":[18],"145":[18],"146":[18],"151":[18],"152":[18],"175":[18],"176":[18],"181":[18],"187":[18],"193":[18],"199":[18],"200":[18],"205":[18],"206":[18],"211":[18],"212":[18],"217":[18],"218":[18],"223":[18],"224":[18],"229":[18],"230":[18],"237":[18],"238":[18],"276":[18],"304":[18],"307":[18],"351":[18],"377":[18],"396":[18],"440":[18],"447":[18],"494":[18],"501":[18],"561":[18],"563":[18],"591":[18],"659":[18],"670":[18],"709":[18],"721":[18],"769":[18],"795":[18]},"packages/@n8n/ai-workflow-builder.ee/src/tools/get-documentation.tool.ts":{"60":[18],"81":[18],"88":[18],"113":[18],"115":[18],"136":[18],"146":[18]},"packages/@n8n/ai-workflow-builder.ee/src/tools/node-search.tool.ts":{"46":[18],"91":[18],"105":[18],"121":[18],"123":[18],"170":[18]},"packages/@n8n/ai-workflow-builder.ee/src/tools/utils/ssrf-guard.ts":{"27":[18],"37":[18],"39":[18],"40":[18],"42":[18],"52":[18],"62":[18]},"packages/@n8n/ai-workflow-builder.ee/src/tools/utils/web-fetch-security.ts":{"35":[18],"48":[18],"55":[18],"61":[18],"64":[18],"67":[18],"70":[18],"111":[18],"112":[18],"120":[18],"121":[18],"122":[18],"123":[18],"127":[18],"131":[18],"144":[18],"146":[18],"163":[18],"167":[18]},"packages/@n8n/ai-workflow-builder.ee/src/tools/web-fetch.tool.ts":{"30":[18],"69":[18],"83":[18],"86":[18]},"packages/@n8n/ai-workflow-builder.ee/src/utils/cleanup-dangling-tool-call-messages.ts":{"10":[18],"13":[18],"19":[18],"23":[18]},"packages/@n8n/ai-workflow-builder.ee/src/utils/http-proxy-agent.ts":{"8":[18]},"packages/@n8n/ai-workflow-builder.ee/src/utils/state-modifier.ts":{"34":[18],"56":[18],"72":[18],"84":[18],"118":[18],"144":[18],"155":[18],"165":[18],"192":[18],"201":[18],"227":[18],"231":[18],"261":[18],"274":[18]},"packages/@n8n/ai-workflow-builder.ee/src/utils/stream-processor.ts":{"86":[18],"87":[18],"91":[18],"96":[18],"101":[18],"107":[18],"110":[18],"117":[18],"122":[18],"131":[18],"140":[18],"141":[18],"158":[18],"183":[18],"187":[18],"191":[18],"196":[18],"201":[18],"211":[18],"237":[18],"272":[18],"285":[18],"298":[18],"317":[18],"337":[18],"378":[18],"391":[18],"418":[18],"426":[18],"445":[18],"469":[18],"477":[18],"480":[18],"488":[18],"497":[18],"506":[18],"549":[18],"551":[18],"555":[18],"563":[18],"581":[18],"634":[18],"657":[18],"661":[18],"662":[18],"668":[18],"690":[18]},"packages/@n8n/ai-workflow-builder.ee/src/utils/thread-id.ts":{"7":[18]},"packages/@n8n/ai-workflow-builder.ee/src/utils/token-usage.ts":{"27":[18],"29":[18],"43":[18],"44":[18],"50":[18],"67":[18],"71":[18]},"packages/@n8n/ai-workflow-builder.ee/src/workflow-builder-agent.ts":{"166":[18],"184":[18],"196":[18],"204":[18],"213":[18],"234":[18],"315":[18],"344":[18],"362":[18],"392":[18],"410":[18],"441":[18],"463":[18],"476":[18],"515":[18],"587":[18],"602":[18],"618":[18],"668":[18],"686":[18],"690":[18]},"packages/@n8n/api-types/src/dto/ai/ai-build-request.dto.ts":{"41":[18],"51":[18],"61":[18],"63":[18],"72":[18],"75":[18],"86":[18],"95":[18]},"packages/cli/src/controllers/ai.controller.ts":{"42":[18],"56":[18],"65":[18],"139":[18],"144":[18],"153":[18],"175":[18],"189":[18],"216":[18],"248":[18],"268":[18],"279":[18],"290":[18],"305":[18],"319":[18],"340":[18],"356":[18]},"packages/cli/src/modules/workflow-builder/workflow-builder-session.repository.ts":{"22":[18],"26":[18],"46":[18],"73":[18],"78":[18]},"packages/cli/src/services/ai-workflow-builder.service.ts":{"41":[18],"58":[18],"66":[18],"73":[18],"81":[18],"97":[18],"103":[18],"117":[18],"122":[18],"123":[18],"178":[18],"195":[18],"200":[18],"206":[18],"211":[18],"216":[18]},"packages/@n8n/design-system/src/components/CanvasPill/CanvasPill.vue":{"8":[13,18],"9":[13,18]},"packages/@n8n/design-system/src/components/CanvasThinkingPill/CanvasThinkingPill.vue":{"17":[13,18],"23":[13,18],"27":[13,18],"30":[13,18]},"packages/frontend/editor-ui/src/features/ai/assistant/assistant.types.ts":{"422":[13,18],"439":[13],"458":[13,18],"464":[13,18],"468":[13],"492":[13],"505":[13],"511":[13],"523":[13],"529":[13],"535":[13],"545":[13],"551":[13],"555":[13],"561":[13],"573":[13,18],"579":[13]},"packages/frontend/editor-ui/src/features/ai/assistant/builder.utils.ts":{"19":[13,18],"23":[13,18],"27":[13,18],"130":[13,18],"141":[13,18]},"packages/frontend/editor-ui/src/features/ai/assistant/components/HubSwitcher.vue":{"12":[13,18],"22":[13,18],"29":[13,18],"36":[13,18]},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/nodes/render-types/CanvasNodeChoicePrompt.vue":{"20":[13,151,18],"29":[13,151,18],"38":[13,151,18],"42":[151],"53":[13,151,18],"63":[151],"71":[13,151,18],"75":[13,151,18],"100":[151]},"packages/localhost-38277/assets/_plugin-vue_export-helper-Da88TEg1.js":{"2":[18]},"packages/localhost-38277/assets/chunk-CC9Q-vWm.js":{"8":[18],"9":[18],"10":[18],"19":[18],"23":[18],"29":[18],"33":[18],"34":[18]},"packages/@n8n/db/src/repositories/workflow-published-version.repository.ts":{"8":[143],"12":[143],"16":[143],"20":[143],"33":[143]},"packages/cli/src/workflows/workflow-published-data.service.ts":{"12":[143],"22":[143]},"packages/cli/src/metrics/prometheus/token-exchange-metrics.service.ts":{"22":[145],"27":[145],"31":[145],"72":[145],"76":[145],"81":[145],"85":[145],"90":[145],"94":[145]},"packages/cli/src/modules/token-exchange/controllers/embed-auth.controller.ts":{"22":[145],"37":[145],"55":[145],"66":[145]},"packages/cli/src/modules/token-exchange/controllers/token-exchange.controller.ts":{"22":[145],"43":[145]},"packages/cli/src/modules/token-exchange/database/repositories/token-exchange-jti.repository.ts":{"14":[145],"18":[145],"31":[145],"32":[145],"79":[145],"80":[145]},"packages/cli/src/modules/token-exchange/database/repositories/trusted-key.repository.ts":{"8":[145],"12":[145],"16":[145]},"packages/cli/src/modules/token-exchange/services/identity-resolution.service.ts":{"31":[145],"35":[145],"43":[145],"65":[145],"106":[145],"122":[145],"152":[145],"163":[145],"206":[145],"249":[145],"286":[145]},"packages/cli/src/modules/token-exchange/services/jti-store.service.ts":{"25":[145],"34":[145]},"packages/cli/src/modules/token-exchange/services/scoped-jwt.strategy.ts":{"17":[145],"22":[145],"67":[145],"74":[145],"97":[145],"104":[145]},"packages/cli/src/modules/token-exchange/services/token-exchange.service.ts":{"34":[145],"56":[145],"143":[145],"156":[145]},"packages/cli/src/modules/token-exchange/services/trusted-key.service.ts":{"80":[145],"105":[145],"118":[145],"126":[145],"130":[145],"138":[145],"144":[145],"158":[145],"208":[145],"216":[145],"220":[145],"226":[145],"254":[145],"263":[145],"264":[145],"266":[145],"267":[145],"312":[145],"327":[145],"344":[145],"370":[145],"372":[145],"391":[145],"443":[145],"462":[145],"481":[145],"496":[145],"511":[145],"520":[145],"551":[145],"597":[145]},"packages/cli/src/modules/token-exchange/token-exchange.errors.ts":{"11":[145],"24":[145]},"packages/cli/src/utils/validate-redirect-url.ts":{"5":[145]},"packages/@n8n/design-system/src/components/N8nFormInputs/FormInputs.vue":{"19":[26,28,1,69,89,90],"37":[26,28,1,69,89,90],"38":[26,28,1,69,89,90],"43":[28,69,89,90],"44":[28,69,89,90],"55":[26,28,1,69,89,90],"56":[26,28,1,69,89,90],"59":[26,28,1,69,89,90],"63":[26,28,1,69,89,90],"64":[90],"67":[90],"68":[90],"69":[90],"74":[28,69,89,90],"80":[26,28,1,69,89,90],"107":[90],"116":[28,69,89,90],"123":[28,69,89,90],"136":[26,28,1,69,89,90],"147":[26,28,1,69,89,90],"151":[26,28,1,69,89,90],"154":[26,28,1,69,89,90],"177":[28,69,89,90],"178":[26,28,1,69,89,90]},"packages/@n8n/design-system/src/components/ResizeObserver/ResizeObserver.vue":{"6":[26,28,1,69,89,90],"21":[26,28,1,69,89,90],"23":[26,28,1,69,89,90],"25":[26,28,1,69,89,90],"30":[26,28,1,69,89,90],"36":[26,28,1,69,89,90],"37":[26,28,1,69,89,90],"38":[26,28,1,69,89,90],"47":[28,69,90],"52":[26,28,1,69,89,90]},"packages/frontend/editor-ui/src/features/core/auth/views/SettingsPersonalView.vue":{"90":[1,89,90],"94":[1,89,90],"98":[1,89,90],"109":[1,89,90],"113":[1,89,90],"116":[1,89,90],"119":[1,89,90],"123":[1,89,90],"127":[1,89,90],"131":[1,89,90],"160":[1,89,90],"162":[1,89,90],"205":[89,90],"209":[1,89,90],"214":[89,90],"230":[89,90],"237":[90],"267":[89,90],"282":[89,90],"290":[89,90],"298":[90],"317":[90],"337":[90],"359":[1,89,90],"360":[1,89,90],"399":[1,89,90],"408":[1,89,90],"414":[1,89,90],"449":[1,89,90]},"packages/localhost-43467/assets/_plugin-vue_export-helper-Da88TEg1.js":{"2":[1,71,72,119]},"packages/localhost-43467/assets/chunk-CC9Q-vWm.js":{"8":[1,71,72,119],"9":[1,71,72,119],"10":[1,71,72,119],"19":[1,71,72,119],"23":[1,71,72,119],"29":[1,71,72,119],"33":[1,71,72,119],"34":[1,71,72,119]},"packages/frontend/editor-ui/src/features/credentials/components/CredentialsSelect.vue":{"21":[30,44,45],"36":[30,44,45],"37":[30,44,45],"43":[30,44,45],"44":[30,44,45],"47":[44,45],"57":[30,44,45],"84":[30,44,45],"92":[30,44],"101":[30,44,45],"102":[30,44,45],"125":[30,44,45],"139":[44,45],"141":[44,45],"142":[44,45],"143":[30,44,45],"145":[30,44,45],"151":[30,44,45],"173":[30,44,45]},"packages/localhost-39753/assets/_plugin-vue_export-helper-Da88TEg1.js":{"2":[45]},"packages/localhost-39753/assets/chunk-CC9Q-vWm.js":{"8":[45],"9":[45],"10":[45],"19":[45],"23":[45],"29":[45],"33":[45],"34":[45]},"packages/@n8n/design-system/src/components/N8nIcon/nodes/merge.svg":{"11":[19,97,107,119]},"packages/localhost-43467/assets/shield-alt-B7h2cjjC.js":{"8":[119]},"packages/localhost-43335/assets/_plugin-vue_export-helper-Da88TEg1.js":{"2":[21,70,94,96,105,120]},"packages/localhost-43335/assets/chunk-CC9Q-vWm.js":{"8":[21,70,94,96,105,120],"9":[21,70,94,96,105,120],"10":[21,70,94,96,105,120],"19":[21,70,94,96,105,120],"23":[21,70,94,96,105,120],"29":[21,70,94,96,105,120],"33":[21,70,94,96,105,120],"34":[21,70,94,96,105,120]},"packages/cli/src/modules/provisioning.ee/role-mapping-rule.service.ee.ts":{"46":[27],"52":[27],"79":[27],"83":[27],"129":[27],"142":[27],"166":[27],"216":[27],"233":[27],"239":[27],"262":[27],"268":[27],"278":[27],"281":[27],"298":[27],"308":[27],"310":[27],"313":[27],"329":[27],"336":[27]},"packages/cli/src/modules/sso-oidc/oidc.controller.ee.ts":{"23":[27],"36":[27],"47":[27],"65":[27],"87":[27],"108":[27]},"packages/cli/src/modules/sso-oidc/oidc.service.ee.ts":{"72":[27],"91":[27],"104":[27],"113":[27],"115":[27],"119":[27],"123":[27],"131":[27],"143":[27],"178":[27],"186":[27],"219":[27],"257":[27],"352":[27],"385":[27],"425":[27],"491":[27],"492":[27],"504":[27],"526":[27],"528":[27],"536":[27],"567":[27],"600":[27],"610":[27],"672":[27],"701":[27],"722":[27],"750":[27]},"packages/core/src/execution-engine/node-execution-context/utils/construct-execution-metadata.ts":{"8":[60,111,118],"13":[60,111,118]},"packages/nodes-base/nodes/Kafka/Kafka.node.ts":{"211":[60],"219":[60],"261":[60],"289":[60]},"packages/nodes-base/nodes/Kafka/KafkaTrigger.node.ts":{"381":[60],"409":[60],"418":[60],"442":[60],"480":[60],"503":[60]},"packages/nodes-base/nodes/Kafka/utils.ts":{"65":[60],"68":[60],"102":[60],"153":[60],"159":[60],"194":[60],"222":[60],"223":[60],"226":[60],"229":[60],"234":[60],"238":[60],"241":[60],"244":[60],"247":[60],"250":[60],"271":[60],"274":[60],"282":[60],"304":[60],"325":[60],"334":[60],"359":[60],"365":[60],"366":[60],"402":[60],"424":[60],"432":[60]},"packages/localhost-32893/assets/_plugin-vue_export-helper-Da88TEg1.js":{"2":[60]},"packages/localhost-32893/assets/chunk-CC9Q-vWm.js":{"8":[60],"9":[60],"10":[60],"19":[60],"23":[60],"29":[60],"33":[60],"34":[60]},"packages/@n8n/api-types/src/dto/folders/list-folder-query.dto.ts":{"46":[67,68,69],"74":[67,68,69],"75":[67,68,69],"83":[67,68,69],"84":[67,68,69],"93":[67,68,69],"102":[67,68,69]},"packages/frontend/editor-ui/src/app/api/workflows.ee.ts":{"7":[151,6],"20":[151,68,69],"28":[151]},"packages/frontend/editor-ui/src/features/collaboration/projects/components/ProjectMoveResourceModal.vue":{"41":[68],"66":[68],"73":[68],"90":[68],"94":[68],"97":[68],"98":[68],"99":[68],"102":[68],"112":[68],"115":[68],"120":[68],"124":[68],"173":[68],"189":[68],"192":[68],"194":[68],"202":[68],"206":[68],"207":[68],"213":[68],"214":[68],"222":[68],"240":[68],"245":[68],"329":[68],"332":[68],"340":[68]},"packages/frontend/editor-ui/src/features/collaboration/projects/components/ProjectMoveSuccessToastMessage.vue":{"19":[68],"20":[68],"21":[68],"24":[68]},"packages/frontend/editor-ui/src/features/collaboration/projects/composables/useMoveResourceToProjectToast.ts":{"26":[68]},"packages/frontend/editor-ui/src/features/core/folders/components/MoveToFolderDropdown.vue":{"40":[67,68,69],"41":[67,68,69],"42":[67,68,69],"54":[67,68,69],"64":[67],"94":[67,68,69],"95":[67,68,69],"105":[67,68,69],"107":[67],"109":[67,68,69],"128":[67,68,69],"130":[67,68,69],"132":[67,68,69],"137":[67,68,69],"141":[67,68,69],"148":[67],"151":[67]},"packages/frontend/editor-ui/src/features/core/folders/components/MoveToFolderModal.vue":{"65":[67,68,69],"81":[67,68,69],"84":[67,68,69],"90":[67,68,69],"100":[67,68,69],"101":[67,68,69],"105":[69],"108":[67,68,69],"109":[69],"127":[67,68,69],"130":[67,68,69],"134":[67,68,69],"143":[67,68,69],"153":[67,68,69],"167":[67,68,69],"168":[68,69],"174":[67,68,69],"175":[67,68,69],"182":[67,68,69],"186":[68],"192":[68,69],"200":[67,68,69],"354":[67],"379":[67,68,69],"381":[67,68,69],"386":[67,68,69],"390":[67,68,69],"417":[67,68,69],"427":[67,68,69],"436":[67,68,69],"438":[67,68,69],"452":[68,69],"457":[68,69],"478":[67,68,69],"497":[69],"506":[69],"532":[69],"556":[67,68,69]},"packages/localhost-36273/assets/_plugin-vue_export-helper-Da88TEg1.js":{"2":[68]},"packages/localhost-36273/assets/chunk-CC9Q-vWm.js":{"8":[68],"9":[68],"10":[68],"19":[68],"23":[68],"29":[68],"33":[68],"34":[68]},"packages/nodes-base/nodes/Discourse/Discourse.node.ts":{"93":[70],"107":[70]},"packages/nodes-base/nodes/Discourse/GenericFunctions.ts":{"11":[70],"40":[70]},"packages/nodes-base/nodes/Filter/Filter.node.ts":{"8":[70,107]},"packages/nodes-base/nodes/Filter/V1/FilterV1.node.ts":{"17":[70,107],"310":[70,107]},"packages/nodes-base/nodes/Filter/V1/GenericFunctions.ts":{"5":[70,107],"8":[70,107],"13":[70,107],"14":[70,107],"15":[70,107],"17":[70,107],"19":[70,107],"21":[70,107],"23":[70,107],"24":[70,107],"25":[70,107],"26":[70,107],"28":[70,107],"30":[70,107],"32":[70,107],"34":[70,107],"36":[70,107],"42":[70,107],"50":[70,107],"64":[70,107],"81":[70,107]},"packages/nodes-base/nodes/Filter/V2/FilterV2.node.ts":{"21":[70,107],"96":[70,107],"100":[70,107]},"packages/workflow/src/extensions/date-extensions.ts":{"85":[70],"89":[70],"99":[70],"104":[70],"114":[70],"120":[70],"145":[70],"153":[70],"176":[70],"183":[70],"195":[70],"200":[70],"221":[70],"242":[70],"251":[70],"256":[70],"270":[70],"275":[70],"284":[70],"289":[70],"293":[70]},"packages/@n8n/design-system/src/components/N8nIcon/nodes/filter.svg":{"11":[70,107]},"packages/cli/src/modules/source-control.ee/source-control-export.service.ee.ts":{"70":[84],"94":[84],"98":[84],"102":[84],"106":[84],"114":[84],"116":[84],"123":[84],"130":[84],"152":[84],"155":[84],"164":[84],"175":[84],"208":[84],"219":[84],"232":[84],"257":[84],"273":[84],"324":[84],"346":[84],"347":[84],"380":[84],"414":[84],"419":[84],"455":[84],"486":[84],"488":[84],"497":[84],"515":[84],"518":[84],"525":[84],"527":[84],"531":[84],"538":[84],"577":[84],"596":[84],"600":[84],"607":[84],"621":[84],"637":[84]},"packages/cli/src/modules/source-control.ee/source-control-git.service.ee.ts":{"46":[84],"56":[84],"79":[84],"116":[84],"129":[84],"133":[84],"186":[84],"190":[84],"205":[84],"212":[84],"227":[84],"283":[84],"298":[84],"314":[84],"347":[84],"355":[84],"364":[84],"365":[84],"379":[84],"388":[84],"399":[84],"411":[84],"423":[84],"431":[84],"443":[84],"460":[84],"474":[84],"488":[84],"495":[84],"509":[84],"524":[84],"525":[84],"533":[84]},"packages/cli/src/modules/source-control.ee/source-control-helper.ee.ts":{"41":[84],"65":[84],"73":[84],"96":[84],"123":[84],"153":[84],"157":[84],"161":[84],"168":[84],"172":[84],"176":[84],"180":[84],"184":[84],"202":[84],"211":[84],"224":[84],"239":[84],"245":[84],"262":[84],"267":[84],"268":[84],"307":[84],"316":[84],"320":[84],"321":[84],"325":[84],"333":[84],"337":[84],"339":[84],"343":[84],"350":[84],"352":[84],"354":[84],"356":[84],"358":[84],"362":[84],"369":[84],"370":[84],"372":[84],"374":[84],"384":[84],"401":[84],"438":[84],"453":[84],"461":[84],"462":[84],"464":[84],"481":[84],"500":[84],"504":[84],"517":[84]},"packages/cli/src/modules/source-control.ee/source-control-preferences.service.ee.ts":{"33":[84],"45":[84],"53":[84],"60":[84],"68":[84],"78":[84],"86":[84],"94":[84],"106":[84],"115":[84],"130":[84],"138":[84],"164":[84],"178":[84],"192":[84],"205":[84],"233":[84],"237":[84],"241":[84],"245":[84],"249":[84],"253":[84],"272":[84],"324":[84],"326":[84],"332":[84]},"packages/cli/src/modules/source-control.ee/source-control.controller.ee.ts":{"32":[84],"41":[84],"68":[84],"133":[84],"178":[84],"188":[84],"197":[84],"233":[84],"249":[84],"258":[84],"274":[84],"290":[84],"304":[84]},"packages/cli/src/modules/source-control.ee/source-control.service.ee.ts":{"62":[84],"79":[84],"94":[84],"103":[84],"116":[84],"139":[84],"148":[84],"178":[84],"209":[84],"258":[84],"267":[84],"280":[84],"296":[84],"312":[84],"339":[84],"340":[84],"351":[84],"370":[84],"371":[84],"390":[84],"393":[84],"449":[84],"474":[84],"488":[84],"503":[84],"525":[84],"597":[84],"602":[84],"610":[84]},"packages/@n8n/design-system/src/components/N8nColorPicker/ColorPicker.vue":{"21":[84],"34":[84],"59":[84]},"packages/frontend/editor-ui/src/app/components/layouts/EmptyStateLayout.vue":{"25":[24,27,69,84,90,131],"58":[69],"63":[24,27,69,84,90,131],"74":[24,27,69,84,90,131],"100":[24,27,69,84,90,131],"116":[24,27,69,84,90,131],"202":[24,27,69,84,90,131],"212":[84],"277":[24,27,69,84,90,131],"286":[24,27,69,84,90,131]},"packages/frontend/editor-ui/src/experiments/surfaceMcpToNewCloudUsers/composables/useSurfaceMcpEmptyState.ts":{"21":[24,27,69,84,90,131],"33":[24,27,69,84,90,131],"59":[24,27,69,84,90,131],"63":[24,27,69,84,90,131],"71":[24,27,69,84,90,131],"88":[24,27,69,84,90,131]},"packages/frontend/editor-ui/src/experiments/surfaceMcpToNewCloudUsers/composables/useSurfaceMcpToNewCloudUsersEligibility.ts":{"7":[24,27,69,84,90,131],"13":[24,27,69,84,90,131]},"packages/frontend/editor-ui/src/experiments/surfaceMcpToNewCloudUsers/stores/surfaceMcpToNewCloudUsers.store.ts":{"26":[24,27,69,84,90,131]},"packages/frontend/editor-ui/src/features/integrations/sourceControl.ee/views/SettingsSourceControl.vue":{"43":[84],"44":[84],"55":[84],"86":[84],"115":[84],"133":[84],"144":[84],"153":[84],"174":[84],"178":[84],"206":[84],"284":[84],"285":[84],"335":[84],"345":[84],"349":[84],"426":[84],"444":[84],"449":[84],"450":[84],"467":[84],"489":[84],"496":[84],"515":[84],"517":[84],"536":[84]},"packages/localhost-40183/assets/_plugin-vue_export-helper-Da88TEg1.js":{"2":[84]},"packages/localhost-40183/assets/chunk-CC9Q-vWm.js":{"8":[84],"9":[84],"10":[84],"19":[84],"23":[84],"29":[84],"33":[84],"34":[84]},"packages/frontend/editor-ui/src/app/views/DemoDiffView.vue":{"19":[94],"26":[94],"35":[94],"62":[94]},"packages/frontend/editor-ui/src/features/workflows/workflowDiff/HighlightedEdge.vue":{"6":[94]},"packages/frontend/editor-ui/src/features/workflows/workflowDiff/SyncedWorkflowCanvas.vue":{"16":[94],"39":[94],"49":[94],"68":[94],"71":[94],"76":[94],"90":[94],"98":[94],"102":[94],"131":[94],"146":[94],"149":[94],"152":[94]},"packages/frontend/editor-ui/src/features/workflows/workflowDiff/WorkflowDiffContent.vue":{"15":[94],"41":[94],"46":[94],"48":[94],"59":[94],"70":[94],"75":[94],"87":[94],"102":[94],"113":[94],"118":[94],"130":[94]},"packages/frontend/editor-ui/src/features/workflows/workflowDiff/WorkflowDiffView.vue":{"64":[94],"65":[94],"84":[94],"85":[94],"102":[94],"148":[94],"169":[94],"174":[94],"176":[94],"183":[94]},"packages/frontend/editor-ui/src/features/workflows/workflowDiff/useViewportSync.ts":{"30":[94],"47":[94],"53":[94],"72":[94]},"packages/frontend/editor-ui/src/features/workflows/workflowDiff/useWorkflowDiff.ts":{"31":[94],"32":[94],"42":[94],"43":[94],"47":[94],"52":[94],"71":[94],"83":[94],"94":[94],"100":[94],"117":[94],"128":[94],"147":[94],"151":[94],"168":[94],"211":[94],"233":[94],"261":[94]},"packages/frontend/editor-ui/src/features/workflows/workflowDiff/useWorkflowDiffUI.ts":{"25":[94],"40":[94],"94":[94],"97":[94],"98":[94],"130":[94],"167":[94],"182":[94],"221":[94],"225":[94]},"packages/localhost-33543/assets/_plugin-vue_export-helper-Da88TEg1.js":{"2":[27]},"packages/localhost-33543/assets/chunk-CC9Q-vWm.js":{"8":[27],"9":[27],"10":[27],"19":[27],"23":[27],"29":[27],"33":[27],"34":[27]},"packages/localhost-43335/assets/shield-alt-B7h2cjjC.js":{"8":[96,120]},"packages/frontend/editor-ui/src/features/workflows/workflowHistory/components/WorkflowHistoryContent.vue":{"71":[105],"119":[105],"125":[105]},"packages/frontend/editor-ui/src/features/workflows/workflowHistory/components/WorkflowHistoryList.vue":{"22":[105],"49":[105],"61":[105],"73":[105],"82":[105],"86":[105],"92":[105],"119":[105],"151":[105],"179":[105],"184":[105]},"packages/frontend/editor-ui/src/features/workflows/workflowHistory/components/WorkflowHistoryListItem.vue":{"26":[105],"58":[105],"63":[105],"74":[105],"83":[105],"99":[105],"165":[105],"172":[105],"203":[105],"211":[105],"214":[105]},"packages/frontend/editor-ui/src/features/workflows/workflowHistory/views/WorkflowHistory.vue":{"61":[105],"78":[105],"81":[105],"92":[105],"93":[105],"100":[105],"101":[105],"106":[105],"112":[105],"117":[105],"127":[105],"128":[105],"143":[105],"154":[105],"169":[105],"177":[105],"181":[105],"199":[105],"228":[105],"572":[105],"587":[105],"624":[105],"643":[105]},"packages/@n8n/nodes-langchain/nodes/embeddings/EmbeddingsHuggingFaceInference/EmbeddingsHuggingFaceInference.node.ts":{"15":[120],"85":[120],"93":[120],"119":[120]},"packages/@n8n/nodes-langchain/nodes/memory/MemoryXata/MemoryXata.node.ts":{"23":[120],"105":[120]},"packages/@n8n/nodes-langchain/nodes/output_parser/OutputParserStructured/OutputParserStructured.node.ts":{"30":[120],"196":[120]},"packages/@n8n/nodes-langchain/nodes/text_splitters/TextSplitterTokenSplitter/TextSplitterTokenSplitter.node.ts":{"13":[120],"62":[120]},"packages/@n8n/nodes-langchain/nodes/text_splitters/TextSplitterTokenSplitter/TokenTextSplitter.ts":{"16":[120],"28":[120],"36":[120]},"packages/@n8n/nodes-langchain/nodes/vector_store/VectorStoreQdrant/Qdrant.utils.ts":{"9":[120],"28":[120]},"packages/@n8n/nodes-langchain/nodes/vector_store/VectorStoreSupabase/VectorStoreSupabase.node.ts":{"67":[120],"84":[120]},"packages/@n8n/nodes-langchain/nodes/vector_store/VectorStoreWeaviate/Weaviate.utils.ts":{"22":[120],"68":[120],"127":[120]},"packages/@n8n/nodes-langchain/nodes/vector_store/shared/methods/listSearch.ts":{"10":[120],"19":[120],"27":[120],"58":[120],"65":[120],"73":[120],"87":[120],"95":[120],"102":[120]},"packages/nodes-base/credentials/NotionApi.credentials.ts":{"33":[120]},"packages/@n8n/design-system/src/components/N8nIcon/nodes/contextual-compression-retriever.svg":{"11":[120]},"packages/@n8n/design-system/src/components/N8nIcon/nodes/guardrails.svg":{"11":[120]},"packages/@n8n/design-system/src/components/N8nIcon/nodes/multiquery-retriever.svg":{"11":[120]},"packages/@n8n/design-system/src/components/N8nIcon/nodes/sentiment-analysis.svg":{"11":[120]},"packages/@n8n/design-system/src/components/N8nIcon/nodes/summarization-chain.svg":{"11":[120]},"packages/@n8n/design-system/src/components/N8nIcon/nodes/text-classifier.svg":{"11":[120]},"packages/@n8n/design-system/src/components/N8nIcon/nodes/token-splitter.svg":{"11":[120]},"packages/@n8n/design-system/src/components/N8nIcon/nodes/workflow-retriever.svg":{"11":[120]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/FixedCollection/FixedCollectionParameter.vue":{"39":[19,20,57,64,97,112,113,120]},"packages/frontend/editor-ui/src/features/shared/nodeCreator/components/ItemTypes/LinkItem.vue":{"13":[65,120]},"packages/localhost-38519/assets/_plugin-vue_export-helper-Da88TEg1.js":{"2":[120]},"packages/localhost-38519/assets/chunk-CC9Q-vWm.js":{"8":[120],"9":[120],"10":[120],"19":[120],"23":[120],"29":[120],"33":[120],"34":[120]},"packages/localhost-42789/assets/_plugin-vue_export-helper-Da88TEg1.js":{"2":[14,26,55,57,64,73,77,107]},"packages/localhost-42789/assets/chunk-CC9Q-vWm.js":{"8":[14,26,55,57,64,73,77,107],"9":[14,26,55,57,64,73,77,107],"10":[14,26,55,57,64,73,77,107],"19":[14,26,55,57,64,73,77,107],"23":[14,26,55,57,64,73,77,107],"29":[14,26,55,57,64,73,77,107],"33":[14,26,55,57,64,73,77,107],"34":[14,26,55,57,64,73,77,107]},"packages/frontend/editor-ui/src/app/components/NodeExecutionErrorMessage.vue":{"4":[151]},"packages/frontend/editor-ui/src/features/ai/evaluation.ee/evaluation.api.ts":{"59":[151,93],"63":[151,93],"68":[151],"81":[151],"107":[151],"123":[151],"131":[151],"135":[151],"150":[151],"166":[151],"174":[151],"188":[151],"201":[151]},"packages/frontend/editor-ui/src/features/workflows/canvas/experimental/components/ExperimentalEmbeddedNdvActions.vue":{"6":[151]},"packages/frontend/editor-ui/src/features/workflows/canvas/experimental/components/ExperimentalEmbeddedNodeDetails.vue":{"25":[151],"28":[151],"34":[151],"35":[151],"43":[151],"56":[151],"62":[151],"66":[151],"70":[151],"78":[151],"81":[151],"107":[151],"119":[151],"122":[151]},"packages/frontend/editor-ui/src/features/workflows/canvas/experimental/experimentalNdv.utils.ts":{"5":[151],"25":[151],"26":[151]},"packages/nodes-base/nodes/Linear/GenericFunctions.ts":{"16":[29],"66":[29],"70":[29],"100":[29],"126":[29]},"packages/nodes-base/nodes/Linear/Linear.node.ts":{"109":[29],"119":[29],"136":[29],"154":[29],"172":[29],"220":[29]},"packages/nodes-base/nodes/Linear/Queries.ts":{"2":[29],"15":[29],"28":[29],"41":[29],"95":[29],"102":[29],"138":[29],"147":[29],"189":[29],"245":[29],"255":[29]},"packages/@n8n/design-system/src/components/N8nFormBox/FormBox.vue":{"34":[26,28,69,90],"41":[28,69,90],"42":[28,69,90],"43":[28,69,90],"45":[26,28,69,90],"51":[26,28,69,90],"80":[26,28,69,90]},"packages/frontend/editor-ui/src/app/utils/rbac/checks/isGuest.ts":{"4":[26,28,69,90]},"packages/frontend/editor-ui/src/app/utils/rbac/middleware/guest.ts":{"6":[26,28,69,90]},"packages/frontend/editor-ui/src/features/core/auth/views/AuthView.vue":{"28":[28,69,90],"32":[28,69,90],"59":[26,28,69,90]},"packages/frontend/editor-ui/src/features/core/auth/views/SigninView.vue":{"45":[26,28,69,90],"46":[26,28,69,90],"89":[90],"98":[28,69,90],"102":[28,69,90],"119":[28,69,90],"127":[28,69,90],"190":[90],"195":[90]},"packages/frontend/editor-ui/src/features/settings/sso/components/SSOLogin.vue":{"23":[26,28,69,90]},"packages/community-packages.controller.ts":{"9":[55],"13":[55],"21":[55],"27":[55],"35":[55]},"packages/community-packages.lifecycle.service.ts":{"33":[55],"35":[55],"47":[55],"58":[55],"64":[55],"108":[55],"207":[55],"223":[55],"231":[55],"249":[55],"284":[55],"294":[55],"309":[55],"316":[55],"335":[55],"372":[55],"386":[55]},"packages/frontend/editor-ui/src/features/settings/communityNodes/communityNodes.utils.ts":{"10":[55]},"packages/frontend/editor-ui/src/features/settings/communityNodes/components/nodeCreator/CommunityNodeDetails.vue":{"19":[55,65],"28":[65],"30":[65],"39":[55,65],"41":[65],"43":[65],"74":[65],"79":[65],"97":[55,65],"115":[65],"118":[65]},"packages/frontend/editor-ui/src/features/settings/communityNodes/components/nodeCreator/CommunityNodeDocsLink.vue":{"9":[55,65],"11":[65],"14":[55,65],"23":[55,65]},"packages/frontend/editor-ui/src/features/settings/communityNodes/components/nodeCreator/CommunityNodeFooter.vue":{"15":[55],"32":[55],"52":[55],"57":[55],"72":[55],"73":[55],"79":[55],"80":[55]},"packages/frontend/editor-ui/src/features/settings/communityNodes/components/nodeCreator/CommunityNodeInfo.vue":{"17":[55,65],"29":[55,65],"33":[55,65],"41":[55,65],"43":[65],"48":[55,65],"65":[65],"101":[65],"109":[55,65],"114":[55,65],"119":[55,65],"130":[65],"132":[65],"138":[65],"144":[65],"145":[55,65],"148":[55,65],"156":[65],"163":[65],"168":[65],"169":[65],"172":[65]},"packages/frontend/editor-ui/src/features/shared/nodeCreator/components/ItemTypes/CommunityNodeItem.vue":{"11":[55,65]},"packages/cli/src/webhooks/waiting-forms.ts":{"23":[19,20,57],"26":[19,20,57],"30":[19,20,57],"36":[19,20,57],"47":[19,20,57],"59":[19,20,57],"79":[19,20,57],"158":[19,20,57]},"packages/cli/src/webhooks/webhook-form-data.ts":{"4":[19,20,57,63],"16":[19,20,57,63],"17":[19,20,57,63],"30":[19,20,57,63],"31":[19,20,57,63]},"packages/@n8n/design-system/src/components/N8nPulse/Pulse.vue":{"6":[20,57,64,107]},"packages/nodes-base/nodes/Files/ConvertToFile/ConvertToFile.node.ts":{"107":[64]},"packages/nodes-base/nodes/Files/ConvertToFile/actions/iCall.operation.ts":{"16":[64]},"packages/nodes-base/nodes/Files/ConvertToFile/actions/spreadsheet.operation.ts":{"94":[64]},"packages/nodes-base/nodes/Files/ConvertToFile/actions/toBinary.operation.ts":{"105":[64]},"packages/nodes-base/nodes/Files/ConvertToFile/actions/toJson.operation.ts":{"90":[64],"102":[64]},"packages/nodes-base/nodes/Files/ConvertToFile/actions/toText.operation.ts":{"78":[64]},"packages/nodes-base/nodes/ICalendar/createEvent.operation.ts":{"275":[64]},"packages/localhost-42789/assets/shield-alt-B7h2cjjC.js":{"8":[64]},"packages/@n8n/api-types/src/push/heartbeat.ts":{"9":[8,41,69]},"packages/@n8n/design-system/src/components/N8nIcon/custom/binary.svg":{"8":[69]},"packages/@n8n/design-system/src/components/N8nIcon/custom/status-canceled.svg":{"8":[69]},"packages/@n8n/design-system/src/components/N8nIcon/custom/status-completed.svg":{"8":[69]},"packages/@n8n/design-system/src/components/N8nIcon/custom/status-error.svg":{"8":[69]},"packages/@n8n/design-system/src/components/N8nIcon/custom/status-new.svg":{"8":[69]},"packages/@n8n/design-system/src/components/N8nIcon/custom/status-unknown.svg":{"8":[69]},"packages/@n8n/design-system/src/components/N8nIcon/custom/status-warning.svg":{"8":[24,69]},"packages/@n8n/design-system/src/types/menu.ts":{"55":[24,69,90,102]},"packages/frontend/editor-ui/src/features/collaboration/projects/components/ProjectIcon.vue":{"35":[69]},"packages/frontend/editor-ui/src/features/core/auth/views/SignoutView.vue":{"14":[69,90],"23":[69,90]},"packages/localhost-39203/assets/_plugin-vue_export-helper-Da88TEg1.js":{"2":[69]},"packages/localhost-39203/assets/chunk-CC9Q-vWm.js":{"8":[69],"9":[69],"10":[69],"19":[69],"23":[69],"29":[69],"33":[69],"34":[69]},"packages/localhost-39203/assets/shield-alt-B7h2cjjC.js":{"8":[69]},"packages/localhost-45407/assets/_plugin-vue_export-helper-Da88TEg1.js":{"2":[29,76,88,97,130]},"packages/localhost-45407/assets/chunk-CC9Q-vWm.js":{"8":[29,76,88,97,130],"9":[29,76,88,97,130],"10":[29,76,88,97,130],"19":[29,76,88,97,130],"23":[29,76,88,97,130],"29":[29,76,88,97,130],"33":[29,76,88,97,130],"34":[29,76,88,97,130]},"packages/localhost-45407/assets/shield-alt-B7h2cjjC.js":{"8":[29,76,97]},"packages/@n8n/design-system/src/components/N8nIcon/nodes/switch.svg":{"11":[59,73,97,102,113,118,121,136]},"packages/cli/src/execution-lifecycle/save-execution-progress.ts":{"8":[107]},"packages/nodes-base/nodes/Telegram/GenericFunctions.ts":{"70":[13,74,107,138],"194":[13,74,107,138],"234":[13,74,107,138],"247":[13,74,107,138],"251":[13,74,107,138],"257":[13,74,107,138],"278":[13,74,107,138]},"packages/nodes-base/nodes/Telegram/Telegram.node.ts":{"1809":[13,74,107,138],"1815":[13,74,107,138]},"packages/nodes-base/nodes/Pipedrive/PipedriveTrigger.node.ts":{"16":[44],"280":[44],"314":[44],"362":[44],"386":[44]},"packages/nodes-base/nodes/Pipedrive/v1/GenericFunctions.ts":{"31":[44,122],"103":[44,122],"142":[44,122],"187":[44,122],"195":[44,122],"210":[44,122],"230":[44,122],"278":[44,122],"292":[44,122],"293":[44,122],"302":[44,122],"305":[44,122]},"packages/nodes-base/nodes/Trello/GenericFunctions.ts":{"14":[44],"46":[44]},"packages/nodes-base/nodes/Trello/Trello.node.ts":{"138":[44],"161":[44],"169":[44],"192":[44],"203":[44]},"packages/localhost-46685/assets/_plugin-vue_export-helper-Da88TEg1.js":{"2":[44,53,65,67,79,80,113,115]},"packages/localhost-46685/assets/chunk-CC9Q-vWm.js":{"8":[44,53,65,67,79,80,113,115],"9":[44,53,65,67,79,80,113,115],"10":[44,53,65,67,79,80,113,115],"19":[44,53,65,67,79,80,113,115],"23":[44,53,65,67,79,80,113,115],"29":[44,53,65,67,79,80,113,115],"33":[44,53,65,67,79,80,113,115],"34":[44,53,65,67,79,80,113,115]},"packages/localhost-46685/assets/shield-alt-B7h2cjjC.js":{"8":[44,113]},"packages/frontend/editor-ui/src/features/shared/nodeCreator/components/ItemTypes/OpenTemplateItem.vue":{"14":[53,65],"23":[53,65],"27":[65]},"packages/nodes-base/nodes/Shopify/GenericFunctions.ts":{"12":[74,138],"85":[74,138],"124":[74,138]},"packages/nodes-base/nodes/Shopify/ShopifyTrigger.node.ts":{"335":[74,138],"350":[74,138],"373":[74,138],"389":[74,138]},"packages/nodes-base/nodes/Twitter/Twitter.node.ts":{"8":[74,138]},"packages/nodes-base/nodes/Twitter/V1/GenericFunctions.ts":{"12":[74,138],"44":[74,138],"67":[74,138],"79":[74,138]},"packages/nodes-base/nodes/Twitter/V1/TwitterV1.node.ts":{"27":[74,138],"76":[74,138],"92":[74,138],"123":[74,138],"164":[74,138],"171":[74,138]},"packages/nodes-base/nodes/Twitter/V2/GenericFunctions.ts":{"13":[74,138],"60":[74,138],"83":[74,138],"105":[74,138]},"packages/nodes-base/nodes/Twitter/V2/TwitterV2.node.ts":{"31":[74,138],"100":[74,138],"116":[74,138]},"packages/@n8n/chat/src/components/GetStarted.vue":{"5":[65]},"packages/@n8n/chat/src/utils/streamingHandlers.ts":{"11":[65],"55":[65],"64":[65],"78":[65],"98":[65]},"packages/frontend/editor-ui/src/app/components/ConsumedTokensDetails.vue":{"7":[65],"13":[65],"24":[65]},"packages/frontend/editor-ui/src/app/components/DuplicateWorkflowDialog.vue":{"20":[65],"58":[65],"64":[65],"72":[65],"76":[65],"147":[65],"156":[65],"161":[65],"172":[65],"192":[65]},"packages/frontend/editor-ui/src/app/components/MainHeader/utils.ts":{"1":[65]},"packages/frontend/editor-ui/src/app/composables/usePushConnection/handlers/builderCreditsUpdated.ts":{"4":[65]},"packages/frontend/editor-ui/src/app/composables/usePushConnection/handlers/executionRecovered.ts":{"14":[65]},"packages/frontend/editor-ui/src/app/composables/usePushConnection/handlers/nodeDescriptionUpdated.ts":{"10":[65]},"packages/frontend/editor-ui/src/app/composables/usePushConnection/handlers/reloadNodeType.ts":{"9":[65]},"packages/frontend/editor-ui/src/app/composables/usePushConnection/handlers/removeNodeType.ts":{"10":[65],"17":[65]},"packages/frontend/editor-ui/src/app/composables/usePushConnection/handlers/sendWorkerStatusMessage.ts":{"8":[65]},"packages/frontend/editor-ui/src/app/composables/usePushConnection/handlers/testWebhookDeleted.ts":{"8":[65]},"packages/frontend/editor-ui/src/app/composables/usePushConnection/handlers/workflowActivated.ts":{"9":[65]},"packages/frontend/editor-ui/src/app/composables/usePushConnection/handlers/workflowAutoDeactivated.ts":{"10":[65]},"packages/frontend/editor-ui/src/app/composables/usePushConnection/handlers/workflowDeactivated.ts":{"8":[65]},"packages/frontend/editor-ui/src/app/composables/usePushConnection/handlers/workflowFailedToActivate.ts":{"9":[65],"25":[65]},"packages/frontend/editor-ui/src/app/composables/usePushConnection/handlers/workflowSettingsUpdated.ts":{"8":[65]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/CanvasChatFloatingMenu.vue":{"10":[65],"26":[65],"27":[65],"32":[65],"34":[65],"43":[65],"75":[65],"108":[65],"120":[65],"133":[65],"148":[65],"149":[65],"154":[65]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/CanvasChatFloatingWindow.vue":{"23":[65],"28":[65],"37":[65],"46":[65],"58":[65],"59":[65],"62":[65],"66":[65],"70":[65],"78":[65],"90":[65],"92":[65],"100":[65],"105":[65],"122":[65],"125":[65],"130":[65],"140":[65]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/CanvasChatHubPanel.vue":{"30":[65],"50":[65],"51":[65],"61":[65],"62":[65],"63":[65],"66":[65],"72":[65],"100":[65],"101":[65],"136":[65],"138":[65],"144":[65],"150":[65],"159":[65],"164":[65],"174":[65],"175":[65],"181":[65],"196":[65],"200":[65],"214":[65],"218":[65],"222":[65],"243":[65],"254":[65],"266":[65],"278":[65],"279":[65],"280":[65],"281":[65],"282":[65],"294":[65],"308":[65],"312":[65],"322":[65],"324":[65],"334":[65],"336":[65],"361":[65],"372":[65],"382":[65]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/CanvasChatOverlay.vue":{"9":[65],"18":[65],"19":[65],"26":[65],"31":[65],"39":[65],"42":[65],"51":[65],"59":[65],"60":[65],"68":[65],"72":[65],"76":[65],"81":[65]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/CanvasChatSessionDropdown.vue":{"19":[65],"32":[65],"33":[65],"40":[65],"42":[65],"51":[65],"52":[65],"54":[65],"67":[65],"72":[65],"77":[65],"78":[65],"91":[65],"99":[65],"100":[65],"103":[65],"112":[65],"117":[65],"129":[65],"131":[65],"137":[65],"150":[65],"156":[65],"161":[65],"164":[65],"167":[65],"168":[65]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/ChatButtons.vue":{"11":[65],"14":[65],"27":[65],"33":[65],"40":[65],"41":[65]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/ChatMarkdownChunk.vue":{"33":[65],"38":[65],"47":[65],"84":[65],"91":[65]},"packages/frontend/editor-ui/src/features/ai/evaluation.ee/components/Paywall/EvaluationsPaywall.vue":{"7":[65],"10":[65],"17":[65]},"packages/frontend/editor-ui/src/features/settings/communityNodes/components/nodeCreator/CommunityNodeInstallHint.vue":{"10":[65],"11":[65]},"packages/frontend/editor-ui/src/features/shared/tags/components/TagsDropdown.vue":{"64":[130,137],"65":[130,137],"70":[130,137],"71":[130,137],"74":[130,137],"78":[65,130,137],"87":[130,137],"88":[130],"96":[130,137],"104":[130],"122":[130,137],"126":[130],"131":[130,137],"133":[130,137],"136":[130],"152":[130,137],"153":[130,137],"154":[130,137],"163":[130,137],"172":[130,137],"183":[130],"190":[130,137],"199":[130],"200":[130],"206":[130,137],"240":[130],"247":[65,130,137],"255":[130,137],"265":[65,130,137]},"packages/frontend/editor-ui/src/features/core/folders/components/DeleteFolderModal.vue":{"16":[67],"41":[67],"46":[67],"50":[67],"55":[67],"74":[67],"82":[67],"105":[67],"141":[67],"143":[67],"155":[67],"162":[67],"165":[67],"168":[67],"181":[67],"197":[67],"199":[67],"227":[67]},"packages/localhost-34611/assets/_plugin-vue_export-helper-Da88TEg1.js":{"2":[82]},"packages/localhost-34611/assets/chunk-CC9Q-vWm.js":{"8":[82],"9":[82],"10":[82],"19":[82],"23":[82],"29":[82],"33":[82],"34":[82]},"packages/nodes-base/nodes/Switch/Switch.node.ts":{"9":[97,113,118,121]},"packages/nodes-base/nodes/Switch/V1/SwitchV1.node.ts":{"15":[97,113,118,121],"523":[97,113,118,121],"538":[97,113,118,121],"540":[97,113,118,121],"542":[97,113,118,121],"544":[97,113,118,121],"546":[97,113,118,121],"548":[97,113,118,121],"550":[97,113,118,121],"551":[97,113,118,121],"552":[97,113,118,121],"554":[97,113,118,121],"556":[97,113,118,121],"558":[97,113,118,121],"560":[97,113,118,121],"562":[97,113,118,121],"564":[97,113,118,121],"578":[97,113,118,121],"595":[97,113,118,121],"616":[97,113,118,121]},"packages/nodes-base/nodes/Switch/V2/SwitchV2.node.ts":{"17":[97,113,118,121],"521":[97,113,118,121],"523":[97,113,118,121],"538":[97,113,118,121],"553":[97,113,118,121],"555":[97,113,118,121],"557":[97,113,118,121],"559":[97,113,118,121],"561":[97,113,118,121],"563":[97,113,118,121],"565":[97,113,118,121],"566":[97,113,118,121],"567":[97,113,118,121],"569":[97,113,118,121],"571":[97,113,118,121],"573":[97,113,118,121],"575":[97,113,118,121],"577":[97,113,118,121],"579":[97,113,118,121],"593":[97,113,118,121],"610":[97,113,118,121],"631":[97,113,118,121],"652":[97,113,118,121],"662":[97,113,118,121]},"packages/nodes-base/nodes/Switch/V3/SwitchV3.node.ts":{"21":[97,113,118,121],"25":[97,113,118,121],"31":[97,113,118,121],"51":[97,113,118,121],"347":[97,113,118,121],"377":[97,113,118,121],"383":[97,113,118,121],"409":[97,113,118,121],"422":[97,113,118,121]},"packages/frontend/editor-ui/src/app/utils/formatters/listFormatter.ts":{"15":[74,138]},"packages/frontend/editor-ui/src/features/workflows/templates/components/AppsRequiringCredsNotice.vue":{"10":[74,138],"17":[74,138],"24":[74,138],"27":[74,138],"33":[74,138],"38":[74,138]},"packages/frontend/editor-ui/src/features/workflows/templates/components/IconSuccess.vue":{"2":[74,138]},"packages/frontend/editor-ui/src/features/workflows/templates/components/SetupTemplateFormStep.vue":{"42":[74,138],"44":[74,138],"48":[74,138],"52":[74,138],"53":[74,138],"60":[74,138],"71":[138],"85":[74,138],"98":[74,138]},"packages/frontend/editor-ui/src/features/workflows/templates/components/SetupWorkflowCredentialsModal.vue":{"13":[74,138],"29":[74,138],"46":[74,138],"52":[138],"61":[74,138],"65":[74,138],"67":[74,138],"71":[74,138],"83":[74,138],"90":[138],"98":[74,138],"105":[138]},"packages/frontend/editor-ui/src/features/workflows/templates/composables/useCredentialSetupState.ts":{"29":[74,138],"34":[74,138],"38":[74,138],"43":[74,138],"77":[74,138],"103":[74,138],"115":[74,138],"123":[74,138],"126":[74,138],"132":[74,138],"136":[74,138],"140":[74,138],"144":[138],"163":[74,138],"171":[138]},"packages/frontend/editor-ui/src/features/workflows/templates/composables/useSetupWorkflowCredentialsModalState.ts":{"9":[74,138],"15":[74,138],"34":[74,138],"40":[138],"52":[138],"66":[138]},"packages/frontend/editor-ui/src/features/workflows/templates/utils/templateTransforms.ts":{"38":[74,138],"47":[74,138],"55":[138],"73":[138],"99":[138],"122":[138],"127":[138]},"packages/localhost-36813/assets/_plugin-vue_export-helper-Da88TEg1.js":{"2":[74]},"packages/localhost-36813/assets/chunk-CC9Q-vWm.js":{"8":[74],"9":[74],"10":[74],"19":[74],"23":[74],"29":[74],"33":[74],"34":[74]},"packages/@n8n/design-system/src/components/N8nIcon/nodes/sort.svg":{"11":[113,118,121]},"packages/frontend/editor-ui/src/features/ndv/parameters/utils/assignmentCollection.utils.ts":{"8":[113],"18":[113]},"packages/workflow/src/extensions/array-extensions.ts":{"17":[115],"21":[115],"25":[115],"29":[115],"33":[115],"40":[115],"43":[115],"44":[115],"59":[115],"64":[115],"65":[115],"67":[115],"74":[115],"77":[115],"78":[115],"83":[115],"86":[115],"97":[115],"101":[115],"113":[115],"117":[115],"129":[115],"140":[115],"142":[115],"147":[115],"155":[115],"163":[115],"173":[115],"187":[115],"193":[115],"200":[115],"213":[115],"233":[115],"238":[115],"267":[115],"274":[115],"281":[115],"290":[115],"297":[115],"306":[115],"311":[115],"318":[115],"322":[115],"326":[115],"330":[115],"334":[115],"338":[115]},"packages/workflow/src/extensions/string-extensions.ts":{"126":[115],"157":[115],"161":[115],"165":[115],"169":[115],"173":[115],"215":[115],"219":[115],"232":[115],"254":[115],"262":[115],"270":[115],"281":[115],"295":[115],"305":[115],"312":[115],"318":[115],"322":[115],"326":[115],"337":[115],"341":[115],"345":[115],"368":[115],"375":[115],"383":[115],"401":[115],"409":[115],"418":[115],"429":[115],"435":[115],"439":[115]},"packages/frontend/editor-ui/src/app/components/VersionUpdateCTA.vue":{"13":[24],"30":[24]},"packages/localhost-43055/assets/_plugin-vue_export-helper-Da88TEg1.js":{"2":[24,31,47,51,58,111,123,125,137]},"packages/localhost-43055/assets/chunk-CC9Q-vWm.js":{"8":[24,31,47,51,58,111,123,125,137],"9":[24,31,47,51,58,111,123,125,137],"10":[24,31,47,51,58,111,123,125,137],"19":[24,31,47,51,58,111,123,125,137],"23":[24,31,47,51,58,111,123,125,137],"29":[24,31,47,51,58,111,123,125,137],"33":[24,31,47,51,58,111,123,125,137],"34":[24,31,47,51,58,111,123,125,137]},"packages/localhost-43055/assets/shield-alt-B7h2cjjC.js":{"8":[31,51,125,137]},"packages/@n8n/api-types/src/dto/data-table/delete-data-table-rows.dto.ts":{"7":[47],"52":[47]},"packages/@n8n/api-types/src/dto/data-table/update-data-table-row.dto.ts":{"10":[47],"18":[47]},"packages/frontend/editor-ui/src/app/components/common/SelectedItemsInfo.vue":{"17":[47],"24":[47],"28":[47],"32":[47]},"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":[47],"6":[47]},"packages/frontend/editor-ui/src/app/utils/json-schema.ts":{"5":[111],"9":[111],"12":[111],"25":[111],"32":[111],"35":[111]},"packages/@n8n/client-oauth2/src/client-oauth2-token.ts":{"25":[146,154,123],"40":[146,154,123],"72":[146,154,123],"120":[146,154,123]},"packages/core/src/execution-engine/node-execution-context/utils/request-helpers/oauth.ts":{"37":[154,123],"41":[154,123],"58":[154,123],"86":[154,123],"97":[154,123],"103":[154,123],"117":[154,123],"206":[154,123],"214":[154,123],"325":[154,123],"340":[154,123],"342":[154,123],"350":[154,123],"362":[154,123],"365":[154,123],"373":[154,123],"397":[154,123],"439":[154,123],"445":[154,123]},"packages/@n8n/permissions/src/schemas.ee.ts":{"23":[131],"50":[131],"73":[131]},"packages/@n8n/design-system/src/components/N8nUserStack/UserStack.vue":{"9":[131],"23":[131],"35":[131],"39":[131],"49":[131],"55":[131],"59":[131],"62":[131],"73":[131],"83":[131],"85":[131],"92":[131],"96":[131]},"packages/localhost-44819/assets/_plugin-vue_export-helper-Da88TEg1.js":{"2":[131]},"packages/localhost-44819/assets/chunk-CC9Q-vWm.js":{"8":[131],"9":[131],"10":[131],"19":[131],"23":[131],"29":[131],"33":[131],"34":[131]},"packages/cli/src/middlewares/list-query/dtos/base.select.dto.ts":{"7":[137],"12":[137]},"packages/cli/src/middlewares/list-query/dtos/workflow.select.dto.ts":{"4":[137],"22":[137]},"packages/@n8n/design-system/src/components/N8nCommandBar/CommandBarItem.vue":{"6":[137],"17":[137],"21":[137],"27":[137]},"packages/@n8n/design-system/src/components/N8nTags/Tags.vue":{"21":[137,138],"37":[137,138],"45":[137],"50":[137,138],"56":[137,138]},"packages/frontend/editor-ui/src/features/shared/commandBar/components/CommandBarItemTitle.vue":{"23":[137]},"packages/frontend/editor-ui/src/features/shared/tags/components/WorkflowTagsDropdown.vue":{"33":[130,137],"34":[130,137],"37":[130,137],"38":[130,137],"39":[130,137],"41":[130],"45":[130],"53":[130,137]},"packages/frontend/editor-ui/src/features/workflows/workflowHistory/components/WorkflowHistoryVersionUnpublishModal.vue":{"15":[137],"36":[137],"42":[137],"45":[137],"49":[137],"51":[137],"58":[137],"62":[137],"70":[137],"73":[137],"76":[137]},"packages/@n8n/ai-utilities/src/utils/loaders/n8n-pdf-loader.ts":{"22":[8],"27":[8],"31":[8],"35":[8],"44":[8],"58":[8],"74":[8],"83":[8]},"packages/@n8n/ai-utilities/src/utils/n8n-binary-loader.ts":{"33":[8],"40":[8],"54":[8],"60":[8],"86":[8],"104":[8],"151":[8],"158":[8],"166":[8],"174":[8],"198":[8],"227":[8]},"packages/localhost-39921/assets/_plugin-vue_export-helper-Da88TEg1.js":{"2":[8,30,54,102,114,118]},"packages/localhost-39921/assets/chunk-CC9Q-vWm.js":{"8":[8,30,54,102,114,118],"9":[8,30,54,102,114,118],"10":[8,30,54,102,114,118],"19":[8,30,54,102,114,118],"23":[8,30,54,102,114,118],"29":[8,30,54,102,114,118],"33":[8,30,54,102,114,118],"34":[8,30,54,102,114,118]},"packages/cli/src/modules/external-secrets.ee/external-secrets.controller.ee.ts":{"13":[147],"22":[147],"34":[147],"40":[147],"47":[147],"60":[147],"68":[147],"76":[147],"90":[147]},"packages/cli/src/modules/external-secrets.ee/external-secrets.service.ee.ts":{"10":[147],"15":[147],"30":[147],"31":[147],"44":[147],"50":[147],"54":[147],"61":[147],"66":[147],"70":[147],"77":[147]},"packages/cli/src/modules/external-secrets.ee/provider-lifecycle.service.ts":{"25":[147,86],"36":[147,86],"78":[147,86],"112":[147,86],"127":[147,86]},"packages/cli/src/modules/external-secrets.ee/redaction.service.ee.ts":{"14":[147],"18":[147],"19":[147],"41":[147],"52":[147],"61":[147]},"packages/cli/src/modules/external-secrets.ee/retry-manager.service.ts":{"27":[147,86],"30":[147,86],"31":[147,86],"42":[147,86],"62":[147,86],"70":[147,86],"97":[147,86],"112":[147,86],"123":[147,86],"130":[147,86]},"packages/cli/src/modules/external-secrets.ee/secrets-cache.service.ts":{"15":[147,86],"25":[147,86],"29":[147,86],"38":[147,86],"54":[147,86],"56":[147,86],"57":[147,86],"78":[147,86],"86":[147,86],"94":[147,86],"102":[147,86]},"packages/cli/src/modules/external-secrets.ee/settings-store.service.ts":{"18":[147],"26":[147],"38":[147],"54":[147],"61":[147],"80":[147],"108":[147],"116":[147],"127":[147],"142":[147]},"packages/@n8n/design-system/src/components/N8nIcon/nodes/n8n-trigger.svg":{"11":[54]},"packages/localhost-39921/assets/shield-alt-B7h2cjjC.js":{"8":[54,102]},"packages/cli/src/modules/instance-registry/instance-registry.controller.ts":{"9":[102],"15":[102],"23":[102],"38":[102]},"packages/frontend/editor-ui/src/app/components/AboutModal.vue":{"16":[102],"24":[102],"28":[102],"57":[102],"68":[102],"72":[102],"75":[102],"80":[102],"83":[102],"88":[102],"91":[102],"92":[102],"98":[102],"101":[102],"102":[102],"108":[102],"111":[102],"116":[102],"119":[102],"120":[102],"127":[102]},"packages/frontend/editor-ui/src/app/components/ImportWorkflowUrlModal.vue":{"10":[102,136],"16":[102,136],"20":[102,136],"24":[136],"29":[102,136],"32":[102,136],"45":[102,136],"60":[102,136],"68":[102,136],"76":[102,136]},"packages/localhost-41061/assets/_plugin-vue_export-helper-Da88TEg1.js":{"2":[108]},"packages/localhost-41061/assets/chunk-CC9Q-vWm.js":{"8":[108],"9":[108],"10":[108],"19":[108],"23":[108],"29":[108],"33":[108],"34":[108]},"packages/frontend/editor-ui/src/app/utils/forceParse.ts":{"9":[10,103,114]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/ExpressionEditorModal/ExpressionEditorModalInput.vue":{"27":[114],"39":[114],"49":[114],"57":[114],"65":[114],"66":[114],"72":[114],"79":[114],"85":[114],"90":[114],"93":[114]},"packages/nodes-base/nodes/N8nTrainingCustomerDatastore/N8nTrainingCustomerDatastore.node.ts":{"119":[118]},"packages/nodes-base/nodes/Transform/Sort/Sort.node.ts":{"164":[118,121],"221":[118,121],"226":[118,121]},"packages/nodes-base/nodes/Transform/Sort/utils.ts":{"8":[118,121]},"packages/cli/src/errors/response-errors/workflow-activation-bad-request.error.ts":{"8":[160]},"packages/cli/src/errors/response-errors/workflow-validation.error.ts":{"9":[160]},"packages/cli/src/modules/external-secrets.ee/secret-provider-access-check.service.ee.ts":{"17":[86],"24":[86],"34":[86],"77":[86],"98":[86],"100":[86]},"packages/frontend/editor-ui/src/features/integrations/externalSecrets.ee/assets/images/aws-secrets-manager.svg":{"8":[86]},"packages/frontend/editor-ui/src/features/integrations/secretsProviders.ee/components/DeleteSecretsProviderModal.ee.vue":{"28":[86],"41":[86],"43":[86],"47":[86],"54":[86],"64":[86],"74":[86],"90":[86],"128":[86],"142":[86],"145":[86],"157":[86],"162":[86],"163":[86],"179":[86],"190":[86],"195":[86],"198":[86],"206":[86]},"packages/frontend/editor-ui/src/features/integrations/secretsProviders.ee/components/SecretsProviderConnectionCard.ee.vue":{"49":[86],"57":[86],"61":[86],"63":[86],"74":[86],"85":[86],"87":[86],"95":[86],"115":[86],"156":[86],"167":[86],"180":[86],"183":[86],"205":[86],"231":[86],"237":[86]},"packages/frontend/editor-ui/src/features/integrations/secretsProviders.ee/components/SecretsProviderConnectionModal.ee.vue":{"43":[86],"75":[86],"76":[86],"77":[86],"78":[86],"92":[86],"93":[86],"103":[86],"120":[86],"130":[86],"146":[86],"150":[86],"151":[86],"157":[86],"166":[86],"171":[86],"175":[86],"179":[86],"183":[86],"208":[86],"228":[86],"235":[86],"248":[86],"264":[86],"270":[86],"303":[86],"308":[86],"313":[86],"344":[86],"418":[86],"439":[86],"441":[86],"451":[86],"460":[86],"477":[86],"481":[86],"490":[86],"502":[86],"505":[86],"510":[86]},"packages/frontend/editor-ui/src/features/integrations/secretsProviders.ee/components/SecretsProviderImage.ee.vue":{"17":[86]},"packages/frontend/editor-ui/src/features/integrations/secretsProviders.ee/components/SecretsProvidersEmptyState.ee.vue":{"8":[86],"16":[86],"45":[86],"56":[86],"62":[86],"64":[86],"73":[86],"95":[86],"101":[86],"108":[86],"112":[86]},"packages/frontend/editor-ui/src/features/integrations/secretsProviders.ee/composables/useConnectionModal.ee.ts":{"31":[86],"35":[86],"60":[86],"66":[86],"92":[86],"118":[86],"138":[86],"142":[86],"151":[86],"159":[86],"164":[86],"166":[86],"167":[86],"173":[86],"174":[86],"181":[86],"187":[86],"194":[86],"199":[86],"200":[86],"207":[86],"208":[86],"212":[86],"213":[86],"215":[86],"225":[86],"233":[86],"239":[86],"257":[86],"276":[86],"281":[86],"283":[86],"291":[86],"298":[86],"306":[86],"307":[86],"357":[86],"401":[86],"442":[86],"450":[86],"478":[86],"516":[86]},"packages/frontend/editor-ui/src/features/integrations/secretsProviders.ee/composables/useSecretsProviderConnection.ee.ts":{"34":[86],"39":[86],"62":[86],"79":[86],"100":[86]},"packages/frontend/editor-ui/src/features/integrations/secretsProviders.ee/views/SettingsSecretsProviders.ee.vue":{"47":[86],"49":[86],"52":[86],"97":[86],"101":[86],"105":[86],"137":[86],"138":[86],"141":[86],"154":[86],"193":[86],"194":[86],"205":[86],"212":[86],"237":[86],"243":[86],"251":[86],"266":[86],"269":[86],"285":[86],"298":[86],"310":[86]},"packages/localhost-40003/assets/_plugin-vue_export-helper-Da88TEg1.js":{"2":[86]},"packages/localhost-40003/assets/chunk-CC9Q-vWm.js":{"8":[86],"9":[86],"10":[86],"19":[86],"23":[86],"29":[86],"33":[86],"34":[86]},"packages/cli/src/modules/log-streaming.ee/destinations/message-event-bus-destination-webhook.ee.ts":{"32":[88],"84":[88],"122":[88],"131":[88],"136":[88],"150":[88],"188":[88],"189":[88],"206":[88],"231":[88],"288":[88],"322":[88],"337":[88]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/FilterConditions/Condition.vue":{"43":[59,97],"63":[59,97],"67":[59,97],"79":[59,97],"97":[59,97],"110":[59,97],"120":[59,97],"131":[59,97],"143":[59],"145":[59],"166":[59],"170":[59],"215":[59,97],"221":[59,97],"250":[59,97],"269":[59,97],"278":[59,97],"306":[59,97],"316":[59]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/FilterConditions/FilterConditions.vue":{"39":[59,97],"62":[59,97],"71":[59],"75":[59,97],"78":[59,97],"90":[59],"94":[59,97],"96":[59],"100":[59,97],"105":[59,97],"134":[59,97],"135":[59,97],"144":[59,97],"145":[59,97],"152":[59,97],"160":[59],"164":[59],"172":[59],"176":[59,97],"178":[59,97],"210":[59,97],"232":[59],"233":[59]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/FilterConditions/OperatorSelect.vue":{"19":[59,97],"30":[59,97],"31":[59,97],"34":[59,97],"36":[59,97],"38":[59,97],"41":[59,97],"42":[59,97],"55":[59,97],"73":[59,97],"86":[59,97],"88":[59,97]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/FilterConditions/utils.ts":{"19":[59,97],"81":[59,97],"124":[59,97],"145":[59,97]},"packages/frontend/editor-ui/src/features/shared/tags/components/TagsManager/NoTagsView.vue":{"19":[130],"20":[130],"25":[130],"29":[130],"38":[130]},"packages/frontend/editor-ui/src/features/shared/tags/components/TagsManager/TagsManager.vue":{"29":[130],"42":[130],"46":[130],"48":[130],"49":[130],"51":[130],"55":[130],"59":[130],"63":[130],"67":[130],"117":[130],"118":[130],"130":[130],"133":[130],"148":[130],"161":[130],"183":[130]},"packages/frontend/editor-ui/src/features/shared/tags/components/TagsManager/TagsView/TagsTable.vue":{"33":[130],"42":[130],"46":[130],"73":[130],"84":[130],"88":[130],"92":[130],"93":[130],"100":[130],"101":[130],"109":[130],"118":[130],"119":[130],"127":[130],"132":[130],"145":[130],"147":[130],"148":[130],"150":[130],"169":[130],"171":[130],"181":[130],"183":[130],"234":[130]},"packages/frontend/editor-ui/src/features/shared/tags/components/TagsManager/TagsView/TagsTableHeader.vue":{"19":[130],"28":[130],"34":[130],"39":[130],"40":[130],"48":[130],"54":[130]},"packages/frontend/editor-ui/src/features/shared/tags/components/TagsManager/TagsView/TagsView.vue":{"13":[130],"33":[130],"47":[130],"49":[130],"50":[130],"57":[130],"58":[130],"72":[130],"81":[130],"108":[130],"112":[130],"116":[130],"118":[130],"128":[130],"133":[130],"138":[130],"141":[130],"152":[130],"173":[130]},"packages/frontend/editor-ui/src/features/shared/tags/components/TagsManager/WorkflowTagsManager.vue":{"10":[130],"14":[130],"15":[130],"17":[130],"27":[130],"62":[130],"83":[130]},"packages/@n8n/api-types/src/dto/binary-data/binary-data-query.dto.ts":{"8":[140],"12":[140]},"packages/cli/src/controllers/binary-data.controller.ts":{"16":[140],"19":[140],"36":[140],"50":[140],"74":[140]},"packages/@n8n/chat/src/components/ChatFile.vue":{"28":[36],"33":[36]},"packages/frontend/editor-ui/src/app/utils/fileUtils.ts":{"5":[36],"6":[36]},"packages/localhost-33775/assets/_plugin-vue_export-helper-Da88TEg1.js":{"2":[36,41]},"packages/localhost-33775/assets/chunk-CC9Q-vWm.js":{"8":[36,41],"9":[36,41],"10":[36,41],"19":[36,41],"23":[36,41],"29":[36,41],"33":[36,41],"34":[36,41]},"packages/localhost-38803/assets/_plugin-vue_export-helper-Da88TEg1.js":{"2":[20,59,5,101,112,134]},"packages/localhost-38803/assets/chunk-CC9Q-vWm.js":{"8":[20,59,5,101,112,134],"9":[20,59,5,101,112,134],"10":[20,59,5,101,112,134],"19":[20,59,5,101,112,134],"23":[20,59,5,101,112,134],"29":[20,59,5,101,112,134],"33":[20,59,5,101,112,134],"34":[20,59,5,101,112,134]},"packages/cli/src/controllers/password-reset.controller.ts":{"44":[144],"70":[144],"114":[144],"170":[144],"198":[144],"229":[144]},"packages/cli/src/middlewares/jitter.ts":{"14":[144],"18":[144],"21":[144]},"packages/cli/src/user-management/email/node-mailer.ts":{"19":[144],"48":[144],"84":[144]},"packages/@n8n/decorators/src/credential-resolver/errors.ts":{"5":[146],"16":[146],"27":[146]},"packages/cli/src/modules/dynamic-credentials.ee/credential-resolvers/identifiers/oauth2-userinfo-identifier.ts":{"47":[146],"52":[146],"75":[146],"106":[146],"117":[146],"130":[146],"155":[146],"164":[146],"171":[146]},"packages/cli/src/modules/dynamic-credentials.ee/credential-resolvers/identifiers/oauth2-utils.ts":{"11":[146]},"packages/cli/src/modules/dynamic-credentials.ee/credential-resolvers/oauth-credential-resolver.ts":{"39":[146],"125":[146],"154":[146],"175":[146],"185":[146],"189":[146],"202":[146],"207":[146],"218":[146],"226":[146]},"packages/cli/src/modules/dynamic-credentials.ee/credential-resolvers/storage/dynamic-credential-entry-storage.ts":{"10":[146],"14":[146],"31":[146],"53":[146],"66":[146]},"packages/cli/src/modules/dynamic-credentials.ee/credential-resolvers.controller.ts":{"39":[146,150],"43":[146,150],"53":[146,150],"64":[146,150],"67":[146,150],"78":[146,150],"110":[146,150],"131":[146,150],"151":[146,150],"189":[146,150]},"packages/cli/src/modules/dynamic-credentials.ee/dynamic-credentials.controller.ts":{"28":[146],"41":[146],"67":[146],"95":[146],"107":[146],"137":[146],"149":[146],"202":[146]},"packages/cli/src/modules/dynamic-credentials.ee/services/credential-resolver-workflow.service.ts":{"22":[146],"38":[146],"48":[146],"82":[146],"133":[146],"145":[146]},"packages/cli/src/modules/dynamic-credentials.ee/services/credential-resolver.service.ts":{"47":[146,150],"63":[146,150],"87":[146,150],"90":[146,150],"95":[146,150],"98":[146,150],"105":[146,150],"110":[146,150],"111":[146,150],"119":[146,150],"132":[146,150],"188":[146,150],"202":[146,150],"216":[146,150],"247":[146,150],"274":[146,150],"281":[146,150],"295":[146,150]},"packages/cli/src/modules/dynamic-credentials.ee/services/dynamic-credential-cors.service.ts":{"10":[146],"28":[146],"29":[146],"51":[146],"59":[146]},"packages/cli/src/modules/dynamic-credentials.ee/services/dynamic-credential-storage.service.ts":{"25":[146],"34":[146],"115":[146],"121":[146]},"packages/cli/src/modules/dynamic-credentials.ee/services/dynamic-credential-web.service.ts":{"15":[146],"34":[146],"36":[146],"53":[146]},"packages/cli/src/modules/dynamic-credentials.ee/services/dynamic-credential.service.ts":{"40":[146,154],"61":[146,154],"172":[146,154],"179":[146,154],"210":[146,154],"256":[146,154],"271":[146,154],"288":[146,154],"301":[146,154],"304":[146,154],"324":[146,154]},"packages/cli/src/modules/dynamic-credentials.ee/services/resolver-config-expression.service.ts":{"16":[146],"23":[146]},"packages/cli/src/modules/dynamic-credentials.ee/services/shared-fields.ts":{"12":[146],"31":[146]},"packages/cli/src/modules/dynamic-credentials.ee/workflow-status.controller.ts":{"22":[146],"36":[146],"57":[146],"73":[146],"81":[146]},"packages/workflow/src/node-parameters/node-parameter-value-type-guard.ts":{"13":[146],"27":[146],"38":[146],"54":[146],"66":[146],"84":[146],"120":[146]},"packages/cli/src/modules/dynamic-credentials.ee/context-establishment-hooks/bearer-token-extractor.ts":{"29":[154],"37":[154],"41":[154]},"packages/cli/src/modules/dynamic-credentials.ee/context-establishment-hooks/http-header-extractor.ts":{"24":[154],"32":[154],"53":[154],"75":[154],"101":[154],"105":[154]},"packages/nodes-base/nodes/EmailSend/EmailSend.node.ts":{"8":[56]},"packages/nodes-base/nodes/EmailSend/v1/EmailSendV1.node.ts":{"135":[56],"142":[56]},"packages/nodes-base/nodes/EmailSend/v2/EmailSendV2.node.ts":{"88":[56],"101":[56]},"packages/nodes-base/nodes/EmailSend/v2/send.operation.ts":{"185":[56]},"packages/nodes-base/nodes/EmailSend/v2/sendAndWait.operation.ts":{"27":[56]},"packages/nodes-base/nodes/EmailSend/v2/utils.ts":{"20":[56],"51":[56]},"packages/localhost-38301/assets/_plugin-vue_export-helper-Da88TEg1.js":{"2":[56]},"packages/localhost-38301/assets/chunk-CC9Q-vWm.js":{"8":[56],"9":[56],"10":[56],"19":[56],"23":[56],"29":[56],"33":[56],"34":[56]},"packages/core/src/execution-engine/node-execution-context/utils/create-node-as-tool.ts":{"30":[41],"76":[41],"84":[41],"96":[41],"108":[41],"122":[41]},"packages/workflow/src/from-ai-parse-utils.ts":{"27":[41],"59":[41],"110":[41],"120":[41],"148":[41],"199":[41],"248":[41],"324":[41],"327":[41],"329":[41],"331":[41],"335":[41],"342":[41],"344":[41],"362":[41],"460":[41],"491":[41],"511":[41],"527":[41]},"packages/workflow/src/schemas.ts":{"89":[41],"102":[41],"166":[41],"240":[41],"265":[41],"430":[41]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/FilterConditions/CombinatorSelect.vue":{"14":[59],"22":[59],"31":[59],"32":[59]},"packages/localhost-38803/assets/shield-alt-B7h2cjjC.js":{"8":[59,5]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/ToolListItem.vue":{"25":[41],"32":[41],"38":[41],"48":[41],"51":[41],"58":[41],"68":[41],"79":[41],"94":[41]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/ToolsManagerModal.vue":{"41":[41],"42":[41],"46":[41],"53":[41],"69":[41],"92":[41],"94":[41],"102":[41],"107":[41],"108":[41],"114":[41],"121":[41],"135":[41],"147":[41],"151":[41],"208":[41],"231":[41],"241":[41],"250":[41],"270":[41],"273":[41],"295":[41],"308":[41],"317":[41],"325":[41],"340":[41],"348":[41],"352":[41],"373":[41],"374":[41]},"packages/frontend/editor-ui/src/features/shared/toolConfig/NodeToolSettingsContent.vue":{"65":[41],"66":[41],"68":[41],"78":[41],"82":[41],"86":[41],"96":[41],"101":[41],"104":[41],"112":[41],"113":[41],"116":[41],"130":[41],"138":[41],"145":[41],"155":[41],"167":[41],"176":[41],"185":[41],"221":[41],"237":[41],"238":[41],"299":[41],"300":[41],"315":[41],"319":[41],"320":[41],"328":[41],"355":[41],"384":[41]},"packages/localhost-35873/assets/_plugin-vue_export-helper-Da88TEg1.js":{"2":[12,13,22,81,89,6,103,121,122]},"packages/localhost-35873/assets/chunk-CC9Q-vWm.js":{"8":[12,13,22,81,89,6,103,121,122],"9":[12,13,22,81,89,6,103,121,122],"10":[12,13,22,81,89,6,103,121,122],"19":[12,13,22,81,89,6,103,121,122],"23":[12,13,22,81,89,6,103,121,122],"29":[12,13,22,81,89,6,103,121,122],"33":[12,13,22,81,89,6,103,121,122],"34":[12,13,22,81,89,6,103,121,122]},"packages/nodes-base/nodes/Telegram/TelegramTrigger.node.ts":{"205":[13],"216":[13],"242":[13],"257":[13],"293":[13],"301":[13]},"packages/nodes-base/nodes/Telegram/util/triggerUtils.ts":{"11":[13]},"packages/@n8n/design-system/src/components/AskAssistantChat/messages/MessageRating.vue":{"15":[13],"62":[13]},"packages/frontend/editor-ui/src/features/ai/assistant/components/Agent/BuilderSetupCard.vue":{"28":[13],"53":[13],"57":[13],"59":[13],"82":[13],"89":[13],"95":[13],"99":[13],"103":[13],"104":[13],"105":[13],"109":[13],"110":[13],"111":[13],"112":[13],"114":[13],"120":[13],"136":[13],"149":[13],"182":[13],"189":[13],"205":[13],"206":[13],"209":[13],"218":[13],"219":[13]},"packages/frontend/editor-ui/src/features/ai/assistant/components/Agent/BuilderSetupWizard.vue":{"14":[13],"39":[13],"43":[13],"47":[13],"51":[13],"55":[13],"59":[13],"75":[13],"86":[13],"91":[13],"96":[13],"102":[13],"104":[13],"107":[13],"115":[13],"122":[13],"131":[13],"162":[13],"175":[13],"187":[13],"204":[13],"210":[13]},"packages/frontend/editor-ui/src/features/ai/assistant/components/Agent/CreditsSettingsDropdown.vue":{"29":[13],"79":[13]},"packages/frontend/editor-ui/src/features/ai/assistant/components/Agent/ExecuteMessage.vue":{"34":[13],"51":[13],"58":[13],"87":[13],"136":[13],"146":[13],"191":[13],"223":[13]},"packages/frontend/editor-ui/src/features/ai/assistant/composables/useBuilderExecution.ts":{"22":[13],"55":[13]},"packages/frontend/editor-ui/src/features/ai/assistant/composables/useBuilderSetupCards.ts":{"10":[13],"21":[13],"26":[13],"30":[13],"45":[13],"59":[13],"60":[13],"65":[13],"67":[13],"71":[13],"74":[13],"77":[13],"89":[13],"90":[13],"104":[13],"110":[13],"157":[13]},"packages/frontend/editor-ui/src/features/credentials/composables/useCredentialTestInBackground.ts":{"4":[13],"12":[13],"28":[13]},"packages/frontend/editor-ui/src/features/setupPanel/components/TriggerExecuteButton.vue":{"6":[13],"18":[13],"22":[13],"30":[13]},"packages/frontend/editor-ui/src/features/setupPanel/components/cards/SetupCardBody.vue":{"22":[13],"57":[13],"61":[13],"63":[13],"70":[13],"77":[13],"94":[13],"97":[13],"106":[13],"110":[13],"111":[13],"113":[13],"124":[13],"135":[13],"136":[13],"183":[13],"197":[13],"200":[13],"206":[13]},"packages/frontend/editor-ui/src/features/setupPanel/components/cards/SetupCardSection.vue":{"9":[13],"13":[13],"16":[13]},"packages/frontend/editor-ui/src/features/setupPanel/composables/groupSetupCards.ts":{"20":[13],"81":[13]},"packages/frontend/editor-ui/src/features/setupPanel/composables/useTriggerExecution.ts":{"18":[13],"38":[13],"40":[13],"46":[13],"70":[13],"77":[13],"81":[13],"87":[13],"91":[13]},"packages/frontend/editor-ui/src/features/setupPanel/composables/useWebhookUrls.ts":{"21":[13],"25":[13],"27":[13],"33":[13],"35":[13],"83":[13]},"packages/frontend/editor-ui/src/features/setupPanel/composables/useWorkflowSetupState.ts":{"46":[13],"63":[13],"70":[13],"117":[13],"120":[13],"156":[13],"194":[13],"222":[13],"227":[13],"291":[13],"293":[13],"294":[13],"300":[13],"324":[13],"347":[13],"348":[13],"355":[13],"356":[13],"359":[13],"360":[13],"370":[13],"384":[13],"398":[13],"411":[13],"428":[13],"429":[13],"431":[13],"435":[13],"443":[13],"462":[13],"465":[13],"471":[13],"472":[13],"507":[13],"616":[13],"632":[13],"635":[13],"658":[13],"659":[13],"661":[13],"663":[13],"794":[13],"805":[13],"831":[13],"862":[13]},"packages/frontend/editor-ui/src/features/setupPanel/setupPanel.utils.ts":{"7":[13],"25":[13],"50":[13],"103":[13],"136":[13],"227":[13],"267":[13],"310":[13],"318":[13]},"packages/@n8n/api-types/src/dto/user/user-update-request.dto.ts":{"6":[89,90],"13":[89,90],"15":[89,90]},"packages/core/src/utils/signature-helpers.ts":{"9":[63],"16":[63],"31":[63]},"packages/@n8n/design-system/src/components/N8nCircleLoader/CircleLoader.vue":{"3":[103],"15":[103],"16":[103],"18":[103],"22":[103],"23":[103],"24":[103],"28":[103]},"packages/frontend/editor-ui/src/features/shared/editors/plugins/codemirror/typescript/client/completions.ts":{"19":[103],"30":[103]},"packages/frontend/editor-ui/src/features/shared/editors/plugins/codemirror/typescript/client/linter.ts":{"4":[103],"8":[103]},"packages/localhost-35873/assets/shield-alt-B7h2cjjC.js":{"8":[103,122]},"packages/nodes-base/nodes/Pipedrive/Pipedrive.node.ts":{"8":[122]},"packages/nodes-base/nodes/Pipedrive/v1/PipedriveV1.node.ts":{"37":[122],"2256":[122],"2393":[122],"3809":[122],"3820":[122],"3834":[122],"3862":[122],"3876":[122],"3900":[122],"3904":[122],"3908":[122],"3912":[122],"3916":[122],"3926":[122],"3930":[122],"3944":[122],"3962":[122],"3978":[122],"3994":[122],"4023":[122],"4053":[122],"4058":[122],"4063":[122],"4068":[122],"4073":[122],"4103":[122],"4949":[122]},"packages/nodes-base/nodes/Pipedrive/v2/PipedriveV2.node.ts":{"16":[122],"28":[122]},"packages/nodes-base/nodes/Pipedrive/v2/actions/activity/create.operation.ts":{"119":[122]},"packages/nodes-base/nodes/Pipedrive/v2/actions/activity/delete.operation.ts":{"31":[122]},"packages/nodes-base/nodes/Pipedrive/v2/actions/activity/get.operation.ts":{"34":[122]},"packages/nodes-base/nodes/Pipedrive/v2/actions/activity/getAll.operation.ts":{"126":[122]},"packages/nodes-base/nodes/Pipedrive/v2/actions/activity/update.operation.ts":{"140":[122]},"packages/nodes-base/nodes/Pipedrive/v2/actions/deal/create.operation.ts":{"222":[122]},"packages/nodes-base/nodes/Pipedrive/v2/actions/deal/delete.operation.ts":{"31":[122]},"packages/nodes-base/nodes/Pipedrive/v2/actions/deal/duplicate.operation.ts":{"31":[122]},"packages/nodes-base/nodes/Pipedrive/v2/actions/deal/get.operation.ts":{"34":[122]},"packages/nodes-base/nodes/Pipedrive/v2/actions/deal/getAll.operation.ts":{"124":[122]},"packages/nodes-base/nodes/Pipedrive/v2/actions/deal/search.operation.ts":{"138":[122]},"packages/nodes-base/nodes/Pipedrive/v2/actions/deal/update.operation.ts":{"179":[122]},"packages/nodes-base/nodes/Pipedrive/v2/actions/dealProduct/add.operation.ts":{"117":[122]},"packages/nodes-base/nodes/Pipedrive/v2/actions/dealProduct/getAll.operation.ts":{"54":[122]},"packages/nodes-base/nodes/Pipedrive/v2/actions/dealProduct/remove.operation.ts":{"40":[122]},"packages/nodes-base/nodes/Pipedrive/v2/actions/dealProduct/update.operation.ts":{"116":[122]},"packages/nodes-base/nodes/Pipedrive/v2/actions/file/create.operation.ts":{"87":[122]},"packages/nodes-base/nodes/Pipedrive/v2/actions/file/delete.operation.ts":{"31":[122]},"packages/nodes-base/nodes/Pipedrive/v2/actions/file/download.operation.ts":{"34":[122]},"packages/nodes-base/nodes/Pipedrive/v2/actions/file/get.operation.ts":{"31":[122]},"packages/nodes-base/nodes/Pipedrive/v2/actions/file/update.operation.ts":{"54":[122]},"packages/nodes-base/nodes/Pipedrive/v2/actions/lead/create.operation.ts":{"148":[122],"175":[122]},"packages/nodes-base/nodes/Pipedrive/v2/actions/lead/delete.operation.ts":{"31":[122]},"packages/nodes-base/nodes/Pipedrive/v2/actions/lead/get.operation.ts":{"31":[122]},"packages/nodes-base/nodes/Pipedrive/v2/actions/lead/getAll.operation.ts":{"100":[122]},"packages/nodes-base/nodes/Pipedrive/v2/actions/lead/update.operation.ts":{"105":[122],"132":[122]},"packages/nodes-base/nodes/Pipedrive/v2/actions/note/create.operation.ts":{"96":[122]},"packages/nodes-base/nodes/Pipedrive/v2/actions/note/delete.operation.ts":{"31":[122]},"packages/nodes-base/nodes/Pipedrive/v2/actions/note/get.operation.ts":{"31":[122]},"packages/nodes-base/nodes/Pipedrive/v2/actions/note/getAll.operation.ts":{"143":[122]},"packages/nodes-base/nodes/Pipedrive/v2/actions/note/update.operation.ts":{"103":[122]},"packages/nodes-base/nodes/Pipedrive/v2/actions/organization/create.operation.ts":{"71":[122]},"packages/nodes-base/nodes/Pipedrive/v2/actions/organization/delete.operation.ts":{"31":[122]},"packages/nodes-base/nodes/Pipedrive/v2/actions/organization/get.operation.ts":{"34":[122]},"packages/nodes-base/nodes/Pipedrive/v2/actions/organization/getAll.operation.ts":{"81":[122]},"packages/nodes-base/nodes/Pipedrive/v2/actions/organization/search.operation.ts":{"98":[122]},"packages/nodes-base/nodes/Pipedrive/v2/actions/organization/update.operation.ts":{"78":[122]},"packages/nodes-base/nodes/Pipedrive/v2/actions/person/create.operation.ts":{"164":[122]},"packages/nodes-base/nodes/Pipedrive/v2/actions/person/delete.operation.ts":{"31":[122]},"packages/nodes-base/nodes/Pipedrive/v2/actions/person/get.operation.ts":{"34":[122]},"packages/nodes-base/nodes/Pipedrive/v2/actions/person/getAll.operation.ts":{"80":[122]},"packages/nodes-base/nodes/Pipedrive/v2/actions/person/search.operation.ts":{"117":[122]},"packages/nodes-base/nodes/Pipedrive/v2/actions/person/update.operation.ts":{"171":[122]},"packages/nodes-base/nodes/Pipedrive/v2/actions/product/create.operation.ts":{"126":[122]},"packages/nodes-base/nodes/Pipedrive/v2/actions/product/delete.operation.ts":{"31":[122]},"packages/nodes-base/nodes/Pipedrive/v2/actions/product/get.operation.ts":{"34":[122]},"packages/nodes-base/nodes/Pipedrive/v2/actions/product/getAll.operation.ts":{"53":[122]},"packages/nodes-base/nodes/Pipedrive/v2/actions/product/search.operation.ts":{"101":[122]},"packages/nodes-base/nodes/Pipedrive/v2/actions/product/update.operation.ts":{"133":[122]},"packages/nodes-base/nodes/Pipedrive/v2/actions/router.ts":{"15":[122]},"packages/nodes-base/nodes/Pipedrive/v2/helpers/customFields.ts":{"24":[122],"36":[122],"58":[122],"59":[122],"61":[122],"69":[122],"97":[122],"130":[122],"142":[122],"143":[122]},"packages/nodes-base/nodes/Pipedrive/v2/helpers/fields.ts":{"10":[122]},"packages/nodes-base/nodes/Pipedrive/v2/helpers/index.ts":{"3":[122],"7":[122]},"packages/nodes-base/nodes/Pipedrive/v2/helpers/searchResponse.ts":{"9":[122],"14":[122],"25":[122]},"packages/nodes-base/nodes/Pipedrive/v2/helpers/typeCoercion.ts":{"4":[122],"18":[122],"32":[122],"55":[122]},"packages/nodes-base/nodes/Pipedrive/v2/methods/loadOptions.ts":{"9":[122],"34":[122],"65":[122],"83":[122],"117":[122],"120":[122],"127":[122],"130":[122],"137":[122],"143":[122],"150":[122],"162":[122],"187":[122],"193":[122],"203":[122],"206":[122],"213":[122],"223":[122],"226":[122]},"packages/nodes-base/nodes/Pipedrive/v2/transport/pipedrive.api.ts":{"30":[122],"96":[122],"126":[122],"170":[122],"229":[122],"232":[122]},"packages/nodes-base/nodes/StopAndError/StopAndError.node.ts":{"82":[9]},"packages/nodes-base/nodes/StopAndError/utils.ts":{"14":[9],"18":[9]},"packages/@n8n/design-system/src/components/AskAssistantChat/messages/EventMessage.vue":{"24":[9],"40":[9],"44":[9]},"packages/@n8n/design-system/src/components/N8nIcon/nodes/stop-and-error.svg":{"11":[9,10]},"packages/frontend/editor-ui/src/features/ai/assistant/components/Chat/NewAssistantSessionModal.vue":{"14":[9],"27":[9],"31":[9],"44":[9],"56":[9],"62":[9],"65":[9],"68":[9],"72":[9]},"packages/localhost-37003/assets/_plugin-vue_export-helper-Da88TEg1.js":{"2":[9,10,19,28,93,136]},"packages/localhost-37003/assets/chunk-CC9Q-vWm.js":{"8":[9,10,19,28,93,136],"9":[9,10,19,28,93,136],"10":[9,10,19,28,93,136],"19":[9,10,19,28,93,136],"23":[9,10,19,28,93,136],"29":[9,10,19,28,93,136],"33":[9,10,19,28,93,136],"34":[9,10,19,28,93,136]},"packages/localhost-40857/assets/_plugin-vue_export-helper-Da88TEg1.js":{"2":[63]},"packages/localhost-40857/assets/chunk-CC9Q-vWm.js":{"8":[63],"9":[63],"10":[63],"19":[63],"23":[63],"29":[63],"33":[63],"34":[63]},"packages/@n8n/design-system/src/components/AskAssistantChat/messages/CodeDiffMessage.vue":{"19":[10],"20":[10],"32":[10],"40":[10],"41":[10]},"packages/@n8n/design-system/src/components/CodeDiff/CodeDiff.vue":{"10":[10],"43":[10],"48":[10],"85":[10],"93":[10],"120":[10],"121":[10],"137":[10],"138":[10]},"packages/frontend/editor-ui/src/features/ai/assistant/composables/useCodeDiff.ts":{"39":[10],"41":[10],"62":[10],"66":[10],"72":[10],"85":[10],"131":[10]},"packages/localhost-37003/assets/shield-alt-B7h2cjjC.js":{"8":[19,93]},"packages/cli/src/controllers/mfa.controller.ts":{"22":[90],"33":[90],"68":[90],"76":[90],"119":[90],"160":[90],"204":[90]},"packages/cli/src/mfa/mfa.service.ts":{"17":[90],"27":[90],"35":[90],"36":[90],"39":[90],"45":[90],"60":[90],"68":[90],"80":[90],"83":[90],"91":[90],"95":[90],"100":[90],"107":[90],"120":[90],"127":[90],"136":[90],"145":[90],"155":[90],"165":[90]},"packages/cli/src/mfa/totp.service.ts":{"6":[90],"10":[90],"26":[90],"38":[90]},"packages/frontend/editor-ui/src/features/core/auth/components/MfaSetupModal.vue":{"26":[90],"57":[90],"61":[90],"68":[90],"77":[90],"90":[90],"105":[90],"133":[90],"152":[90],"155":[90],"174":[90],"178":[90],"183":[90],"184":[90],"187":[90],"203":[90],"212":[90],"231":[90],"235":[90],"236":[90],"240":[90],"241":[90],"244":[90],"246":[90],"263":[90]},"packages/frontend/editor-ui/src/features/core/auth/components/PromptMfaCodeModal.vue":{"12":[90],"31":[90],"48":[90],"52":[90],"54":[90],"67":[90],"78":[90]},"packages/frontend/editor-ui/src/features/core/auth/views/MfaView.vue":{"63":[90],"86":[90],"107":[90],"116":[90],"117":[90],"129":[90],"155":[90],"164":[90],"189":[90],"194":[90],"204":[90],"225":[90]},"packages/localhost-34923/assets/_plugin-vue_export-helper-Da88TEg1.js":{"2":[90]},"packages/localhost-34923/assets/chunk-CC9Q-vWm.js":{"8":[90],"9":[90],"10":[90],"19":[90],"23":[90],"29":[90],"33":[90],"34":[90]},"packages/@n8n/db/src/repositories/test-run.repository.ee.ts":{"17":[93],"21":[93],"44":[93],"52":[93],"56":[93],"61":[93],"70":[93],"81":[93],"88":[93],"96":[93],"100":[93],"115":[93],"128":[93]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/OpenAi.node.ts":{"12":[93]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/helpers/binary-data.ts":{"11":[93]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/helpers/description.ts":{"3":[93],"20":[93],"38":[93]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/helpers/polling.ts":{"4":[93],"34":[93]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/helpers/utils.ts":{"17":[93],"27":[93],"39":[93],"50":[93],"58":[93],"66":[93],"88":[93]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/methods/listSearch.ts":{"13":[93],"36":[93],"45":[93],"46":[93],"49":[93],"63":[93],"69":[93],"75":[93],"82":[93],"85":[93],"89":[93],"92":[93],"96":[93],"121":[93],"126":[93],"130":[93],"173":[93]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/methods/loadOptions.ts":{"5":[93]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/transport/index.ts":{"15":[93]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v1/OpenAiV1.node.ts":{"22":[93],"82":[93]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v1/actions/assistant/create.operation.ts":{"176":[93],"185":[93]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v1/actions/assistant/deleteAssistant.operation.ts":{"18":[93]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v1/actions/assistant/list.operation.ts":{"25":[93],"62":[93]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v1/actions/assistant/message.operation.ts":{"158":[93],"165":[93],"225":[93],"232":[93]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v1/actions/assistant/update.operation.ts":{"120":[93],"126":[93],"132":[93],"207":[93],"213":[93],"214":[93],"217":[93],"223":[93],"224":[93],"228":[93]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v1/actions/audio/generate.operation.ts":{"134":[93]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v1/actions/audio/transcribe.operation.ts":{"58":[93]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v1/actions/audio/translate.operation.ts":{"50":[93]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v1/actions/descriptions.ts":{"3":[93]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v1/actions/file/deleteFile.operation.ts":{"51":[93]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v1/actions/file/list.operation.ts":{"53":[93],"63":[93]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v1/actions/file/upload.operation.ts":{"57":[93]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v1/actions/image/analyze.operation.ts":{"131":[93],"158":[93],"172":[93]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v1/actions/image/generate.operation.ts":{"255":[93],"291":[93]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v1/actions/router.ts":{"16":[93]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v1/actions/text/classify.operation.ts":{"53":[93]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v1/actions/text/message.operation.ts":{"240":[93],"244":[93],"360":[93]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v2/OpenAiV2.node.ts":{"23":[93],"92":[93]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v2/actions/audio/generate.operation.ts":{"134":[93]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v2/actions/audio/transcribe.operation.ts":{"58":[93]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v2/actions/audio/translate.operation.ts":{"50":[93]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v2/actions/conversation/create.operation.ts":{"82":[93]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v2/actions/conversation/get.operation.ts":{"27":[93]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v2/actions/conversation/remove.operation.ts":{"27":[93]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v2/actions/conversation/update.operation.ts":{"34":[93]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v2/actions/descriptions.ts":{"3":[93]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v2/actions/file/deleteFile.operation.ts":{"51":[93]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v2/actions/file/list.operation.ts":{"62":[93],"72":[93]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v2/actions/file/upload.operation.ts":{"65":[93]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v2/actions/image/analyze.operation.ts":{"133":[93],"157":[93],"169":[93]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v2/actions/image/edit.operation.ts":{"584":[93],"618":[93],"695":[93]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v2/actions/image/generate.operation.ts":{"73":[93],"118":[93]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v2/actions/router.ts":{"17":[93]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v2/actions/text/classify.operation.ts":{"58":[93]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v2/actions/text/helpers/responses.ts":{"14":[93],"16":[93],"19":[93],"22":[93],"25":[93],"31":[93],"101":[93]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v2/actions/text/response.operation.ts":{"583":[93],"587":[93],"629":[93],"632":[93],"652":[93],"659":[93],"717":[93],"719":[93],"736":[93]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v2/actions/video/generate.operation.ts":{"92":[93],"132":[93],"135":[93]},"packages/cli/src/evaluation.ee/test-runs.controller.ee.ts":{"19":[93],"27":[93],"50":[93],"68":[93],"77":[93],"90":[93],"99":[93],"112":[93],"130":[93],"158":[93]},"packages/cli/src/environments.ee/variables/variables.controller.ee.ts":{"19":[85],"22":[85],"32":[85],"50":[85],"60":[85],"80":[85]},"packages/frontend/editor-ui/src/app/components/RedactionMembersModal.vue":{"9":[93],"24":[93],"26":[93],"41":[93]},"packages/frontend/editor-ui/src/app/components/WorkflowSettings/WorkflowSettings.vue":{"72":[93],"214":[93],"221":[93],"224":[93],"227":[93],"228":[93],"229":[93],"230":[93],"233":[93],"238":[93],"248":[93],"252":[93],"254":[93],"258":[93],"263":[93],"278":[93],"282":[93],"286":[93],"287":[93],"295":[93],"314":[93],"330":[93],"346":[93],"380":[93],"382":[93],"387":[93],"391":[93],"402":[93],"416":[93],"441":[93],"471":[93],"495":[93],"519":[93],"542":[93],"565":[93],"592":[93],"648":[93],"836":[93],"994":[93],"1009":[93],"1017":[93],"1020":[93],"1028":[93],"1031":[93],"1035":[93],"1046":[93],"1047":[93],"1051":[93],"1056":[93],"1066":[93],"1068":[93],"1073":[93],"1148":[93],"1152":[93],"1158":[93],"1164":[93],"1166":[93],"1199":[93],"1203":[93],"1208":[93],"1215":[93],"1217":[93],"1228":[93],"1232":[93],"1237":[93],"1244":[93],"1246":[93],"1257":[93],"1261":[93],"1266":[93],"1273":[93],"1275":[93],"1286":[93],"1290":[93],"1295":[93],"1302":[93],"1304":[93],"1315":[93],"1319":[93],"1324":[93],"1331":[93],"1333":[93],"1344":[93],"1347":[93],"1370":[93],"1376":[93],"1384":[93],"1401":[93],"1417":[93],"1419":[93],"1441":[93],"1466":[93],"1472":[93],"1480":[93],"1505":[93],"1519":[93],"1521":[93],"1534":[93],"1538":[93],"1543":[93],"1633":[93],"1638":[93],"1644":[93],"1652":[93],"1654":[93],"1665":[93],"1755":[93]},"packages/frontend/editor-ui/src/features/ai/evaluation.ee/composables/useWorkflowEvaluationState.ts":{"25":[93],"26":[93],"51":[93]},"packages/frontend/editor-ui/src/features/ai/evaluation.ee/views/EvaluationsRootView.vue":{"44":[93],"91":[93],"101":[93],"118":[93]},"packages/@n8n/imap/src/errors.ts":{"5":[138],"18":[138],"24":[138]},"packages/@n8n/imap/src/helpers/get-message.ts":{"13":[138],"17":[138],"21":[138],"24":[138],"29":[138],"41":[138],"45":[138]},"packages/@n8n/imap/src/imap-simple.ts":{"12":[138],"16":[138],"21":[138],"27":[138],"35":[138],"39":[138],"57":[138],"65":[138],"66":[138],"87":[138],"94":[138],"98":[138],"104":[138],"111":[138],"122":[138],"128":[138],"134":[138],"146":[138],"152":[138],"157":[138],"167":[138],"173":[138],"174":[138],"179":[138],"180":[138],"181":[138],"186":[138],"190":[138],"191":[138],"196":[138],"200":[138],"201":[138]},"packages/@n8n/imap/src/index.ts":{"12":[138],"18":[138],"19":[138],"26":[138],"31":[138],"40":[138],"45":[138],"81":[138]},"packages/@n8n/imap/src/part-data.ts":{"8":[138],"10":[138],"14":[138],"41":[138],"47":[138],"55":[138],"59":[138],"65":[138],"72":[138],"78":[138]},"packages/@n8n/imap/src/uudecode.ts":{"9":[138]},"packages/cli/src/controllers/oauth/oauth1-credential.controller.ts":{"13":[138],"21":[138],"36":[138]},"packages/nodes-base/nodes/EmailReadImap/EmailReadImap.node.ts":{"8":[138]},"packages/nodes-base/nodes/EmailReadImap/v1/EmailReadImapV1.node.ts":{"24":[138],"222":[138],"231":[138],"271":[138],"285":[138],"290":[138],"310":[138],"320":[138],"329":[138],"344":[138],"441":[138],"500":[138],"510":[138],"529":[138],"561":[138],"585":[138],"586":[138],"617":[138],"628":[138]},"packages/nodes-base/nodes/EmailReadImap/v2/EmailReadImapV2.node.ts":{"200":[138],"209":[138],"261":[138],"291":[138],"300":[138],"320":[138],"331":[138],"334":[138],"347":[138],"365":[138],"384":[138],"430":[138],"442":[138],"448":[138],"469":[138],"472":[138],"483":[138],"502":[138],"525":[138]},"packages/nodes-base/nodes/EmailReadImap/v2/utils.ts":{"19":[138],"57":[138],"105":[138],"194":[138]},"packages/nodes-base/nodes/NextCloud/GenericFunctions.ts":{"14":[138]},"packages/nodes-base/nodes/NextCloud/NextCloud.node.ts":{"866":[138],"1068":[138],"1142":[138],"1150":[138],"1177":[138],"1185":[138],"1215":[138],"1223":[138],"1243":[138],"1248":[138],"1256":[138]},"packages/frontend/editor-ui/src/app/components/GoBackButton.vue":{"11":[138]},"packages/frontend/editor-ui/src/features/workflows/templates/components/TemplateDetails.vue":{"21":[138],"32":[138],"34":[138],"49":[138],"59":[138],"62":[138],"79":[138],"86":[138],"89":[138]},"packages/frontend/editor-ui/src/features/workflows/templates/setupTemplate.store.ts":{"39":[138],"56":[138],"60":[138],"80":[138],"98":[138],"115":[138],"128":[138],"149":[138],"176":[138]},"packages/frontend/editor-ui/src/features/workflows/templates/views/SetupWorkflowFromTemplateView.vue":{"22":[138],"25":[138],"26":[138],"28":[138],"49":[138],"57":[138],"79":[138],"89":[138],"109":[138],"135":[138],"143":[138],"151":[138]},"packages/frontend/editor-ui/src/features/workflows/templates/views/TemplatesCollectionView.vue":{"32":[138],"37":[138],"39":[138],"44":[138],"45":[138],"48":[138],"49":[138],"64":[138],"87":[138],"88":[138],"98":[138],"117":[138],"121":[138],"124":[138]},"packages/localhost-43789/assets/_plugin-vue_export-helper-Da88TEg1.js":{"2":[138]},"packages/localhost-43789/assets/chunk-CC9Q-vWm.js":{"8":[138],"9":[138],"10":[138],"19":[138],"23":[138],"29":[138],"33":[138],"34":[138]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/CredentialSelectorModal.vue":{"35":[38],"36":[38],"45":[38],"105":[38],"113":[38],"117":[38],"120":[38],"142":[38],"145":[38]}}} \ No newline at end of file diff --git a/.github/workflows/build-base-image.yml b/.github/workflows/build-base-image.yml index 0d33c50c0b5..bff25b729f5 100644 --- a/.github/workflows/build-base-image.yml +++ b/.github/workflows/build-base-image.yml @@ -29,7 +29,7 @@ jobs: # While we're on alpine 3.22 awaiting NODE-4184 (graphicsmagick → sharp # migration that unblocks 3.23), Node 26 base builds can't succeed. # Restore '26' to this matrix once 3.23 is back. - node_version: ['22', '24.15.0'] + node_version: ['22', '24.16.0'] steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 diff --git a/.github/workflows/ci-cla-check.yml b/.github/workflows/ci-cla-check.yml index 37448dfd8fe..747ef7e0383 100644 --- a/.github/workflows/ci-cla-check.yml +++ b/.github/workflows/ci-cla-check.yml @@ -39,7 +39,21 @@ permissions: statuses: write concurrency: - group: cla-check-${{ github.event.pull_request.number || github.event.issue.number || github.event.merge_group.head_sha || github.event.inputs.pr_number || github.ref }} + # Concurrency is evaluated BEFORE the job-level `if` below, so a comment that + # isn't `/cla-check` (e.g. a bot's "StageReview" comment) still creates a run. + # If that run shared the PR's group (issue number == PR number) it would, with + # cancel-in-progress, cancel the in-progress pull_request_target check — then + # get skipped by the `if` and do nothing, leaving the "CLA Check" status stuck + # on pending. Keep comment-triggered runs in their own group so they can only + # ever cancel each other, never the PR push check that gates the merge. PR + # pushes, merge_group and dispatch keep the head-based group (push debounce). + group: >- + cla-check-${{ github.event_name == 'issue_comment' + && format('comment-{0}', github.event.issue.number) + || github.event.pull_request.number + || github.event.merge_group.head_sha + || github.event.inputs.pr_number + || github.ref }} cancel-in-progress: true env: diff --git a/.github/workflows/ci-codeowners-validation.yml b/.github/workflows/ci-codeowners-validation.yml index 6afd8f1ab9a..6190f46c2d8 100644 --- a/.github/workflows/ci-codeowners-validation.yml +++ b/.github/workflows/ci-codeowners-validation.yml @@ -1,12 +1,12 @@ # .github/workflows/ci-codeowners-validation.yml -name: "CI: Validate CODEOWNERS" +name: 'CI: Validate CODEOWNERS' # Only run when CODEOWNERS or packages change on: pull_request: paths: - - ".github/CODEOWNERS" - - "packages/**" + - '.github/CODEOWNERS' + - 'packages/**' jobs: validate: @@ -19,5 +19,5 @@ jobs: # Start with safe checks only. Add "owners" and # experimental_checks: "notowned" once the file has settled # and skip patterns are configured. - checks: "files,duppatterns,syntax" - github_access_token: "${{ secrets.GITHUB_TOKEN }}" + checks: 'files,duppatterns,syntax' + github_access_token: '${{ secrets.GITHUB_TOKEN }}' diff --git a/.github/workflows/ci-instance-ai-evals.yml b/.github/workflows/ci-instance-ai-evals.yml index 89f6c367ada..26278bc4eb5 100644 --- a/.github/workflows/ci-instance-ai-evals.yml +++ b/.github/workflows/ci-instance-ai-evals.yml @@ -1,13 +1,25 @@ name: 'CI: Instance AI Evals' -# Auto-trigger disabled — run manually via workflow_dispatch. +# Auto-runs on PR open/reopen/ready (non-draft, path-filtered). Pushes don't +# re-trigger (no `synchronize`); use workflow_dispatch for manual runs. on: + pull_request: + types: [opened, reopened, ready_for_review] + paths: + - 'packages/@n8n/instance-ai/src/**' + - 'packages/@n8n/instance-ai/evaluations/**' + - 'packages/cli/src/modules/instance-ai/**' + - 'packages/core/src/execution-engine/eval-mock-helpers.ts' workflow_dispatch: inputs: branch: description: 'GitHub branch to test' required: false default: 'master' + tier: + description: 'Test-case dataset to run (e.g. `pr`, `full`)' + required: false + default: 'full' sandbox-provider: description: 'Sandbox provider (n8n-sandbox or daytona)' required: false @@ -28,11 +40,19 @@ concurrency: jobs: run-evals: name: Instance AI Workflow Evals - if: github.repository == 'n8n-io/n8n' + # Skip drafts; allow workflow_dispatch (no pull_request payload). + if: >- + github.repository == 'n8n-io/n8n' && + (github.event_name != 'pull_request' || github.event.pull_request.draft == false) uses: ./.github/workflows/test-evals-instance-ai.yml with: - branch: ${{ inputs.branch }} - sandbox-provider: ${{ inputs.sandbox-provider }} + # On PR events github.sha is the merge commit, so the eval tests the + # merged state (like e2e) and the checkout matches the key under which + # prepare-docker publishes the docker image cache. + branch: ${{ inputs.branch || github.sha }} + # PR events default to `pr`; dispatch defaults to `full`. + tier: ${{ inputs.tier || 'pr' }} + sandbox-provider: ${{ inputs.sandbox-provider || 'n8n-sandbox' }} iterations: ${{ inputs.iterations }} experiment-name: ${{ inputs.experiment-name }} secrets: inherit diff --git a/.github/workflows/ci-master.yml b/.github/workflows/ci-master.yml index e640f15333d..15b1e6a3307 100644 --- a/.github/workflows/ci-master.yml +++ b/.github/workflows/ci-master.yml @@ -30,11 +30,11 @@ jobs: strategy: fail-fast: false matrix: - node-version: [22.22.3, 24.15.0] + node-version: [22.22.3, 24.16.0] with: ref: ${{ github.sha }} nodeVersion: ${{ matrix.node-version }} - collectCoverage: ${{ matrix.node-version == '24.15.0' }} + collectCoverage: ${{ matrix.node-version == '24.16.0' }} secrets: inherit lint: diff --git a/.github/workflows/ci-owners-assign-reviewers.yml b/.github/workflows/ci-owners-assign-reviewers.yml new file mode 100644 index 00000000000..0bc017a38c9 --- /dev/null +++ b/.github/workflows/ci-owners-assign-reviewers.yml @@ -0,0 +1,60 @@ +name: 'CI: Owners Assign Reviewers' + +# Opt-in reviewer auto-assignment. +# +# When a PR carries the `Auto-assign reviewers` label, requests review from +# every team that owns a changed file (based on .github/OWNERS). Without the +# label this is a no-op — opting in is entirely up to the PR author. +# +# Assignment runs once: afterwards the trigger label is swapped for a +# `Reviewers auto-assigned` marker, and any PR already carrying that marker is +# skipped. This keeps later `synchronize` events from re-requesting the teams. +# +# Runs on `labeled` (so adding the label assigns immediately) and on +# `synchronize` (so newly-touched files still get assigned before the marker +# lands). The label checks live in the script, so other PRs exit early. + +on: + pull_request: + types: + - labeled + - synchronize + - reopened + branches: + - master + +jobs: + assign-reviewers: + name: Assign reviewers + # Skipped for: + # - PRs from forks (no token to assign with) + # - Bot-authored PRs (Dependabot, Renovate, etc.) + if: | + github.event.pull_request.head.repo.full_name == github.repository && + github.event.pull_request.user.type != 'Bot' + runs-on: ubuntu-latest + timeout-minutes: 5 + permissions: + contents: read + pull-requests: write + steps: + - name: Generate App Token + id: app-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 }} + + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + + - name: Setup Node.js + uses: ./.github/actions/setup-nodejs + with: + build-command: '' + install-command: pnpm install --frozen-lockfile --dir ./.github/scripts --ignore-workspace + + - name: Assign reviewer teams + env: + GITHUB_TOKEN: ${{ steps.app-token.outputs.token }} + PULL_REQUEST_NUMBER: ${{ github.event.pull_request.number }} + run: node .github/scripts/owners-assign-reviewers.mjs diff --git a/.github/workflows/ci-owners-review-recommendations.yml b/.github/workflows/ci-owners-review-recommendations.yml index f5ca25cfef8..aa9be8e386e 100644 --- a/.github/workflows/ci-owners-review-recommendations.yml +++ b/.github/workflows/ci-owners-review-recommendations.yml @@ -1,7 +1,8 @@ name: 'CI: Owners Review Recommendations' -# Posts (or updates) a PR comment recommending which @n8n-io teams should -# review the PR, based on file ownership defined in .github/OWNERS. +# Posts (or updates) a PR comment with recommended reviewer teams (based on +# file ownership in .github/OWNERS) and a breakdown of changed lines by +# category (source code, test files, misc). # # Advisory only — does not gate merging. diff --git a/.github/workflows/ci-pr-quality.yml b/.github/workflows/ci-pr-quality.yml index d34951a901f..688e876761e 100644 --- a/.github/workflows/ci-pr-quality.yml +++ b/.github/workflows/ci-pr-quality.yml @@ -44,39 +44,6 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: node .github/scripts/quality/handle-size-override.mjs - check-ownership-checkbox: - name: Ownership Acknowledgement - # Checks that the author has acknowledged the ownership of their code - # by checking the checkbox in the PR summary. - # Skipped for bot-authored PRs (Dependabot, Renovate, github-actions, Aikido, etc.). - # The required aggregator `required-pr-quality-checks` treats skipped as success. - if: | - github.event_name == 'pull_request' && - github.event.pull_request.head.repo.full_name == github.repository && - !contains(github.event.pull_request.labels.*.name, 'automation:backport') && - !contains(github.event.pull_request.title, '(backport to') && - github.event.pull_request.user.type != 'Bot' - runs-on: ubuntu-latest - timeout-minutes: 5 - permissions: - contents: read - issues: write - pull-requests: write - steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - - - name: Setup Node.js - uses: ./.github/actions/setup-nodejs - with: - build-command: '' - install-command: pnpm install --frozen-lockfile --dir ./.github/scripts --ignore-workspace - cache-dependency-path: .github/scripts/pnpm-lock.yaml - - - name: Check ownership checkbox - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: node .github/scripts/quality/check-ownership-checkbox.mjs - check-pr-size: name: PR Size Limit # Checks that the PR size doesn't exceed the limit (currently 1000 lines) @@ -160,7 +127,7 @@ jobs: required-pr-quality-checks: name: Required PR Quality Checks - needs: [check-ownership-checkbox, check-pr-size, check-static-analysis] + needs: [check-pr-size, check-static-analysis] if: always() runs-on: ubuntu-latest timeout-minutes: 5 @@ -174,4 +141,3 @@ jobs: with: mode: validate job-results: ${{ toJSON(needs) }} - diff --git a/.github/workflows/ci-pull-requests.yml b/.github/workflows/ci-pull-requests.yml index 5441cb9b104..905f5479979 100644 --- a/.github/workflows/ci-pull-requests.yml +++ b/.github/workflows/ci-pull-requests.yml @@ -95,7 +95,9 @@ jobs: packages/testing/playwright/package.json .github/workflows/test-dev-server-smoke-reusable.yml workflows: .github/** - workflow-scripts: .github/scripts/** + workflow-scripts: + .github/scripts/** + scripts/licenses/** performance: packages/testing/performance/** packages/workflow/src/** @@ -120,16 +122,26 @@ jobs: packages/cli/test/integration/** packages/cli/test/migration/** packages/cli/test/shared/db/** + packages/cli/test/setup-testcontainers.js + packages/cli/test/teardown-testcontainers.js + packages/cli/jest.config.integration.js + packages/cli/jest.config.integration.testcontainers.js + packages/cli/jest.config.migration.js + packages/cli/jest.config.migration.testcontainers.js packages/@n8n/db/** + packages/@n8n/backend-test-utils/** packages/cli/**/__tests__/** packages/testing/containers/services/postgres.ts .github/workflows/test-db-reusable.yml + docs/generated/** + .tbls.sqlite.yml + .tbls.postgres.yml - name: Setup and Build if: fromJSON(steps.ci-filter.outputs.results).ci || fromJSON(steps.ci-filter.outputs.results).e2e uses: ./.github/actions/setup-nodejs with: - build-command: ${{ fromJSON(steps.ci-filter.outputs.results).ci && 'pnpm build:unchecked' || 'pnpm turbo run build --filter=@n8n/playwright-janitor' }} + build-command: ${{ fromJSON(steps.ci-filter.outputs.results).ci && 'pnpm build' || 'pnpm turbo run build --filter=@n8n/playwright-janitor' }} - name: Run format check if: fromJSON(steps.ci-filter.outputs.results).ci @@ -174,6 +186,8 @@ jobs: if: needs.install-and-build.outputs.ci == 'true' runs-on: ${{ vars.RUNNER_PROVIDER == 'github' && 'ubuntu-latest' || 'blacksmith-4vcpu-ubuntu-2204' }} needs: install-and-build + env: + NODE_OPTIONS: --max-old-space-size=7168 steps: - uses: useblacksmith/checkout@41cdeedae8edb2e684ba22896a5fd2a3cb85db6b # v1 with: @@ -222,7 +236,8 @@ jobs: (needs.install-and-build.outputs.runtime == 'true' || needs.install-and-build.outputs.e2e == 'true' || needs.install-and-build.outputs.e2e_performance == 'true' - || contains(github.event.pull_request.labels.*.name, 'force-e2e')) + || contains(github.event.pull_request.labels.*.name, 'force-e2e') + || contains(github.event.pull_request.labels.*.name, 'run-perf-tests')) uses: ./.github/workflows/prepare-docker-reusable.yml with: branch: ${{ needs.install-and-build.outputs.commit_sha }} @@ -304,9 +319,13 @@ jobs: name: E2E Performance needs: [install-and-build, prepare-docker] # Performance is internal-only (license secrets required, not available on forks). + # Runs when path filter trips OR when the PR carries the `run-perf-tests` label + # (opt-in coverage for shared-utility / Vue Flow changes that the path filter + # would otherwise miss). if: >- needs.prepare-docker.result == 'success' && - needs.install-and-build.outputs.e2e_performance == 'true' && + (needs.install-and-build.outputs.e2e_performance == 'true' || + contains(github.event.pull_request.labels.*.name, 'run-perf-tests')) && github.event.pull_request.head.repo.fork != true uses: ./.github/workflows/test-e2e-performance-reusable.yml secrets: inherit @@ -387,5 +406,5 @@ jobs: if: always() uses: ./.github/workflows/util-qa-metrics-comment-reusable.yml with: - metrics: memory-heap-used-baseline,memory-rss-baseline,instance-ai-heap-used-baseline,instance-ai-rss-baseline,agents-heap-used-baseline,agents-rss-baseline,docker-image-size-n8n,docker-image-size-runners + metrics: memory-heap-used-baseline,memory-rss-baseline,instance-ai-heap-used-baseline,instance-ai-rss-baseline,agents-heap-used-baseline,agents-rss-baseline,docker-image-size-n8n,docker-image-size-runners,canvas-cold-load-S-ms,canvas-cold-load-M-ms,canvas-cold-load-L-ms,canvas-server-heap-M-mb,canvas-server-heap-L-mb,canvas-browser-heap-M-mb,canvas-browser-heap-L-mb,canvas-pan-frame-p95-M-ms,canvas-pan-frame-p95-L-ms,canvas-tidy-up-M-ms,canvas-tidy-up-L-ms,canvas-exec-heavy-M-ms,canvas-exec-heavy-L-ms secrets: inherit diff --git a/.github/workflows/clean-stale-branches.yml b/.github/workflows/clean-stale-branches.yml index 3d36614e57a..c89adb63e58 100644 --- a/.github/workflows/clean-stale-branches.yml +++ b/.github/workflows/clean-stale-branches.yml @@ -2,7 +2,7 @@ name: 'Util: Clean Stale Branches' on: schedule: - - cron: "0 10 * * 1" # Every monday + - cron: '0 10 * * 1' # Every monday workflow_dispatch: inputs: dry-run: diff --git a/.github/workflows/docker-build-push.yml b/.github/workflows/docker-build-push.yml index 0366a705200..2fcf869b211 100644 --- a/.github/workflows/docker-build-push.yml +++ b/.github/workflows/docker-build-push.yml @@ -7,7 +7,7 @@ name: 'Docker: Build and Push' env: NODE_OPTIONS: '--max-old-space-size=7168' - NODE_VERSION: '24.15.0' + NODE_VERSION: '24.16.0' on: schedule: @@ -421,6 +421,65 @@ jobs: --predicate security/vex.openvex.json \ ${{ needs.create_multi_arch_manifest.outputs.runners_distroless_image }}@${{ needs.create_multi_arch_manifest.outputs.runners_distroless_digest }} + # SBOM Attestation - one enriched, license-gated CycloneDX SBOM per image. + # cdxgen scans the image (OS + npm), enrich-sbom resolves first-party + override + # licenses, check-sbom-licenses gates the npm components, and the result is + # attested to the image digest via cosign (same mechanism as VEX/provenance). + # This replaces BuildKit's `sbom: true` so the image carries the same resolved + # license picture as the release SBOM rather than the un-enriched syft output. + sbom-attestation: + name: SBOM Attestation + needs: + [ + determine-build-context, + build-and-push-docker, + create_multi_arch_manifest, + provenance-n8n, + provenance-runners, + provenance-runners-distroless, + ] + if: | + always() && + needs.create_multi_arch_manifest.result == 'success' && + (needs.determine-build-context.outputs.release_type == 'stable' || + needs.determine-build-context.outputs.release_type == 'rc' || + needs.determine-build-context.outputs.release_type == 'nightly') + runs-on: ubuntu-latest + timeout-minutes: 30 + permissions: + id-token: write + packages: write + steps: + - name: Checkout + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + + - name: Setup Node.js and install SBOM tooling + uses: ./.github/actions/setup-nodejs + with: + build-command: '' + install-command: pnpm install --frozen-lockfile --dir ./.github/scripts --ignore-workspace + cache-dependency-path: .github/scripts/pnpm-lock.yaml + + - name: Install Cosign + uses: sigstore/cosign-installer@7e8b541eb2e61bf99390e1afd4be13a184e9ebc5 # v3.10.1 + + - name: Login to GHCR + uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4.0.0 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Generate, enrich, gate and attest SBOM per image + env: + N8N_IMAGE: ${{ needs.create_multi_arch_manifest.outputs.n8n_image }} + N8N_DIGEST: ${{ needs.create_multi_arch_manifest.outputs.n8n_digest }} + RUNNERS_IMAGE: ${{ needs.create_multi_arch_manifest.outputs.runners_image }} + RUNNERS_DIGEST: ${{ needs.create_multi_arch_manifest.outputs.runners_digest }} + DISTROLESS_IMAGE: ${{ needs.create_multi_arch_manifest.outputs.runners_distroless_image }} + DISTROLESS_DIGEST: ${{ needs.create_multi_arch_manifest.outputs.runners_distroless_digest }} + run: node .github/scripts/attest-image-sbom.mjs + security-scan: name: Security Scan needs: [determine-build-context, build-and-push-docker, create_multi_arch_manifest] diff --git a/.github/workflows/mutation-health-nightly.yml b/.github/workflows/mutation-health-nightly.yml index 83a964d448b..fd5e3858439 100644 --- a/.github/workflows/mutation-health-nightly.yml +++ b/.github/workflows/mutation-health-nightly.yml @@ -14,6 +14,10 @@ on: - baseline # score files with no result yet (the `new` bucket) - coverage # revisit the weakest scored files (`red`/`stale`, lowest first) default: both + source_file: + description: 'Optional: re-score this exact repo-relative file, skipping the picker (e.g. packages/workflow/src/common/get-node-by-name.ts). Used by the lane:mutation-increase close handler to refresh the ledger.' + type: string + default: '' permissions: contents: read @@ -36,6 +40,7 @@ jobs: id: build env: REQUESTED_MODE: ${{ github.event.inputs.mode || 'both' }} + SOURCE_FILE: ${{ github.event.inputs.source_file || '' }} # vitest packages only. A package with its own stryker.config.mjs overrides # the shared default (scripts/mutation-health/stryker.default.mjs) — n8n-workflow # does this to run the legacy expression engine and dodge the isolated-vm @@ -48,9 +53,17 @@ jobs: { name: "@n8n/crdt", dir: "packages/@n8n/crdt", slug: "crdt" }, { name: "@n8n/decorators", dir: "packages/@n8n/decorators", slug: "decorators" }, ]; - const req = process.env.REQUESTED_MODE; - const modes = req === "both" ? ["baseline", "coverage"] : [req]; - const include = packages.flatMap((p) => modes.map((mode) => ({ ...p, mode }))); + const sourceFile = (process.env.SOURCE_FILE || "").trim(); + let include; + if (sourceFile) { + const pkg = packages.find((p) => sourceFile.startsWith(p.dir + "/")); + if (!pkg) throw new Error("No mutation-tracked package owns " + sourceFile); + include = [{ ...pkg, mode: "file", source_file: sourceFile }]; + } else { + const req = process.env.REQUESTED_MODE; + const modes = req === "both" ? ["baseline", "coverage"] : [req]; + include = packages.flatMap((p) => modes.map((mode) => ({ ...p, mode }))); + } console.log("matrix=" + JSON.stringify({ include })); ' >> "$GITHUB_OUTPUT" @@ -72,6 +85,7 @@ jobs: PKG_DIR: ${{ matrix.dir }} MODE: ${{ matrix.mode }} REPORTS_DIR: ${{ matrix.dir }}/reports/mutation + SOURCE_FILE: ${{ matrix.source_file || '' }} steps: - name: Checkout uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 @@ -90,6 +104,12 @@ jobs: - name: Pick next source file id: pick run: | + if [ -n "$SOURCE_FILE" ]; then + echo "::notice::On-demand re-score of $SOURCE_FILE (picker skipped)." + echo "skip=false" >> "$GITHUB_OUTPUT" + echo "source-rel=${SOURCE_FILE#"$PKG_DIR"/}" >> "$GITHUB_OUTPUT" + exit 0 + fi picked_json=$(node scripts/mutation-health/pick-next.mjs \ --package-dir "$PKG_DIR" \ --ledger-file "$REPORTS_DIR/live-ledger.json" \ @@ -108,11 +128,12 @@ jobs: - name: Mutate the picked source file if: steps.pick.outputs.skip != 'true' # Exit code semantics from mutate.mjs: - # 0 — score >= threshold (green) - # 1 — score < threshold (red) — emit step still runs, this is normal + # 0 — gate passed: score >= threshold AND no unjustified survivors (green) + # 1 — gate failed: score < threshold OR >=1 Survived/NoCoverage mutant (red) + # — emit step still runs, this is normal # 2 — usage error # 3 — Stryker hard failure (no summary.json) — must fail the job - # We capture rc explicitly so we can distinguish "below threshold" from + # We capture rc explicitly so we can distinguish "gate failed" from # "Stryker crashed." continue-on-error: true would collapse them. run: | set +e diff --git a/.github/workflows/release-create-patch-pr.yml b/.github/workflows/release-create-patch-pr.yml index 70061838aff..27b4881422c 100644 --- a/.github/workflows/release-create-patch-pr.yml +++ b/.github/workflows/release-create-patch-pr.yml @@ -8,6 +8,11 @@ on: description: 'Release Track' required: true type: string + force: + description: 'Create the PR even when there are no actionable commits' + required: false + type: boolean + default: false workflow_dispatch: inputs: @@ -16,6 +21,11 @@ on: required: true type: choice options: [stable, beta, v1] + force: + description: 'Create the PR even when there are no actionable commits' + required: false + type: boolean + default: true jobs: determine-version-info: @@ -23,7 +33,7 @@ jobs: runs-on: ubuntu-latest outputs: release_candidate_branch: ${{ steps.determine-branch.outputs.release_candidate_branch }} - should_update: ${{ steps.determine-branch.outputs.should_update }} + should_create_pr: ${{ steps.determine-branch.outputs.should_create_pr }} steps: - name: Checkout uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 @@ -41,12 +51,13 @@ jobs: id: determine-branch env: TRACK: ${{ inputs.track }} + FORCE: ${{ inputs.force }} run: node .github/scripts/determine-release-candidate-branch-for-track.mjs skip-release-pr: name: Skip release PR (no new commits) needs: [determine-version-info] - if: needs.determine-version-info.outputs.should_update != 'true' + if: needs.determine-version-info.outputs.should_create_pr != 'true' runs-on: ubuntu-latest steps: - name: Log skip reason @@ -55,7 +66,7 @@ jobs: create-release-pr: name: Create release PR needs: [determine-version-info] - if: needs.determine-version-info.outputs.should_update == 'true' + if: needs.determine-version-info.outputs.should_create_pr == 'true' uses: ./.github/workflows/release-create-pr.yml secrets: inherit with: diff --git a/.github/workflows/release-create-pr.yml b/.github/workflows/release-create-pr.yml index 75f65015db4..9eaf3660f16 100644 --- a/.github/workflows/release-create-pr.yml +++ b/.github/workflows/release-create-pr.yml @@ -128,7 +128,7 @@ jobs: branch: 'release-pr/${{ env.NEXT_RELEASE }}' commit-message: ':rocket: Release ${{ env.NEXT_RELEASE }}' delete-branch: true - labels: release,release:${{ inputs.release-type }} + labels: release,release:${{ inputs.release-type }},automation:release title: ':rocket: Release ${{ env.NEXT_RELEASE }}' body: ${{ steps.generate-body.outputs.content }} diff --git a/.github/workflows/release-publish.yml b/.github/workflows/release-publish.yml index aa14b6ac9c7..8861da8c784 100644 --- a/.github/workflows/release-publish.yml +++ b/.github/workflows/release-publish.yml @@ -43,7 +43,7 @@ jobs: needs: [determine-version-info] runs-on: ubuntu-latest if: github.event.pull_request.merged == true - timeout-minutes: 20 + timeout-minutes: 30 environment: npm permissions: id-token: write diff --git a/.github/workflows/release-push-to-channel.yml b/.github/workflows/release-push-to-channel.yml index 528b57bf74e..25e48fe7fe9 100644 --- a/.github/workflows/release-push-to-channel.yml +++ b/.github/workflows/release-push-to-channel.yml @@ -75,7 +75,7 @@ jobs: steps: - uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 with: - node-version: 24.15.0 + node-version: 24.16.0 # Remove after https://github.com/npm/cli/issues/8547 gets resolved - run: echo "//registry.npmjs.org/:_authToken=${NPM_TOKEN}" > ~/.npmrc diff --git a/.github/workflows/release-schedule-patch-prs.yml b/.github/workflows/release-schedule-patch-prs.yml index dda26312b0b..b41526258ff 100644 --- a/.github/workflows/release-schedule-patch-prs.yml +++ b/.github/workflows/release-schedule-patch-prs.yml @@ -15,3 +15,4 @@ jobs: secrets: inherit with: track: ${{ matrix.track }} + force: ${{ github.event_name == 'workflow_dispatch' }} diff --git a/.github/workflows/sbom-generation-callable.yml b/.github/workflows/sbom-generation-callable.yml index b3a6d2692ee..2ac911c2c11 100644 --- a/.github/workflows/sbom-generation-callable.yml +++ b/.github/workflows/sbom-generation-callable.yml @@ -56,6 +56,16 @@ jobs: # produce sbom-source.cdx.json + packages/cli/THIRD_PARTY_LICENSES.md. N8N_GENERATE_LICENSES: 'true' + # Release-blocking gate. build:deploy already enriches + gates the SBOM via + # the generate-licenses pipeline; re-run the gate here as an explicit, + # un-skippable check on the exact artifact we are about to attest, so an + # unlicensed or non-SPDX component can never reach the signed attestation. + - name: Gate SBOM on resolved SPDX licenses + run: | + node scripts/licenses/check-sbom-licenses.mjs \ + sbom-source.cdx.json \ + --allow-ref=LicenseRef-n8n-sustainable-use --allow-ref=LicenseRef-n8n-enterprise + - name: Attest SBOM for release uses: actions/attest@59d89421af93a897026c735860bf21b6eb4f7b26 # v4.1.0 with: @@ -74,11 +84,10 @@ jobs: --clobber COMPONENT_COUNT=$(jq '.components | length' sbom-source.cdx.json 2>/dev/null || echo "unknown") - MISSING_LICENSES=$(jq '[.components[] | select((.licenses // []) | length == 0)] | length' sbom-source.cdx.json 2>/dev/null || echo "unknown") VEX_STATEMENTS=$(jq '.statements | length' security/vex.openvex.json 2>/dev/null || echo "0") echo "SBOM, VEX, and license manifest attached to release" echo " - SBOM: $COMPONENT_COUNT components from shipped artifact (no devDeps, no optional deps)" - echo " - SBOM: $MISSING_LICENSES components missing license metadata" + echo " - SBOM: all components carry a resolved SPDX license (gated before attest)" echo " - VEX: $VEX_STATEMENTS CVE statements" echo " - THIRD_PARTY_LICENSES.md: rendered from SBOM (same artefact served by /third-party-licenses endpoint)" diff --git a/.github/workflows/security-trivy-scan-callable.yml b/.github/workflows/security-trivy-scan-callable.yml index 369f47e5cc8..3deab7429cd 100644 --- a/.github/workflows/security-trivy-scan-callable.yml +++ b/.github/workflows/security-trivy-scan-callable.yml @@ -13,16 +13,10 @@ on: type: string description: 'Full image reference to scan e.g. ghcr.io/n8n-io/n8n:latest' required: true - secrets: - QBOT_SLACK_TOKEN: - required: true permissions: contents: read -env: - SLACK_CHANNEL_ID: C0AHNJU9XFA #updates-security - jobs: security_scan: name: Security - Scan Docker Image With Trivy @@ -36,7 +30,6 @@ jobs: security/trivy.yaml security/trivy-ignore-policy.rego .github/scripts/retry.mjs - .github/scripts/slack sparse-checkout-cone-mode: false - name: Pull Docker image with retry @@ -165,17 +158,3 @@ jobs: echo "🔍 **View detailed logs above for full analysis**" } >> "$GITHUB_STEP_SUMMARY" fi - - - name: Send Slack notification - if: steps.process_results.outputs.vulnerabilities_found == 'true' - env: - SLACK_TOKEN: ${{ secrets.QBOT_SLACK_TOKEN }} - IMAGE_REF: ${{ inputs.image_ref }} - run: | - node .github/scripts/slack/notify.mjs \ - --channel "$SLACK_CHANNEL_ID" \ - --text "🚨 Trivy Scan: ${{ steps.process_results.outputs.critical_count }} Critical, ${{ steps.process_results.outputs.high_count }} High, ${{ steps.process_results.outputs.medium_count }} Medium, ${{ steps.process_results.outputs.low_count }} Low vulnerabilities found in $IMAGE_REF" \ - --blocks trivy \ - --results trivy-results.json \ - --image-ref "$IMAGE_REF" - diff --git a/.github/workflows/test-db-reusable.yml b/.github/workflows/test-db-reusable.yml index 96392052e8d..86987fa7b51 100644 --- a/.github/workflows/test-db-reusable.yml +++ b/.github/workflows/test-db-reusable.yml @@ -24,11 +24,17 @@ jobs: runner: blacksmith-4vcpu-ubuntu-2204 test-cmd: pnpm test:sqlite migration-cmd: pnpm test:sqlite:migrations + schema-check-cmd: pnpm --filter=@n8n/db schema:check:sqlite collectCoverage: 'false' - name: Postgres 16 - runner: blacksmith-8vcpu-ubuntu-2204 + # 4vcpu is enough since persistent-worker + template-DB make PG16 + # complete in ~480s, which is now close to the SQLite leg (~360s) + # — the matrix wall is bounded by the slower leg, so the larger + # 8vcpu runner buys headroom we can't cash in anywhere. + runner: blacksmith-4vcpu-ubuntu-2204 test-cmd: pnpm test:postgres:integration:tc migration-cmd: pnpm test:postgres:migrations:tc + schema-check-cmd: pnpm --filter=@n8n/db schema:check:postgres TEST_IMAGE_POSTGRES: 'postgres:16' collectCoverage: 'true' env: @@ -54,6 +60,12 @@ jobs: working-directory: packages/cli run: ${{ matrix.migration-cmd }} + # Regenerates the schema docs for this leg's database (sqlite temp file / + # postgres testcontainer) and fails if they differ from what's committed. + # tbls runs as a Docker image in CI. + - name: Verify schema docs are up to date + run: ${{ matrix.schema-check-cmd }} + - name: Upload coverage to Codecov if: env.COVERAGE_ENABLED == 'true' uses: codecov/codecov-action@671740ac38dd9b0130fbe1cec585b89eea48d3de # v5.5.2 @@ -61,5 +73,5 @@ jobs: token: ${{ secrets.CODECOV_TOKEN }} flags: backend-integration-postgres name: backend-integration-postgres - files: ./packages/cli/coverage/cobertura-coverage.xml + files: ./packages/cli/coverage/lcov.info fail_ci_if_error: false diff --git a/.github/workflows/test-e2e-coverage-nightly.yml b/.github/workflows/test-e2e-coverage-nightly.yml index 7fd2212b58d..345091319fa 100644 --- a/.github/workflows/test-e2e-coverage-nightly.yml +++ b/.github/workflows/test-e2e-coverage-nightly.yml @@ -10,6 +10,19 @@ concurrency: cancel-in-progress: true jobs: + # Shared build so the Turbo remote cache is warm before any test job starts. + # Downstream jobs call setup-nodejs with the default build-command and get + # ~30s cache hits rather than racing to build in parallel from cold. + build: + name: Install & Build + runs-on: blacksmith-4vcpu-ubuntu-2204 + steps: + - name: Checkout + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + + - name: Setup and Build + uses: ./.github/actions/setup-nodejs + prepare-docker: name: Prepare Docker (coverage) uses: ./.github/workflows/prepare-docker-reusable.yml @@ -24,6 +37,7 @@ jobs: # then blew past the timeout; duration-weighting keeps every shard even. generate-matrix: name: Generate shard matrix + needs: build runs-on: blacksmith-2vcpu-ubuntu-2204 outputs: matrix: ${{ steps.gen.outputs.matrix }} @@ -31,15 +45,15 @@ jobs: - name: Checkout uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - - name: Setup and Build janitor + - name: Setup uses: ./.github/actions/setup-nodejs with: build-command: pnpm turbo run build --filter=@n8n/playwright-janitor - - name: Generate matrix (8 shards, duration-weighted) + - name: Generate matrix (16 shards, duration-weighted) id: gen run: | - MATRIX=$(node packages/testing/playwright/scripts/distribute-tests.mjs --matrix 8 --orchestrate) + MATRIX=$(node packages/testing/playwright/scripts/distribute-tests.mjs --matrix 16 --orchestrate) echo "matrix=$MATRIX" >> "$GITHUB_OUTPUT" e2e: @@ -60,9 +74,116 @@ jobs: currents-project-id: 'LRxcNt' secrets: inherit + # Unit + integration coverage, one leg per suite — no change-scoping, run in + # parallel with the E2E shards (the shared `build` job keeps Turbo cache warm). + # The integration leg adds a Postgres pre-pull and runs from packages/cli to + # reach branches a mocked DB can't (real query paths, multi-main, migrations). + unit-coverage: + name: ${{ matrix.name }} + needs: build + runs-on: blacksmith-4vcpu-ubuntu-2204 + strategy: + fail-fast: false + matrix: + include: + - name: Unit Coverage (backend + nodes) + artifact: unit-coverage + test-command: pnpm test:ci:backend:unit + artifact-path: packages/**/coverage/lcov.info + - name: Unit Coverage (frontend) + artifact: frontend-coverage + test-command: pnpm test:ci:frontend + artifact-path: packages/**/coverage/lcov.info + - name: Unit Coverage (CLI integration + Postgres) + artifact: integration-coverage + test-command: pnpm test:postgres:integration:tc + # Glob (not the single file) so the artifact keeps its packages/<pkg>/ + # path, which aggregate-coverage.mjs uses to qualify SF: keys. + artifact-path: packages/**/coverage/lcov.info + working-directory: packages/cli + pre-pull-containers: true + env: + COVERAGE_ENABLED: 'true' + NODE_OPTIONS: --max-old-space-size=7168 + steps: + - name: Checkout + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + + - name: Setup + uses: ./.github/actions/setup-nodejs + + - name: Pre-pull Test Container Images + if: matrix.pre-pull-containers + run: pnpm tsx packages/testing/containers/pull-test-images.ts || true + + - name: Run tests + working-directory: ${{ matrix.working-directory || github.workspace }} + run: ${{ matrix.test-command }} + + - name: Upload coverage artifact + if: always() + uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 + with: + name: ${{ matrix.artifact }} + path: ${{ matrix.artifact-path }} + retention-days: 3 + + # Both Python packages in one job — they're fast and share the uv install + # (each still pins its own Python version: 3.13 task-runner, 3.11 evals). + python-coverage: + name: Python Coverage (task-runner + ai-workflow-builder) + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + + - name: Install uv + uses: astral-sh/setup-uv@6ee6290f1cbc4156c0bdd66691b2c144ef8df19a # v7.4.0 + with: + enable-cache: true + + - name: Install just + uses: extractions/setup-just@e33e0265a09d6d736e2ee1e0eb685ef1de4669ff # v3.0.0 + + - name: Install Python 3.13 (task-runner) + working-directory: packages/@n8n/task-runner-python + run: uv python install 3.13 + + - name: Install task-runner dependencies + working-directory: packages/@n8n/task-runner-python + run: just sync-all + + - name: Test task-runner-python + working-directory: packages/@n8n/task-runner-python + run: uv run pytest --cov=src --cov-report=xml --cov-report=term-missing + + - name: Install Python 3.11 (ai-workflow-builder evals) + working-directory: packages/@n8n/ai-workflow-builder.ee/evaluations/programmatic/python + run: uv python install 3.11 + + - name: Install ai-workflow-builder eval dependencies + working-directory: packages/@n8n/ai-workflow-builder.ee/evaluations/programmatic/python + run: just sync-all + + - name: Test ai-workflow-builder evals + working-directory: packages/@n8n/ai-workflow-builder.ee/evaluations/programmatic/python + run: uv run pytest --cov=src --cov-report=xml --cov-report=term-missing + + - name: Upload Python Coverage to Codecov + if: always() + uses: codecov/codecov-action@671740ac38dd9b0130fbe1cec585b89eea48d3de # v5.5.2 + with: + token: ${{ secrets.CODECOV_TOKEN }} + files: | + packages/@n8n/task-runner-python/coverage.xml + packages/@n8n/ai-workflow-builder.ee/evaluations/programmatic/python/coverage.xml + flags: nightly-python + name: nightly-python-coverage + fail_ci_if_error: false + aggregate: name: Aggregate Coverage - needs: e2e + needs: [e2e, unit-coverage, python-coverage] if: always() && needs.e2e.result != 'skipped' && needs.e2e.result != 'cancelled' runs-on: blacksmith-4vcpu-ubuntu-2204 steps: @@ -72,21 +193,34 @@ jobs: - name: Setup Environment uses: ./.github/actions/setup-nodejs - - name: Download shard artifacts + - name: Download E2E shard artifacts uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0 with: pattern: coverage-shard-* path: /tmp/shards/ - - name: Build janitor (tested merge-coverage) + # No merge-multiple: packages/cli/coverage/lcov.info exists in both + # unit-coverage and integration-coverage — separate artifact subdirs + # prevent clobbering, and findFiles recurses into all of them so MCR + # unions unit + integration coverage for CLI correctly. + - name: Download unit + integration + frontend coverage artifacts + uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0 + with: + pattern: '*-coverage' + path: /tmp/unit-lcovs/ + + - name: Build janitor (merge-coverage) run: pnpm turbo run build --filter=@n8n/playwright-janitor - # Report (shard lcovs → unified lcov) + impact map (per-spec lcovs → - # spec-keyed map), both via the property-tested janitor merge-coverage. - # Logic lives in the tested aggregate-coverage.mjs, not inline bash. + # Merges all lcovs into one lcov.info (SF: paths normalised to repo-root- + # relative) and builds the per-spec E2E impact map for PR selection. - name: Aggregate coverage + build impact map working-directory: packages/testing/playwright - run: node scripts/aggregate-coverage.mjs --shards=/tmp/shards --out=coverage + run: | + node scripts/aggregate-coverage.mjs \ + --shards=/tmp/shards \ + --unit-shards=/tmp/unit-lcovs \ + --out=coverage - name: Upload Coverage Report Artifact if: always() @@ -96,14 +230,14 @@ jobs: path: packages/testing/playwright/coverage/ retention-days: 14 - - name: Upload E2E Coverage to Codecov + - name: Upload Combined Coverage to Codecov if: always() uses: codecov/codecov-action@671740ac38dd9b0130fbe1cec585b89eea48d3de # v5.5.2 with: token: ${{ secrets.CODECOV_TOKEN }} files: packages/testing/playwright/coverage/lcov.info - flags: frontend-e2e - name: playwright-e2e + flags: nightly-full + name: nightly-full-coverage fail_ci_if_error: false # Codecov needs ~60-90s to finish indexing the fresh upload before its diff --git a/.github/workflows/test-e2e-performance-reusable.yml b/.github/workflows/test-e2e-performance-reusable.yml index d84182548ec..adc1a93c200 100644 --- a/.github/workflows/test-e2e-performance-reusable.yml +++ b/.github/workflows/test-e2e-performance-reusable.yml @@ -21,3 +21,35 @@ jobs: currents-project-id: 'O9BJaN' artifact-prefix: performance secrets: inherit + + canvas-perf-sentinels: + name: Canvas Perf Sentinels + # Sentinels are nightly only — wall-clock browser perf has 15-30% variance, + # so gating PR runs on these would produce false-positive blockers. + if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' + needs: build-and-test-performance + runs-on: ubuntu-slim + permissions: + contents: read + steps: + - name: Checkout + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + sparse-checkout: packages/testing/playwright/scripts/canvas-perf-sentinels.mjs + sparse-checkout-cone-mode: false + + - name: Download performance shard artifacts + uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 + with: + pattern: performance-shard-* + path: performance-artifacts + merge-multiple: true + + - name: Run canvas perf sentinels + run: | + RESULTS_PATH=$(find performance-artifacts -name 'test-results.json' -print -quit) + if [ -z "$RESULTS_PATH" ]; then + echo "::warning::No test-results.json found in performance artifacts — sentinel skipped." + exit 0 + fi + node packages/testing/playwright/scripts/canvas-perf-sentinels.mjs "$RESULTS_PATH" diff --git a/.github/workflows/test-e2e-reusable.yml b/.github/workflows/test-e2e-reusable.yml index 8870ae1a921..bfabbc5dc8d 100644 --- a/.github/workflows/test-e2e-reusable.yml +++ b/.github/workflows/test-e2e-reusable.yml @@ -123,8 +123,15 @@ jobs: - name: Run Tests run: | + # --pass-with-no-tests makes Playwright exit 0 when the selected specs + # resolve to zero runnable tests. Covers the impact-map vs current-suite + # skew window: a spec the committed coverage map points at may have been + # quarantined (test.skip/fixme) since the map was built, or a capability + # --grep on the test-command may filter every test on a shard. The + # selector is doing the right thing; the run shouldn't treat "nothing + # to run" as failure. # shellcheck disable=SC2086 - $TEST_COMMAND --workers="$WORKERS" $SHARD_ARGS + $TEST_COMMAND --workers="$WORKERS" $SHARD_ARGS --pass-with-no-tests env: # Protect args from template injections TEST_COMMAND: ${{ inputs.test-command }} @@ -149,9 +156,12 @@ jobs: name: ${{ inputs.artifact-prefix }}-shard-${{ matrix.shard }} path: | packages/testing/playwright/test-results/ + packages/testing/playwright/test-results.json packages/testing/playwright/playwright-report/ packages/testing/playwright/coverage/lcov.info packages/testing/playwright/coverage/by-spec/ + packages/testing/playwright/coverage/index.html + packages/testing/playwright/coverage/assets/ retention-days: 1 if-no-files-found: ignore diff --git a/.github/workflows/test-evals-discovery.yml b/.github/workflows/test-evals-discovery.yml index 814fb0819ac..a7fe2a7970b 100644 --- a/.github/workflows/test-evals-discovery.yml +++ b/.github/workflows/test-evals-discovery.yml @@ -38,6 +38,8 @@ jobs: name: 'Run Discovery Evals' runs-on: blacksmith-4vcpu-ubuntu-2204 timeout-minutes: 15 + env: + NODE_OPTIONS: '--max-old-space-size=7168' permissions: contents: read pull-requests: write diff --git a/.github/workflows/test-evals-instance-ai.yml b/.github/workflows/test-evals-instance-ai.yml index a13ada506df..f13737224f1 100644 --- a/.github/workflows/test-evals-instance-ai.yml +++ b/.github/workflows/test-evals-instance-ai.yml @@ -9,7 +9,12 @@ on: type: string default: 'master' filter: - description: 'Filter test cases by name (e.g. "contact-form")' + description: 'Filter test cases by filename substring (e.g. "contact-form")' + required: false + type: string + default: '' + tier: + description: 'Test-case dataset to run (e.g. "pr", "full"). Empty = no filter.' required: false type: string default: '' @@ -35,7 +40,11 @@ on: required: false default: 'master' filter: - description: 'Filter test cases by name (e.g. "contact-form")' + description: 'Filter test cases by filename substring (e.g. "contact-form")' + required: false + default: '' + tier: + description: 'Test-case dataset to run (e.g. "pr", "full"). Empty = no filter.' required: false default: '' sandbox-provider: @@ -76,18 +85,12 @@ jobs: with: build-command: 'pnpm build' - # Cache populated by prepare-docker; fallback covers PRs that only touch this workflow file. + # Cache populated by prepare-docker; on a miss (e.g. fresh PR-open runs + # that outpace prepare-docker) the action itself falls back to a rebuild + # via build-n8n-docker. - name: Load n8n Docker image - id: load-image - continue-on-error: true uses: ./.github/actions/load-n8n-docker - - name: Build Docker image (fallback on cache miss) - if: steps.load-image.outcome == 'failure' - run: pnpm build:docker - env: - INCLUDE_TEST_CONTROLLER: 'true' - - name: Start sandbox service if: ${{ inputs.sandbox-provider == 'n8n-sandbox' }} run: pnpm --filter n8n-containers services --services sandbox --network n8n-eval-net --name n8n-svc-sandbox @@ -99,7 +102,8 @@ jobs: N8N_LICENSE_CERT: ${{ secrets.N8N_LICENSE_CERT }} N8N_ENCRYPTION_KEY: ${{ secrets.N8N_ENCRYPTION_KEY }} DAYTONA_API_KEY: ${{ secrets.DAYTONA_API_KEY }} - SANDBOX_NAME_PREFIX: evals-ci-${{ inputs.branch || github.ref_name }} + # Prefer head_ref: inputs.branch may be a merge ref (refs/pull/N/merge). + SANDBOX_NAME_PREFIX: evals-ci-${{ github.head_ref || inputs.branch || github.ref_name }} SANDBOX_PROVIDER: ${{ inputs.sandbox-provider || 'n8n-sandbox' }} run: | # Build provider-specific env args @@ -223,6 +227,7 @@ jobs: LANGSMITH_REVISION_ID: ${{ github.sha }} LANGSMITH_BRANCH: ${{ github.event.pull_request.head.ref || github.head_ref || github.ref_name }} FILTER: ${{ inputs.filter }} + TIER: ${{ inputs.tier }} ITERATIONS: ${{ inputs.iterations }} EXPERIMENT_NAME: ${{ inputs.experiment-name }} run: | @@ -234,6 +239,7 @@ jobs: BASE_URLS=$(IFS=,; printf '%s' "${URLS[*]}") ARGS=(--base-url "$BASE_URLS" --concurrency 32 --verbose --iterations "${ITERATIONS:-3}") [ -n "$FILTER" ] && ARGS+=(--filter "$FILTER") + [ -n "$TIER" ] && ARGS+=(--tier "$TIER") [ -n "$EXPERIMENT_NAME" ] && ARGS+=(--experiment-name "$EXPERIMENT_NAME") pnpm eval:instance-ai "${ARGS[@]}" diff --git a/.github/workflows/test-linting-reusable.yml b/.github/workflows/test-linting-reusable.yml index 41b1a34c7ac..1657c59672b 100644 --- a/.github/workflows/test-linting-reusable.yml +++ b/.github/workflows/test-linting-reusable.yml @@ -12,7 +12,7 @@ on: description: Version of node to use. required: false type: string - default: 24.15.0 + default: 24.16.0 env: NODE_OPTIONS: --max-old-space-size=7168 diff --git a/.github/workflows/test-unit-reusable.yml b/.github/workflows/test-unit-reusable.yml index 4b7a2521856..80eddd53ce9 100644 --- a/.github/workflows/test-unit-reusable.yml +++ b/.github/workflows/test-unit-reusable.yml @@ -12,7 +12,7 @@ on: description: Version of node to use. required: false type: string - default: 24.15.0 + default: 24.16.0 collectCoverage: required: false default: false @@ -59,8 +59,10 @@ jobs: # the workspace bulk run excludes it and a dedicated step invokes the # scoped variant. This avoids turbo silently no-op'ing `test:unit:changed` # for every backend package that hasn't yet added the script. - - name: Test Unit (backend, except cli) - run: pnpm turbo test:unit --continue --filter='!./packages/frontend/**' --filter='!n8n' --summarize + # nodes-base is excluded too: it has its own (change-scoped) unit-test-nodes + # job, so its `test:unit` script must only run in the full nightly, not here. + - name: Test Unit (backend, except cli and nodes-base) + run: pnpm turbo test:unit --continue --filter='!./packages/frontend/**' --filter='!n8n' --filter='!n8n-nodes-base' --summarize - name: Test Unit (cli, scoped) if: ${{ !cancelled() }} @@ -89,7 +91,7 @@ jobs: token: ${{ secrets.CODECOV_TOKEN }} flags: backend-unit name: backend-unit - files: ./packages/**/coverage/cobertura-coverage.xml,./coverage/cobertura-coverage.xml + files: ./packages/**/coverage/lcov.info integration-test-backend: name: Backend Integration Tests @@ -149,7 +151,7 @@ jobs: token: ${{ secrets.CODECOV_TOKEN }} flags: backend-integration name: backend-integration - files: ./packages/**/coverage/cobertura-coverage.xml,./coverage/cobertura-coverage.xml + files: ./packages/**/coverage/lcov.info unit-test-nodes: name: Nodes Unit Tests @@ -194,7 +196,7 @@ jobs: token: ${{ secrets.CODECOV_TOKEN }} flags: nodes-unit name: nodes-unit - files: ./packages/**/coverage/cobertura-coverage.xml,./coverage/cobertura-coverage.xml + files: ./packages/**/coverage/lcov.info unit-test-frontend: name: Frontend (${{ matrix.shard }}/2) @@ -245,7 +247,7 @@ jobs: token: ${{ secrets.CODECOV_TOKEN }} flags: frontend name: frontend-shard-${{ matrix.shard }} - files: ./packages/**/coverage/cobertura-coverage.xml,./coverage/cobertura-coverage.xml + files: ./packages/**/coverage/lcov.info unit-test: name: Unit tests diff --git a/.github/workflows/test-workflow-scripts-reusable.yml b/.github/workflows/test-workflow-scripts-reusable.yml index 798f16bdd15..c76231ff690 100644 --- a/.github/workflows/test-workflow-scripts-reusable.yml +++ b/.github/workflows/test-workflow-scripts-reusable.yml @@ -12,7 +12,7 @@ on: description: Version of node to use. required: false type: string - default: 24.15.0 + default: 24.16.0 env: NODE_OPTIONS: --max-old-space-size=7168 diff --git a/.github/workflows/util-claude-task.yml b/.github/workflows/util-claude-task.yml index b53730d93f1..ee510181400 100644 --- a/.github/workflows/util-claude-task.yml +++ b/.github/workflows/util-claude-task.yml @@ -134,8 +134,8 @@ jobs: prompt: ${{ env.CLAUDE_PROMPT }} show_full_output: ${{ inputs.suppress_output != true }} display_report: false - plugin_marketplaces: "./.claude/plugins/n8n" - plugins: "n8n@n8n" + plugin_marketplaces: './.claude/plugins/n8n' + plugins: 'n8n@n8n' settings: | { "permissions": { diff --git a/.github/workflows/util-claude.yml b/.github/workflows/util-claude.yml deleted file mode 100644 index 6644555c54b..00000000000 --- a/.github/workflows/util-claude.yml +++ /dev/null @@ -1,62 +0,0 @@ -name: 'Util: Claude' - -on: - issue_comment: - types: [created] - pull_request_review_comment: - types: [created] - issues: - types: [opened, assigned] - pull_request_review: - types: [submitted] - -jobs: - claude-code-action: - if: | - (github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) || - (github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude')) || - (github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude')) || - (github.event_name == 'issues' && contains(github.event.issue.body, '@claude')) - runs-on: ubuntu-latest - permissions: - contents: read - pull-requests: read - issues: read - id-token: write - steps: - - name: Checkout repository - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - with: - fetch-depth: 1 - - - name: Run Claude PR Action - uses: anthropics/claude-code-action@d668cc452deb931732f24c6b1bbf24d97bc0c586 # v1 - with: - anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} - # Or use OAuth token instead: - # claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} - timeout_minutes: '60' - settings: | - { - "extraKnownMarketplaces": { - "n8n": { - "source": { - "source": "directory", - "path": "./.claude/plugins/n8n" - } - } - }, - "enabledPlugins": { - "n8n@n8n": true - } - } - # mode: tag # Default: responds to @claude mentions - # Optional: Restrict network access to specific domains only - # experimental_allowed_domains: | - # .anthropic.com - # .github.com - # api.github.com - # .githubusercontent.com - # bun.sh - # registry.npmjs.org - # .blob.core.windows.net diff --git a/.gitignore b/.gitignore index a3ad611cd8a..43083c72e32 100644 --- a/.gitignore +++ b/.gitignore @@ -1,10 +1,12 @@ node_modules .DS_Store .tmp +.tmp-schema-docs tmp dist coverage coverage-by-spec +coverage-by-spec-backend npm-debug.log* yarn.lock google-generated-credentials.json @@ -31,6 +33,7 @@ CHANGELOG-*.md !packages/frontend/@n8n/design-system/**/*.mdx build-storybook.log build.log +.agent-setup/ sbom-source.cdx.json *.junit.xml junit.xml @@ -61,6 +64,10 @@ packages/cli/THIRD_PARTY_LICENSES.md .coverage .nyc_output coverage-gaps.json + +# Local regeneration cache for scripts/generate-lucide-icon-data.mjs (committed output: lucideIconData.ts) +scripts/.lucide-tags-cache.json + packages/cli/src/commands/export/outputs *.bak .data @@ -74,5 +81,6 @@ packages/cli/src/commands/export/outputs .conductor .n8n lefthook-local.yml +IMPROVEMENTS.md .playwright-mcp stryker.log diff --git a/.opencode/skills/setup-mcps/SKILL.md b/.opencode/skills/setup-mcps/SKILL.md new file mode 100644 index 00000000000..c7bf8e17806 --- /dev/null +++ b/.opencode/skills/setup-mcps/SKILL.md @@ -0,0 +1,84 @@ +--- +name: n8n:setup-mcps +description: >- + Configure MCP servers for n8n development in OpenCode. Use when the user says + /setup-mcps or asks to set up MCP servers for n8n. +--- + +# MCP Setup for n8n Development in OpenCode + +Configure commonly used MCP servers for n8n engineers using OpenCode MCP config. + +## Instructions + +1. Check which MCPs are already configured by running, if available: + +```bash +opencode mcp list +``` + +Parse by URL or command, not just server name. Skip any MCP whose URL is already +present. + +Known MCP URLs: + +- Linear: `https://mcp.linear.app/mcp` +- Notion: `https://mcp.notion.com/mcp` +- Context7: `https://mcp.context7.com/mcp` +- Figma: `https://mcp.figma.com/mcp` + +2. Ask the user which unconfigured MCPs they want to add. If all are already + configured, tell the user and stop. + +| Option | Label | Description | +|--------|-------|-------------| +| Linear | `Linear` | Linear ticket management with OAuth | +| Notion | `Notion` | Notion workspace integration with OAuth | +| Context7 | `Context7` | Library documentation lookup | +| Figma | `Figma` | Figma design integration with OAuth | + +3. Ask once whether to install in user or project scope. + +| Scope | Config path | When to use | +|-------|-------------|-------------| +| user | `~/.config/opencode/opencode.json` | Default. Available in all projects. | +| project | `./opencode.json` | Only when the user explicitly wants repo-local config. | + +4. Add the selected MCP entries under the `mcp` object in the selected config. + Preserve existing config keys and existing MCP entries. + +```json +{ + "mcp": { + "linear": { + "type": "remote", + "url": "https://mcp.linear.app/mcp", + "enabled": true + }, + "notion": { + "type": "remote", + "url": "https://mcp.notion.com/mcp", + "enabled": true + }, + "context7": { + "type": "remote", + "url": "https://mcp.context7.com/mcp", + "enabled": true + }, + "figma": { + "type": "remote", + "url": "https://mcp.figma.com/mcp", + "enabled": true + } + } +} +``` + +5. After editing config, tell the user to authenticate OAuth-backed servers with: + +```bash +opencode mcp auth <server-name> +``` + +Use the configured server names, for example `linear`, `notion`, or `figma`. +Context7 does not require OAuth by default. diff --git a/.tbls.postgres.yml b/.tbls.postgres.yml new file mode 100644 index 00000000000..c28046997c5 --- /dev/null +++ b/.tbls.postgres.yml @@ -0,0 +1,19 @@ +# Auto-generated DB schema docs config (PostgreSQL). See docs/db.md. +# Generated by `pnpm db:schema:docs`; do not point this at a real database. +name: n8n database schema (PostgreSQL) +desc: Auto-generated from the PostgreSQL migrations in @n8n/db. Do not edit by hand. +dsn: ${TBLS_DSN} +docPath: docs/generated/postgres-schema + +# Skip the machine-readable schema.json dump; only the Markdown docs are committed. +disableOutputSchema: true + +er: + format: mermaid + +format: + sort: true + +# The migrations bookkeeping table is operational noise, not part of the schema. +exclude: + - migrations diff --git a/.tbls.sqlite.yml b/.tbls.sqlite.yml new file mode 100644 index 00000000000..8cacced947c --- /dev/null +++ b/.tbls.sqlite.yml @@ -0,0 +1,19 @@ +# Auto-generated DB schema docs config (SQLite). See docs/db.md. +# Generated by `pnpm db:schema:docs`; do not point this at a real database. +name: n8n database schema (SQLite) +desc: Auto-generated from the SQLite migrations in @n8n/db. Do not edit by hand. +dsn: ${TBLS_DSN} +docPath: docs/generated/sqlite-schema + +# Skip the machine-readable schema.json dump; only the Markdown docs are committed. +disableOutputSchema: true + +er: + format: mermaid + +format: + sort: true + +# The migrations bookkeeping table is operational noise, not part of the schema. +exclude: + - migrations diff --git a/AGENTS.md b/AGENTS.md index afcedab66c8..9bfa5570cdb 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -20,15 +20,38 @@ frontend, and extensible node-based workflow engine. Hygiene below) - Use mermaid diagrams in MD files when you need to visualise something -## Claude Code Plugin +## Agent Skills and Claude Code Plugin -n8n-specific skills, commands, and agents live in `.claude/plugins/n8n/` and -are namespaced under `n8n:`. Use `n8n:` prefix when invoking them -(e.g. `/n8n:create-pr`, `/n8n:plan`, `n8n:developer` agent). -See [plugin README](.claude/plugins/n8n/README.md) for structure and details. +n8n shared skills live in `.agents/skills/`. Claude Code consumes them through +symlinks in `.claude/plugins/n8n/skills/`; OpenCode reads `.agents/skills/` +directly. Harness-specific overrides remain real directories in the harness +path, such as `.opencode/skills/setup-mcps/`. See +[skills README](.agents/skills/AGENTS.md) for editing and sync guidance. + +n8n-specific Claude Code commands and agents live in `.claude/plugins/n8n/` and +are namespaced under `n8n:`. Use `n8n:` prefix when invoking them (e.g. +`/n8n:create-pr`, `/n8n:plan`, `n8n:developer` agent). See +[plugin README](.claude/plugins/n8n/README.md) for structure and details. ## Essential Commands +### Fresh checkout / agent setup + +For a fresh checkout (cat-bot, a new hire, any agent verifying the repo +builds), prefer `pnpm agent:setup` over running install + build + tests by +hand. It chains them in one process, caps per-process memory and turbo +concurrency so a 6GB box doesn't OOM, streams all output to +`.agent-setup/<step>.log` (gitignored), and surfaces only a one-line summary +per step plus the tail of the failing log. A machine-readable +`.agent-setup/summary.json` is always written so a backgrounded run is +readable in a single shot — no polling, no scrolling logs. + +```bash +pnpm agent:setup # install → build → test (full suite) +pnpm agent:setup install # one step at a time +pnpm agent:setup --json # JSON summary on stdout (for scripts/agents) +``` + ### Building Use `pnpm build` to build all packages. ALWAYS redirect the output of the build command to a file: @@ -42,6 +65,13 @@ You can inspect the last few lines of the build log file to check for errors: tail -n 20 build.log ``` +If build outputs or the turbo cache are stale (e.g. after switching branches +or worktrees) but dependencies haven't changed, use `pnpm reset` (lightweight +by default) for a fast recovery: it cleans build outputs and force-rebuilds +(keeping `node_modules` and untracked files). If that doesn't fix your issue, +use `pnpm reset --full`, which also wipes untracked files and reinstalls +dependencies. + ### Testing - `pnpm test` - Run all tests - `pnpm test:affected` - Runs tests based on what has changed since the last diff --git a/CHANGELOG.md b/CHANGELOG.md index 36f738e10da..792ec26057f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,247 @@ +# [2.27.0](https://github.com/n8n-io/n8n/compare/n8n@2.26.0...n8n@2.27.0) (2026-06-16) + + +### Bug Fixes + +* **API:** Make conditional credential fields optional instead of forbidden ([#32010](https://github.com/n8n-io/n8n/issues/32010)) ([0ab043c](https://github.com/n8n-io/n8n/commit/0ab043c8bb3c0ccdb21c57a885d454eabaacbb35)) +* Bump task-runner-launcher to 1.4.7 to clear stdlib CVEs ([#32095](https://github.com/n8n-io/n8n/issues/32095)) ([4d974e3](https://github.com/n8n-io/n8n/commit/4d974e38efaed7e3e7d869fd3490b5cfa2465b51)) +* Computer use disconnect status on client stop ([#32059](https://github.com/n8n-io/n8n/issues/32059)) ([5c61d0e](https://github.com/n8n-io/n8n/commit/5c61d0e65795d3bb92aaac1f3528c2dec873bd8f)) +* **core:** Add RFC 8707 resource parameter to client-side OAuth flow ([#30924](https://github.com/n8n-io/n8n/issues/30924)) ([04b4a79](https://github.com/n8n-io/n8n/commit/04b4a793cca1a99de5a8fc7bd5c3f6b6efb4b0d4)) +* **core:** Allow publishing workflows that use private credentials ([#32306](https://github.com/n8n-io/n8n/issues/32306)) ([27d8426](https://github.com/n8n-io/n8n/commit/27d84260c66479b8b040cea922ed7d6a6261864f)) +* **core:** Enforce API key scope/endpoint parity in public API ([#32231](https://github.com/n8n-io/n8n/issues/32231)) ([58999f0](https://github.com/n8n-io/n8n/commit/58999f030fa08e640ad56a38fd05b7e3b52589c0)) +* **core:** Ensure workflows that fail to activate are removed from active, preventing unintended executions ([#31767](https://github.com/n8n-io/n8n/issues/31767)) ([79d1695](https://github.com/n8n-io/n8n/commit/79d1695c42668a1ddd503e7f6fb73ce417d63400)) +* **core:** Fix workers processing queued jobs before module initialization completes ([#32145](https://github.com/n8n-io/n8n/issues/32145)) ([506461f](https://github.com/n8n-io/n8n/commit/506461ff7ae44915b1937f212a8e04ea7add5ffb)) +* **core:** Hide resource URL for synthetic OAuth2 credentials for MCP registry tools ([#32351](https://github.com/n8n-io/n8n/issues/32351)) ([51fe9ff](https://github.com/n8n-io/n8n/commit/51fe9ff8554220d70d648553413d8c47f98eef30)) +* **core:** Include indexes and TOAST in Postgres data table size ([#31606](https://github.com/n8n-io/n8n/issues/31606)) ([c9f4aa8](https://github.com/n8n-io/n8n/commit/c9f4aa83c4048a717833fbd65ce60ac9a1f621ab)) +* **core:** Preserve trailing letter-less text in toSentenceCase() exp… ([#32242](https://github.com/n8n-io/n8n/issues/32242)) ([7a77898](https://github.com/n8n-io/n8n/commit/7a778985c153b16b244c7adef0d8f989b1a70a86)) +* **core:** Prevent nodes from throwing `context.getNodeParameter is not a function` when n8n is installed via npm ([#32123](https://github.com/n8n-io/n8n/issues/32123)) ([a254a89](https://github.com/n8n-io/n8n/commit/a254a89d498ccf345b9067ef515b2123ff9e08a2)) +* **core:** Prevent pollers from starting executions for old workflow versions when registered while in-flight ([#32006](https://github.com/n8n-io/n8n/issues/32006)) ([21c786c](https://github.com/n8n-io/n8n/commit/21c786c8a1ed54f6690b213aa35bcb74cf13b99e)) +* **core:** Prevent post-execution writes against closed pool on worker shutdown ([#31915](https://github.com/n8n-io/n8n/issues/31915)) ([3059088](https://github.com/n8n-io/n8n/commit/3059088ab65248c2a708bb899872c33aacca40de)) +* **core:** Prevent queue recovery from marking waiting executions as crashed ([#32316](https://github.com/n8n-io/n8n/issues/32316)) ([c4c0e91](https://github.com/n8n-io/n8n/commit/c4c0e91807549793fab1f4cb339641d9c832dd8d)) +* **core:** Propagate sub-workflow errors to parent after wait resume ([#31927](https://github.com/n8n-io/n8n/issues/31927)) ([6afba57](https://github.com/n8n-io/n8n/commit/6afba57091dd1cbdc4dccf0a8fdd5f86508c555d)) +* **core:** Remove user:enforceMfa from public API key scopes ([#32223](https://github.com/n8n-io/n8n/issues/32223)) ([3c39a0e](https://github.com/n8n-io/n8n/commit/3c39a0e336e9ebbeb10b2c4398e4924c2acb1ae6)) +* **core:** Retry role mapping create order conflicts ([#30687](https://github.com/n8n-io/n8n/issues/30687)) ([448c114](https://github.com/n8n-io/n8n/commit/448c114127aa6fdec5e72e5042cdadb07c0324dc)) +* **core:** Surface a final response when a builder follow-up completes silently ([#31986](https://github.com/n8n-io/n8n/issues/31986)) ([29abe78](https://github.com/n8n-io/n8n/commit/29abe781d53475f92b6edde7e786a666d67ee22b)) +* **core:** Throw a clear error for $evaluateExpression in the Code node under secure mode ([#31721](https://github.com/n8n-io/n8n/issues/31721)) ([fbad049](https://github.com/n8n-io/n8n/commit/fbad049db972d850e09154ee18f2ada8f00a38ad)) +* **core:** Upgrade nodemailer to 8.0.10 (DEVP-401) ([#31998](https://github.com/n8n-io/n8n/issues/31998)) ([c339095](https://github.com/n8n-io/n8n/commit/c339095c47247f2e38c054fa9f835206a95d2aa4)) +* **core:** Use npm's bundled node-gyp for isolated-vm Docker rebuild ([#32158](https://github.com/n8n-io/n8n/issues/32158)) ([67cdf44](https://github.com/n8n-io/n8n/commit/67cdf44fe71134ba6b549e663f11d192e627e310)) +* Correct Form URL Encoded label in HTTP Request node ([#31852](https://github.com/n8n-io/n8n/issues/31852)) ([ff7f35e](https://github.com/n8n-io/n8n/commit/ff7f35eefcd3bce9728b1312d39ec0b1b0acbeb0)) +* **editor:** Agent builder progress log lines visual glitches ([#32077](https://github.com/n8n-io/n8n/issues/32077)) ([f9496c2](https://github.com/n8n-io/n8n/commit/f9496c2397f9e7a52f8b5abef77ea320f47e1b20)) +* **editor:** Auto-reload editor on stale Vite chunk preload error ([#31747](https://github.com/n8n-io/n8n/issues/31747)) ([2f3ebb6](https://github.com/n8n-io/n8n/commit/2f3ebb620cf7cd16fcedaa94a1be6ec61f66626b)) +* **editor:** Close credential modal after successful setup ([#31925](https://github.com/n8n-io/n8n/issues/31925)) ([7b2c722](https://github.com/n8n-io/n8n/commit/7b2c722182d741bb455db22b46eacfea6390a2c9)) +* **editor:** Harden credential modal against async hangs ([#31292](https://github.com/n8n-io/n8n/issues/31292)) ([037bdb2](https://github.com/n8n-io/n8n/commit/037bdb216f2c942e049e1fcca61b22ee8cc2b2b0)) +* **editor:** Hide template setup button once setup is complete ([#31912](https://github.com/n8n-io/n8n/issues/31912)) ([af9caff](https://github.com/n8n-io/n8n/commit/af9caffc7e1fd81aa6e3c41b5231f4d56cfa3bf6)) +* **editor:** Insert instance ai prompt suggestions instead of submit ([#32008](https://github.com/n8n-io/n8n/issues/32008)) ([3386aa8](https://github.com/n8n-io/n8n/commit/3386aa81ccbfa2ed21ff7ac2b00369fb5a1376c7)) +* **editor:** Make workflow settings and actions menu work in the AI artifact view ([#32082](https://github.com/n8n-io/n8n/issues/32082)) ([5a28683](https://github.com/n8n-io/n8n/commit/5a28683c7811530a7bbcfcfa4aebc0223efe5f47)) +* **editor:** Mute Never expiration in API keys table ([#32224](https://github.com/n8n-io/n8n/issues/32224)) ([115d9c7](https://github.com/n8n-io/n8n/commit/115d9c7597c1d7c376046df1963f0eb1e66450b7)) +* **editor:** Open sticky note color picker from context menu ([#31917](https://github.com/n8n-io/n8n/issues/31917)) ([0685db8](https://github.com/n8n-io/n8n/commit/0685db8ff6dabd5121a6b0adcec9a53fb58b8b75)) +* **editor:** Preserve loaded options value when navigating between nodes ([#31946](https://github.com/n8n-io/n8n/issues/31946)) ([f6e5705](https://github.com/n8n-io/n8n/commit/f6e57059caf420a03bc638bdcf94a8085c9ff94f)) +* **editor:** Refresh Instance AI workflow preview on update and restore-version ([#31904](https://github.com/n8n-io/n8n/issues/31904)) ([f2c764a](https://github.com/n8n-io/n8n/commit/f2c764a804f1efb458363bcc2b6f30d4cb1b0b67)) +* **editor:** Remove 'Building your agent' loading state and go straight to full-page builder ([#32120](https://github.com/n8n-io/n8n/issues/32120)) ([d553602](https://github.com/n8n-io/n8n/commit/d55360245a0cc5091b964f6cdffcc8bf9084f0cc)) +* **editor:** Restore cross-origin notification after OAuth popup completes ([#32087](https://github.com/n8n-io/n8n/issues/32087)) ([090fa9e](https://github.com/n8n-io/n8n/commit/090fa9e84b8fe8b0dc5d714c65835b0ee4689e0e)) +* **editor:** Scope publish history scrollbar to timeline sidebar ([#31661](https://github.com/n8n-io/n8n/issues/31661)) ([497226e](https://github.com/n8n-io/n8n/commit/497226e8945d780262af409565ef546b29b89299)) +* **editor:** Send only credential id when authorizing OAuth credentials ([#31926](https://github.com/n8n-io/n8n/issues/31926)) ([4f10853](https://github.com/n8n-io/n8n/commit/4f10853a1585663dbc76ce97a3b3bb53361b1301)) +* **editor:** Show AI assistant error when stream ends with unparseable content ([#32068](https://github.com/n8n-io/n8n/issues/32068)) ([a7b910f](https://github.com/n8n-io/n8n/commit/a7b910f3653093d9550234d48085afe6012bd325)) +* **editor:** Show an error when imported JSON is not a valid workflow ([#31782](https://github.com/n8n-io/n8n/issues/31782)) ([0731871](https://github.com/n8n-io/n8n/commit/073187137ac5aced3cc7514526c968d742696def)) +* **editor:** Show correct project in workflow breadcrumb for projectId links ([#32103](https://github.com/n8n-io/n8n/issues/32103)) ([fd23d4d](https://github.com/n8n-io/n8n/commit/fd23d4da56ed35bc1fceb5503011ff899d7a4578)) +* **editor:** Show run data of stopped executions in scaling mode ([#32142](https://github.com/n8n-io/n8n/issues/32142)) ([889769a](https://github.com/n8n-io/n8n/commit/889769a34dc5f652e8fa05c15e1a33719ee05081)) +* **editor:** Skip external-secrets fetch on Community Edition ([#31906](https://github.com/n8n-io/n8n/issues/31906)) ([f6518a5](https://github.com/n8n-io/n8n/commit/f6518a5780ea6610dd98de38d83a773db5caadfc)) +* **editor:** Stop showing deleted resources in dependency pill ([#32106](https://github.com/n8n-io/n8n/issues/32106)) ([4e10568](https://github.com/n8n-io/n8n/commit/4e105682ac5b92ab4ec7c81a71e087a6c227aea1)) +* **editor:** Truncate long API key labels in settings table ([#32232](https://github.com/n8n-io/n8n/issues/32232)) ([607634a](https://github.com/n8n-io/n8n/commit/607634ad274b956e413850bf7ba93b80ed1d039d)) +* **editor:** Use workflow-scoped credential fetch in node credential picker ([#31938](https://github.com/n8n-io/n8n/issues/31938)) ([8cd67d3](https://github.com/n8n-io/n8n/commit/8cd67d300d57563da9f1cc867c688db44d3b31e2)) +* Fix 4 security issues in @grpc/grpc-js, hono ([#32281](https://github.com/n8n-io/n8n/issues/32281)) ([e292779](https://github.com/n8n-io/n8n/commit/e292779f1a739b6188efac25f171a8da913ce16b)) +* Fix security issue in shell-quote via minor version upgrade from 1.8.3 to 1.8.4 (SEC-809) ([#32107](https://github.com/n8n-io/n8n/issues/32107)) ([131e4ea](https://github.com/n8n-io/n8n/commit/131e4ea9d6a7046b36f64a483ea4fa39f83fa845)) +* **Http Request Node:** Preserve multipart filenames for binary uploads ([#29022](https://github.com/n8n-io/n8n/issues/29022)) ([f412820](https://github.com/n8n-io/n8n/commit/f412820f522ab8cc3aa42097b618b046cb000288)) +* **Kafka Node:** Distinguish the Schema Registry credential from the Kafka credential ([#32335](https://github.com/n8n-io/n8n/issues/32335)) ([41ee940](https://github.com/n8n-io/n8n/commit/41ee9408813ba061546ebe59671fe99257558ea1)) +* Move unstable PURL-pinned overrides to version-agnostic byName ([#31985](https://github.com/n8n-io/n8n/issues/31985)) ([e77dd74](https://github.com/n8n-io/n8n/commit/e77dd74a70e105f6099a001eeefed5df3023ab0f)) +* **Oracle Database Node:** Support OUT bind parameters ([#30083](https://github.com/n8n-io/n8n/issues/30083)) ([d3406dd](https://github.com/n8n-io/n8n/commit/d3406dd75f222d4e2bae46dc7906cb14f6fc6f76)) +* Require justified mutants in mutation-health gate ([#32340](https://github.com/n8n-io/n8n/issues/32340)) ([b3a34fc](https://github.com/n8n-io/n8n/commit/b3a34fcd81659f6e33b5857a8c68816f7e105320)) +* Set task status to 'cancelled' in BackgroundTaskManager.cancelAll() ([#31764](https://github.com/n8n-io/n8n/issues/31764)) ([5733fb7](https://github.com/n8n-io/n8n/commit/5733fb794b3de6bb048ef48f91747075a6c0a896)) +* Store messages even if stream is undrained ([#32119](https://github.com/n8n-io/n8n/issues/32119)) ([f2da1d1](https://github.com/n8n-io/n8n/commit/f2da1d14bbd8b210e0d2f9f95387372c1e00bece)) + + +### Features + +* **Calendly Trigger Node:** Deprecate API key auth and default to OAuth2 ([#28367](https://github.com/n8n-io/n8n/issues/28367)) ([3f88c6e](https://github.com/n8n-io/n8n/commit/3f88c6e61f948e19f4175521619cab8db2d899af)) +* Computer use supports reading local pdf and image files ([#30704](https://github.com/n8n-io/n8n/issues/30704)) ([b810bfd](https://github.com/n8n-io/n8n/commit/b810bfde435036d93f640f2a2025b5c95a521bc9)) +* **core:** Add cred-filename-against-convention community node lint rule ([#32356](https://github.com/n8n-io/n8n/issues/32356)) ([e436e1a](https://github.com/n8n-io/n8n/commit/e436e1a6c9f7577095605b506dfada7ee0bfda0f)) +* **core:** Add explore_node_resources MCP tool ([#31018](https://github.com/n8n-io/n8n/issues/31018)) ([9373433](https://github.com/n8n-io/n8n/commit/9373433aae472444314334bafd963274fcbae3aa)) +* **core:** Add Instance AI builder planning guardrails ([#31984](https://github.com/n8n-io/n8n/issues/31984)) ([63cdd9f](https://github.com/n8n-io/n8n/commit/63cdd9f777b859e4c6d0e835f2b13014d2e39976)) +* **core:** Add instance settings env telemetry ([#31949](https://github.com/n8n-io/n8n/issues/31949)) ([3753c34](https://github.com/n8n-io/n8n/commit/3753c34e0adebdefc24c6b43dc4c3d6a5b88ebac)) +* **core:** Add OpenTelemetry test trace endpoint and settings button ([#32333](https://github.com/n8n-io/n8n/issues/32333)) ([4fde44b](https://github.com/n8n-io/n8n/commit/4fde44bdaf06727eae8cb85db727cece376ebae6)) +* **core:** Add output redactor guardrail for instance AI use ([#31929](https://github.com/n8n-io/n8n/issues/31929)) ([06df815](https://github.com/n8n-io/n8n/commit/06df815c4b74a0860d31653e162ba60b178f3996)) +* **core:** Add S3 storage mode for execution data ([#32226](https://github.com/n8n-io/n8n/issues/32226)) ([2a6acf3](https://github.com/n8n-io/n8n/commit/2a6acf3cd602e6d414f92ecf3e021d87a1149f1e)) +* **core:** Add tags support to MCP server ([#31446](https://github.com/n8n-io/n8n/issues/31446)) ([1640a69](https://github.com/n8n-io/n8n/commit/1640a69ea66baa68cfcdb04be71818560a78a48d)) +* **core:** Add telemetry for import/export on server CLI ([#32297](https://github.com/n8n-io/n8n/issues/32297)) ([2ac0660](https://github.com/n8n-io/n8n/commit/2ac06605522ec0b63f6d5e0c0ceb9a7ef057af98)) +* **core:** Add valid-author community node lint rule ([#32357](https://github.com/n8n-io/n8n/issues/32357)) ([029cf72](https://github.com/n8n-io/n8n/commit/029cf72b97c6cf64b7fe38fb7a8e0af22ca6ba7a)) +* **core:** Add validation and size limits to package archive reading ([#31812](https://github.com/n8n-io/n8n/issues/31812)) ([e0cb99e](https://github.com/n8n-io/n8n/commit/e0cb99eb84d70ce3e15b4ad466aa7b0f28c45952)) +* **core:** Add workflowPublishingPolicy to package import ([#31961](https://github.com/n8n-io/n8n/issues/31961)) ([140a319](https://github.com/n8n-io/n8n/commit/140a319ccd2284817026a63cc3fa7014725ed585)) +* **core:** Configure OpenTelemetry settings via UI ([#31781](https://github.com/n8n-io/n8n/issues/31781)) ([e2dd95d](https://github.com/n8n-io/n8n/commit/e2dd95d15a115559c216b1d0bc6964fd2b8624d0)) +* **core:** Email public API key owners when their key is revoked by an admin ([#32086](https://github.com/n8n-io/n8n/issues/32086)) ([ac19787](https://github.com/n8n-io/n8n/commit/ac197878d95a15ce30e1201a544cd79fa02efa0c)) +* **core:** Expose DNS cache metrics via PrometheusMetricsService ([#32013](https://github.com/n8n-io/n8n/issues/32013)) ([5ab381c](https://github.com/n8n-io/n8n/commit/5ab381c8bc2ea9f924e66ed46b5456086706e7e0)) +* **core:** Expose SSRF protection check outcomes as Prometheus metrics ([#32004](https://github.com/n8n-io/n8n/issues/32004)) ([58c4cd1](https://github.com/n8n-io/n8n/commit/58c4cd1d87a61bbd25c3fc5fb0a563d6cc6188e6)) +* **core:** Introduce credentialBindings for package import ([#32228](https://github.com/n8n-io/n8n/issues/32228)) ([f161bf0](https://github.com/n8n-io/n8n/commit/f161bf07861674643e7547174e4d07345d737205)) +* **core:** Make data redaction enforcement generally available ([#31966](https://github.com/n8n-io/n8n/issues/31966)) ([2afc32a](https://github.com/n8n-io/n8n/commit/2afc32a3ec5a7f6279f2ddd13b5522a51c74c210)) +* **core:** Remove n8n packages license check ([#32317](https://github.com/n8n-io/n8n/issues/32317)) ([93e2f86](https://github.com/n8n-io/n8n/commit/93e2f8629eef8ac5877950d688a11458a780464e)) +* **core:** Workflow import workflowIdPolicy ([#32075](https://github.com/n8n-io/n8n/issues/32075)) ([24c264c](https://github.com/n8n-io/n8n/commit/24c264ca288ebf0af9d958dca7323437fe97b25f)) +* **editor:** Add docs links for data redaction ([#32220](https://github.com/n8n-io/n8n/issues/32220)) ([bc90a4b](https://github.com/n8n-io/n8n/commit/bc90a4b8f2bbb746baf6523f1115d123b6be1ee0)) +* **editor:** Allow creating variables and data tables from the universal add menu ([#32079](https://github.com/n8n-io/n8n/issues/32079)) ([3cff611](https://github.com/n8n-io/n8n/commit/3cff611c6e8c568b0de0888de2ab4208e126b403)) +* **editor:** Open API key modal in read-only mode for non-owners ([#32254](https://github.com/n8n-io/n8n/issues/32254)) ([9496996](https://github.com/n8n-io/n8n/commit/94969962cf994ecf090101a946d2b5ffa4843b8e)) +* **editor:** Redesign API key created modal ([#32256](https://github.com/n8n-io/n8n/issues/32256)) ([e6bc501](https://github.com/n8n-io/n8n/commit/e6bc5012bacd037c9dc60e0b81312559c61765ee)) +* **editor:** Reposition nodes on group collapse/expand ([#32128](https://github.com/n8n-io/n8n/issues/32128)) ([053126f](https://github.com/n8n-io/n8n/commit/053126fc7c62df8f033f89cf4150f5117f48c953)) +* **editor:** Rewrite icon picker with search, full Lucide set, emoji sections, and color/skin tone pickers ([#25649](https://github.com/n8n-io/n8n/issues/25649)) ([12ba0d0](https://github.com/n8n-io/n8n/commit/12ba0d00803222495693de89eb3d1e919d4a663f)) +* **editor:** Use an action menu for API key row actions ([#32339](https://github.com/n8n-io/n8n/issues/32339)) ([f80fca2](https://github.com/n8n-io/n8n/commit/f80fca2617e8e6d57f497502bd26e1717673dee0)) +* Force Microsoft account selection on OAuth for all Microsoft credentials ([#32015](https://github.com/n8n-io/n8n/issues/32015)) ([939307a](https://github.com/n8n-io/n8n/commit/939307a4d5fc4179d7e0a7233ec31b23ad698df2)) +* **GitHub Node:** Introduce get members operation on organization resource ([#23822](https://github.com/n8n-io/n8n/issues/23822)) ([05d44e4](https://github.com/n8n-io/n8n/commit/05d44e45b2a166823ae23a1b68ff211e0bb9b922)) +* **JWT Node:** Support custom header claims for the Sign operation ([#31918](https://github.com/n8n-io/n8n/issues/31918)) ([160cb09](https://github.com/n8n-io/n8n/commit/160cb095c819f15e55ccf55ad4f7458500fdca65)) +* **Kafka Node:** Add Schema Registry credential type ([#32026](https://github.com/n8n-io/n8n/issues/32026)) ([93d9387](https://github.com/n8n-io/n8n/commit/93d9387f3eaa33c19099b2b6a5db4f270c455f35)) +* **LmChatAnthropic Node:** Add streaming option ([#30991](https://github.com/n8n-io/n8n/issues/30991)) ([cf223af](https://github.com/n8n-io/n8n/commit/cf223af11cd310d75fb8149dc27214071423fa97)) +* **MCP Server Trigger Node:** Add n8n OAuth2 authentication option ([#32326](https://github.com/n8n-io/n8n/issues/32326)) ([e7b1c1c](https://github.com/n8n-io/n8n/commit/e7b1c1c2ef60abb65bf7502c0df5d777276f6ac1)) +* **Microsoft OneDrive Node:** Support the generic Microsoft OAuth2 credential ([#32295](https://github.com/n8n-io/n8n/issues/32295)) ([30b5451](https://github.com/n8n-io/n8n/commit/30b54515d6bd6728c1961ec37d3b6cc8e2340a23)) +* **Pipedrive Trigger Node:** Allow lead entities to be triggered upon ([#23977](https://github.com/n8n-io/n8n/issues/23977)) ([da8b7c7](https://github.com/n8n-io/n8n/commit/da8b7c7317c538f3340b5b1d4212251abbda7f54)) +* Reduces delay in displaying AI Assistant workflow preview examples ([#32194](https://github.com/n8n-io/n8n/issues/32194)) ([2e9946c](https://github.com/n8n-io/n8n/commit/2e9946c458d6c91552b0f8de5b75547cd6b2c079)) +* Show the workflow name on the OAuth consent screen ([#32362](https://github.com/n8n-io/n8n/issues/32362)) ([7a5c208](https://github.com/n8n-io/n8n/commit/7a5c2087f7e3c42c373ef397cb83df14d66a28a6)) + + +### Performance Improvements + +* **core:** Add partial index on execution_entity to fix executions list CPU spike ([#32116](https://github.com/n8n-io/n8n/issues/32116)) ([3b53949](https://github.com/n8n-io/n8n/commit/3b539497928f8cb9f50621f683061dc7631adbfc)) +* **core:** Optimize workflow lookups ([#24690](https://github.com/n8n-io/n8n/issues/24690)) ([c3b35c1](https://github.com/n8n-io/n8n/commit/c3b35c1a60fb32dcff2f0ef2338dc7330e4d80bd)) +* **core:** Ungate minimize execution data fetching ([#30969](https://github.com/n8n-io/n8n/issues/30969)) ([4b4a76a](https://github.com/n8n-io/n8n/commit/4b4a76a375d550679bc0312561a6b71f189bee84)) + + +# [2.26.0](https://github.com/n8n-io/n8n/compare/n8n@2.25.1...n8n@2.26.0) (2026-06-09) + + +### Bug Fixes + +* **API:** Enforce the redaction floor when creating workflows ([#31898](https://github.com/n8n-io/n8n/issues/31898)) ([03eecb1](https://github.com/n8n-io/n8n/commit/03eecb1f50f144d72bcd074f4bb5710634b53860)) +* **AWS Rekognition Node:** Handle all binary data modes correctly ([#31065](https://github.com/n8n-io/n8n/issues/31065)) ([e264e06](https://github.com/n8n-io/n8n/commit/e264e061b4ab3e0cd7d61499858453c107ad780b)) +* Bump hono and postcss to patch CVEs from Trivy nightly scan ([#31790](https://github.com/n8n-io/n8n/issues/31790)) ([0c26304](https://github.com/n8n-io/n8n/commit/0c2630408573c8578d953ccd5bb87632bd5409a9)) +* **core:** Allow exporting workflows with AI Gateway-managed credentials ([#31136](https://github.com/n8n-io/n8n/issues/31136)) ([8376a4f](https://github.com/n8n-io/n8n/commit/8376a4f2a4592e805e4a911bc0b6af2d4cb4b1e0)) +* **core:** Bump qs, tmp, uuid, @tootallnate/once ([#31674](https://github.com/n8n-io/n8n/issues/31674)) ([868e988](https://github.com/n8n-io/n8n/commit/868e988c0945a0affd6c0a18705f247a97c0e6d8)) +* **core:** Dedupe getConnectedNodes results and add fast-check property tests ([#31793](https://github.com/n8n-io/n8n/issues/31793)) ([be85b10](https://github.com/n8n-io/n8n/commit/be85b1079e2ca88bc6f854b260ab846d1b3d1687)) +* **core:** Delete orphaned per-user entries on unshare and membership changes ([#31741](https://github.com/n8n-io/n8n/issues/31741)) ([8832194](https://github.com/n8n-io/n8n/commit/8832194aa2d2c6e36712ee49741a6786eb5ddb43)) +* **core:** Disable iAI e2e tests temporarily ([#31779](https://github.com/n8n-io/n8n/issues/31779)) ([91ae2a2](https://github.com/n8n-io/n8n/commit/91ae2a2c01df556dc9e5c4aba66153f082f52954)) +* **core:** External agent channels correctly utilise the user ID for episodic memory ([#31584](https://github.com/n8n-io/n8n/issues/31584)) ([2a9a23f](https://github.com/n8n-io/n8n/commit/2a9a23f77473f4a450655cec3d1382ea8f26c2cf)) +* **core:** Fix dropdown menu safety triangle ([#31583](https://github.com/n8n-io/n8n/issues/31583)) ([ff1a7ae](https://github.com/n8n-io/n8n/commit/ff1a7aeb191980a8547202f62a9e769b97f0ed40)) +* **core:** Fix hardcoded `aud` claim in MCP OAuth tokens ([#30558](https://github.com/n8n-io/n8n/issues/30558)) ([6bcd02a](https://github.com/n8n-io/n8n/commit/6bcd02a5f0210721cad326c7f107794cd1ebeec9)) +* **core:** Ground AI workflow completion in saved graph ([#31742](https://github.com/n8n-io/n8n/issues/31742)) ([491360f](https://github.com/n8n-io/n8n/commit/491360fbc79147592989633996e24a9bcfd58bdc)) +* **core:** Improve validator error messages for name and label fields ([#31391](https://github.com/n8n-io/n8n/issues/31391)) ([24f27ed](https://github.com/n8n-io/n8n/commit/24f27ed559a2e977b2a22812e8da2b0c89618ee5)) +* **core:** Include node and field details in WorkflowHasIssuesError message ([#30944](https://github.com/n8n-io/n8n/issues/30944)) ([68b2053](https://github.com/n8n-io/n8n/commit/68b205317a83bcbf4277876ad8c1727fd716d894)) +* **core:** Invalidate cached redaction floor across mains on change ([#31831](https://github.com/n8n-io/n8n/issues/31831)) ([ad59171](https://github.com/n8n-io/n8n/commit/ad59171afebcc0cdab824f00694f21b3d3fa7fbe)) +* **core:** Keep Instance AI builder sandboxes thread-scoped and non-ephemeral ([#31745](https://github.com/n8n-io/n8n/issues/31745)) ([2993afb](https://github.com/n8n-io/n8n/commit/2993afb31dfbd12797bc12192f9fee0a439d88b0)) +* **core:** Lock execution row during data-only condition re-check ([#31547](https://github.com/n8n-io/n8n/issues/31547)) ([f83efe5](https://github.com/n8n-io/n8n/commit/f83efe5b04999e11a5de0d3a742ac836a98b33f6)) +* **core:** Make AI assistant conversation pruning happen regularly ([#31707](https://github.com/n8n-io/n8n/issues/31707)) ([13a1a99](https://github.com/n8n-io/n8n/commit/13a1a993f58e449447f0568677cbf6471d446420)) +* **core:** Make Sentry event loop block detection configurable ([#31823](https://github.com/n8n-io/n8n/issues/31823)) ([ddac0e0](https://github.com/n8n-io/n8n/commit/ddac0e0cbb880c1f03c78d6c9e5ddfa223dbae1b)) +* **core:** Move instance AI builds to a skill ([#31412](https://github.com/n8n-io/n8n/issues/31412)) ([332d2df](https://github.com/n8n-io/n8n/commit/332d2df44e7504d0a5084a1423fe2cf3c1ca0648)) +* **core:** Normalize LangChain parser errors ([#31499](https://github.com/n8n-io/n8n/issues/31499)) ([872171c](https://github.com/n8n-io/n8n/commit/872171cd6681f6179ce133c3f466e0ccf8bb7aee)) +* **core:** Polyfill DOMMatrix when parsing PDFs in Data Loader ([#31669](https://github.com/n8n-io/n8n/issues/31669)) ([5e0e266](https://github.com/n8n-io/n8n/commit/5e0e2661f5fd33af600b6865c677dfd650fc23eb)) +* **core:** Prefer MCP registry nodes when wiring AI Agent tools ([#30774](https://github.com/n8n-io/n8n/issues/30774)) ([f4e998f](https://github.com/n8n-io/n8n/commit/f4e998f2451a5b93a3adfbe005fff5e3ce442c80)) +* **core:** Preserve verification failure in budget-exhausted blocked responses ([#31907](https://github.com/n8n-io/n8n/issues/31907)) ([f7076a3](https://github.com/n8n-io/n8n/commit/f7076a345eb0bd0c8987228da79bbe0b3e5a5e2c)) +* **core:** Prevent evaluation executions from stalling in status new ([#31619](https://github.com/n8n-io/n8n/issues/31619)) ([ea800f7](https://github.com/n8n-io/n8n/commit/ea800f715d91f9c44a56ee7de0f49586cb6f8ed1)) +* **core:** Prevent isUniqueConstraintError false positives ([#31284](https://github.com/n8n-io/n8n/issues/31284)) ([a3e37fc](https://github.com/n8n-io/n8n/commit/a3e37fcd1216231e1d8fb0a39e051f229ca10bc0)) +* **core:** Reclassify expected backend errors out of the Sentry error stream ([#31423](https://github.com/n8n-io/n8n/issues/31423)) ([ecce350](https://github.com/n8n-io/n8n/commit/ecce35049d40d6a3ddfe814f5c3af760b5709d61)) +* **core:** Report only error class and stack for unhandled node errors ([#31628](https://github.com/n8n-io/n8n/issues/31628)) ([364c250](https://github.com/n8n-io/n8n/commit/364c250ceb55d58c8525599e919b6c5b5e1474cb)) +* **core:** Resolve custom node icon paths ([#30946](https://github.com/n8n-io/n8n/issues/30946)) ([7ab8254](https://github.com/n8n-io/n8n/commit/7ab8254329e10ee91d9675ea196d161fc6b47545)) +* **core:** Restore OIDC login for IdPs returning expires_in: 0 ([#31265](https://github.com/n8n-io/n8n/issues/31265)) ([41b2bda](https://github.com/n8n-io/n8n/commit/41b2bda41d18623d5d99e86f434630d39c34d357)) +* **core:** Resume Instance AI sandboxes that were stopped or deleted while idle ([#31761](https://github.com/n8n-io/n8n/issues/31761)) ([06cf1d9](https://github.com/n8n-io/n8n/commit/06cf1d9a7d55a256c70137e57aa1f150cbe49012)) +* **core:** Show actionable message when OAuth2 token refresh fails ([#30460](https://github.com/n8n-io/n8n/issues/30460)) ([5e9a8a0](https://github.com/n8n-io/n8n/commit/5e9a8a071fb41133adbb14288bcaa37690cb1a4a)) +* **core:** Stop parent workflows getting stuck waiting on sub-workflow completion ([#31736](https://github.com/n8n-io/n8n/issues/31736)) ([61af45a](https://github.com/n8n-io/n8n/commit/61af45aa03fc045365d732a3e3e9faf8a2c7cccf)) +* **core:** Store OAuth CSRF and PKCE state per-flow in the cache ([#31254](https://github.com/n8n-io/n8n/issues/31254)) ([7d729ff](https://github.com/n8n-io/n8n/commit/7d729ff243cf3c49feef1047b8ae22bef51453bb)) +* **core:** Strip legacy unsupported config before agent JSON validation ([#31577](https://github.com/n8n-io/n8n/issues/31577)) ([255b7a1](https://github.com/n8n-io/n8n/commit/255b7a1543660e010b8ca6cf09424617fc5af2cb)) +* **core:** Sub-workflows to respect own timeout settings and global timeout config ([#31536](https://github.com/n8n-io/n8n/issues/31536)) ([0b2a632](https://github.com/n8n-io/n8n/commit/0b2a6328cfa901955522f709dc3392cbfba55c7f)) +* **core:** Teach the builder the SDK language subset and stop repeated invalid repairs ([#31911](https://github.com/n8n-io/n8n/issues/31911)) ([4271d42](https://github.com/n8n-io/n8n/commit/4271d423983093e87b383a0dc0a4561d1fdab302)) +* **core:** Temporarily disable error card from iAi chat ([#31740](https://github.com/n8n-io/n8n/issues/31740)) ([d58b7ea](https://github.com/n8n-io/n8n/commit/d58b7ea943b8195f272762b68bc01065564d0184)) +* **core:** The n8n import:workflow --activeState=fromJson cli can fail for subworkflow dependencies ([#31377](https://github.com/n8n-io/n8n/issues/31377)) ([e785e4e](https://github.com/n8n-io/n8n/commit/e785e4e7f3851d022314a3985151ff6783412466)) +* Declare @smithy/node-http-handler and [@aws-sdk](https://github.com/aws-sdk) ([#31562](https://github.com/n8n-io/n8n/issues/31562)) ([485c153](https://github.com/n8n-io/n8n/commit/485c153ad69284059fcc1464c7d5f6a03a7fb9c8)) +* **Discord Node:** Preserve object author in embed JSON for icon_url support ([#30046](https://github.com/n8n-io/n8n/issues/30046)) ([cb38338](https://github.com/n8n-io/n8n/commit/cb383388f6e43ae41e1e6511e803fae0f1aa2506)) +* **editor:** Add evaluation trigger from setup ([#31102](https://github.com/n8n-io/n8n/issues/31102)) ([5504361](https://github.com/n8n-io/n8n/commit/5504361d0f06b03b26e609e314835e97594917a4)) +* **editor:** Allow editing IdP mapping rules when SSO is configured v… ([#31809](https://github.com/n8n-io/n8n/issues/31809)) ([b9af480](https://github.com/n8n-io/n8n/commit/b9af480f755379e0ed8b00537976c894c071b414)) +* **editor:** Attribute experiment telemetry in PostHog ([#31137](https://github.com/n8n-io/n8n/issues/31137)) ([4ea8068](https://github.com/n8n-io/n8n/commit/4ea80680d8e674c9d0b85515d3466b2e7805f4ae)) +* **editor:** Constrain debug overwrite pinned data confirmation modal ([#31665](https://github.com/n8n-io/n8n/issues/31665)) ([6e67ffd](https://github.com/n8n-io/n8n/commit/6e67ffda3c14a8be9b816eae1df8c20abf774518)) +* **editor:** Copy only selected markdown editor text ([#31851](https://github.com/n8n-io/n8n/issues/31851)) ([5036147](https://github.com/n8n-io/n8n/commit/5036147430ec365682ab49c47761a69855396446)) +* **editor:** Load all SSO role mapping rules instead of first page ([#31523](https://github.com/n8n-io/n8n/issues/31523)) ([330d441](https://github.com/n8n-io/n8n/commit/330d44148f318c86685882ac3829c42ac76f56b2)) +* **editor:** Make project delete dialog backdrop cover the sidebar ([#31735](https://github.com/n8n-io/n8n/issues/31735)) ([c02665a](https://github.com/n8n-io/n8n/commit/c02665a5b0604053a4727d83a6060e42b373c3b8)) +* **editor:** Move the AI Assistant status line into the conversation flow ([#31811](https://github.com/n8n-io/n8n/issues/31811)) ([4c0628a](https://github.com/n8n-io/n8n/commit/4c0628a5b5287d1a9c3bd61fcc1bde56d6548231)) +* **editor:** Persist switching workflow credential resolver back to system resolver ([#31703](https://github.com/n8n-io/n8n/issues/31703)) ([f723f54](https://github.com/n8n-io/n8n/commit/f723f548795a419609d8eb89add4d8f83a8d0211)) +* **editor:** Polish Instance AI panel interactions ([#31903](https://github.com/n8n-io/n8n/issues/31903)) ([054c85d](https://github.com/n8n-io/n8n/commit/054c85d635042a7c60be85d036bb2a3146a26849)) +* **editor:** Polish private credential pills, callout, and banners ([#31604](https://github.com/n8n-io/n8n/issues/31604)) ([7e83c7b](https://github.com/n8n-io/n8n/commit/7e83c7b591e962af09ed41fe791766b2f603c473)) +* **editor:** Preserve non-string JSON values when importing cURL commands ([#31791](https://github.com/n8n-io/n8n/issues/31791)) ([ed09c08](https://github.com/n8n-io/n8n/commit/ed09c08dd45bc2031da753a594336a38c77febb8)) +* **editor:** Preserve workflow redaction policy under instance floor ([#31932](https://github.com/n8n-io/n8n/issues/31932)) ([72ab6d7](https://github.com/n8n-io/n8n/commit/72ab6d770bda66b38ad5065e1454ea03f979073a)) +* **editor:** Reference manage data redaction permission in enforcement dialogs ([#31893](https://github.com/n8n-io/n8n/issues/31893)) ([c05a623](https://github.com/n8n-io/n8n/commit/c05a623b0573dcd2e41f8b5964da04edd61e4e87)) +* **editor:** Reset connection state when switching credential to private ([#31713](https://github.com/n8n-io/n8n/issues/31713)) ([b2942b4](https://github.com/n8n-io/n8n/commit/b2942b4b542a239eb37ccd1e4643c3ab1b012e4d)) +* **editor:** Show data redaction upgrade prompt on unlicensed instances ([#31816](https://github.com/n8n-io/n8n/issues/31816)) ([b755ee4](https://github.com/n8n-io/n8n/commit/b755ee4b32e1310a47e013d3880d32d94d6d1811)) +* **editor:** Show error feedback when copying non-duplicatable triggers ([#31104](https://github.com/n8n-io/n8n/issues/31104)) ([151fd83](https://github.com/n8n-io/n8n/commit/151fd83e0a546dd47820a74fdc5cf7952dbbcb50)) +* **editor:** Show switch-to-static warning after connecting a private credential ([#31712](https://github.com/n8n-io/n8n/issues/31712)) ([f1d87fd](https://github.com/n8n-io/n8n/commit/f1d87fddb2728e77e7a098f65cd54c1b61ae7ea8)) +* Format single-line PEM keys when newlines are stripped on paste ([#31129](https://github.com/n8n-io/n8n/issues/31129)) ([ec44980](https://github.com/n8n-io/n8n/commit/ec44980689cc4e03446362ad273f9d151218d427)) +* **Google Sheets Trigger Node:** Custom OAuth option not availble when there are managed credentials ([#29933](https://github.com/n8n-io/n8n/issues/29933)) ([a44197c](https://github.com/n8n-io/n8n/commit/a44197c13506ec3e220d2280e637d5e5a518518a)) +* Harden mutation picker against low-value source files ([#31914](https://github.com/n8n-io/n8n/issues/31914)) ([7e5c5c4](https://github.com/n8n-io/n8n/commit/7e5c5c4eac26edef7f52074e7eb19e5671d471b4)) +* **HTTP Request Node:** Sign Amazon Bedrock requests as 'bedrock' service ([#31250](https://github.com/n8n-io/n8n/issues/31250)) ([9963143](https://github.com/n8n-io/n8n/commit/9963143c5759a42151f7cbddb53895eb9ced6794)) +* Improve Instance AI workflow-builder eval reliability and node diagnostics ([#31506](https://github.com/n8n-io/n8n/issues/31506)) ([4e0e0ed](https://github.com/n8n-io/n8n/commit/4e0e0ed11a6dfaadc86c9ef566e2e4956c678c5e)) +* **LangChain Code Node:** Hide node from the node catalogue ([#31464](https://github.com/n8n-io/n8n/issues/31464)) ([18d4fdd](https://github.com/n8n-io/n8n/commit/18d4fddebbe3b279eb6fcf04aa945429c65a1e41)) +* **MCP Client Tool Node:** Tie transport lifecycle to execution cancel signal to prevent GET stream leak ([#31087](https://github.com/n8n-io/n8n/issues/31087)) ([2a88b50](https://github.com/n8n-io/n8n/commit/2a88b50360b3acf3d83fe54d00b157aea186e61b)) +* **Microsoft Entra Node:** Refresh expired OAuth2 tokens ([#30943](https://github.com/n8n-io/n8n/issues/30943)) ([ab849d3](https://github.com/n8n-io/n8n/commit/ab849d3fa894acf9edff73d9c499097ec74f56b5)) +* **Postgres Node:** Spread array queryReplacement across multiple bind values ([#31704](https://github.com/n8n-io/n8n/issues/31704)) ([ee7aa0b](https://github.com/n8n-io/n8n/commit/ee7aa0b66a072574c246cd9d43e8178fe9070bb9)) +* **Read/Write Files from Disk Node:** Escape square brackets in file path selector ([#31706](https://github.com/n8n-io/n8n/issues/31706)) ([89ae45f](https://github.com/n8n-io/n8n/commit/89ae45f6ec52dfb0ecda82744f838b7b3d2b8c9b)) +* Remove PLAYWRIGHT_BROWSERS_PATH from install-browsers turbo ([#31856](https://github.com/n8n-io/n8n/issues/31856)) ([a0df2a3](https://github.com/n8n-io/n8n/commit/a0df2a3a941fef369609d490ef0cc74c5b3f74a3)) +* **Salesforce Node:** Preserve detailed API errors in continueOnFail mode ([#30990](https://github.com/n8n-io/n8n/issues/30990)) ([8cfc9d2](https://github.com/n8n-io/n8n/commit/8cfc9d2a60b74a1a5a5f32ffb73344498a4913ec)) +* **Slack Node:** Normalize multiOptions values when expression returns a string ([#31269](https://github.com/n8n-io/n8n/issues/31269)) ([95e4ee7](https://github.com/n8n-io/n8n/commit/95e4ee7ee2b82b8a8fdf23618f04c7f66b30072e)) +* Stabilise midnight-sensitive integration tests and harden CTE ([#31901](https://github.com/n8n-io/n8n/issues/31901)) ([4ef9944](https://github.com/n8n-io/n8n/commit/4ef9944ef6211cf630bf031c48a1e66b0857ec69)) +* **TheHiveProject Node:** Normalize analyzers when expression returns a string ([#31580](https://github.com/n8n-io/n8n/issues/31580)) ([43d32fd](https://github.com/n8n-io/n8n/commit/43d32fd28ff9d3bdabd2b234249d3be5d9ffc6ab)) +* Use logical-or fallback for GitHub env vars in send-metrics ([#31783](https://github.com/n8n-io/n8n/issues/31783)) ([d39d944](https://github.com/n8n-io/n8n/commit/d39d94433518705ad5d05113361b5f7a3ccfaa2d)) + + +### Features + +* Add AWS Assume Role support for Bedrock nodes ([#28663](https://github.com/n8n-io/n8n/issues/28663)) ([add5ab2](https://github.com/n8n-io/n8n/commit/add5ab29dd8ee658573b5b7fdcb29cae1c008702)) +* Add MCP registry instance AI connections endpoints ([#31618](https://github.com/n8n-io/n8n/issues/31618)) ([7efcc31](https://github.com/n8n-io/n8n/commit/7efcc311b5a30afca8441762459eba1d5a695c97)) +* Add support for NVIDIA Nemotron Embeddings Node ([#31797](https://github.com/n8n-io/n8n/issues/31797)) ([3dd9c9d](https://github.com/n8n-io/n8n/commit/3dd9c9d9c4324bbea0c6efa79f88e1727fc5295b)) +* **API:** Expose mfaEnabled field in Public API user endpoints ([#25512](https://github.com/n8n-io/n8n/issues/25512)) ([717b860](https://github.com/n8n-io/n8n/commit/717b8602df6f51b96e97d41dc2e84a8c45b59608)) +* **core:** Add "Additional scopes" field to OIDC SSO setup ([#31708](https://github.com/n8n-io/n8n/issues/31708)) ([f459d73](https://github.com/n8n-io/n8n/commit/f459d73236a49f45dffadda7cfb07c1d9b0c2142)) +* **core:** Add id-only credential resolution to package import ([#31223](https://github.com/n8n-io/n8n/issues/31223)) ([91166af](https://github.com/n8n-io/n8n/commit/91166af946350d2dde411674a94edb0b0819f0e6)) +* **core:** Add inline sub-agent delegation ([#31553](https://github.com/n8n-io/n8n/issues/31553)) ([73d8bbe](https://github.com/n8n-io/n8n/commit/73d8bbe1213755bca6723ab8a0d4893464e739bc)) +* **core:** Add KB tools to orchestrator and planner ([#31608](https://github.com/n8n-io/n8n/issues/31608)) ([21d7daa](https://github.com/n8n-io/n8n/commit/21d7daaa820b9a17f96ad7ba1b4c21121aa31a29)) +* **core:** Add knowledge base to snapshot image ([#31551](https://github.com/n8n-io/n8n/issues/31551)) ([8a245a5](https://github.com/n8n-io/n8n/commit/8a245a5a889023d115e4d020ad11a0accf664cb5)) +* **core:** Add Prometheus metrics for execution data ([#31655](https://github.com/n8n-io/n8n/issues/31655)) ([b858fbe](https://github.com/n8n-io/n8n/commit/b858fbe91f1d941133e10294e0a8e6f6046ba8bf)) +* **core:** Add smooth stream options to agents sdk ([#31715](https://github.com/n8n-io/n8n/issues/31715)) ([790afbc](https://github.com/n8n-io/n8n/commit/790afbcf3dfc8c10169ca7ae3e54d1f242d76108)) +* **core:** Add sub-agent executions ([#31540](https://github.com/n8n-io/n8n/issues/31540)) ([bfff25f](https://github.com/n8n-io/n8n/commit/bfff25f05dd5fbcdf7f5c0f13ecbf96fecbda174)) +* **core:** Add sub-agent session linkage migration ([#31534](https://github.com/n8n-io/n8n/issues/31534)) ([25f2d3c](https://github.com/n8n-io/n8n/commit/25f2d3cf3204248cad6671a8cf7a5817bd58dcea)) +* **core:** Add support for per-user connections to MCP servers from the registry in instance AI ([#31325](https://github.com/n8n-io/n8n/issues/31325)) ([ee3b277](https://github.com/n8n-io/n8n/commit/ee3b277ff0169076a144d44f91607183b1c2c515)) +* **core:** Add workflowConflictPolicy to package import ([#31798](https://github.com/n8n-io/n8n/issues/31798)) ([05985ba](https://github.com/n8n-io/n8n/commit/05985ba1fcde7f75051f08241ae921700d57fe30)) +* **core:** Allow stricter-than-floor workflow redaction updates ([#31304](https://github.com/n8n-io/n8n/issues/31304)) ([de95eb8](https://github.com/n8n-io/n8n/commit/de95eb84ae077052f0df1ef7ca3497e6b4cfeebe)) +* **core:** Apply instance redaction floor to new workflows ([#31532](https://github.com/n8n-io/n8n/issues/31532)) ([21db4bc](https://github.com/n8n-io/n8n/commit/21db4bcd6c9b02f338babdca95b8c8729524eb5b)) +* **core:** Attach executionId and execution deep link to Sentry events ([#31645](https://github.com/n8n-io/n8n/issues/31645)) ([7afc32a](https://github.com/n8n-io/n8n/commit/7afc32a15d7737b886ac519196d0d14488c8899e)) +* **core:** Decouple Instance AI workflow verification from planning ([#31340](https://github.com/n8n-io/n8n/issues/31340)) ([52a1a08](https://github.com/n8n-io/n8n/commit/52a1a0809a7b54b13791840e6d46181ddcdbc781)) +* **core:** Grant execution owners access to their own redacted data ([#31139](https://github.com/n8n-io/n8n/issues/31139)) ([8de9958](https://github.com/n8n-io/n8n/commit/8de9958c5f4417b944793b58671011743f7ebdad)) +* **core:** Implement preview-workflow app ([#31647](https://github.com/n8n-io/n8n/issues/31647)) ([bef0eda](https://github.com/n8n-io/n8n/commit/bef0edaccf02fe8f4d1395ef6ad3513e67a45fa1)) +* **core:** Invalidate instance-ai build-workflow cache on canvas edits ([#31274](https://github.com/n8n-io/n8n/issues/31274)) ([e27c4fe](https://github.com/n8n-io/n8n/commit/e27c4feaca1c8fda39040b9b717448bfdeb9e3ee)) +* **core:** Monitor and recover Postgres connection pool ([#31008](https://github.com/n8n-io/n8n/issues/31008)) ([957fdec](https://github.com/n8n-io/n8n/commit/957fdecabcc4dd679fb03ea3bee34d4febc4db90)) +* **core:** Replace get_suggested_nodes MCP tool with get_workflow_best_practices ([#31048](https://github.com/n8n-io/n8n/issues/31048)) ([cc9fa17](https://github.com/n8n-io/n8n/commit/cc9fa172c81ae6fa77bb07b954813abb44f93e0e)) +* **core:** Revamp infisical implementation ([#30843](https://github.com/n8n-io/n8n/issues/30843)) ([a82384f](https://github.com/n8n-io/n8n/commit/a82384f90d60fb688921d4d9237c70529ec04641)) +* **core:** Signal team-projects availability via MCP search_projects ([#31445](https://github.com/n8n-io/n8n/issues/31445)) ([dba4717](https://github.com/n8n-io/n8n/commit/dba4717f485fe0ac22fa3e1b370f6ffa920dd197)) +* **core:** Split API key scopes and let admins see and revoke any key ([#31237](https://github.com/n8n-io/n8n/issues/31237)) ([4120447](https://github.com/n8n-io/n8n/commit/412044731e4536fb27ffc0dccd247cf01fc1b5a2)) +* **core:** Support inline sub-agent difficulty models ([#31749](https://github.com/n8n-io/n8n/issues/31749)) ([950e99f](https://github.com/n8n-io/n8n/commit/950e99f399aef26a9c3b538837acc52cbf880970)) +* **core:** Track OpenTelemetry usage telemetry ([#31570](https://github.com/n8n-io/n8n/issues/31570)) ([c32a33c](https://github.com/n8n-io/n8n/commit/c32a33cda2c5ed43a4e9c5febcf27cb92e379cad)) +* **core:** Track redaction policy source on execution runtime data ([#31079](https://github.com/n8n-io/n8n/issues/31079)) ([58b0965](https://github.com/n8n-io/n8n/commit/58b0965f66b6d3b4c08ed15bf29133f4a1aaf0fd)) +* **core:** Use maxChildren for sub-agent fanout ([#31730](https://github.com/n8n-io/n8n/issues/31730)) ([34f85d9](https://github.com/n8n-io/n8n/commit/34f85d9f72dbe5a299c180573d671ccb9ee98289)) +* **editor:** Add Mine and All tabs to the API keys settings ([#31239](https://github.com/n8n-io/n8n/issues/31239)) ([1401190](https://github.com/n8n-io/n8n/commit/1401190289e2121377e2f1703c3dc4f1805460ad)) +* **editor:** Add pagination to MCP workflows table ([#31780](https://github.com/n8n-io/n8n/issues/31780)) ([4f3669c](https://github.com/n8n-io/n8n/commit/4f3669c35b7c9b972d91bced05a4a4d3b868db16)) +* **editor:** Add shared tools-connection modal ([#31381](https://github.com/n8n-io/n8n/issues/31381)) ([11dfca2](https://github.com/n8n-io/n8n/commit/11dfca24d9ccc8f48a5dd3aa9ffa42e8b56a1a70)) +* Gate custom telemetry attributes by license ([#31723](https://github.com/n8n-io/n8n/issues/31723)) ([b66d33c](https://github.com/n8n-io/n8n/commit/b66d33c305ee67ef2a4bc518b41e8db999c76b3d)) +* **Google Cloud Storage Node:** Add service account authentication ([#30928](https://github.com/n8n-io/n8n/issues/30928)) ([b430039](https://github.com/n8n-io/n8n/commit/b43003934961b7565144053965189f0f91f202ce)) +* Implements AI Assistant empty state workflow previews experiment ([#31519](https://github.com/n8n-io/n8n/issues/31519)) ([ef3a560](https://github.com/n8n-io/n8n/commit/ef3a5606e00a4db478aa262cf447dc71343599a9)) +* MCP registry servers support extending existing credentials ([#31460](https://github.com/n8n-io/n8n/issues/31460)) ([0d7297c](https://github.com/n8n-io/n8n/commit/0d7297c6809803e51a55b5cc24b7a2629f9f232c)) +* **NVIDIA Nemotron Chat Model Node:** Restrict model selector to supported models ([#31698](https://github.com/n8n-io/n8n/issues/31698)) ([ac4778b](https://github.com/n8n-io/n8n/commit/ac4778bb5c956e6d8e98d347d1e13bcb6ea6d4cd)) +* **Trello Node:** Add OAuth1 credential support ([#30369](https://github.com/n8n-io/n8n/issues/30369)) ([700b1cd](https://github.com/n8n-io/n8n/commit/700b1cd2273dba798257b3f310de8b0068138fdc)) + + +### Performance Improvements + +* **core:** Skip execution data pre-read on full overwrite ([#31634](https://github.com/n8n-io/n8n/issues/31634)) ([c8ef1be](https://github.com/n8n-io/n8n/commit/c8ef1be0d4a6d9f7ad877765b4b30e581541048b)) +* Reduce Instance AI memory usage ([#31656](https://github.com/n8n-io/n8n/issues/31656)) ([7e8c042](https://github.com/n8n-io/n8n/commit/7e8c04299cdbc641a18ee49cd4ce3eb3c2c3a920)) + + # [2.25.0](https://github.com/n8n-io/n8n/compare/n8n@2.24.0...n8n@2.25.0) (2026-06-02) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index dc09e06539b..5e70ac087bb 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -135,6 +135,21 @@ brew install actionlint ``` > **Note:** actionlint is only required if you're modifying workflow files. It runs automatically via git hooks when workflow files are changed. +#### tbls (for database schema docs) + +The database schema docs under [`docs/generated/`](docs/generated) are generated from the migrations with [tbls](https://github.com/k1LoW/tbls). If you plan to modify DB migrations, you'll need **either** tbls installed **or** Docker available. + +**macOS (Homebrew):** +```bash +brew install tbls +``` + +For other platforms, see the [tbls install guide](https://github.com/k1LoW/tbls#install). + +> **Note:** tbls is only required if you're modifying DB migrations. It runs automatically via git hooks when migration files are changed. + +--- + ### Actual n8n setup > **IMPORTANT**: All the steps below have to get executed at least once to get the development setup up and running! diff --git a/biome.jsonc b/biome.jsonc index c4d1ee78581..8057f9e4d12 100644 --- a/biome.jsonc +++ b/biome.jsonc @@ -31,7 +31,13 @@ "attributePosition": "auto", "ignore": [ // Handled by prettier - "**/*.vue" + "**/*.vue", + // Generated DB schema docs + "docs/generated/**", + // Generated / vendored test-impact data + ".github/test-metrics/**", + // Vendored SPDX license data and overrides + "scripts/licenses/**" ] }, "organizeImports": { "enabled": false }, diff --git a/codecov.yml b/codecov.yml index 7598d9682af..3939969fbff 100644 --- a/codecov.yml +++ b/codecov.yml @@ -17,6 +17,8 @@ coverage: project: default: threshold: 0.5 + flags: + - nightly-full github_checks: annotations: false @@ -36,6 +38,10 @@ flags: carryforward: true python: carryforward: true + nightly-full: + carryforward: true + nightly-python: + carryforward: true component_management: default_rules: diff --git a/docker/images/engine/Dockerfile b/docker/images/engine/Dockerfile index 8498b42d7eb..01479b0613e 100644 --- a/docker/images/engine/Dockerfile +++ b/docker/images/engine/Dockerfile @@ -1,4 +1,4 @@ -ARG NODE_VERSION=24.15.0 +ARG NODE_VERSION=24.16.0 FROM node:${NODE_VERSION}-alpine3.22 diff --git a/docker/images/n8n-base/Dockerfile b/docker/images/n8n-base/Dockerfile index e838faff902..fbf20988bdc 100644 --- a/docker/images/n8n-base/Dockerfile +++ b/docker/images/n8n-base/Dockerfile @@ -1,6 +1,9 @@ -ARG NODE_VERSION=24.15.0 +ARG NODE_VERSION=24.16.0 -FROM dhi.io/node:${NODE_VERSION}-alpine3.22-dev +# Pinned to multi-arch index digest (linux/amd64 + linux/arm64) for reproducible builds. +# Bump the digest together with the tag when updating the base image. +# Digest pins to dhi.io/node:24.16.0-alpine3.22-dev (Node 24.16.0, Alpine 3.22, DHI dev variant). +FROM dhi.io/node:24.16.0-alpine3.22-dev@sha256:67906dda1e458153488aecb9a7a5a926cb03cf1e8890eb8602a86a78162b2556 ARG NODE_VERSION @@ -12,13 +15,13 @@ RUN apk add --no-cache busybox-binsh && \ fc-cache -f && \ apk del .build-deps-fonts && \ find /usr/share/fonts/truetype/msttcorefonts/ -type l -exec unlink {} \; && \ - # Install OS dependencies - apk update && \ - apk upgrade --no-cache && \ + # Install OS dependencies. No blanket `apk upgrade` — it floats the whole + # world off the Alpine repos at build time and defeats the pinned base; + # patched bytes come from bumping the pinned DHI digest instead. git and + # openssl omitted: the base already provides git and the libssl3/libcrypto3 + # libs Node uses (the openssl CLI binary isn't needed at runtime). apk add --no-cache \ - git \ openssh \ - openssl \ graphicsmagick=1.3.45-r0 `# pinned to avoid ghostscript-fonts (GPL-2.0); see SEC-398 + NODE-4184` \ tini \ tzdata \ diff --git a/docker/images/n8n/Dockerfile b/docker/images/n8n/Dockerfile index 4b6a018b467..55c7a45a166 100644 --- a/docker/images/n8n/Dockerfile +++ b/docker/images/n8n/Dockerfile @@ -1,8 +1,11 @@ -ARG NODE_VERSION=24.15.0 +ARG NODE_VERSION=24.16.0 ARG N8N_VERSION=snapshot # Builder stage exists because the runtime base image has no toolchain. -FROM node:${NODE_VERSION}-alpine3.22 AS builder +# Pinned to multi-arch index digest (linux/amd64 + linux/arm64) for reproducible builds. +# Bump the digest together with the tag when updating the base image. +# Digest pins to node:24.16.0-alpine3.22 (Node 24.16.0, Alpine 3.22). +FROM node:24.16.0-alpine3.22@sha256:191c9f0080fcbbc6547a85dc0ff7988072214a355aabdc1d2ec55a7dae5eea8a AS builder COPY ./compiled /usr/local/lib/node_modules/n8n RUN apk add --no-cache python3 make g++ && \ cd /usr/local/lib/node_modules/n8n && \ @@ -13,11 +16,20 @@ RUN apk add --no-cache python3 make g++ && \ # Removing prebuilds and invoking node-gyp directly avoids npm rebuild's # double-build behavior (built-in node-gyp + install-script node-gyp) # which races on dep-file state. + # Use npm's bundled node-gyp rather than `npx node-gyp` so the toolchain + # version is fixed by the pinned image digest instead of being fetched + # from the registry at build time. rm -rf node_modules/isolated-vm/prebuilds && \ cd node_modules/isolated-vm && \ - npx --yes node-gyp rebuild --release -j max + node /usr/local/lib/node_modules/npm/node_modules/node-gyp/bin/node-gyp.js rebuild --release -j max -FROM n8nio/base:${NODE_VERSION} +# Pinned to multi-arch index digest (linux/amd64 + linux/arm64) for reproducible builds. +# n8nio/base is republished by a separate workflow (docker/images/n8n-base) on every +# base change, so a base rebuild does not reach this image until the digest is +# manually re-pinned here. Bump the digest together with the tag whenever the base +# image is intentionally updated. +# Digest pins to n8nio/base:24.16.0 (Node 24.16.0, Alpine 3.22). +FROM n8nio/base:24.16.0@sha256:a1aa4005e4faebd6da3ba51ec28180a3fb421243d921fa0efbba2d21395012f0 ARG N8N_VERSION ARG N8N_RELEASE_TYPE=dev diff --git a/docker/images/runners/Dockerfile b/docker/images/runners/Dockerfile index 73ecae4d1e5..c1dfadfc9b5 100644 --- a/docker/images/runners/Dockerfile +++ b/docker/images/runners/Dockerfile @@ -1,4 +1,4 @@ -ARG NODE_VERSION=24.15.0 +ARG NODE_VERSION=24.16.0 ARG PYTHON_VERSION=3.13 # ============================================================================== @@ -82,7 +82,7 @@ RUN uv pip install . && rm -rf /app/task-runner-python/src # ============================================================================== FROM alpine:3.22 AS launcher-downloader ARG TARGETPLATFORM -ARG LAUNCHER_VERSION=1.4.6 +ARG LAUNCHER_VERSION=1.4.7 RUN set -e; \ case "$TARGETPLATFORM" in \ diff --git a/docker/images/runners/Dockerfile.distroless b/docker/images/runners/Dockerfile.distroless index 2448c562109..8aa8f5b2a92 100644 --- a/docker/images/runners/Dockerfile.distroless +++ b/docker/images/runners/Dockerfile.distroless @@ -7,12 +7,12 @@ # # Key differences: # - Uses Debian-based builders (glibc instead of musl) -# - Final image is Google's distroless/cc-debian12 +# - Final image is Google's distroless/cc-debian13 # - Extra runtime-prep stage to organize filesystem # - Uses distroless nonroot user (UID 65532) # ============================================================================== -ARG NODE_VERSION=24.15.0 +ARG NODE_VERSION=24.16.0 ARG PYTHON_VERSION=3.13 @@ -106,7 +106,7 @@ RUN uv pip install . && rm -rf /app/task-runner-python/src # ============================================================================== FROM debian:bookworm-slim AS launcher-downloader ARG TARGETPLATFORM -ARG LAUNCHER_VERSION=1.4.6 +ARG LAUNCHER_VERSION=1.4.7 RUN set -e; \ apt-get update && apt-get install -y --no-install-recommends wget ca-certificates && \ @@ -146,7 +146,10 @@ COPY --from=python-runner-builder /usr/local/lib/libpython3.13.so* /runtime/usr/ # Copy Python dependencies (architecture-specific directories) # The /* glob will match x86_64-linux-gnu or aarch64-linux-gnu -COPY --from=python-runner-builder /lib/*-linux-gnu* /runtime/lib/ +# Stage glibc into /usr/lib/ because cc-debian13 completes the usr-merge: +# /lib is a symlink to /usr/lib, so a final COPY into /lib/ would collide +# with that symlink at the runtime stage. +COPY --from=python-runner-builder /lib/*-linux-gnu* /runtime/usr/lib/ COPY --from=python-runner-builder /usr/lib/*-linux-gnu* /runtime/usr/lib/ # Copy Node.js runtime @@ -170,14 +173,14 @@ RUN mkdir -p /runtime/home/runner && \ # ============================================================================== # STAGE 6: Distroless Runtime # ============================================================================== -# Uses Google's distroless/cc-debian12 which provides: +# Uses Google's distroless/cc-debian13 which provides: # - glibc, libgcc, libstdc++ # - CA certificates # - Timezone data # - nonroot user (UID 65532) # - NO shell, NO package manager, NO system utilities # ============================================================================== -FROM gcr.io/distroless/cc-debian12:latest AS runtime +FROM gcr.io/distroless/cc-debian13:latest AS runtime ARG N8N_VERSION=snapshot ARG N8N_RELEASE_TYPE=dev diff --git a/docs/db.md b/docs/db.md new file mode 100644 index 00000000000..5dd4eeab09c --- /dev/null +++ b/docs/db.md @@ -0,0 +1,37 @@ +# Database + +n8n persists its state in a relational database, accessed through TypeORM. The +schema supports both SQLite (the default) and PostgreSQL, and is defined by the +**migrations** in `@n8n/db` rather than the entities (entities run with +`synchronize: false`). + +## Schema reference + +Auto-generated documentation of the schema, one set per supported database: + +- [SQLite](./generated/sqlite-schema/README.md) +- [PostgreSQL](./generated/postgres-schema/README.md) + +Each set lists every table with its columns, types, defaults, indexes, and +foreign keys, plus a Mermaid ER diagram of the relationships. The two differ +where the column types do (e.g. `datetime` vs `timestamptz`, `text`/`simple-json` +vs `json`/`jsonb`, `boolean` representation). + +### How it's generated + +The generator spins up an empty database, runs the full `@n8n/db` migration set +against it, and points [tbls](https://github.com/k1LoW/tbls) at the result. +SQLite uses a throwaway file; PostgreSQL uses a throwaway testcontainer, so +**Docker is required**. + +```bash +# Regenerate both (requires Docker; tbls locally via `brew install tbls`) +pnpm db:schema:docs + +# Verify the committed docs match the current migrations +pnpm db:schema:check +``` + +The schema reference is **auto-generated — do not edit by hand.** CI fails when +a migration changes the schema but the docs weren't regenerated; when that +happens, run `pnpm db:schema:docs` and commit the result. diff --git a/docs/generated/postgres-schema/README.md b/docs/generated/postgres-schema/README.md new file mode 100644 index 00000000000..f5df60e6608 --- /dev/null +++ b/docs/generated/postgres-schema/README.md @@ -0,0 +1,1322 @@ +# n8n database schema (PostgreSQL) + +## Description + +Auto-generated from the PostgreSQL migrations in @n8n/db. Do not edit by hand. + +## Tables + +| Name | Columns | Comment | Type | +| ---- | ------- | ------- | ---- | +| [public.agent_chat_subscriptions](public.agent_chat_subscriptions.md) | 6 | | BASE TABLE | +| [public.agent_checkpoints](public.agent_checkpoints.md) | 6 | | BASE TABLE | +| [public.agent_execution](public.agent_execution.md) | 20 | | BASE TABLE | +| [public.agent_execution_threads](public.agent_execution_threads.md) | 17 | | BASE TABLE | +| [public.agent_files](public.agent_files.md) | 8 | | BASE TABLE | +| [public.agent_history](public.agent_history.md) | 9 | | BASE TABLE | +| [public.agent_task_definition](public.agent_task_definition.md) | 7 | | 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) | 8 | | BASE TABLE | +| [public.agents](public.agents.md) | 12 | | BASE TABLE | +| [public.agents_memory_entries](public.agents_memory_entries.md) | 13 | | BASE TABLE | +| [public.agents_memory_entry_cursors](public.agents_memory_entry_cursors.md) | 6 | | BASE TABLE | +| [public.agents_memory_entry_locks](public.agents_memory_entry_locks.md) | 6 | | BASE TABLE | +| [public.agents_memory_entry_sources](public.agents_memory_entry_sources.md) | 9 | | BASE TABLE | +| [public.agents_messages](public.agents_messages.md) | 8 | | BASE TABLE | +| [public.agents_observation_cursors](public.agents_observation_cursors.md) | 6 | | BASE TABLE | +| [public.agents_observation_locks](public.agents_observation_locks.md) | 7 | | BASE TABLE | +| [public.agents_observations](public.agents_observations.md) | 11 | | BASE TABLE | +| [public.agents_resources](public.agents_resources.md) | 4 | | BASE TABLE | +| [public.agents_threads](public.agents_threads.md) | 6 | | BASE TABLE | +| [public.ai_builder_temporary_workflow](public.ai_builder_temporary_workflow.md) | 4 | | BASE TABLE | +| [public.annotation_tag_entity](public.annotation_tag_entity.md) | 4 | | BASE TABLE | +| [public.auth_identity](public.auth_identity.md) | 5 | | BASE TABLE | +| [public.auth_provider_sync_history](public.auth_provider_sync_history.md) | 11 | | BASE TABLE | +| [public.binary_data](public.binary_data.md) | 9 | | BASE TABLE | +| [public.chat_hub_agent_tools](public.chat_hub_agent_tools.md) | 2 | | BASE TABLE | +| [public.chat_hub_agents](public.chat_hub_agents.md) | 13 | | BASE TABLE | +| [public.chat_hub_messages](public.chat_hub_messages.md) | 17 | | BASE TABLE | +| [public.chat_hub_session_tools](public.chat_hub_session_tools.md) | 2 | | BASE TABLE | +| [public.chat_hub_sessions](public.chat_hub_sessions.md) | 13 | | BASE TABLE | +| [public.chat_hub_tools](public.chat_hub_tools.md) | 9 | | BASE TABLE | +| [public.credential_dependency](public.credential_dependency.md) | 5 | | BASE TABLE | +| [public.credentials_entity](public.credentials_entity.md) | 11 | | BASE TABLE | +| [public.data_table](public.data_table.md) | 5 | | BASE TABLE | +| [public.data_table_column](public.data_table_column.md) | 7 | | BASE TABLE | +| [public.deployment_key](public.deployment_key.md) | 7 | | BASE TABLE | +| [public.dynamic_credential_entry](public.dynamic_credential_entry.md) | 6 | | BASE TABLE | +| [public.dynamic_credential_resolver](public.dynamic_credential_resolver.md) | 6 | | BASE TABLE | +| [public.dynamic_credential_user_entry](public.dynamic_credential_user_entry.md) | 6 | | BASE TABLE | +| [public.evaluation_collection](public.evaluation_collection.md) | 9 | | BASE TABLE | +| [public.evaluation_config](public.evaluation_config.md) | 12 | | BASE TABLE | +| [public.event_destinations](public.event_destinations.md) | 4 | | BASE TABLE | +| [public.execution_annotation_tags](public.execution_annotation_tags.md) | 2 | | BASE TABLE | +| [public.execution_annotations](public.execution_annotations.md) | 6 | | BASE TABLE | +| [public.execution_data](public.execution_data.md) | 4 | | BASE TABLE | +| [public.execution_entity](public.execution_entity.md) | 18 | | BASE TABLE | +| [public.execution_metadata](public.execution_metadata.md) | 4 | | BASE TABLE | +| [public.folder](public.folder.md) | 6 | | BASE TABLE | +| [public.folder_tag](public.folder_tag.md) | 2 | | BASE TABLE | +| [public.insights_by_period](public.insights_by_period.md) | 6 | | BASE TABLE | +| [public.insights_metadata](public.insights_metadata.md) | 5 | | BASE TABLE | +| [public.insights_raw](public.insights_raw.md) | 5 | | BASE TABLE | +| [public.installed_nodes](public.installed_nodes.md) | 4 | | BASE TABLE | +| [public.installed_packages](public.installed_packages.md) | 6 | | BASE TABLE | +| [public.instance_ai_checkpoints](public.instance_ai_checkpoints.md) | 8 | | BASE TABLE | +| [public.instance_ai_iteration_logs](public.instance_ai_iteration_logs.md) | 6 | | BASE TABLE | +| [public.instance_ai_mcp_registry_connections](public.instance_ai_mcp_registry_connections.md) | 7 | | BASE TABLE | +| [public.instance_ai_messages](public.instance_ai_messages.md) | 8 | | BASE TABLE | +| [public.instance_ai_observation_cursors](public.instance_ai_observation_cursors.md) | 5 | | BASE TABLE | +| [public.instance_ai_observation_locks](public.instance_ai_observation_locks.md) | 6 | | BASE TABLE | +| [public.instance_ai_observational_memory](public.instance_ai_observational_memory.md) | 32 | | BASE TABLE | +| [public.instance_ai_observations](public.instance_ai_observations.md) | 10 | | BASE TABLE | +| [public.instance_ai_pending_confirmations](public.instance_ai_pending_confirmations.md) | 12 | | BASE TABLE | +| [public.instance_ai_resources](public.instance_ai_resources.md) | 5 | | BASE TABLE | +| [public.instance_ai_run_snapshots](public.instance_ai_run_snapshots.md) | 11 | | BASE TABLE | +| [public.instance_ai_threads](public.instance_ai_threads.md) | 7 | | BASE TABLE | +| [public.instance_ai_workflow_snapshots](public.instance_ai_workflow_snapshots.md) | 7 | | BASE TABLE | +| [public.instance_version_history](public.instance_version_history.md) | 5 | | BASE TABLE | +| [public.invalid_auth_token](public.invalid_auth_token.md) | 2 | | BASE TABLE | +| [public.mcp_registry_server](public.mcp_registry_server.md) | 7 | | BASE TABLE | +| [public.oauth_access_tokens](public.oauth_access_tokens.md) | 3 | | BASE TABLE | +| [public.oauth_authorization_codes](public.oauth_authorization_codes.md) | 13 | | BASE TABLE | +| [public.oauth_clients](public.oauth_clients.md) | 9 | | BASE TABLE | +| [public.oauth_refresh_tokens](public.oauth_refresh_tokens.md) | 7 | | BASE TABLE | +| [public.oauth_user_consents](public.oauth_user_consents.md) | 4 | | BASE TABLE | +| [public.processed_data](public.processed_data.md) | 5 | | BASE TABLE | +| [public.project](public.project.md) | 9 | | BASE TABLE | +| [public.project_relation](public.project_relation.md) | 5 | | BASE TABLE | +| [public.project_secrets_provider_access](public.project_secrets_provider_access.md) | 5 | | BASE TABLE | +| [public.role](public.role.md) | 7 | | BASE TABLE | +| [public.role_mapping_rule](public.role_mapping_rule.md) | 7 | | BASE TABLE | +| [public.role_mapping_rule_project](public.role_mapping_rule_project.md) | 2 | | BASE TABLE | +| [public.role_scope](public.role_scope.md) | 2 | | BASE TABLE | +| [public.scope](public.scope.md) | 3 | | BASE TABLE | +| [public.secrets_provider_connection](public.secrets_provider_connection.md) | 7 | | BASE TABLE | +| [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.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 | +| [public.token_exchange_jti](public.token_exchange_jti.md) | 3 | | BASE TABLE | +| [public.trusted_key](public.trusted_key.md) | 4 | | BASE TABLE | +| [public.trusted_key_source](public.trusted_key_source.md) | 8 | | BASE TABLE | +| [public.user](public.user.md) | 15 | | BASE TABLE | +| [public.user_api_keys](public.user_api_keys.md) | 9 | | BASE TABLE | +| [public.user_favorites](public.user_favorites.md) | 4 | | BASE TABLE | +| [public.variables](public.variables.md) | 5 | | BASE TABLE | +| [public.webhook_entity](public.webhook_entity.md) | 6 | | BASE TABLE | +| [public.workflow_builder_session](public.workflow_builder_session.md) | 9 | | BASE TABLE | +| [public.workflow_dependency](public.workflow_dependency.md) | 9 | | BASE TABLE | +| [public.workflow_entity](public.workflow_entity.md) | 20 | | BASE TABLE | +| [public.workflow_history](public.workflow_history.md) | 11 | | BASE TABLE | +| [public.workflow_publication_outbox](public.workflow_publication_outbox.md) | 7 | | BASE TABLE | +| [public.workflow_publish_history](public.workflow_publish_history.md) | 6 | | BASE TABLE | +| [public.workflow_published_version](public.workflow_published_version.md) | 4 | | BASE TABLE | +| [public.workflow_statistics](public.workflow_statistics.md) | 7 | | BASE TABLE | +| [public.workflows_tags](public.workflows_tags.md) | 2 | | BASE TABLE | + +## Stored procedures and functions + +| Name | ReturnType | Arguments | Type | +| ---- | ------- | ------- | ---- | +| public.increment_workflow_version | trigger | | FUNCTION | +| public.uuid_generate_v1 | uuid | | FUNCTION | +| public.uuid_generate_v1mc | uuid | | FUNCTION | +| public.uuid_generate_v3 | uuid | namespace uuid, name text | FUNCTION | +| public.uuid_generate_v4 | uuid | | FUNCTION | +| public.uuid_generate_v5 | uuid | namespace uuid, name text | FUNCTION | +| public.uuid_nil | uuid | | FUNCTION | +| public.uuid_ns_dns | uuid | | FUNCTION | +| public.uuid_ns_oid | uuid | | FUNCTION | +| public.uuid_ns_url | uuid | | FUNCTION | +| public.uuid_ns_x500 | uuid | | FUNCTION | + +## Relations + +```mermaid +erDiagram + +"public.agent_chat_subscriptions" }o--|| "public.agents" : "FOREIGN KEY (#quot;agentId#quot;) REFERENCES agents(id) ON DELETE CASCADE" +"public.agent_checkpoints" }o--o| "public.agents" : "FOREIGN KEY (#quot;agentId#quot;) REFERENCES agents(id) ON DELETE CASCADE" +"public.agent_execution" }o--|| "public.agent_execution_threads" : "FOREIGN KEY (#quot;threadId#quot;) REFERENCES agent_execution_threads(id) ON DELETE CASCADE" +"public.agent_execution_threads" }o--|| "public.project" : "FOREIGN KEY (#quot;projectId#quot;) REFERENCES project(id) ON DELETE CASCADE" +"public.agent_execution_threads" }o--|| "public.agents" : "FOREIGN KEY (#quot;agentId#quot;) REFERENCES agents(id) ON DELETE CASCADE" +"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_files" }o--|| "public.agents" : "FOREIGN KEY (#quot;agentId#quot;) REFERENCES agents(id) ON DELETE CASCADE" +"public.agent_history" }o--o| "public.user" : "FOREIGN KEY (#quot;publishedById#quot;) REFERENCES #quot;user#quot;(id) ON DELETE SET NULL" +"public.agent_history" }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_task_snapshot" }o--|| "public.agent_history" : "FOREIGN KEY (#quot;versionId#quot;) REFERENCES agent_history(#quot;versionId#quot;) ON DELETE CASCADE" +"public.agents" }o--|| "public.project" : "FOREIGN KEY (#quot;projectId#quot;) REFERENCES project(id) 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.agents_memory_entries" }o--|| "public.agents" : "FOREIGN KEY (#quot;agentId#quot;) REFERENCES agents(id) ON DELETE CASCADE" +"public.agents_memory_entries" }o--|| "public.agents_resources" : "FOREIGN KEY (#quot;resourceId#quot;) REFERENCES agents_resources(id) ON DELETE CASCADE" +"public.agents_memory_entries" }o--o| "public.agents_memory_entries" : "FOREIGN KEY (#quot;supersededBy#quot;) REFERENCES agents_memory_entries(id)" +"public.agents_memory_entry_cursors" }o--|| "public.agents" : "FOREIGN KEY (#quot;agentId#quot;) REFERENCES agents(id) ON DELETE CASCADE" +"public.agents_memory_entry_cursors" }o--|| "public.agents_threads" : "FOREIGN KEY (#quot;observationScopeId#quot;) REFERENCES agents_threads(id) ON DELETE CASCADE" +"public.agents_memory_entry_locks" }o--|| "public.agents" : "FOREIGN KEY (#quot;agentId#quot;) REFERENCES agents(id) ON DELETE CASCADE" +"public.agents_memory_entry_locks" }o--|| "public.agents_resources" : "FOREIGN KEY (#quot;resourceId#quot;) REFERENCES agents_resources(id) ON DELETE CASCADE" +"public.agents_memory_entry_sources" }o--|| "public.agents" : "FOREIGN KEY (#quot;agentId#quot;) REFERENCES agents(id) ON DELETE CASCADE" +"public.agents_memory_entry_sources" }o--|| "public.agents_observations" : "FOREIGN KEY (#quot;observationId#quot;) REFERENCES agents_observations(id) ON DELETE CASCADE" +"public.agents_memory_entry_sources" }o--|| "public.agents_memory_entries" : "FOREIGN KEY (#quot;memoryEntryId#quot;) REFERENCES agents_memory_entries(id) ON DELETE CASCADE" +"public.agents_memory_entry_sources" }o--|| "public.agents_threads" : "FOREIGN KEY (#quot;threadId#quot;) REFERENCES agents_threads(id) ON DELETE CASCADE" +"public.agents_messages" }o--|| "public.agents_threads" : "FOREIGN KEY (#quot;threadId#quot;) REFERENCES agents_threads(id) ON DELETE CASCADE" +"public.agents_observation_cursors" }o--|| "public.agents" : "FOREIGN KEY (#quot;agentId#quot;) REFERENCES agents(id) ON DELETE CASCADE" +"public.agents_observation_cursors" }o--|| "public.agents_threads" : "FOREIGN KEY (#quot;observationScopeId#quot;) REFERENCES agents_threads(id) ON DELETE CASCADE" +"public.agents_observation_locks" }o--|| "public.agents" : "FOREIGN KEY (#quot;agentId#quot;) REFERENCES agents(id) ON DELETE CASCADE" +"public.agents_observation_locks" }o--|| "public.agents_threads" : "FOREIGN KEY (#quot;observationScopeId#quot;) REFERENCES agents_threads(id) ON DELETE CASCADE" +"public.agents_observations" }o--|| "public.agents" : "FOREIGN KEY (#quot;agentId#quot;) REFERENCES agents(id) ON DELETE CASCADE" +"public.agents_observations" }o--o| "public.agents_observations" : "FOREIGN KEY (#quot;supersededBy#quot;) REFERENCES agents_observations(id)" +"public.agents_observations" }o--o| "public.agents_observations" : "FOREIGN KEY (#quot;parentId#quot;) REFERENCES agents_observations(id)" +"public.agents_observations" }o--|| "public.agents_threads" : "FOREIGN KEY (#quot;observationScopeId#quot;) REFERENCES agents_threads(id) ON DELETE CASCADE" +"public.ai_builder_temporary_workflow" |o--|| "public.workflow_entity" : "FOREIGN KEY (#quot;workflowId#quot;) REFERENCES workflow_entity(id) ON DELETE CASCADE" +"public.ai_builder_temporary_workflow" }o--|| "public.instance_ai_threads" : "FOREIGN KEY (#quot;threadId#quot;) REFERENCES instance_ai_threads(id) ON DELETE CASCADE" +"public.auth_identity" }o--o| "public.user" : "FOREIGN KEY (#quot;userId#quot;) REFERENCES #quot;user#quot;(id)" +"public.chat_hub_agent_tools" }o--|| "public.chat_hub_agents" : "FOREIGN KEY (#quot;agentId#quot;) REFERENCES chat_hub_agents(id) ON DELETE CASCADE" +"public.chat_hub_agent_tools" }o--|| "public.chat_hub_tools" : "FOREIGN KEY (#quot;toolId#quot;) REFERENCES chat_hub_tools(id) ON DELETE CASCADE" +"public.chat_hub_agents" }o--|| "public.user" : "FOREIGN KEY (#quot;ownerId#quot;) REFERENCES #quot;user#quot;(id) ON DELETE CASCADE" +"public.chat_hub_agents" }o--o| "public.credentials_entity" : "FOREIGN KEY (#quot;credentialId#quot;) REFERENCES credentials_entity(id) ON DELETE SET NULL" +"public.chat_hub_messages" }o--o| "public.execution_entity" : "FOREIGN KEY (#quot;executionId#quot;) REFERENCES execution_entity(id) ON DELETE SET NULL" +"public.chat_hub_messages" }o--o| "public.workflow_entity" : "FOREIGN KEY (#quot;workflowId#quot;) REFERENCES workflow_entity(id) ON DELETE SET NULL" +"public.chat_hub_messages" }o--|| "public.chat_hub_sessions" : "FOREIGN KEY (#quot;sessionId#quot;) REFERENCES chat_hub_sessions(id) ON DELETE CASCADE" +"public.chat_hub_messages" }o--o| "public.chat_hub_messages" : "FOREIGN KEY (#quot;revisionOfMessageId#quot;) REFERENCES chat_hub_messages(id) ON DELETE CASCADE" +"public.chat_hub_messages" }o--o| "public.chat_hub_messages" : "FOREIGN KEY (#quot;retryOfMessageId#quot;) REFERENCES chat_hub_messages(id) ON DELETE CASCADE" +"public.chat_hub_messages" }o--o| "public.chat_hub_messages" : "FOREIGN KEY (#quot;previousMessageId#quot;) REFERENCES chat_hub_messages(id) ON DELETE CASCADE" +"public.chat_hub_messages" }o--o| "public.chat_hub_agents" : "FOREIGN KEY (#quot;agentId#quot;) REFERENCES chat_hub_agents(id) ON DELETE SET NULL" +"public.chat_hub_session_tools" }o--|| "public.chat_hub_sessions" : "FOREIGN KEY (#quot;sessionId#quot;) REFERENCES chat_hub_sessions(id) ON DELETE CASCADE" +"public.chat_hub_session_tools" }o--|| "public.chat_hub_tools" : "FOREIGN KEY (#quot;toolId#quot;) REFERENCES chat_hub_tools(id) ON DELETE CASCADE" +"public.chat_hub_sessions" }o--|| "public.user" : "FOREIGN KEY (#quot;ownerId#quot;) REFERENCES #quot;user#quot;(id) ON DELETE CASCADE" +"public.chat_hub_sessions" }o--o| "public.workflow_entity" : "FOREIGN KEY (#quot;workflowId#quot;) REFERENCES workflow_entity(id) ON DELETE SET NULL" +"public.chat_hub_sessions" }o--o| "public.credentials_entity" : "FOREIGN KEY (#quot;credentialId#quot;) REFERENCES credentials_entity(id) ON DELETE SET NULL" +"public.chat_hub_sessions" }o--o| "public.chat_hub_agents" : "FOREIGN KEY (#quot;agentId#quot;) REFERENCES chat_hub_agents(id) ON DELETE SET NULL" +"public.chat_hub_tools" }o--|| "public.user" : "FOREIGN KEY (#quot;ownerId#quot;) REFERENCES #quot;user#quot;(id) ON DELETE CASCADE" +"public.credential_dependency" }o--|| "public.credentials_entity" : "FOREIGN KEY (#quot;credentialId#quot;) REFERENCES credentials_entity(id) ON DELETE CASCADE" +"public.credentials_entity" }o--o| "public.dynamic_credential_resolver" : "FOREIGN KEY (#quot;resolverId#quot;) REFERENCES dynamic_credential_resolver(id) ON DELETE SET NULL" +"public.data_table" }o--|| "public.project" : "FOREIGN KEY (#quot;projectId#quot;) REFERENCES project(id) ON DELETE CASCADE" +"public.data_table_column" }o--|| "public.data_table" : "FOREIGN KEY (#quot;dataTableId#quot;) REFERENCES data_table(id) ON DELETE CASCADE" +"public.dynamic_credential_entry" }o--|| "public.credentials_entity" : "FOREIGN KEY (credential_id) REFERENCES credentials_entity(id) ON DELETE CASCADE" +"public.dynamic_credential_entry" }o--|| "public.dynamic_credential_resolver" : "FOREIGN KEY (resolver_id) REFERENCES dynamic_credential_resolver(id) ON DELETE CASCADE" +"public.dynamic_credential_user_entry" }o--|| "public.user" : "FOREIGN KEY (#quot;userId#quot;) REFERENCES #quot;user#quot;(id) ON DELETE CASCADE" +"public.dynamic_credential_user_entry" }o--|| "public.credentials_entity" : "FOREIGN KEY (#quot;credentialId#quot;) REFERENCES credentials_entity(id) ON DELETE CASCADE" +"public.dynamic_credential_user_entry" }o--|| "public.dynamic_credential_resolver" : "FOREIGN KEY (#quot;resolverId#quot;) REFERENCES dynamic_credential_resolver(id) ON DELETE CASCADE" +"public.evaluation_collection" }o--o| "public.user" : "FOREIGN KEY (#quot;createdById#quot;) REFERENCES #quot;user#quot;(id) ON DELETE SET NULL" +"public.evaluation_collection" }o--|| "public.workflow_entity" : "FOREIGN KEY (#quot;workflowId#quot;) REFERENCES workflow_entity(id) ON DELETE CASCADE" +"public.evaluation_collection" }o--|| "public.evaluation_config" : "FOREIGN KEY (#quot;evaluationConfigId#quot;) REFERENCES evaluation_config(id) ON DELETE CASCADE" +"public.evaluation_config" }o--|| "public.workflow_entity" : "FOREIGN KEY (#quot;workflowId#quot;) REFERENCES workflow_entity(id) ON DELETE CASCADE" +"public.execution_annotation_tags" }o--|| "public.execution_annotations" : "FOREIGN KEY (#quot;annotationId#quot;) REFERENCES execution_annotations(id) ON DELETE CASCADE" +"public.execution_annotation_tags" }o--|| "public.annotation_tag_entity" : "FOREIGN KEY (#quot;tagId#quot;) REFERENCES annotation_tag_entity(id) ON DELETE CASCADE" +"public.execution_annotations" }o--|| "public.execution_entity" : "FOREIGN KEY (#quot;executionId#quot;) REFERENCES execution_entity(id) ON DELETE CASCADE" +"public.execution_data" |o--|| "public.execution_entity" : "FOREIGN KEY (#quot;executionId#quot;) REFERENCES execution_entity(id) ON DELETE CASCADE" +"public.execution_entity" }o--|| "public.workflow_entity" : "FOREIGN KEY (#quot;workflowId#quot;) REFERENCES workflow_entity(id) ON DELETE CASCADE" +"public.execution_metadata" }o--|| "public.execution_entity" : "FOREIGN KEY (#quot;executionId#quot;) REFERENCES execution_entity(id) ON DELETE CASCADE" +"public.folder" }o--|| "public.project" : "FOREIGN KEY (#quot;projectId#quot;) REFERENCES project(id) ON DELETE CASCADE" +"public.folder" }o--o| "public.folder" : "FOREIGN KEY (#quot;parentFolderId#quot;) REFERENCES folder(id) ON DELETE CASCADE" +"public.folder_tag" }o--|| "public.tag_entity" : "FOREIGN KEY (#quot;tagId#quot;) REFERENCES tag_entity(id) ON DELETE CASCADE" +"public.folder_tag" }o--|| "public.folder" : "FOREIGN KEY (#quot;folderId#quot;) REFERENCES folder(id) ON DELETE CASCADE" +"public.insights_by_period" }o--|| "public.insights_metadata" : "FOREIGN KEY (#quot;metaId#quot;) REFERENCES insights_metadata(#quot;metaId#quot;) ON DELETE CASCADE" +"public.insights_metadata" }o--o| "public.workflow_entity" : "FOREIGN KEY (#quot;workflowId#quot;) REFERENCES workflow_entity(id) ON DELETE SET NULL" +"public.insights_metadata" }o--o| "public.project" : "FOREIGN KEY (#quot;projectId#quot;) REFERENCES project(id) ON DELETE SET NULL" +"public.insights_raw" }o--|| "public.insights_metadata" : "FOREIGN KEY (#quot;metaId#quot;) REFERENCES insights_metadata(#quot;metaId#quot;) ON DELETE CASCADE" +"public.installed_nodes" }o--|| "public.installed_packages" : "FOREIGN KEY (package) REFERENCES installed_packages(#quot;packageName#quot;) ON UPDATE CASCADE ON DELETE CASCADE" +"public.instance_ai_checkpoints" }o--|| "public.instance_ai_threads" : "FOREIGN KEY (#quot;threadId#quot;) REFERENCES instance_ai_threads(id) ON DELETE CASCADE" +"public.instance_ai_iteration_logs" }o--|| "public.instance_ai_threads" : "FOREIGN KEY (#quot;threadId#quot;) REFERENCES instance_ai_threads(id) ON DELETE CASCADE" +"public.instance_ai_mcp_registry_connections" }o--|| "public.user" : "FOREIGN KEY (#quot;userId#quot;) REFERENCES #quot;user#quot;(id) ON DELETE CASCADE" +"public.instance_ai_mcp_registry_connections" }o--|| "public.credentials_entity" : "FOREIGN KEY (#quot;credentialId#quot;) REFERENCES credentials_entity(id) ON DELETE CASCADE" +"public.instance_ai_mcp_registry_connections" }o--|| "public.mcp_registry_server" : "FOREIGN KEY (#quot;serverSlug#quot;) REFERENCES mcp_registry_server(slug) ON DELETE CASCADE" +"public.instance_ai_messages" }o--|| "public.instance_ai_threads" : "FOREIGN KEY (#quot;threadId#quot;) REFERENCES instance_ai_threads(id) ON DELETE CASCADE" +"public.instance_ai_observation_cursors" |o--|| "public.instance_ai_threads" : "FOREIGN KEY (#quot;observationScopeId#quot;) REFERENCES instance_ai_threads(id) ON DELETE CASCADE" +"public.instance_ai_observation_locks" }o--|| "public.instance_ai_threads" : "FOREIGN KEY (#quot;observationScopeId#quot;) REFERENCES instance_ai_threads(id) ON DELETE CASCADE" +"public.instance_ai_observational_memory" }o--o| "public.instance_ai_threads" : "FOREIGN KEY (#quot;threadId#quot;) REFERENCES instance_ai_threads(id) ON DELETE SET NULL" +"public.instance_ai_observations" }o--|| "public.instance_ai_threads" : "FOREIGN KEY (#quot;observationScopeId#quot;) REFERENCES instance_ai_threads(id) ON DELETE CASCADE" +"public.instance_ai_observations" }o--o| "public.instance_ai_observations" : "FOREIGN KEY (#quot;supersededBy#quot;) REFERENCES instance_ai_observations(id)" +"public.instance_ai_observations" }o--o| "public.instance_ai_observations" : "FOREIGN KEY (#quot;parentId#quot;) REFERENCES instance_ai_observations(id)" +"public.instance_ai_pending_confirmations" }o--|| "public.user" : "FOREIGN KEY (#quot;userId#quot;) REFERENCES #quot;user#quot;(id) ON DELETE CASCADE" +"public.instance_ai_pending_confirmations" }o--|| "public.instance_ai_threads" : "FOREIGN KEY (#quot;threadId#quot;) REFERENCES instance_ai_threads(id) ON DELETE CASCADE" +"public.instance_ai_pending_confirmations" }o--o| "public.instance_ai_checkpoints" : "FOREIGN KEY (#quot;checkpointKey#quot;) REFERENCES instance_ai_checkpoints(key) ON DELETE CASCADE" +"public.instance_ai_run_snapshots" }o--|| "public.instance_ai_threads" : "FOREIGN KEY (#quot;threadId#quot;) REFERENCES instance_ai_threads(id) ON DELETE CASCADE" +"public.instance_ai_threads" }o--|| "public.project" : "FOREIGN KEY (#quot;projectId#quot;) REFERENCES project(id) ON DELETE CASCADE" +"public.oauth_access_tokens" }o--|| "public.user" : "FOREIGN KEY (#quot;userId#quot;) REFERENCES #quot;user#quot;(id) ON DELETE CASCADE" +"public.oauth_access_tokens" }o--|| "public.oauth_clients" : "FOREIGN KEY (#quot;clientId#quot;) REFERENCES oauth_clients(id) ON DELETE CASCADE" +"public.oauth_authorization_codes" }o--|| "public.user" : "FOREIGN KEY (#quot;userId#quot;) REFERENCES #quot;user#quot;(id) ON DELETE CASCADE" +"public.oauth_authorization_codes" }o--|| "public.oauth_clients" : "FOREIGN KEY (#quot;clientId#quot;) REFERENCES oauth_clients(id) ON DELETE CASCADE" +"public.oauth_refresh_tokens" }o--|| "public.user" : "FOREIGN KEY (#quot;userId#quot;) REFERENCES #quot;user#quot;(id) ON DELETE CASCADE" +"public.oauth_refresh_tokens" }o--|| "public.oauth_clients" : "FOREIGN KEY (#quot;clientId#quot;) REFERENCES oauth_clients(id) ON DELETE CASCADE" +"public.oauth_user_consents" }o--|| "public.user" : "FOREIGN KEY (#quot;userId#quot;) REFERENCES #quot;user#quot;(id) ON DELETE CASCADE" +"public.oauth_user_consents" }o--|| "public.oauth_clients" : "FOREIGN KEY (#quot;clientId#quot;) REFERENCES oauth_clients(id) ON DELETE CASCADE" +"public.processed_data" }o--|| "public.workflow_entity" : "FOREIGN KEY (#quot;workflowId#quot;) REFERENCES workflow_entity(id) ON DELETE CASCADE" +"public.project" }o--o| "public.user" : "FOREIGN KEY (#quot;creatorId#quot;) REFERENCES #quot;user#quot;(id) ON DELETE SET NULL" +"public.project_relation" }o--|| "public.user" : "FOREIGN KEY (#quot;userId#quot;) REFERENCES #quot;user#quot;(id) ON DELETE CASCADE" +"public.project_relation" }o--|| "public.project" : "FOREIGN KEY (#quot;projectId#quot;) REFERENCES project(id) ON DELETE CASCADE" +"public.project_relation" }o--|| "public.role" : "FOREIGN KEY (role) REFERENCES role(slug)" +"public.project_secrets_provider_access" }o--|| "public.project" : "FOREIGN KEY (#quot;projectId#quot;) REFERENCES project(id) ON DELETE CASCADE" +"public.project_secrets_provider_access" }o--|| "public.secrets_provider_connection" : "FOREIGN KEY (#quot;secretsProviderConnectionId#quot;) REFERENCES secrets_provider_connection(id) ON DELETE CASCADE" +"public.role_mapping_rule" }o--|| "public.role" : "FOREIGN KEY (role) REFERENCES role(slug) ON UPDATE CASCADE ON DELETE CASCADE" +"public.role_mapping_rule_project" }o--|| "public.project" : "FOREIGN KEY (#quot;projectId#quot;) REFERENCES project(id) ON DELETE CASCADE" +"public.role_mapping_rule_project" }o--|| "public.role_mapping_rule" : "FOREIGN KEY (#quot;roleMappingRuleId#quot;) REFERENCES role_mapping_rule(id) ON DELETE CASCADE" +"public.role_scope" }o--|| "public.scope" : "FOREIGN KEY (#quot;scopeSlug#quot;) REFERENCES scope(slug) ON UPDATE CASCADE ON DELETE CASCADE" +"public.role_scope" }o--|| "public.role" : "FOREIGN KEY (#quot;roleSlug#quot;) REFERENCES role(slug) ON UPDATE CASCADE ON DELETE CASCADE" +"public.shared_credentials" }o--|| "public.credentials_entity" : "FOREIGN KEY (#quot;credentialsId#quot;) REFERENCES credentials_entity(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.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.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" +"public.test_run" }o--o| "public.evaluation_config" : "FOREIGN KEY (#quot;evaluationConfigId#quot;) REFERENCES evaluation_config(id) ON DELETE SET NULL" +"public.test_run" }o--o| "public.evaluation_collection" : "FOREIGN KEY (#quot;collectionId#quot;) REFERENCES evaluation_collection(id) ON DELETE SET NULL" +"public.trusted_key" }o--|| "public.trusted_key_source" : "FOREIGN KEY (#quot;sourceId#quot;) REFERENCES trusted_key_source(id) ON DELETE CASCADE" +"public.user" }o--|| "public.role" : "FOREIGN KEY (#quot;roleSlug#quot;) REFERENCES role(slug)" +"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" +"public.variables" }o--o| "public.project" : "FOREIGN KEY (#quot;projectId#quot;) REFERENCES project(id) ON DELETE CASCADE" +"public.webhook_entity" }o--|| "public.workflow_entity" : "FOREIGN KEY (#quot;workflowId#quot;) REFERENCES workflow_entity(id) ON DELETE CASCADE" +"public.workflow_builder_session" }o--|| "public.user" : "FOREIGN KEY (#quot;userId#quot;) REFERENCES #quot;user#quot;(id) ON DELETE CASCADE" +"public.workflow_builder_session" }o--|| "public.workflow_entity" : "FOREIGN KEY (#quot;workflowId#quot;) REFERENCES workflow_entity(id) ON DELETE CASCADE" +"public.workflow_dependency" }o--|| "public.workflow_entity" : "FOREIGN KEY (#quot;workflowId#quot;) REFERENCES workflow_entity(id) ON DELETE CASCADE" +"public.workflow_entity" }o--o| "public.workflow_history" : "FOREIGN KEY (#quot;activeVersionId#quot;) REFERENCES workflow_history(#quot;versionId#quot;) ON DELETE RESTRICT" +"public.workflow_entity" }o--o| "public.folder" : "FOREIGN KEY (#quot;parentFolderId#quot;) REFERENCES folder(id) ON DELETE CASCADE" +"public.workflow_history" }o--|| "public.workflow_entity" : "FOREIGN KEY (#quot;workflowId#quot;) REFERENCES workflow_entity(id) ON DELETE CASCADE" +"public.workflow_publish_history" }o--o| "public.user" : "FOREIGN KEY (#quot;userId#quot;) REFERENCES #quot;user#quot;(id) ON DELETE SET NULL" +"public.workflow_publish_history" }o--|| "public.workflow_entity" : "FOREIGN KEY (#quot;workflowId#quot;) REFERENCES workflow_entity(id) ON DELETE CASCADE" +"public.workflow_publish_history" }o--o| "public.workflow_history" : "FOREIGN KEY (#quot;versionId#quot;) REFERENCES workflow_history(#quot;versionId#quot;) ON DELETE SET NULL" +"public.workflow_published_version" |o--|| "public.workflow_entity" : "FOREIGN KEY (#quot;workflowId#quot;) REFERENCES workflow_entity(id) ON DELETE RESTRICT" +"public.workflow_published_version" }o--|| "public.workflow_history" : "FOREIGN KEY (#quot;publishedVersionId#quot;) REFERENCES workflow_history(#quot;versionId#quot;) ON DELETE RESTRICT" +"public.workflows_tags" }o--|| "public.workflow_entity" : "FOREIGN KEY (#quot;workflowId#quot;) REFERENCES workflow_entity(id) ON DELETE CASCADE" +"public.workflows_tags" }o--|| "public.tag_entity" : "FOREIGN KEY (#quot;tagId#quot;) REFERENCES tag_entity(id) ON DELETE CASCADE" + +"public.agent_chat_subscriptions" { + varchar_36_ agentId FK + timestamp_3__with_time_zone createdAt + varchar_255_ credentialId + varchar_64_ integrationType + varchar_255_ threadId + timestamp_3__with_time_zone updatedAt +} +"public.agent_checkpoints" { + varchar_255_ agentId FK + timestamp_3__with_time_zone createdAt + boolean expired + varchar_255_ runId + text state + timestamp_3__with_time_zone updatedAt +} +"public.agent_execution" { + text assistantResponse + integer completionTokens + double_precision cost + timestamp_3__with_time_zone createdAt + integer duration + text error + varchar_16_ hitlStatus + varchar_36_ id + varchar_255_ model + integer promptTokens + varchar_32_ source + timestamp_3__with_time_zone startedAt + varchar_16_ status + timestamp_3__with_time_zone stoppedAt + varchar_128_ threadId FK + json timeline + json toolCalls + integer totalTokens + timestamp_3__with_time_zone updatedAt + text userMessage +} +"public.agent_execution_threads" { + varchar_36_ agentId FK + varchar_255_ agentName + timestamp_3__with_time_zone createdAt + varchar_8_ emoji + varchar_128_ id + varchar_36_ parentAgentId + varchar_128_ parentThreadId + varchar_255_ projectId FK + integer sessionNumber + varchar_32_ taskId + varchar_36_ taskVersionId FK + varchar_255_ title + integer totalCompletionTokens + double_precision totalCost + integer totalDuration + integer totalPromptTokens + timestamp_3__with_time_zone updatedAt +} +"public.agent_files" { + varchar_36_ agentId FK + text binaryDataId + timestamp_3__with_time_zone createdAt + varchar_255_ fileName + integer fileSizeBytes + varchar_16_ id + varchar_255_ mimeType + timestamp_3__with_time_zone updatedAt +} +"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.agent_task_definition" { + varchar_36_ agentId FK + timestamp_3__with_time_zone createdAt + varchar_128_ cronExpression + varchar_32_ id + varchar_128_ name + text objective + timestamp_3__with_time_zone updatedAt +} +"public.agent_task_run_lock" { + varchar_36_ agentId FK + timestamp_3__with_time_zone createdAt + timestamp_3__with_time_zone heldUntil + uuid holderId + varchar_32_ taskId + timestamp_3__with_time_zone updatedAt +} +"public.agent_task_snapshot" { + timestamp_3__with_time_zone createdAt + varchar_128_ cronExpression + boolean enabled + varchar_128_ name + text objective + varchar_32_ taskId + timestamp_3__with_time_zone updatedAt + varchar_36_ versionId FK +} +"public.agents" { + varchar_36_ activeVersionId FK + timestamp_3__with_time_zone createdAt + varchar_512_ description + varchar_36_ id + json integrations + varchar_128_ name + varchar_255_ projectId FK + json schema + json skills + json tools + timestamp_3__with_time_zone updatedAt + varchar_36_ versionId +} +"public.agents_memory_entries" { + varchar_36_ agentId FK + text content + varchar_64_ contentHash + timestamp_3__with_time_zone createdAt + json embedding + varchar_128_ embeddingModel + varchar_36_ id + timestamp_3__with_time_zone lastSeenAt + json metadata + varchar_255_ resourceId FK + varchar_16_ status + varchar_36_ supersededBy FK + timestamp_3__with_time_zone updatedAt +} +"public.agents_memory_entry_cursors" { + varchar_36_ agentId FK + timestamp_3__with_time_zone createdAt + timestamp_3__with_time_zone lastIndexedObservationCreatedAt + varchar_36_ lastIndexedObservationId + varchar_255_ observationScopeId FK + timestamp_3__with_time_zone updatedAt +} +"public.agents_memory_entry_locks" { + varchar_36_ agentId FK + timestamp_3__with_time_zone createdAt + timestamp_3__with_time_zone heldUntil + varchar_64_ holderId + varchar_255_ resourceId FK + timestamp_3__with_time_zone updatedAt +} +"public.agents_memory_entry_sources" { + varchar_36_ agentId FK + timestamp_3__with_time_zone createdAt + varchar_64_ evidenceHash + text evidenceText + varchar_36_ id + varchar_36_ memoryEntryId FK + varchar_36_ observationId FK + varchar_255_ threadId FK + timestamp_3__with_time_zone updatedAt +} +"public.agents_messages" { + json content + timestamp_3__with_time_zone createdAt + varchar_36_ id + varchar_255_ resourceId + varchar_36_ role + varchar_255_ threadId FK + varchar_36_ type + timestamp_3__with_time_zone updatedAt +} +"public.agents_observation_cursors" { + varchar_36_ agentId FK + timestamp_3__with_time_zone createdAt + timestamp_3__with_time_zone lastObservedAt + varchar_36_ lastObservedMessageId + varchar_255_ observationScopeId FK + timestamp_3__with_time_zone updatedAt +} +"public.agents_observation_locks" { + varchar_36_ agentId FK + timestamp_3__with_time_zone createdAt + timestamp_3__with_time_zone heldUntil + varchar_64_ holderId + varchar_255_ observationScopeId FK + varchar_20_ taskKind + timestamp_3__with_time_zone updatedAt +} +"public.agents_observations" { + varchar_36_ agentId FK + timestamp_3__with_time_zone createdAt + varchar_36_ id + varchar_16_ marker + varchar_255_ observationScopeId FK + varchar_36_ parentId FK + varchar_16_ status + varchar_36_ supersededBy FK + text text + integer tokenCount + timestamp_3__with_time_zone updatedAt +} +"public.agents_resources" { + timestamp_3__with_time_zone createdAt + varchar_255_ id + text metadata + timestamp_3__with_time_zone updatedAt +} +"public.agents_threads" { + timestamp_3__with_time_zone createdAt + varchar_128_ id + text metadata + varchar_255_ resourceId + varchar_255_ title + timestamp_3__with_time_zone updatedAt +} +"public.ai_builder_temporary_workflow" { + timestamp_3__with_time_zone createdAt + uuid threadId FK + timestamp_3__with_time_zone updatedAt + varchar_36_ workflowId FK +} +"public.annotation_tag_entity" { + timestamp_3__with_time_zone createdAt + varchar_16_ id + varchar_24_ name + timestamp_3__with_time_zone updatedAt +} +"public.auth_identity" { + timestamp_3__with_time_zone createdAt + varchar_255_ providerId + varchar_32_ providerType + timestamp_3__with_time_zone updatedAt + uuid userId FK +} +"public.auth_provider_sync_history" { + integer created + integer disabled + timestamp_3__with_time_zone endedAt + text error + integer id + varchar_32_ providerType + text runMode + integer scanned + timestamp_3__with_time_zone startedAt + text status + integer updated +} +"public.binary_data" { + timestamp_3__with_time_zone createdAt + bytea data + uuid fileId + varchar_255_ fileName + integer fileSize + varchar_255_ mimeType + varchar_255_ sourceId + varchar_50_ sourceType + timestamp_3__with_time_zone updatedAt +} +"public.chat_hub_agent_tools" { + uuid agentId FK + uuid toolId FK +} +"public.chat_hub_agents" { + timestamp_3__with_time_zone createdAt + varchar_36_ credentialId FK + varchar_512_ description + json files + json icon + uuid id + varchar_64_ model + varchar_256_ name + uuid ownerId FK + varchar_16_ provider + json suggestedPrompts + text systemPrompt + timestamp_3__with_time_zone updatedAt +} +"public.chat_hub_messages" { + uuid agentId FK + json attachments + text content + timestamp_3__with_time_zone createdAt + integer executionId FK + uuid id + varchar_256_ model + varchar_128_ name + uuid previousMessageId FK + varchar_16_ provider + uuid retryOfMessageId FK + uuid revisionOfMessageId FK + uuid sessionId FK + varchar_16_ status + varchar_16_ type + timestamp_3__with_time_zone updatedAt + varchar_36_ workflowId FK +} +"public.chat_hub_session_tools" { + uuid sessionId FK + uuid toolId FK +} +"public.chat_hub_sessions" { + uuid agentId FK + varchar_128_ agentName + timestamp_3__with_time_zone createdAt + varchar_36_ credentialId FK + uuid id + timestamp_3__with_time_zone lastMessageAt + varchar_256_ model + uuid ownerId FK + varchar_16_ provider + varchar_256_ title + varchar_16_ type + timestamp_3__with_time_zone updatedAt + varchar_36_ workflowId FK +} +"public.chat_hub_tools" { + timestamp_3__with_time_zone createdAt + json definition + boolean enabled + uuid id + varchar_255_ name + uuid ownerId FK + varchar_255_ type + double_precision typeVersion + timestamp_3__with_time_zone updatedAt +} +"public.credential_dependency" { + timestamp_3__with_time_zone createdAt + varchar_36_ credentialId FK + varchar_255_ dependencyId + varchar_64_ dependencyType + integer id +} +"public.credentials_entity" { + timestamp_3__with_time_zone createdAt + text data + varchar_36_ id + boolean isGlobal + boolean isManaged + boolean isResolvable + varchar_128_ name + boolean resolvableAllowFallback + varchar_16_ resolverId FK + varchar_128_ type + timestamp_3__with_time_zone updatedAt +} +"public.data_table" { + timestamp_3__with_time_zone createdAt + varchar_36_ id + varchar_128_ name + varchar_36_ projectId FK + timestamp_3__with_time_zone updatedAt +} +"public.data_table_column" { + timestamp_3__with_time_zone createdAt + varchar_36_ dataTableId FK + varchar_36_ id + integer index + varchar_128_ name + varchar_32_ type + timestamp_3__with_time_zone updatedAt +} +"public.deployment_key" { + varchar_20_ algorithm + timestamp_3__with_time_zone createdAt + varchar_36_ id + varchar_20_ status + varchar_64_ type + timestamp_3__with_time_zone updatedAt + text value +} +"public.dynamic_credential_entry" { + timestamp_3__with_time_zone createdAt + varchar_16_ credential_id FK + text data + varchar_16_ resolver_id FK + varchar_2048_ subject_id + timestamp_3__with_time_zone updatedAt +} +"public.dynamic_credential_resolver" { + text config + timestamp_3__with_time_zone createdAt + varchar_16_ id + varchar_128_ name + varchar_128_ type + timestamp_3__with_time_zone updatedAt +} +"public.dynamic_credential_user_entry" { + timestamp_3__with_time_zone createdAt + varchar_16_ credentialId FK + text data + varchar_16_ resolverId FK + timestamp_3__with_time_zone updatedAt + uuid userId FK +} +"public.evaluation_collection" { + timestamp_3__with_time_zone createdAt + uuid createdById FK + text description + varchar_36_ evaluationConfigId FK + varchar_36_ id + json insightsCache + varchar_128_ name + timestamp_3__with_time_zone updatedAt + varchar_36_ workflowId FK +} +"public.evaluation_config" { + timestamp_3__with_time_zone createdAt + json datasetRef + varchar_32_ datasetSource + varchar_255_ endNodeName + varchar_36_ id + varchar_64_ invalidReason + json metrics + varchar_128_ name + varchar_255_ startNodeName + varchar_16_ status + timestamp_3__with_time_zone updatedAt + varchar_36_ workflowId FK +} +"public.event_destinations" { + timestamp_3__with_time_zone createdAt + jsonb destination + uuid id + timestamp_3__with_time_zone updatedAt +} +"public.execution_annotation_tags" { + integer annotationId FK + varchar_24_ tagId FK +} +"public.execution_annotations" { + timestamp_3__with_time_zone createdAt + integer executionId FK + integer id + text note + timestamp_3__with_time_zone updatedAt + varchar_6_ vote +} +"public.execution_data" { + text data + integer executionId FK + json workflowData + varchar_36_ workflowVersionId +} +"public.execution_entity" { + bigint binaryDataSizeBytes + timestamp_3__with_time_zone createdAt + varchar_255_ deduplicationKey + timestamp_3__with_time_zone deletedAt + boolean finished + integer id + bigint jsonSizeBytes + varchar mode + varchar retryOf + varchar retrySuccessId + timestamp_3__with_time_zone startedAt + varchar status + timestamp_3__with_time_zone stoppedAt + varchar_2_ storedAt + json tracingContext + timestamp_3__with_time_zone waitTill + varchar_36_ workflowId FK + varchar_36_ workflowVersionId +} +"public.execution_metadata" { + integer executionId FK + integer id + varchar_255_ key + text value +} +"public.folder" { + timestamp_3__with_time_zone createdAt + varchar_36_ id + varchar_128_ name + varchar_36_ parentFolderId FK + varchar_36_ projectId FK + timestamp_3__with_time_zone updatedAt +} +"public.folder_tag" { + varchar_36_ folderId FK + varchar_36_ tagId FK +} +"public.insights_by_period" { + integer id + integer metaId FK + timestamp_0__with_time_zone periodStart + integer periodUnit + integer type + bigint value +} +"public.insights_metadata" { + integer metaId + varchar_36_ projectId FK + varchar_255_ projectName + varchar_36_ workflowId FK + varchar_128_ workflowName +} +"public.insights_raw" { + integer id + integer metaId FK + timestamp_0__with_time_zone timestamp + integer type + bigint value +} +"public.installed_nodes" { + integer latestVersion + varchar_200_ name + varchar_241_ package FK + varchar_200_ type +} +"public.installed_packages" { + varchar_70_ authorEmail + varchar_70_ authorName + timestamp_3__with_time_zone createdAt + varchar_50_ installedVersion + varchar_214_ packageName + timestamp_3__with_time_zone updatedAt +} +"public.instance_ai_checkpoints" { + timestamp_3__with_time_zone createdAt + timestamp_3__with_time_zone expiredAt + varchar_255_ key + varchar_255_ resourceId + varchar_255_ runId + json state + uuid threadId FK + timestamp_3__with_time_zone updatedAt +} +"public.instance_ai_iteration_logs" { + timestamp_3__with_time_zone createdAt + text entry + varchar_36_ id + varchar taskKey + uuid threadId FK + timestamp_3__with_time_zone updatedAt +} +"public.instance_ai_mcp_registry_connections" { + timestamp_3__with_time_zone createdAt + varchar_36_ credentialId FK + uuid id + varchar_255_ serverSlug FK + json toolFilter + timestamp_3__with_time_zone updatedAt + uuid userId FK +} +"public.instance_ai_messages" { + text content + timestamp_3__with_time_zone createdAt + varchar_36_ id + varchar_255_ resourceId + varchar_16_ role + uuid threadId FK + varchar_32_ type + timestamp_3__with_time_zone updatedAt +} +"public.instance_ai_observation_cursors" { + timestamp_3__with_time_zone createdAt + timestamp_3__with_time_zone lastObservedAt + varchar_36_ lastObservedMessageId + uuid observationScopeId FK + timestamp_3__with_time_zone updatedAt +} +"public.instance_ai_observation_locks" { + timestamp_3__with_time_zone createdAt + timestamp_3__with_time_zone heldUntil + varchar_64_ holderId + uuid observationScopeId FK + varchar_20_ taskKind + timestamp_3__with_time_zone updatedAt +} +"public.instance_ai_observational_memory" { + text activeObservations + json bufferedMessageIds + json bufferedObservationChunks + integer bufferedObservationTokens + text bufferedObservations + text bufferedReflection + integer bufferedReflectionInputTokens + integer bufferedReflectionTokens + text config + timestamp_3__with_time_zone createdAt + integer generationCount + varchar_36_ id + boolean isBufferingObservation + boolean isBufferingReflection + boolean isObserving + boolean isReflecting + timestamp_3__with_time_zone lastBufferedAtTime + integer lastBufferedAtTokens + timestamp_3__with_time_zone lastObservedAt + varchar_255_ lookupKey + json metadata + integer observationTokenCount + json observedMessageIds + varchar observedTimezone + varchar_32_ originType + integer pendingMessageTokens + integer reflectedObservationLineCount + varchar_255_ resourceId + varchar_16_ scope + uuid threadId FK + integer totalTokensObserved + timestamp_3__with_time_zone updatedAt +} +"public.instance_ai_observations" { + timestamp_3__with_time_zone createdAt + varchar_36_ id + varchar_16_ marker + uuid observationScopeId FK + varchar_36_ parentId FK + varchar_16_ status + varchar_36_ supersededBy FK + text text + integer tokenCount + timestamp_3__with_time_zone updatedAt +} +"public.instance_ai_pending_confirmations" { + varchar_255_ checkpointKey FK + varchar_36_ checkpointTaskId + timestamp_3__with_time_zone createdAt + timestamp_3__with_time_zone expiresAt + varchar_16_ kind + varchar_36_ messageGroupId + varchar_36_ requestId + varchar_36_ runId + uuid threadId FK + varchar_64_ toolCallId + timestamp_3__with_time_zone updatedAt + uuid userId FK +} +"public.instance_ai_resources" { + timestamp_3__with_time_zone createdAt + varchar_255_ id + json metadata + timestamp_3__with_time_zone updatedAt + text workingMemory +} +"public.instance_ai_run_snapshots" { + timestamp_3__with_time_zone createdAt + varchar_36_ langsmithRunId + varchar_36_ langsmithTraceId + varchar_36_ messageGroupId + varchar_36_ runId + json runIds + varchar_64_ spanId + uuid threadId FK + varchar_64_ traceId + text tree + timestamp_3__with_time_zone updatedAt +} +"public.instance_ai_threads" { + timestamp_3__with_time_zone createdAt + uuid id + json metadata + varchar_36_ projectId FK + varchar_255_ resourceId + text title + timestamp_3__with_time_zone updatedAt +} +"public.instance_ai_workflow_snapshots" { + timestamp_3__with_time_zone createdAt + varchar_255_ resourceId + varchar_36_ runId + text snapshot + varchar status + timestamp_3__with_time_zone updatedAt + varchar_255_ workflowName +} +"public.instance_version_history" { + timestamp_3__with_time_zone createdAt + integer id + integer major + integer minor + integer patch +} +"public.invalid_auth_token" { + timestamp_3__with_time_zone expiresAt + varchar_512_ token +} +"public.mcp_registry_server" { + timestamp_3__with_time_zone createdAt + json data + timestamp_3__without_time_zone registryUpdatedAt + varchar_255_ slug + varchar_50_ status + timestamp_3__with_time_zone updatedAt + varchar_50_ version +} +"public.oauth_access_tokens" { + varchar clientId FK + varchar token + uuid userId FK +} +"public.oauth_authorization_codes" { + varchar clientId FK + varchar_255_ code + varchar codeChallenge + varchar_255_ codeChallengeMethod + timestamp_3__with_time_zone createdAt + bigint expiresAt + varchar redirectUri + varchar resource + json scope + varchar state + timestamp_3__with_time_zone updatedAt + boolean used + uuid userId FK +} +"public.oauth_clients" { + varchar_255_ clientSecret + bigint clientSecretExpiresAt + timestamp_3__with_time_zone createdAt + json grantTypes + varchar id + varchar_255_ name + json redirectUris + varchar_255_ tokenEndpointAuthMethod + timestamp_3__with_time_zone updatedAt +} +"public.oauth_refresh_tokens" { + varchar clientId FK + timestamp_3__with_time_zone createdAt + bigint expiresAt + json scope + varchar_255_ token + timestamp_3__with_time_zone updatedAt + uuid userId FK +} +"public.oauth_user_consents" { + varchar clientId FK + bigint grantedAt + integer id + uuid userId FK +} +"public.processed_data" { + varchar_255_ context + timestamp_3__with_time_zone createdAt + timestamp_3__with_time_zone updatedAt + text value + varchar_36_ workflowId FK +} +"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 +} +"public.project_relation" { + timestamp_3__with_time_zone createdAt + varchar_36_ projectId FK + varchar role FK + timestamp_3__with_time_zone updatedAt + uuid userId FK +} +"public.project_secrets_provider_access" { + timestamp_3__with_time_zone createdAt + varchar_36_ projectId FK + varchar_128_ role + integer secretsProviderConnectionId FK + timestamp_3__with_time_zone updatedAt +} +"public.role" { + timestamp_3__with_time_zone createdAt + text description + text displayName + text roleType + varchar_128_ slug + boolean systemRole + timestamp_3__with_time_zone updatedAt +} +"public.role_mapping_rule" { + timestamp_3__with_time_zone createdAt + text expression + varchar_16_ id + integer order + varchar_128_ role FK + varchar_64_ type + timestamp_3__with_time_zone updatedAt +} +"public.role_mapping_rule_project" { + varchar_36_ projectId FK + varchar_16_ roleMappingRuleId FK +} +"public.role_scope" { + varchar_128_ roleSlug FK + varchar_128_ scopeSlug FK +} +"public.scope" { + text description + text displayName + varchar_128_ slug +} +"public.secrets_provider_connection" { + timestamp_3__with_time_zone createdAt + text encryptedSettings + integer id + boolean isEnabled + varchar_128_ providerKey + varchar_36_ type + timestamp_3__with_time_zone updatedAt +} +"public.settings" { + varchar_255_ key + boolean loadOnStartup + text value +} +"public.shared_credentials" { + timestamp_3__with_time_zone createdAt + varchar_36_ credentialsId FK + varchar_36_ projectId FK + text role + timestamp_3__with_time_zone updatedAt +} +"public.shared_workflow" { + timestamp_3__with_time_zone createdAt + varchar_36_ projectId FK + text role + timestamp_3__with_time_zone updatedAt + varchar_36_ workflowId FK +} +"public.tag_entity" { + timestamp_3__with_time_zone createdAt + varchar_36_ id + varchar_24_ name + timestamp_3__with_time_zone updatedAt +} +"public.test_case_execution" { + timestamp_3__with_time_zone completedAt + timestamp_3__with_time_zone createdAt + varchar errorCode + json errorDetails + integer executionId FK + varchar_36_ id + json inputs + json metrics + json outputs + timestamp_3__with_time_zone runAt + integer runIndex + varchar status + varchar_36_ testRunId FK + timestamp_3__with_time_zone updatedAt +} +"public.test_run" { + boolean cancelRequested + varchar_36_ collectionId FK + timestamp_3__with_time_zone completedAt + timestamp_3__with_time_zone createdAt + varchar errorCode + json errorDetails + varchar_36_ evaluationConfigId FK + jsonb evaluationConfigSnapshot + varchar_36_ id + json metrics + timestamp_3__with_time_zone runAt + varchar_255_ runningInstanceId + varchar status + timestamp_3__with_time_zone updatedAt + varchar_36_ workflowId FK + varchar_36_ workflowVersionId +} +"public.token_exchange_jti" { + timestamp_3__with_time_zone createdAt + timestamp_3__with_time_zone expiresAt + varchar_255_ jti +} +"public.trusted_key" { + timestamp_3__with_time_zone createdAt + text data + varchar_255_ kid + varchar_36_ sourceId FK +} +"public.trusted_key_source" { + text config + timestamp_3__with_time_zone createdAt + varchar_36_ id + text lastError + timestamp_3__with_time_zone lastRefreshedAt + varchar_32_ status + varchar_32_ type + timestamp_3__with_time_zone updatedAt +} +"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.user_api_keys" { + varchar apiKey + varchar audience + timestamp_3__with_time_zone createdAt + varchar_36_ id + varchar_100_ label + timestamp_3__with_time_zone lastUsedAt + json scopes + timestamp_3__with_time_zone updatedAt + uuid userId FK +} +"public.user_favorites" { + integer id + varchar_255_ resourceId + varchar_64_ resourceType + uuid userId FK +} +"public.variables" { + varchar_36_ id + varchar_50_ key + varchar_36_ projectId FK + varchar_50_ type + text value +} +"public.webhook_entity" { + varchar method + varchar node + integer pathLength + varchar webhookId + varchar webhookPath + varchar_36_ workflowId FK +} +"public.workflow_builder_session" { + varchar_255_ activeVersionCardId + timestamp_3__with_time_zone createdAt + uuid id + json messages + text previousSummary + varchar_255_ resumeAfterRestoreMessageId + timestamp_3__with_time_zone updatedAt + uuid userId FK + varchar_36_ workflowId FK +} +"public.workflow_dependency" { + timestamp_3__with_time_zone createdAt + json dependencyInfo + varchar_255_ dependencyKey + varchar_32_ dependencyType + integer id + smallint indexVersionId + varchar_36_ publishedVersionId + varchar_36_ workflowId FK + integer workflowVersionId +} +"public.workflow_entity" { + boolean active + varchar_36_ activeVersionId FK + json connections + timestamp_3__with_time_zone createdAt + text description + varchar_36_ id + boolean isArchived + json meta + varchar_128_ name + json nodeGroups + json nodes + varchar_36_ parentFolderId FK + json pinData + json settings + varchar sourceWorkflowId + json staticData + integer triggerCount + timestamp_3__with_time_zone updatedAt + integer versionCounter + character_36_ versionId +} +"public.workflow_history" { + varchar_255_ authors + boolean autosaved + json connections + timestamp_3__with_time_zone createdAt + text description + varchar_128_ name + json nodeGroups + json nodes + timestamp_3__with_time_zone updatedAt + varchar_36_ versionId + varchar_36_ workflowId FK +} +"public.workflow_publication_outbox" { + timestamp_3__with_time_zone createdAt + text errorMessage + integer id + varchar_36_ publishedVersionId + varchar_20_ status + timestamp_3__with_time_zone updatedAt + varchar_36_ workflowId +} +"public.workflow_publish_history" { + timestamp_3__with_time_zone createdAt + varchar_36_ event + integer id + uuid userId FK + varchar_36_ versionId FK + varchar_36_ workflowId FK +} +"public.workflow_published_version" { + timestamp_3__with_time_zone createdAt + varchar_36_ publishedVersionId FK + timestamp_3__with_time_zone updatedAt + varchar_36_ workflowId FK +} +"public.workflow_statistics" { + bigint count + integer id + timestamp_3__with_time_zone latestEvent + varchar_128_ name + bigint rootCount + varchar_36_ workflowId + varchar_128_ workflowName +} +"public.workflows_tags" { + varchar_36_ tagId FK + varchar_36_ workflowId FK +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/postgres-schema/public.agent_chat_subscriptions.md b/docs/generated/postgres-schema/public.agent_chat_subscriptions.md new file mode 100644 index 00000000000..1d1982a68f2 --- /dev/null +++ b/docs/generated/postgres-schema/public.agent_chat_subscriptions.md @@ -0,0 +1,67 @@ +# public.agent_chat_subscriptions + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| agentId | varchar(36) | | false | | [public.agents](public.agents.md) | Agent that owns this subscription | +| createdAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| credentialId | varchar(255) | | false | | | Credential connection that owns this subscription | +| integrationType | varchar(64) | | false | | | Chat integration platform for this subscription | +| threadId | varchar(255) | | false | | | Platform thread ID the agent is subscribed to | +| updatedAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| CHK_agent_chat_subscriptions_integrationType | CHECK | CHECK ((("integrationType")::text = ANY ((ARRAY['telegram'::character varying, 'slack'::character varying, 'linear'::character varying])::text[]))) | +| FK_e79153bd179c011e779d5016796 | FOREIGN KEY | FOREIGN KEY ("agentId") REFERENCES agents(id) ON DELETE CASCADE | +| PK_76598cf91038bee1f3ac94c94bc | PRIMARY KEY | PRIMARY KEY ("agentId", "integrationType", "credentialId", "threadId") | +| agent_chat_subscriptions_agentId_not_null | n | NOT NULL "agentId" | +| agent_chat_subscriptions_createdAt_not_null | n | NOT NULL "createdAt" | +| agent_chat_subscriptions_credentialId_not_null | n | NOT NULL "credentialId" | +| agent_chat_subscriptions_integrationType_not_null | n | NOT NULL "integrationType" | +| agent_chat_subscriptions_threadId_not_null | n | NOT NULL "threadId" | +| agent_chat_subscriptions_updatedAt_not_null | n | NOT NULL "updatedAt" | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| PK_76598cf91038bee1f3ac94c94bc | CREATE UNIQUE INDEX "PK_76598cf91038bee1f3ac94c94bc" ON public.agent_chat_subscriptions USING btree ("agentId", "integrationType", "credentialId", "threadId") | + +## Relations + +```mermaid +erDiagram + +"public.agent_chat_subscriptions" }o--|| "public.agents" : "FOREIGN KEY (#quot;agentId#quot;) REFERENCES agents(id) ON DELETE CASCADE" + +"public.agent_chat_subscriptions" { + varchar_36_ agentId FK + timestamp_3__with_time_zone createdAt + varchar_255_ credentialId + varchar_64_ integrationType + varchar_255_ threadId + timestamp_3__with_time_zone updatedAt +} +"public.agents" { + varchar_36_ activeVersionId FK + timestamp_3__with_time_zone createdAt + varchar_512_ description + varchar_36_ id + json integrations + varchar_128_ name + varchar_255_ projectId FK + json schema + json skills + json tools + timestamp_3__with_time_zone updatedAt + varchar_36_ versionId +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/postgres-schema/public.agent_checkpoints.md b/docs/generated/postgres-schema/public.agent_checkpoints.md new file mode 100644 index 00000000000..d9a46bfffa4 --- /dev/null +++ b/docs/generated/postgres-schema/public.agent_checkpoints.md @@ -0,0 +1,65 @@ +# public.agent_checkpoints + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| agentId | varchar(255) | | true | | [public.agents](public.agents.md) | | +| createdAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| expired | boolean | false | false | | | | +| runId | varchar(255) | | false | | | | +| state | text | | true | | | | +| updatedAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| FK_5e31c210f896d539964bf99fe32 | FOREIGN KEY | FOREIGN KEY ("agentId") REFERENCES agents(id) ON DELETE CASCADE | +| PK_50a27cbafa6806c9b162304b5fd | PRIMARY KEY | PRIMARY KEY ("runId") | +| agent_checkpoints_createdAt_not_null | n | NOT NULL "createdAt" | +| agent_checkpoints_expired_not_null | n | NOT NULL expired | +| agent_checkpoints_runId_not_null | n | NOT NULL "runId" | +| agent_checkpoints_updatedAt_not_null | n | NOT NULL "updatedAt" | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_5e31c210f896d539964bf99fe3 | CREATE INDEX "IDX_5e31c210f896d539964bf99fe3" ON public.agent_checkpoints USING btree ("agentId") | +| PK_50a27cbafa6806c9b162304b5fd | CREATE UNIQUE INDEX "PK_50a27cbafa6806c9b162304b5fd" ON public.agent_checkpoints USING btree ("runId") | + +## Relations + +```mermaid +erDiagram + +"public.agent_checkpoints" }o--o| "public.agents" : "FOREIGN KEY (#quot;agentId#quot;) REFERENCES agents(id) ON DELETE CASCADE" + +"public.agent_checkpoints" { + varchar_255_ agentId FK + timestamp_3__with_time_zone createdAt + boolean expired + varchar_255_ runId + text state + timestamp_3__with_time_zone updatedAt +} +"public.agents" { + varchar_36_ activeVersionId FK + timestamp_3__with_time_zone createdAt + varchar_512_ description + varchar_36_ id + json integrations + varchar_128_ name + varchar_255_ projectId FK + json schema + json skills + json tools + timestamp_3__with_time_zone updatedAt + varchar_36_ versionId +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/postgres-schema/public.agent_execution.md b/docs/generated/postgres-schema/public.agent_execution.md new file mode 100644 index 00000000000..9a55ebba2cb --- /dev/null +++ b/docs/generated/postgres-schema/public.agent_execution.md @@ -0,0 +1,104 @@ +# public.agent_execution + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| assistantResponse | text | | false | | | | +| completionTokens | integer | | true | | | | +| cost | double precision | | true | | | | +| createdAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| duration | integer | 0 | false | | | | +| error | text | | true | | | | +| hitlStatus | varchar(16) | | true | | | | +| id | varchar(36) | | false | | | | +| model | varchar(255) | | true | | | | +| promptTokens | integer | | true | | | | +| source | varchar(32) | | true | | | | +| startedAt | timestamp(3) with time zone | | true | | | | +| status | varchar(16) | | false | | | | +| stoppedAt | timestamp(3) with time zone | | true | | | | +| threadId | varchar(128) | | false | | [public.agent_execution_threads](public.agent_execution_threads.md) | | +| timeline | json | | true | | | | +| toolCalls | json | | true | | | | +| totalTokens | integer | | true | | | | +| updatedAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| userMessage | text | | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| CHK_agent_execution_hitlStatus | CHECK | CHECK ((("hitlStatus")::text = ANY ((ARRAY['suspended'::character varying, 'resumed'::character varying])::text[]))) | +| CHK_agent_execution_status | CHECK | CHECK (((status)::text = ANY ((ARRAY['success'::character varying, 'error'::character varying])::text[]))) | +| FK_add2432fb6034cc18b6af299dce | FOREIGN KEY | FOREIGN KEY ("threadId") REFERENCES agent_execution_threads(id) ON DELETE CASCADE | +| PK_ba438acc8532addc12d1ef17049 | PRIMARY KEY | PRIMARY KEY (id) | +| agent_execution_assistantResponse_not_null | n | NOT NULL "assistantResponse" | +| agent_execution_createdAt_not_null | n | NOT NULL "createdAt" | +| agent_execution_duration_not_null | n | NOT NULL duration | +| agent_execution_id_not_null | n | NOT NULL id | +| agent_execution_status_not_null | n | NOT NULL status | +| agent_execution_threadId_not_null | n | NOT NULL "threadId" | +| agent_execution_updatedAt_not_null | n | NOT NULL "updatedAt" | +| agent_execution_userMessage_not_null | n | NOT NULL "userMessage" | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_63d3c3a68b9cebf05f967f0b1c | CREATE INDEX "IDX_63d3c3a68b9cebf05f967f0b1c" ON public.agent_execution USING btree ("threadId", "createdAt") | +| PK_ba438acc8532addc12d1ef17049 | CREATE UNIQUE INDEX "PK_ba438acc8532addc12d1ef17049" ON public.agent_execution USING btree (id) | + +## Relations + +```mermaid +erDiagram + +"public.agent_execution" }o--|| "public.agent_execution_threads" : "FOREIGN KEY (#quot;threadId#quot;) REFERENCES agent_execution_threads(id) ON DELETE CASCADE" + +"public.agent_execution" { + text assistantResponse + integer completionTokens + double_precision cost + timestamp_3__with_time_zone createdAt + integer duration + text error + varchar_16_ hitlStatus + varchar_36_ id + varchar_255_ model + integer promptTokens + varchar_32_ source + timestamp_3__with_time_zone startedAt + varchar_16_ status + timestamp_3__with_time_zone stoppedAt + varchar_128_ threadId FK + json timeline + json toolCalls + integer totalTokens + timestamp_3__with_time_zone updatedAt + text userMessage +} +"public.agent_execution_threads" { + varchar_36_ agentId FK + varchar_255_ agentName + timestamp_3__with_time_zone createdAt + varchar_8_ emoji + varchar_128_ id + varchar_36_ parentAgentId + varchar_128_ parentThreadId + varchar_255_ projectId FK + integer sessionNumber + varchar_32_ taskId + varchar_36_ taskVersionId FK + varchar_255_ title + integer totalCompletionTokens + double_precision totalCost + integer totalDuration + integer totalPromptTokens + timestamp_3__with_time_zone updatedAt +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/postgres-schema/public.agent_execution_threads.md b/docs/generated/postgres-schema/public.agent_execution_threads.md new file mode 100644 index 00000000000..7c1e0dcd043 --- /dev/null +++ b/docs/generated/postgres-schema/public.agent_execution_threads.md @@ -0,0 +1,145 @@ +# public.agent_execution_threads + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| agentId | varchar(36) | | false | | [public.agents](public.agents.md) | | +| agentName | varchar(255) | | false | | | | +| createdAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| emoji | varchar(8) | | true | | | | +| id | varchar(128) | | false | [public.agent_execution](public.agent_execution.md) | | | +| parentAgentId | varchar(36) | | true | | | Saved agent id of the parent that delegated this subagent run. | +| parentThreadId | varchar(128) | | true | | | Parent session thread id that delegated this subagent run. | +| projectId | varchar(255) | | false | | [public.project](public.project.md) | | +| sessionNumber | integer | 0 | false | | | | +| taskId | varchar(32) | | true | | | Published task ID that triggered this session; not an FK because published runs can outlive draft task definition rows | +| taskVersionId | varchar(36) | | true | | [public.agent_history](public.agent_history.md) | Published agent_history version that supplied the task snapshot | +| title | varchar(255) | | true | | | | +| totalCompletionTokens | integer | 0 | false | | | | +| totalCost | double precision | 0 | false | | | | +| totalDuration | integer | 0 | false | | | | +| totalPromptTokens | integer | 0 | false | | | | +| updatedAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| FK_0468a9dc35597314e641d4722aa | FOREIGN KEY | FOREIGN KEY ("agentId") REFERENCES agents(id) ON DELETE CASCADE | +| FK_0e2f8bf92a7a9c88b89670f701c | FOREIGN KEY | FOREIGN KEY ("projectId") REFERENCES project(id) ON DELETE CASCADE | +| FK_f00b52d74fe11838e1fe086deea | FOREIGN KEY | FOREIGN KEY ("taskVersionId") REFERENCES agent_history("versionId") ON DELETE SET NULL | +| PK_22373dbf6ba6929d8ac50093309 | PRIMARY KEY | PRIMARY KEY (id) | +| agent_execution_threads_agentId_not_null | n | NOT NULL "agentId" | +| agent_execution_threads_agentName_not_null | n | NOT NULL "agentName" | +| agent_execution_threads_createdAt_not_null | n | NOT NULL "createdAt" | +| agent_execution_threads_id_not_null | n | NOT NULL id | +| agent_execution_threads_projectId_not_null | n | NOT NULL "projectId" | +| agent_execution_threads_sessionNumber_not_null | n | NOT NULL "sessionNumber" | +| agent_execution_threads_totalCompletionTokens_not_null | n | NOT NULL "totalCompletionTokens" | +| agent_execution_threads_totalCost_not_null | n | NOT NULL "totalCost" | +| agent_execution_threads_totalDuration_not_null | n | NOT NULL "totalDuration" | +| agent_execution_threads_totalPromptTokens_not_null | n | NOT NULL "totalPromptTokens" | +| agent_execution_threads_updatedAt_not_null | n | NOT NULL "updatedAt" | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_0468a9dc35597314e641d4722a | CREATE INDEX "IDX_0468a9dc35597314e641d4722a" ON public.agent_execution_threads USING btree ("agentId") | +| IDX_0e2f8bf92a7a9c88b89670f701 | CREATE INDEX "IDX_0e2f8bf92a7a9c88b89670f701" ON public.agent_execution_threads USING btree ("projectId") | +| IDX_agent_execution_threads_taskVersionId | CREATE INDEX "IDX_agent_execution_threads_taskVersionId" ON public.agent_execution_threads USING btree ("taskVersionId") | +| PK_22373dbf6ba6929d8ac50093309 | CREATE UNIQUE INDEX "PK_22373dbf6ba6929d8ac50093309" ON public.agent_execution_threads USING btree (id) | + +## Relations + +```mermaid +erDiagram + +"public.agent_execution_threads" }o--|| "public.agents" : "FOREIGN KEY (#quot;agentId#quot;) REFERENCES agents(id) ON DELETE CASCADE" +"public.agent_execution" }o--|| "public.agent_execution_threads" : "FOREIGN KEY (#quot;threadId#quot;) REFERENCES agent_execution_threads(id) ON DELETE CASCADE" +"public.agent_execution_threads" }o--|| "public.project" : "FOREIGN KEY (#quot;projectId#quot;) REFERENCES project(id) ON DELETE CASCADE" +"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_execution_threads" { + varchar_36_ agentId FK + varchar_255_ agentName + timestamp_3__with_time_zone createdAt + varchar_8_ emoji + varchar_128_ id + varchar_36_ parentAgentId + varchar_128_ parentThreadId + varchar_255_ projectId FK + integer sessionNumber + varchar_32_ taskId + varchar_36_ taskVersionId FK + varchar_255_ title + integer totalCompletionTokens + double_precision totalCost + integer totalDuration + integer totalPromptTokens + timestamp_3__with_time_zone updatedAt +} +"public.agents" { + varchar_36_ activeVersionId FK + timestamp_3__with_time_zone createdAt + varchar_512_ description + varchar_36_ id + json integrations + varchar_128_ name + varchar_255_ projectId FK + json schema + json skills + json tools + timestamp_3__with_time_zone updatedAt + varchar_36_ versionId +} +"public.agent_execution" { + text assistantResponse + integer completionTokens + double_precision cost + timestamp_3__with_time_zone createdAt + integer duration + text error + varchar_16_ hitlStatus + varchar_36_ id + varchar_255_ model + integer promptTokens + varchar_32_ source + timestamp_3__with_time_zone startedAt + varchar_16_ status + timestamp_3__with_time_zone stoppedAt + varchar_128_ threadId FK + json timeline + json toolCalls + integer totalTokens + timestamp_3__with_time_zone updatedAt + text userMessage +} +"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 +} +"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 +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/postgres-schema/public.agent_files.md b/docs/generated/postgres-schema/public.agent_files.md new file mode 100644 index 00000000000..f77a54103e3 --- /dev/null +++ b/docs/generated/postgres-schema/public.agent_files.md @@ -0,0 +1,73 @@ +# public.agent_files + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| agentId | varchar(36) | | false | | [public.agents](public.agents.md) | Agent that owns this uploaded file | +| binaryDataId | text | | false | | | Opaque BinaryDataService reference (mode-prefixed, e.g. "filesystem-v2:\<uuid\>"); not an FK to binary_data, which only has rows in DB storage mode | +| createdAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| fileName | varchar(255) | | false | | | | +| fileSizeBytes | integer | | false | | | Uploaded file size in bytes | +| id | varchar(16) | | false | | | Application-generated n8n nano ID | +| mimeType | varchar(255) | | false | | | | +| updatedAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| FK_aca4514cb500494b64356c2e164 | FOREIGN KEY | FOREIGN KEY ("agentId") REFERENCES agents(id) ON DELETE CASCADE | +| PK_692920e59217af7d124cd95106f | PRIMARY KEY | PRIMARY KEY (id) | +| agent_files_agentId_not_null | n | NOT NULL "agentId" | +| agent_files_binaryDataId_not_null | n | NOT NULL "binaryDataId" | +| agent_files_createdAt_not_null | n | NOT NULL "createdAt" | +| agent_files_fileName_not_null | n | NOT NULL "fileName" | +| agent_files_fileSizeBytes_not_null | n | NOT NULL "fileSizeBytes" | +| agent_files_id_not_null | n | NOT NULL id | +| agent_files_mimeType_not_null | n | NOT NULL "mimeType" | +| agent_files_updatedAt_not_null | n | NOT NULL "updatedAt" | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_45dafc48fe2ce95eac30fc8ffd | CREATE INDEX "IDX_45dafc48fe2ce95eac30fc8ffd" ON public.agent_files USING btree ("agentId", "createdAt") | +| PK_692920e59217af7d124cd95106f | CREATE UNIQUE INDEX "PK_692920e59217af7d124cd95106f" ON public.agent_files USING btree (id) | + +## Relations + +```mermaid +erDiagram + +"public.agent_files" }o--|| "public.agents" : "FOREIGN KEY (#quot;agentId#quot;) REFERENCES agents(id) ON DELETE CASCADE" + +"public.agent_files" { + varchar_36_ agentId FK + text binaryDataId + timestamp_3__with_time_zone createdAt + varchar_255_ fileName + integer fileSizeBytes + varchar_16_ id + varchar_255_ mimeType + timestamp_3__with_time_zone updatedAt +} +"public.agents" { + varchar_36_ activeVersionId FK + timestamp_3__with_time_zone createdAt + varchar_512_ description + varchar_36_ id + json integrations + varchar_128_ name + varchar_255_ projectId FK + json schema + json skills + json tools + timestamp_3__with_time_zone updatedAt + varchar_36_ versionId +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/postgres-schema/public.agent_history.md b/docs/generated/postgres-schema/public.agent_history.md new file mode 100644 index 00000000000..d23cafe46ae --- /dev/null +++ b/docs/generated/postgres-schema/public.agent_history.md @@ -0,0 +1,123 @@ +# public.agent_history + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| agentId | varchar(36) | | false | | [public.agents](public.agents.md) | | +| author | varchar(255) | | false | | | | +| createdAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| publishedById | uuid | | true | | [public.user](public.user.md) | | +| schema | json | | true | | | Frozen snapshot of the published AgentJsonConfig | +| 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) | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| FK_8771675f44c58fb40e0feb9ee35 | FOREIGN KEY | FOREIGN KEY ("publishedById") REFERENCES "user"(id) ON DELETE SET NULL | +| FK_87cd5a8da20304b089ea2f83fec | FOREIGN KEY | FOREIGN KEY ("agentId") REFERENCES agents(id) ON DELETE CASCADE | +| PK_65ffcfe7a8e112fb826311fb092 | PRIMARY KEY | PRIMARY KEY ("versionId") | +| agent_history_agentId_not_null | n | NOT NULL "agentId" | +| agent_history_author_not_null | n | NOT NULL author | +| agent_history_createdAt_not_null | n | NOT NULL "createdAt" | +| agent_history_updatedAt_not_null | n | NOT NULL "updatedAt" | +| agent_history_versionId_not_null | n | NOT NULL "versionId" | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_87cd5a8da20304b089ea2f83fe | CREATE INDEX "IDX_87cd5a8da20304b089ea2f83fe" ON public.agent_history USING btree ("agentId") | +| PK_65ffcfe7a8e112fb826311fb092 | CREATE UNIQUE INDEX "PK_65ffcfe7a8e112fb826311fb092" ON public.agent_history USING btree ("versionId") | + +## Relations + +```mermaid +erDiagram + +"public.agent_history" }o--|| "public.agents" : "FOREIGN KEY (#quot;agentId#quot;) REFERENCES agents(id) ON DELETE CASCADE" +"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.agents" }o--o| "public.agent_history" : "FOREIGN KEY (#quot;activeVersionId#quot;) REFERENCES agent_history(#quot;versionId#quot;) ON DELETE SET NULL" + +"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.agents" { + varchar_36_ activeVersionId FK + timestamp_3__with_time_zone createdAt + varchar_512_ description + varchar_36_ id + json integrations + varchar_128_ name + varchar_255_ projectId FK + json schema + 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_execution_threads" { + varchar_36_ agentId FK + varchar_255_ agentName + timestamp_3__with_time_zone createdAt + varchar_8_ emoji + varchar_128_ id + varchar_36_ parentAgentId + varchar_128_ parentThreadId + varchar_255_ projectId FK + integer sessionNumber + varchar_32_ taskId + varchar_36_ taskVersionId FK + varchar_255_ title + integer totalCompletionTokens + double_precision totalCost + integer totalDuration + integer totalPromptTokens + timestamp_3__with_time_zone updatedAt +} +"public.agent_task_snapshot" { + timestamp_3__with_time_zone createdAt + varchar_128_ cronExpression + boolean enabled + varchar_128_ name + text objective + varchar_32_ taskId + timestamp_3__with_time_zone updatedAt + varchar_36_ versionId FK +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/postgres-schema/public.agent_task_definition.md b/docs/generated/postgres-schema/public.agent_task_definition.md new file mode 100644 index 00000000000..f33b98e683a --- /dev/null +++ b/docs/generated/postgres-schema/public.agent_task_definition.md @@ -0,0 +1,70 @@ +# public.agent_task_definition + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| agentId | varchar(36) | | false | | [public.agents](public.agents.md) | Owning agent; task definitions are deleted when the agent is deleted | +| createdAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| cronExpression | varchar(128) | | false | | | Cron schedule evaluated using the instance timezone | +| id | varchar(32) | | false | | | Application-generated task ID referenced from agent JSON config | +| name | varchar(128) | | false | | | | +| objective | text | | false | | | User-authored instruction sent to the agent when this task runs | +| updatedAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| FK_f45d0535a2ed59b6c2dd6da98a0 | FOREIGN KEY | FOREIGN KEY ("agentId") REFERENCES agents(id) ON DELETE CASCADE | +| PK_1756c11c637903e97629a7a784a | PRIMARY KEY | PRIMARY KEY (id) | +| agent_task_definition_agentId_not_null | n | NOT NULL "agentId" | +| agent_task_definition_createdAt_not_null | n | NOT NULL "createdAt" | +| agent_task_definition_cronExpression_not_null | n | NOT NULL "cronExpression" | +| agent_task_definition_id_not_null | n | NOT NULL id | +| agent_task_definition_name_not_null | n | NOT NULL name | +| agent_task_definition_objective_not_null | n | NOT NULL objective | +| agent_task_definition_updatedAt_not_null | n | NOT NULL "updatedAt" | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_f45d0535a2ed59b6c2dd6da98a | CREATE INDEX "IDX_f45d0535a2ed59b6c2dd6da98a" ON public.agent_task_definition USING btree ("agentId") | +| PK_1756c11c637903e97629a7a784a | CREATE UNIQUE INDEX "PK_1756c11c637903e97629a7a784a" ON public.agent_task_definition USING btree (id) | + +## Relations + +```mermaid +erDiagram + +"public.agent_task_definition" }o--|| "public.agents" : "FOREIGN KEY (#quot;agentId#quot;) REFERENCES agents(id) ON DELETE CASCADE" + +"public.agent_task_definition" { + varchar_36_ agentId FK + timestamp_3__with_time_zone createdAt + varchar_128_ cronExpression + varchar_32_ id + varchar_128_ name + text objective + timestamp_3__with_time_zone updatedAt +} +"public.agents" { + varchar_36_ activeVersionId FK + timestamp_3__with_time_zone createdAt + varchar_512_ description + varchar_36_ id + json integrations + varchar_128_ name + varchar_255_ projectId FK + json schema + json skills + json tools + timestamp_3__with_time_zone updatedAt + varchar_36_ versionId +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/postgres-schema/public.agent_task_run_lock.md b/docs/generated/postgres-schema/public.agent_task_run_lock.md new file mode 100644 index 00000000000..6076f126d2d --- /dev/null +++ b/docs/generated/postgres-schema/public.agent_task_run_lock.md @@ -0,0 +1,66 @@ +# public.agent_task_run_lock + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| agentId | varchar(36) | | false | | [public.agents](public.agents.md) | Published agent whose scheduled task run is locked | +| createdAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| heldUntil | timestamp(3) with time zone | | false | | | Time after which another main can claim this task run lock | +| holderId | uuid | | false | | | Ephemeral lock owner token generated by the running main | +| taskId | varchar(32) | | false | | | Published task ID whose scheduled run is locked | +| updatedAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| FK_b57a2862ae869aab24e54cefd48 | FOREIGN KEY | FOREIGN KEY ("agentId") REFERENCES agents(id) ON DELETE CASCADE | +| PK_f593adaf7230e964d3c25deda64 | PRIMARY KEY | PRIMARY KEY ("agentId", "taskId") | +| agent_task_run_lock_agentId_not_null | n | NOT NULL "agentId" | +| agent_task_run_lock_createdAt_not_null | n | NOT NULL "createdAt" | +| agent_task_run_lock_heldUntil_not_null | n | NOT NULL "heldUntil" | +| agent_task_run_lock_holderId_not_null | n | NOT NULL "holderId" | +| agent_task_run_lock_taskId_not_null | n | NOT NULL "taskId" | +| agent_task_run_lock_updatedAt_not_null | n | NOT NULL "updatedAt" | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| PK_f593adaf7230e964d3c25deda64 | CREATE UNIQUE INDEX "PK_f593adaf7230e964d3c25deda64" ON public.agent_task_run_lock USING btree ("agentId", "taskId") | + +## Relations + +```mermaid +erDiagram + +"public.agent_task_run_lock" }o--|| "public.agents" : "FOREIGN KEY (#quot;agentId#quot;) REFERENCES agents(id) ON DELETE CASCADE" + +"public.agent_task_run_lock" { + varchar_36_ agentId FK + timestamp_3__with_time_zone createdAt + timestamp_3__with_time_zone heldUntil + uuid holderId + varchar_32_ taskId + timestamp_3__with_time_zone updatedAt +} +"public.agents" { + varchar_36_ activeVersionId FK + timestamp_3__with_time_zone createdAt + varchar_512_ description + varchar_36_ id + json integrations + varchar_128_ name + varchar_255_ projectId FK + json schema + json skills + json tools + timestamp_3__with_time_zone updatedAt + varchar_36_ versionId +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/postgres-schema/public.agent_task_snapshot.md b/docs/generated/postgres-schema/public.agent_task_snapshot.md new file mode 100644 index 00000000000..1c09787a408 --- /dev/null +++ b/docs/generated/postgres-schema/public.agent_task_snapshot.md @@ -0,0 +1,69 @@ +# public.agent_task_snapshot + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| createdAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| cronExpression | varchar(128) | | false | | | Cron schedule evaluated using the instance timezone | +| enabled | boolean | | false | | | Published enabled state for this task at publish time | +| name | varchar(128) | | false | | | | +| objective | text | | false | | | User-authored instruction sent to the agent when this task runs | +| taskId | varchar(32) | | false | | | Stable task ID referenced from the published agent JSON config | +| updatedAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| versionId | varchar(36) | | false | | [public.agent_history](public.agent_history.md) | Published agent_history version this task snapshot belongs to | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| FK_1acedce6690392ef1611cca8b88 | FOREIGN KEY | FOREIGN KEY ("versionId") REFERENCES agent_history("versionId") ON DELETE CASCADE | +| PK_2142a8bcda2360c3c5e34f82640 | PRIMARY KEY | PRIMARY KEY ("versionId", "taskId") | +| agent_task_snapshot_createdAt_not_null | n | NOT NULL "createdAt" | +| agent_task_snapshot_cronExpression_not_null | n | NOT NULL "cronExpression" | +| agent_task_snapshot_enabled_not_null | n | NOT NULL enabled | +| agent_task_snapshot_name_not_null | n | NOT NULL name | +| agent_task_snapshot_objective_not_null | n | NOT NULL objective | +| agent_task_snapshot_taskId_not_null | n | NOT NULL "taskId" | +| agent_task_snapshot_updatedAt_not_null | n | NOT NULL "updatedAt" | +| agent_task_snapshot_versionId_not_null | n | NOT NULL "versionId" | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| PK_2142a8bcda2360c3c5e34f82640 | CREATE UNIQUE INDEX "PK_2142a8bcda2360c3c5e34f82640" ON public.agent_task_snapshot USING btree ("versionId", "taskId") | + +## Relations + +```mermaid +erDiagram + +"public.agent_task_snapshot" }o--|| "public.agent_history" : "FOREIGN KEY (#quot;versionId#quot;) REFERENCES agent_history(#quot;versionId#quot;) ON DELETE CASCADE" + +"public.agent_task_snapshot" { + timestamp_3__with_time_zone createdAt + varchar_128_ cronExpression + boolean enabled + varchar_128_ name + text objective + varchar_32_ taskId + timestamp_3__with_time_zone updatedAt + varchar_36_ versionId 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 +} +``` + +--- + +> 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 new file mode 100644 index 00000000000..6df9196df05 --- /dev/null +++ b/docs/generated/postgres-schema/public.agents.md @@ -0,0 +1,240 @@ +# public.agents + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| activeVersionId | varchar(36) | | true | | [public.agent_history](public.agent_history.md) | | +| createdAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| description | varchar(512) | | true | | | | +| id | varchar(36) | | false | [public.agent_chat_subscriptions](public.agent_chat_subscriptions.md) [public.agent_checkpoints](public.agent_checkpoints.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.agents_memory_entries](public.agents_memory_entries.md) [public.agents_memory_entry_cursors](public.agents_memory_entry_cursors.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) | | | +| integrations | json | '[]'::json | false | | | | +| name | varchar(128) | | false | | | | +| projectId | varchar(255) | | false | | [public.project](public.project.md) | | +| schema | json | | true | | | | +| skills | json | '{}'::json | false | | | | +| tools | json | '{}'::json | false | | | | +| updatedAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| versionId | varchar(36) | | true | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| FK_940597dfe9753375309ce6aeea0 | FOREIGN KEY | FOREIGN KEY ("activeVersionId") REFERENCES agent_history("versionId") ON DELETE SET NULL | +| FK_a30d560207c4071d98aa03c179c | FOREIGN KEY | FOREIGN KEY ("projectId") REFERENCES project(id) ON DELETE CASCADE | +| PK_9c653f28ae19c5884d5baf6a1d9 | PRIMARY KEY | PRIMARY KEY (id) | +| agents_createdAt_not_null | n | NOT NULL "createdAt" | +| agents_id_not_null | n | NOT NULL id | +| agents_integrations_not_null | n | NOT NULL integrations | +| agents_name_not_null | n | NOT NULL name | +| agents_projectId_not_null | n | NOT NULL "projectId" | +| agents_skills_not_null | n | NOT NULL skills | +| agents_tools_not_null | n | NOT NULL tools | +| agents_updatedAt_not_null | n | NOT NULL "updatedAt" | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_a30d560207c4071d98aa03c179 | CREATE INDEX "IDX_a30d560207c4071d98aa03c179" ON public.agents USING btree ("projectId") | +| IDX_agents_projectId | CREATE INDEX "IDX_agents_projectId" ON public.agents USING btree ("projectId") | +| PK_9c653f28ae19c5884d5baf6a1d9 | CREATE UNIQUE INDEX "PK_9c653f28ae19c5884d5baf6a1d9" ON public.agents USING btree (id) | + +## Relations + +```mermaid +erDiagram + +"public.agents" }o--o| "public.agent_history" : "FOREIGN KEY (#quot;activeVersionId#quot;) REFERENCES agent_history(#quot;versionId#quot;) ON DELETE SET NULL" +"public.agent_chat_subscriptions" }o--|| "public.agents" : "FOREIGN KEY (#quot;agentId#quot;) REFERENCES agents(id) ON DELETE CASCADE" +"public.agent_checkpoints" }o--o| "public.agents" : "FOREIGN KEY (#quot;agentId#quot;) REFERENCES agents(id) ON DELETE CASCADE" +"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_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.agents_memory_entries" }o--|| "public.agents" : "FOREIGN KEY (#quot;agentId#quot;) REFERENCES agents(id) ON DELETE CASCADE" +"public.agents_memory_entry_cursors" }o--|| "public.agents" : "FOREIGN KEY (#quot;agentId#quot;) REFERENCES agents(id) ON DELETE CASCADE" +"public.agents_memory_entry_locks" }o--|| "public.agents" : "FOREIGN KEY (#quot;agentId#quot;) REFERENCES agents(id) ON DELETE CASCADE" +"public.agents_memory_entry_sources" }o--|| "public.agents" : "FOREIGN KEY (#quot;agentId#quot;) REFERENCES agents(id) ON DELETE CASCADE" +"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.agents" }o--|| "public.project" : "FOREIGN KEY (#quot;projectId#quot;) REFERENCES project(id) ON DELETE CASCADE" + +"public.agents" { + varchar_36_ activeVersionId FK + timestamp_3__with_time_zone createdAt + varchar_512_ description + varchar_36_ id + json integrations + varchar_128_ name + varchar_255_ projectId FK + json schema + json skills + json tools + timestamp_3__with_time_zone updatedAt + varchar_36_ versionId +} +"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.agent_chat_subscriptions" { + varchar_36_ agentId FK + timestamp_3__with_time_zone createdAt + varchar_255_ credentialId + varchar_64_ integrationType + varchar_255_ threadId + timestamp_3__with_time_zone updatedAt +} +"public.agent_checkpoints" { + varchar_255_ agentId FK + timestamp_3__with_time_zone createdAt + boolean expired + varchar_255_ runId + text state + timestamp_3__with_time_zone updatedAt +} +"public.agent_execution_threads" { + varchar_36_ agentId FK + varchar_255_ agentName + timestamp_3__with_time_zone createdAt + varchar_8_ emoji + varchar_128_ id + varchar_36_ parentAgentId + varchar_128_ parentThreadId + varchar_255_ projectId FK + integer sessionNumber + varchar_32_ taskId + varchar_36_ taskVersionId FK + varchar_255_ title + integer totalCompletionTokens + double_precision totalCost + integer totalDuration + integer totalPromptTokens + timestamp_3__with_time_zone updatedAt +} +"public.agent_files" { + varchar_36_ agentId FK + text binaryDataId + timestamp_3__with_time_zone createdAt + varchar_255_ fileName + integer fileSizeBytes + varchar_16_ id + varchar_255_ mimeType + timestamp_3__with_time_zone updatedAt +} +"public.agent_task_definition" { + varchar_36_ agentId FK + timestamp_3__with_time_zone createdAt + varchar_128_ cronExpression + varchar_32_ id + varchar_128_ name + text objective + timestamp_3__with_time_zone updatedAt +} +"public.agent_task_run_lock" { + varchar_36_ agentId FK + timestamp_3__with_time_zone createdAt + timestamp_3__with_time_zone heldUntil + uuid holderId + varchar_32_ taskId + timestamp_3__with_time_zone updatedAt +} +"public.agents_memory_entries" { + varchar_36_ agentId FK + text content + varchar_64_ contentHash + timestamp_3__with_time_zone createdAt + json embedding + varchar_128_ embeddingModel + varchar_36_ id + timestamp_3__with_time_zone lastSeenAt + json metadata + varchar_255_ resourceId FK + varchar_16_ status + varchar_36_ supersededBy FK + timestamp_3__with_time_zone updatedAt +} +"public.agents_memory_entry_cursors" { + varchar_36_ agentId FK + timestamp_3__with_time_zone createdAt + timestamp_3__with_time_zone lastIndexedObservationCreatedAt + varchar_36_ lastIndexedObservationId + varchar_255_ observationScopeId FK + timestamp_3__with_time_zone updatedAt +} +"public.agents_memory_entry_locks" { + varchar_36_ agentId FK + timestamp_3__with_time_zone createdAt + timestamp_3__with_time_zone heldUntil + varchar_64_ holderId + varchar_255_ resourceId FK + timestamp_3__with_time_zone updatedAt +} +"public.agents_memory_entry_sources" { + varchar_36_ agentId FK + timestamp_3__with_time_zone createdAt + varchar_64_ evidenceHash + text evidenceText + varchar_36_ id + varchar_36_ memoryEntryId FK + varchar_36_ observationId FK + varchar_255_ threadId FK + timestamp_3__with_time_zone updatedAt +} +"public.agents_observation_cursors" { + varchar_36_ agentId FK + timestamp_3__with_time_zone createdAt + timestamp_3__with_time_zone lastObservedAt + varchar_36_ lastObservedMessageId + varchar_255_ observationScopeId FK + timestamp_3__with_time_zone updatedAt +} +"public.agents_observation_locks" { + varchar_36_ agentId FK + timestamp_3__with_time_zone createdAt + timestamp_3__with_time_zone heldUntil + varchar_64_ holderId + varchar_255_ observationScopeId FK + varchar_20_ taskKind + timestamp_3__with_time_zone updatedAt +} +"public.agents_observations" { + varchar_36_ agentId FK + timestamp_3__with_time_zone createdAt + varchar_36_ id + varchar_16_ marker + varchar_255_ observationScopeId FK + varchar_36_ parentId FK + varchar_16_ status + varchar_36_ supersededBy FK + text text + integer tokenCount + timestamp_3__with_time_zone updatedAt +} +"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.agents_memory_entries.md b/docs/generated/postgres-schema/public.agents_memory_entries.md new file mode 100644 index 00000000000..c070feae0b7 --- /dev/null +++ b/docs/generated/postgres-schema/public.agents_memory_entries.md @@ -0,0 +1,110 @@ +# public.agents_memory_entries + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| agentId | varchar(36) | | false | | [public.agents](public.agents.md) | Agent that owns this episodic memory entry | +| content | text | | false | | | | +| contentHash | varchar(64) | | false | | | | +| createdAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| embedding | json | | true | | | Embedding vector for episodic recall | +| embeddingModel | varchar(128) | | true | | | Embedding model used to produce embedding | +| id | varchar(36) | | false | [public.agents_memory_entries](public.agents_memory_entries.md) [public.agents_memory_entry_sources](public.agents_memory_entry_sources.md) | | | +| lastSeenAt | timestamp(3) with time zone | | false | | | Last time equivalent content was observed; updatedAt tracks row mutation time | +| metadata | json | | true | | | Optional system metadata for ranking and debugging | +| resourceId | varchar(255) | | false | | [public.agents_resources](public.agents_resources.md) | agents_resources.id partition used for episodic recall scope | +| status | varchar(16) | | false | | | | +| supersededBy | varchar(36) | | true | | [public.agents_memory_entries](public.agents_memory_entries.md) | Self-reference to replacement memory entry | +| updatedAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| CHK_agents_memory_entries_status | CHECK | CHECK (((status)::text = ANY ((ARRAY['active'::character varying, 'superseded'::character varying, 'dropped'::character varying])::text[]))) | +| FK_0edf1226b77ddc525eae4938079 | FOREIGN KEY | FOREIGN KEY ("supersededBy") REFERENCES agents_memory_entries(id) | +| FK_1443a75e59adbfb796071d66393 | FOREIGN KEY | FOREIGN KEY ("resourceId") REFERENCES agents_resources(id) ON DELETE CASCADE | +| FK_28e981fb675e9b44ce02f0ec1dd | FOREIGN KEY | FOREIGN KEY ("agentId") REFERENCES agents(id) ON DELETE CASCADE | +| PK_bfbc45dc88f66fae4e4b4a15fec | PRIMARY KEY | PRIMARY KEY (id) | +| agents_memory_entries_agentId_not_null | n | NOT NULL "agentId" | +| agents_memory_entries_contentHash_not_null | n | NOT NULL "contentHash" | +| agents_memory_entries_content_not_null | n | NOT NULL content | +| agents_memory_entries_createdAt_not_null | n | NOT NULL "createdAt" | +| agents_memory_entries_id_not_null | n | NOT NULL id | +| agents_memory_entries_lastSeenAt_not_null | n | NOT NULL "lastSeenAt" | +| agents_memory_entries_resourceId_not_null | n | NOT NULL "resourceId" | +| agents_memory_entries_status_not_null | n | NOT NULL status | +| agents_memory_entries_updatedAt_not_null | n | NOT NULL "updatedAt" | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_0edf1226b77ddc525eae493807 | CREATE INDEX "IDX_0edf1226b77ddc525eae493807" ON public.agents_memory_entries USING btree ("supersededBy") | +| IDX_1443a75e59adbfb796071d6639 | CREATE INDEX "IDX_1443a75e59adbfb796071d6639" ON public.agents_memory_entries USING btree ("resourceId") | +| IDX_a03e04e94bea8439dd166d4b52 | CREATE UNIQUE INDEX "IDX_a03e04e94bea8439dd166d4b52" ON public.agents_memory_entries USING btree ("agentId", "resourceId", "contentHash") | +| IDX_aff2807b31eccbafe59d0474f0 | CREATE INDEX "IDX_aff2807b31eccbafe59d0474f0" ON public.agents_memory_entries USING btree ("agentId", "resourceId", status, "createdAt", id) | +| PK_bfbc45dc88f66fae4e4b4a15fec | CREATE UNIQUE INDEX "PK_bfbc45dc88f66fae4e4b4a15fec" ON public.agents_memory_entries USING btree (id) | + +## Relations + +```mermaid +erDiagram + +"public.agents_memory_entries" }o--|| "public.agents" : "FOREIGN KEY (#quot;agentId#quot;) REFERENCES agents(id) ON DELETE CASCADE" +"public.agents_memory_entries" }o--o| "public.agents_memory_entries" : "FOREIGN KEY (#quot;supersededBy#quot;) REFERENCES agents_memory_entries(id)" +"public.agents_memory_entry_sources" }o--|| "public.agents_memory_entries" : "FOREIGN KEY (#quot;memoryEntryId#quot;) REFERENCES agents_memory_entries(id) ON DELETE CASCADE" +"public.agents_memory_entries" }o--|| "public.agents_resources" : "FOREIGN KEY (#quot;resourceId#quot;) REFERENCES agents_resources(id) ON DELETE CASCADE" + +"public.agents_memory_entries" { + varchar_36_ agentId FK + text content + varchar_64_ contentHash + timestamp_3__with_time_zone createdAt + json embedding + varchar_128_ embeddingModel + varchar_36_ id + timestamp_3__with_time_zone lastSeenAt + json metadata + varchar_255_ resourceId FK + varchar_16_ status + varchar_36_ supersededBy FK + timestamp_3__with_time_zone updatedAt +} +"public.agents" { + varchar_36_ activeVersionId FK + timestamp_3__with_time_zone createdAt + varchar_512_ description + varchar_36_ id + json integrations + varchar_128_ name + varchar_255_ projectId FK + json schema + json skills + json tools + timestamp_3__with_time_zone updatedAt + varchar_36_ versionId +} +"public.agents_memory_entry_sources" { + varchar_36_ agentId FK + timestamp_3__with_time_zone createdAt + varchar_64_ evidenceHash + text evidenceText + varchar_36_ id + varchar_36_ memoryEntryId FK + varchar_36_ observationId FK + varchar_255_ threadId FK + timestamp_3__with_time_zone updatedAt +} +"public.agents_resources" { + timestamp_3__with_time_zone createdAt + varchar_255_ id + text metadata + timestamp_3__with_time_zone updatedAt +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/postgres-schema/public.agents_memory_entry_cursors.md b/docs/generated/postgres-schema/public.agents_memory_entry_cursors.md new file mode 100644 index 00000000000..e41c5d19fe0 --- /dev/null +++ b/docs/generated/postgres-schema/public.agents_memory_entry_cursors.md @@ -0,0 +1,77 @@ +# public.agents_memory_entry_cursors + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| agentId | varchar(36) | | false | | [public.agents](public.agents.md) | Agent that owns this cursor | +| createdAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| lastIndexedObservationCreatedAt | timestamp(3) with time zone | | false | | | Creation timestamp for the last indexed observation-log row | +| lastIndexedObservationId | varchar(36) | | false | | | Last observation-log row indexed into episodic memory | +| observationScopeId | varchar(255) | | false | | [public.agents_threads](public.agents_threads.md) | agents_threads.id source stream indexed into episodic memory | +| updatedAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| FK_069e791e428391a5569e7a96b20 | FOREIGN KEY | FOREIGN KEY ("observationScopeId") REFERENCES agents_threads(id) ON DELETE CASCADE | +| FK_746780fd115e5e4352457a3c617 | FOREIGN KEY | FOREIGN KEY ("agentId") REFERENCES agents(id) ON DELETE CASCADE | +| PK_b31a1d5c009a27f4cc5ef8f102a | PRIMARY KEY | PRIMARY KEY ("agentId", "observationScopeId") | +| agents_memory_entry_cursors_agentId_not_null | n | NOT NULL "agentId" | +| agents_memory_entry_cursors_createdAt_not_null | n | NOT NULL "createdAt" | +| agents_memory_entry_cursors_lastIndexedObservationCrea_not_null | n | NOT NULL "lastIndexedObservationCreatedAt" | +| agents_memory_entry_cursors_lastIndexedObservationId_not_null | n | NOT NULL "lastIndexedObservationId" | +| agents_memory_entry_cursors_observationScopeId_not_null | n | NOT NULL "observationScopeId" | +| agents_memory_entry_cursors_updatedAt_not_null | n | NOT NULL "updatedAt" | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_069e791e428391a5569e7a96b2 | CREATE INDEX "IDX_069e791e428391a5569e7a96b2" ON public.agents_memory_entry_cursors USING btree ("observationScopeId") | +| PK_b31a1d5c009a27f4cc5ef8f102a | CREATE UNIQUE INDEX "PK_b31a1d5c009a27f4cc5ef8f102a" ON public.agents_memory_entry_cursors USING btree ("agentId", "observationScopeId") | + +## Relations + +```mermaid +erDiagram + +"public.agents_memory_entry_cursors" }o--|| "public.agents" : "FOREIGN KEY (#quot;agentId#quot;) REFERENCES agents(id) ON DELETE CASCADE" +"public.agents_memory_entry_cursors" }o--|| "public.agents_threads" : "FOREIGN KEY (#quot;observationScopeId#quot;) REFERENCES agents_threads(id) ON DELETE CASCADE" + +"public.agents_memory_entry_cursors" { + varchar_36_ agentId FK + timestamp_3__with_time_zone createdAt + timestamp_3__with_time_zone lastIndexedObservationCreatedAt + varchar_36_ lastIndexedObservationId + varchar_255_ observationScopeId FK + timestamp_3__with_time_zone updatedAt +} +"public.agents" { + varchar_36_ activeVersionId FK + timestamp_3__with_time_zone createdAt + varchar_512_ description + varchar_36_ id + json integrations + varchar_128_ name + varchar_255_ projectId FK + json schema + json skills + json tools + timestamp_3__with_time_zone updatedAt + varchar_36_ versionId +} +"public.agents_threads" { + timestamp_3__with_time_zone createdAt + varchar_128_ id + text metadata + varchar_255_ resourceId + varchar_255_ title + timestamp_3__with_time_zone updatedAt +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/postgres-schema/public.agents_memory_entry_locks.md b/docs/generated/postgres-schema/public.agents_memory_entry_locks.md new file mode 100644 index 00000000000..3cc7fa7bd7e --- /dev/null +++ b/docs/generated/postgres-schema/public.agents_memory_entry_locks.md @@ -0,0 +1,75 @@ +# public.agents_memory_entry_locks + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| agentId | varchar(36) | | false | | [public.agents](public.agents.md) | Agent that owns this lock | +| createdAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| heldUntil | timestamp(3) with time zone | | false | | | | +| holderId | varchar(64) | | false | | | Ephemeral background-task lock owner token | +| resourceId | varchar(255) | | false | | [public.agents_resources](public.agents_resources.md) | agents_resources.id partition locked for episodic indexing | +| updatedAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| FK_0ccf6d9ea6f44fa1c264fc2f795 | FOREIGN KEY | FOREIGN KEY ("agentId") REFERENCES agents(id) ON DELETE CASCADE | +| FK_9594c0983cfee1c8ff49b05848b | FOREIGN KEY | FOREIGN KEY ("resourceId") REFERENCES agents_resources(id) ON DELETE CASCADE | +| PK_a8e0f570d04a174292bea104ae6 | PRIMARY KEY | PRIMARY KEY ("agentId", "resourceId") | +| agents_memory_entry_locks_agentId_not_null | n | NOT NULL "agentId" | +| agents_memory_entry_locks_createdAt_not_null | n | NOT NULL "createdAt" | +| agents_memory_entry_locks_heldUntil_not_null | n | NOT NULL "heldUntil" | +| agents_memory_entry_locks_holderId_not_null | n | NOT NULL "holderId" | +| agents_memory_entry_locks_resourceId_not_null | n | NOT NULL "resourceId" | +| agents_memory_entry_locks_updatedAt_not_null | n | NOT NULL "updatedAt" | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_9594c0983cfee1c8ff49b05848 | CREATE INDEX "IDX_9594c0983cfee1c8ff49b05848" ON public.agents_memory_entry_locks USING btree ("resourceId") | +| PK_a8e0f570d04a174292bea104ae6 | CREATE UNIQUE INDEX "PK_a8e0f570d04a174292bea104ae6" ON public.agents_memory_entry_locks USING btree ("agentId", "resourceId") | + +## Relations + +```mermaid +erDiagram + +"public.agents_memory_entry_locks" }o--|| "public.agents" : "FOREIGN KEY (#quot;agentId#quot;) REFERENCES agents(id) ON DELETE CASCADE" +"public.agents_memory_entry_locks" }o--|| "public.agents_resources" : "FOREIGN KEY (#quot;resourceId#quot;) REFERENCES agents_resources(id) ON DELETE CASCADE" + +"public.agents_memory_entry_locks" { + varchar_36_ agentId FK + timestamp_3__with_time_zone createdAt + timestamp_3__with_time_zone heldUntil + varchar_64_ holderId + varchar_255_ resourceId FK + timestamp_3__with_time_zone updatedAt +} +"public.agents" { + varchar_36_ activeVersionId FK + timestamp_3__with_time_zone createdAt + varchar_512_ description + varchar_36_ id + json integrations + varchar_128_ name + varchar_255_ projectId FK + json schema + json skills + json tools + timestamp_3__with_time_zone updatedAt + varchar_36_ versionId +} +"public.agents_resources" { + timestamp_3__with_time_zone createdAt + varchar_255_ id + text metadata + timestamp_3__with_time_zone updatedAt +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/postgres-schema/public.agents_memory_entry_sources.md b/docs/generated/postgres-schema/public.agents_memory_entry_sources.md new file mode 100644 index 00000000000..36c3ac04919 --- /dev/null +++ b/docs/generated/postgres-schema/public.agents_memory_entry_sources.md @@ -0,0 +1,121 @@ +# public.agents_memory_entry_sources + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| agentId | varchar(36) | | false | | [public.agents](public.agents.md) | Agent that owns the linked episodic memory entry source | +| createdAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| evidenceHash | varchar(64) | | false | | | Bounded hash used to deduplicate exact evidence links | +| evidenceText | text | | false | | | Exact source evidence text from the observation, not recall scope | +| id | varchar(36) | | false | | | | +| memoryEntryId | varchar(36) | | false | | [public.agents_memory_entries](public.agents_memory_entries.md) | Episodic memory entry linked to this source evidence | +| observationId | varchar(36) | | false | | [public.agents_observations](public.agents_observations.md) | Observation-log row used as source evidence | +| threadId | varchar(255) | | false | | [public.agents_threads](public.agents_threads.md) | Source conversation thread that produced the linked observation | +| updatedAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| FK_451d387a182fa8dd8002dfc3a77 | FOREIGN KEY | FOREIGN KEY ("threadId") REFERENCES agents_threads(id) ON DELETE CASCADE | +| FK_4706f6223313959b7437a2b48df | FOREIGN KEY | FOREIGN KEY ("memoryEntryId") REFERENCES agents_memory_entries(id) ON DELETE CASCADE | +| FK_c38e8a57a36b880e39a52ada2e8 | FOREIGN KEY | FOREIGN KEY ("agentId") REFERENCES agents(id) ON DELETE CASCADE | +| FK_cb7c15d22fd068a0806aa57fc03 | FOREIGN KEY | FOREIGN KEY ("observationId") REFERENCES agents_observations(id) ON DELETE CASCADE | +| PK_278f05e98e74baaaa93f52b4bab | PRIMARY KEY | PRIMARY KEY (id) | +| agents_memory_entry_sources_agentId_not_null | n | NOT NULL "agentId" | +| agents_memory_entry_sources_createdAt_not_null | n | NOT NULL "createdAt" | +| agents_memory_entry_sources_evidenceHash_not_null | n | NOT NULL "evidenceHash" | +| agents_memory_entry_sources_evidenceText_not_null | n | NOT NULL "evidenceText" | +| agents_memory_entry_sources_id_not_null | n | NOT NULL id | +| agents_memory_entry_sources_memoryEntryId_not_null | n | NOT NULL "memoryEntryId" | +| agents_memory_entry_sources_observationId_not_null | n | NOT NULL "observationId" | +| agents_memory_entry_sources_threadId_not_null | n | NOT NULL "threadId" | +| agents_memory_entry_sources_updatedAt_not_null | n | NOT NULL "updatedAt" | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_451d387a182fa8dd8002dfc3a7 | CREATE INDEX "IDX_451d387a182fa8dd8002dfc3a7" ON public.agents_memory_entry_sources USING btree ("threadId") | +| IDX_a353ac251315ef0af6ad3c9f0a | CREATE UNIQUE INDEX "IDX_a353ac251315ef0af6ad3c9f0a" ON public.agents_memory_entry_sources USING btree ("memoryEntryId", "observationId", "evidenceHash") | +| IDX_cb7c15d22fd068a0806aa57fc0 | CREATE INDEX "IDX_cb7c15d22fd068a0806aa57fc0" ON public.agents_memory_entry_sources USING btree ("observationId") | +| IDX_f9573af4ed653f13b0ba1f7b12 | CREATE INDEX "IDX_f9573af4ed653f13b0ba1f7b12" ON public.agents_memory_entry_sources USING btree ("agentId", "threadId") | +| PK_278f05e98e74baaaa93f52b4bab | CREATE UNIQUE INDEX "PK_278f05e98e74baaaa93f52b4bab" ON public.agents_memory_entry_sources USING btree (id) | + +## Relations + +```mermaid +erDiagram + +"public.agents_memory_entry_sources" }o--|| "public.agents" : "FOREIGN KEY (#quot;agentId#quot;) REFERENCES agents(id) ON DELETE CASCADE" +"public.agents_memory_entry_sources" }o--|| "public.agents_memory_entries" : "FOREIGN KEY (#quot;memoryEntryId#quot;) REFERENCES agents_memory_entries(id) ON DELETE CASCADE" +"public.agents_memory_entry_sources" }o--|| "public.agents_observations" : "FOREIGN KEY (#quot;observationId#quot;) REFERENCES agents_observations(id) ON DELETE CASCADE" +"public.agents_memory_entry_sources" }o--|| "public.agents_threads" : "FOREIGN KEY (#quot;threadId#quot;) REFERENCES agents_threads(id) ON DELETE CASCADE" + +"public.agents_memory_entry_sources" { + varchar_36_ agentId FK + timestamp_3__with_time_zone createdAt + varchar_64_ evidenceHash + text evidenceText + varchar_36_ id + varchar_36_ memoryEntryId FK + varchar_36_ observationId FK + varchar_255_ threadId FK + timestamp_3__with_time_zone updatedAt +} +"public.agents" { + varchar_36_ activeVersionId FK + timestamp_3__with_time_zone createdAt + varchar_512_ description + varchar_36_ id + json integrations + varchar_128_ name + varchar_255_ projectId FK + json schema + json skills + json tools + timestamp_3__with_time_zone updatedAt + varchar_36_ versionId +} +"public.agents_memory_entries" { + varchar_36_ agentId FK + text content + varchar_64_ contentHash + timestamp_3__with_time_zone createdAt + json embedding + varchar_128_ embeddingModel + varchar_36_ id + timestamp_3__with_time_zone lastSeenAt + json metadata + varchar_255_ resourceId FK + varchar_16_ status + varchar_36_ supersededBy FK + timestamp_3__with_time_zone updatedAt +} +"public.agents_observations" { + varchar_36_ agentId FK + timestamp_3__with_time_zone createdAt + varchar_36_ id + varchar_16_ marker + varchar_255_ observationScopeId FK + varchar_36_ parentId FK + varchar_16_ status + varchar_36_ supersededBy FK + text text + integer tokenCount + timestamp_3__with_time_zone updatedAt +} +"public.agents_threads" { + timestamp_3__with_time_zone createdAt + varchar_128_ id + text metadata + varchar_255_ resourceId + varchar_255_ title + timestamp_3__with_time_zone updatedAt +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/postgres-schema/public.agents_messages.md b/docs/generated/postgres-schema/public.agents_messages.md new file mode 100644 index 00000000000..80600957f09 --- /dev/null +++ b/docs/generated/postgres-schema/public.agents_messages.md @@ -0,0 +1,67 @@ +# public.agents_messages + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| content | json | | false | | | | +| createdAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| id | varchar(36) | | false | | | | +| resourceId | varchar(255) | | false | | | | +| role | varchar(36) | | false | | | | +| threadId | varchar(255) | | false | | [public.agents_threads](public.agents_threads.md) | | +| type | varchar(36) | | true | | | | +| updatedAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| FK_0a8057a61afabd2999608ffd0d9 | FOREIGN KEY | FOREIGN KEY ("threadId") REFERENCES agents_threads(id) ON DELETE CASCADE | +| PK_81020dc608dfb0af1ede386d907 | PRIMARY KEY | PRIMARY KEY (id) | +| agents_messages_content_not_null | n | NOT NULL content | +| agents_messages_createdAt_not_null | n | NOT NULL "createdAt" | +| agents_messages_id_not_null | n | NOT NULL id | +| agents_messages_resourceId_not_null | n | NOT NULL "resourceId" | +| agents_messages_role_not_null | n | NOT NULL role | +| agents_messages_threadId_not_null | n | NOT NULL "threadId" | +| agents_messages_updatedAt_not_null | n | NOT NULL "updatedAt" | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_agents_messages_threadId_createdAt | CREATE INDEX "IDX_agents_messages_threadId_createdAt" ON public.agents_messages USING btree ("threadId", "createdAt") | +| IDX_fc7bf858660bfafd19181e8e35 | CREATE INDEX "IDX_fc7bf858660bfafd19181e8e35" ON public.agents_messages USING btree ("threadId", "createdAt") | +| PK_81020dc608dfb0af1ede386d907 | CREATE UNIQUE INDEX "PK_81020dc608dfb0af1ede386d907" ON public.agents_messages USING btree (id) | + +## Relations + +```mermaid +erDiagram + +"public.agents_messages" }o--|| "public.agents_threads" : "FOREIGN KEY (#quot;threadId#quot;) REFERENCES agents_threads(id) ON DELETE CASCADE" + +"public.agents_messages" { + json content + timestamp_3__with_time_zone createdAt + varchar_36_ id + varchar_255_ resourceId + varchar_36_ role + varchar_255_ threadId FK + varchar_36_ type + timestamp_3__with_time_zone updatedAt +} +"public.agents_threads" { + timestamp_3__with_time_zone createdAt + varchar_128_ id + text metadata + varchar_255_ resourceId + varchar_255_ title + timestamp_3__with_time_zone updatedAt +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/postgres-schema/public.agents_observation_cursors.md b/docs/generated/postgres-schema/public.agents_observation_cursors.md new file mode 100644 index 00000000000..40bb9477736 --- /dev/null +++ b/docs/generated/postgres-schema/public.agents_observation_cursors.md @@ -0,0 +1,77 @@ +# public.agents_observation_cursors + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| agentId | varchar(36) | | false | | [public.agents](public.agents.md) | Agent that owns this cursor | +| createdAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| lastObservedAt | timestamp(3) with time zone | | false | | | | +| lastObservedMessageId | varchar(36) | | false | | | | +| observationScopeId | varchar(255) | | false | | [public.agents_threads](public.agents_threads.md) | agents_threads.id source stream checkpointed by this cursor | +| updatedAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| FK_64e92819f4b413661ed6e2c3c3d | FOREIGN KEY | FOREIGN KEY ("agentId") REFERENCES agents(id) ON DELETE CASCADE | +| FK_87aa187d27ea67eafd164905154 | FOREIGN KEY | FOREIGN KEY ("observationScopeId") REFERENCES agents_threads(id) ON DELETE CASCADE | +| PK_eb777ac57ab872d38f8ebd19317 | PRIMARY KEY | PRIMARY KEY ("agentId", "observationScopeId") | +| agents_observation_cursors_agentId_not_null | n | NOT NULL "agentId" | +| agents_observation_cursors_createdAt_not_null | n | NOT NULL "createdAt" | +| agents_observation_cursors_lastObservedAt_not_null | n | NOT NULL "lastObservedAt" | +| agents_observation_cursors_lastObservedMessageId_not_null | n | NOT NULL "lastObservedMessageId" | +| agents_observation_cursors_observationScopeId_not_null | n | NOT NULL "observationScopeId" | +| agents_observation_cursors_updatedAt_not_null | n | NOT NULL "updatedAt" | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_87aa187d27ea67eafd16490515 | CREATE INDEX "IDX_87aa187d27ea67eafd16490515" ON public.agents_observation_cursors USING btree ("observationScopeId") | +| PK_eb777ac57ab872d38f8ebd19317 | CREATE UNIQUE INDEX "PK_eb777ac57ab872d38f8ebd19317" ON public.agents_observation_cursors USING btree ("agentId", "observationScopeId") | + +## Relations + +```mermaid +erDiagram + +"public.agents_observation_cursors" }o--|| "public.agents" : "FOREIGN KEY (#quot;agentId#quot;) REFERENCES agents(id) ON DELETE CASCADE" +"public.agents_observation_cursors" }o--|| "public.agents_threads" : "FOREIGN KEY (#quot;observationScopeId#quot;) REFERENCES agents_threads(id) ON DELETE CASCADE" + +"public.agents_observation_cursors" { + varchar_36_ agentId FK + timestamp_3__with_time_zone createdAt + timestamp_3__with_time_zone lastObservedAt + varchar_36_ lastObservedMessageId + varchar_255_ observationScopeId FK + timestamp_3__with_time_zone updatedAt +} +"public.agents" { + varchar_36_ activeVersionId FK + timestamp_3__with_time_zone createdAt + varchar_512_ description + varchar_36_ id + json integrations + varchar_128_ name + varchar_255_ projectId FK + json schema + json skills + json tools + timestamp_3__with_time_zone updatedAt + varchar_36_ versionId +} +"public.agents_threads" { + timestamp_3__with_time_zone createdAt + varchar_128_ id + text metadata + varchar_255_ resourceId + varchar_255_ title + timestamp_3__with_time_zone updatedAt +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/postgres-schema/public.agents_observation_locks.md b/docs/generated/postgres-schema/public.agents_observation_locks.md new file mode 100644 index 00000000000..0eb4de0b957 --- /dev/null +++ b/docs/generated/postgres-schema/public.agents_observation_locks.md @@ -0,0 +1,81 @@ +# public.agents_observation_locks + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| agentId | varchar(36) | | false | | [public.agents](public.agents.md) | Agent that owns this lock | +| createdAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| heldUntil | timestamp(3) with time zone | | false | | | | +| holderId | varchar(64) | | false | | | Ephemeral background-task lock owner token, not a user ID | +| observationScopeId | varchar(255) | | false | | [public.agents_threads](public.agents_threads.md) | agents_threads.id source stream locked for observation tasks | +| taskKind | varchar(20) | | false | | | | +| updatedAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| CHK_agents_observation_locks_taskKind | CHECK | CHECK ((("taskKind")::text = ANY ((ARRAY['observer'::character varying, 'reflector'::character varying])::text[]))) | +| FK_093e44ae20f2518e97d83a95433 | FOREIGN KEY | FOREIGN KEY ("agentId") REFERENCES agents(id) ON DELETE CASCADE | +| FK_6b55089892e447c2f82e5ec60ed | FOREIGN KEY | FOREIGN KEY ("observationScopeId") REFERENCES agents_threads(id) ON DELETE CASCADE | +| PK_7e2e315162ac3d80587e15ac2c3 | PRIMARY KEY | PRIMARY KEY ("agentId", "observationScopeId", "taskKind") | +| agents_observation_locks_agentId_not_null | n | NOT NULL "agentId" | +| agents_observation_locks_createdAt_not_null | n | NOT NULL "createdAt" | +| agents_observation_locks_heldUntil_not_null | n | NOT NULL "heldUntil" | +| agents_observation_locks_holderId_not_null | n | NOT NULL "holderId" | +| agents_observation_locks_observationScopeId_not_null | n | NOT NULL "observationScopeId" | +| agents_observation_locks_taskKind_not_null | n | NOT NULL "taskKind" | +| agents_observation_locks_updatedAt_not_null | n | NOT NULL "updatedAt" | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_6b55089892e447c2f82e5ec60e | CREATE INDEX "IDX_6b55089892e447c2f82e5ec60e" ON public.agents_observation_locks USING btree ("observationScopeId") | +| PK_7e2e315162ac3d80587e15ac2c3 | CREATE UNIQUE INDEX "PK_7e2e315162ac3d80587e15ac2c3" ON public.agents_observation_locks USING btree ("agentId", "observationScopeId", "taskKind") | + +## Relations + +```mermaid +erDiagram + +"public.agents_observation_locks" }o--|| "public.agents" : "FOREIGN KEY (#quot;agentId#quot;) REFERENCES agents(id) ON DELETE CASCADE" +"public.agents_observation_locks" }o--|| "public.agents_threads" : "FOREIGN KEY (#quot;observationScopeId#quot;) REFERENCES agents_threads(id) ON DELETE CASCADE" + +"public.agents_observation_locks" { + varchar_36_ agentId FK + timestamp_3__with_time_zone createdAt + timestamp_3__with_time_zone heldUntil + varchar_64_ holderId + varchar_255_ observationScopeId FK + varchar_20_ taskKind + timestamp_3__with_time_zone updatedAt +} +"public.agents" { + varchar_36_ activeVersionId FK + timestamp_3__with_time_zone createdAt + varchar_512_ description + varchar_36_ id + json integrations + varchar_128_ name + varchar_255_ projectId FK + json schema + json skills + json tools + timestamp_3__with_time_zone updatedAt + varchar_36_ versionId +} +"public.agents_threads" { + timestamp_3__with_time_zone createdAt + varchar_128_ id + text metadata + varchar_255_ resourceId + varchar_255_ title + timestamp_3__with_time_zone updatedAt +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/postgres-schema/public.agents_observations.md b/docs/generated/postgres-schema/public.agents_observations.md new file mode 100644 index 00000000000..6cecb9ff490 --- /dev/null +++ b/docs/generated/postgres-schema/public.agents_observations.md @@ -0,0 +1,111 @@ +# public.agents_observations + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| agentId | varchar(36) | | false | | [public.agents](public.agents.md) | Agent that owns this observation row | +| createdAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| id | varchar(36) | | false | [public.agents_memory_entry_sources](public.agents_memory_entry_sources.md) [public.agents_observations](public.agents_observations.md) | | Application-generated n8n string ID, not a database UUID | +| marker | varchar(16) | | false | | | | +| observationScopeId | varchar(255) | | false | | [public.agents_threads](public.agents_threads.md) | agents_threads.id source stream for this observation log | +| parentId | varchar(36) | | true | | [public.agents_observations](public.agents_observations.md) | | +| status | varchar(16) | | false | | | | +| supersededBy | varchar(36) | | true | | [public.agents_observations](public.agents_observations.md) | | +| text | text | | false | | | | +| tokenCount | integer | 0 | false | | | | +| updatedAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| CHK_agents_observations_marker | CHECK | CHECK (((marker)::text = ANY ((ARRAY['critical'::character varying, 'important'::character varying, 'info'::character varying, 'completion'::character varying])::text[]))) | +| CHK_agents_observations_status | CHECK | CHECK (((status)::text = ANY ((ARRAY['active'::character varying, 'superseded'::character varying, 'dropped'::character varying])::text[]))) | +| FK_127ee1078ffa952bb37b511efad | FOREIGN KEY | FOREIGN KEY ("supersededBy") REFERENCES agents_observations(id) | +| FK_4cfd8a70ebb0a5b0cf047dca3cf | FOREIGN KEY | FOREIGN KEY ("observationScopeId") REFERENCES agents_threads(id) ON DELETE CASCADE | +| FK_501e2d1701a10e24fb69ab5fc5f | FOREIGN KEY | FOREIGN KEY ("parentId") REFERENCES agents_observations(id) | +| FK_d206432be97b7ed88d187479b1b | FOREIGN KEY | FOREIGN KEY ("agentId") REFERENCES agents(id) ON DELETE CASCADE | +| PK_9ad319654d12c2649f7caf27135 | PRIMARY KEY | PRIMARY KEY (id) | +| agents_observations_agentId_not_null | n | NOT NULL "agentId" | +| agents_observations_createdAt_not_null | n | NOT NULL "createdAt" | +| agents_observations_id_not_null | n | NOT NULL id | +| agents_observations_marker_not_null | n | NOT NULL marker | +| agents_observations_observationScopeId_not_null | n | NOT NULL "observationScopeId" | +| agents_observations_status_not_null | n | NOT NULL status | +| agents_observations_text_not_null | n | NOT NULL text | +| agents_observations_tokenCount_not_null | n | NOT NULL "tokenCount" | +| agents_observations_updatedAt_not_null | n | NOT NULL "updatedAt" | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_07cb1e4a302629c5fa5d74d2bb | CREATE INDEX "IDX_07cb1e4a302629c5fa5d74d2bb" ON public.agents_observations USING btree ("agentId", "observationScopeId", status) | +| IDX_127ee1078ffa952bb37b511efa | CREATE INDEX "IDX_127ee1078ffa952bb37b511efa" ON public.agents_observations USING btree ("supersededBy") | +| IDX_4cfd8a70ebb0a5b0cf047dca3c | CREATE INDEX "IDX_4cfd8a70ebb0a5b0cf047dca3c" ON public.agents_observations USING btree ("observationScopeId") | +| IDX_501e2d1701a10e24fb69ab5fc5 | CREATE INDEX "IDX_501e2d1701a10e24fb69ab5fc5" ON public.agents_observations USING btree ("parentId") | +| PK_9ad319654d12c2649f7caf27135 | CREATE UNIQUE INDEX "PK_9ad319654d12c2649f7caf27135" ON public.agents_observations USING btree (id) | + +## Relations + +```mermaid +erDiagram + +"public.agents_observations" }o--|| "public.agents" : "FOREIGN KEY (#quot;agentId#quot;) REFERENCES agents(id) ON DELETE CASCADE" +"public.agents_memory_entry_sources" }o--|| "public.agents_observations" : "FOREIGN KEY (#quot;observationId#quot;) REFERENCES agents_observations(id) ON DELETE CASCADE" +"public.agents_observations" }o--o| "public.agents_observations" : "FOREIGN KEY (#quot;supersededBy#quot;) REFERENCES agents_observations(id)" +"public.agents_observations" }o--o| "public.agents_observations" : "FOREIGN KEY (#quot;parentId#quot;) REFERENCES agents_observations(id)" +"public.agents_observations" }o--|| "public.agents_threads" : "FOREIGN KEY (#quot;observationScopeId#quot;) REFERENCES agents_threads(id) ON DELETE CASCADE" + +"public.agents_observations" { + varchar_36_ agentId FK + timestamp_3__with_time_zone createdAt + varchar_36_ id + varchar_16_ marker + varchar_255_ observationScopeId FK + varchar_36_ parentId FK + varchar_16_ status + varchar_36_ supersededBy FK + text text + integer tokenCount + timestamp_3__with_time_zone updatedAt +} +"public.agents" { + varchar_36_ activeVersionId FK + timestamp_3__with_time_zone createdAt + varchar_512_ description + varchar_36_ id + json integrations + varchar_128_ name + varchar_255_ projectId FK + json schema + json skills + json tools + timestamp_3__with_time_zone updatedAt + varchar_36_ versionId +} +"public.agents_memory_entry_sources" { + varchar_36_ agentId FK + timestamp_3__with_time_zone createdAt + varchar_64_ evidenceHash + text evidenceText + varchar_36_ id + varchar_36_ memoryEntryId FK + varchar_36_ observationId FK + varchar_255_ threadId FK + timestamp_3__with_time_zone updatedAt +} +"public.agents_threads" { + timestamp_3__with_time_zone createdAt + varchar_128_ id + text metadata + varchar_255_ resourceId + varchar_255_ title + timestamp_3__with_time_zone updatedAt +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/postgres-schema/public.agents_resources.md b/docs/generated/postgres-schema/public.agents_resources.md new file mode 100644 index 00000000000..93ab87be445 --- /dev/null +++ b/docs/generated/postgres-schema/public.agents_resources.md @@ -0,0 +1,68 @@ +# public.agents_resources + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| createdAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| id | varchar(255) | | false | [public.agents_memory_entries](public.agents_memory_entries.md) [public.agents_memory_entry_locks](public.agents_memory_entry_locks.md) | | | +| metadata | text | | true | | | | +| updatedAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| PK_fa6b20b2d31a9991529dbf8ef7d | PRIMARY KEY | PRIMARY KEY (id) | +| agents_resources_createdAt_not_null | n | NOT NULL "createdAt" | +| agents_resources_id_not_null | n | NOT NULL id | +| agents_resources_updatedAt_not_null | n | NOT NULL "updatedAt" | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| PK_fa6b20b2d31a9991529dbf8ef7d | CREATE UNIQUE INDEX "PK_fa6b20b2d31a9991529dbf8ef7d" ON public.agents_resources USING btree (id) | + +## Relations + +```mermaid +erDiagram + +"public.agents_memory_entries" }o--|| "public.agents_resources" : "FOREIGN KEY (#quot;resourceId#quot;) REFERENCES agents_resources(id) ON DELETE CASCADE" +"public.agents_memory_entry_locks" }o--|| "public.agents_resources" : "FOREIGN KEY (#quot;resourceId#quot;) REFERENCES agents_resources(id) ON DELETE CASCADE" + +"public.agents_resources" { + timestamp_3__with_time_zone createdAt + varchar_255_ id + text metadata + timestamp_3__with_time_zone updatedAt +} +"public.agents_memory_entries" { + varchar_36_ agentId FK + text content + varchar_64_ contentHash + timestamp_3__with_time_zone createdAt + json embedding + varchar_128_ embeddingModel + varchar_36_ id + timestamp_3__with_time_zone lastSeenAt + json metadata + varchar_255_ resourceId FK + varchar_16_ status + varchar_36_ supersededBy FK + timestamp_3__with_time_zone updatedAt +} +"public.agents_memory_entry_locks" { + varchar_36_ agentId FK + timestamp_3__with_time_zone createdAt + timestamp_3__with_time_zone heldUntil + varchar_64_ holderId + varchar_255_ resourceId FK + timestamp_3__with_time_zone updatedAt +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/postgres-schema/public.agents_threads.md b/docs/generated/postgres-schema/public.agents_threads.md new file mode 100644 index 00000000000..606edddac5d --- /dev/null +++ b/docs/generated/postgres-schema/public.agents_threads.md @@ -0,0 +1,114 @@ +# public.agents_threads + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| createdAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| id | varchar(128) | | false | [public.agents_memory_entry_cursors](public.agents_memory_entry_cursors.md) [public.agents_memory_entry_sources](public.agents_memory_entry_sources.md) [public.agents_messages](public.agents_messages.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) | | | +| metadata | text | | true | | | | +| resourceId | varchar(255) | | false | | | | +| title | varchar(255) | | true | | | | +| updatedAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| PK_4a3feb0a13ffe315c009cce64e5 | PRIMARY KEY | PRIMARY KEY (id) | +| agents_threads_createdAt_not_null | n | NOT NULL "createdAt" | +| agents_threads_id_not_null | n | NOT NULL id | +| agents_threads_resourceId_not_null | n | NOT NULL "resourceId" | +| agents_threads_updatedAt_not_null | n | NOT NULL "updatedAt" | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_54fa1b94f34a409beafae567a4 | CREATE INDEX "IDX_54fa1b94f34a409beafae567a4" ON public.agents_threads USING btree ("resourceId") | +| PK_4a3feb0a13ffe315c009cce64e5 | CREATE UNIQUE INDEX "PK_4a3feb0a13ffe315c009cce64e5" ON public.agents_threads USING btree (id) | + +## Relations + +```mermaid +erDiagram + +"public.agents_memory_entry_cursors" }o--|| "public.agents_threads" : "FOREIGN KEY (#quot;observationScopeId#quot;) REFERENCES agents_threads(id) ON DELETE CASCADE" +"public.agents_memory_entry_sources" }o--|| "public.agents_threads" : "FOREIGN KEY (#quot;threadId#quot;) REFERENCES agents_threads(id) ON DELETE CASCADE" +"public.agents_messages" }o--|| "public.agents_threads" : "FOREIGN KEY (#quot;threadId#quot;) REFERENCES agents_threads(id) ON DELETE CASCADE" +"public.agents_observation_cursors" }o--|| "public.agents_threads" : "FOREIGN KEY (#quot;observationScopeId#quot;) REFERENCES agents_threads(id) ON DELETE CASCADE" +"public.agents_observation_locks" }o--|| "public.agents_threads" : "FOREIGN KEY (#quot;observationScopeId#quot;) REFERENCES agents_threads(id) ON DELETE CASCADE" +"public.agents_observations" }o--|| "public.agents_threads" : "FOREIGN KEY (#quot;observationScopeId#quot;) REFERENCES agents_threads(id) ON DELETE CASCADE" + +"public.agents_threads" { + timestamp_3__with_time_zone createdAt + varchar_128_ id + text metadata + varchar_255_ resourceId + varchar_255_ title + timestamp_3__with_time_zone updatedAt +} +"public.agents_memory_entry_cursors" { + varchar_36_ agentId FK + timestamp_3__with_time_zone createdAt + timestamp_3__with_time_zone lastIndexedObservationCreatedAt + varchar_36_ lastIndexedObservationId + varchar_255_ observationScopeId FK + timestamp_3__with_time_zone updatedAt +} +"public.agents_memory_entry_sources" { + varchar_36_ agentId FK + timestamp_3__with_time_zone createdAt + varchar_64_ evidenceHash + text evidenceText + varchar_36_ id + varchar_36_ memoryEntryId FK + varchar_36_ observationId FK + varchar_255_ threadId FK + timestamp_3__with_time_zone updatedAt +} +"public.agents_messages" { + json content + timestamp_3__with_time_zone createdAt + varchar_36_ id + varchar_255_ resourceId + varchar_36_ role + varchar_255_ threadId FK + varchar_36_ type + timestamp_3__with_time_zone updatedAt +} +"public.agents_observation_cursors" { + varchar_36_ agentId FK + timestamp_3__with_time_zone createdAt + timestamp_3__with_time_zone lastObservedAt + varchar_36_ lastObservedMessageId + varchar_255_ observationScopeId FK + timestamp_3__with_time_zone updatedAt +} +"public.agents_observation_locks" { + varchar_36_ agentId FK + timestamp_3__with_time_zone createdAt + timestamp_3__with_time_zone heldUntil + varchar_64_ holderId + varchar_255_ observationScopeId FK + varchar_20_ taskKind + timestamp_3__with_time_zone updatedAt +} +"public.agents_observations" { + varchar_36_ agentId FK + timestamp_3__with_time_zone createdAt + varchar_36_ id + varchar_16_ marker + varchar_255_ observationScopeId FK + varchar_36_ parentId FK + varchar_16_ status + varchar_36_ supersededBy FK + text text + integer tokenCount + timestamp_3__with_time_zone updatedAt +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/postgres-schema/public.ai_builder_temporary_workflow.md b/docs/generated/postgres-schema/public.ai_builder_temporary_workflow.md new file mode 100644 index 00000000000..5de55a0242f --- /dev/null +++ b/docs/generated/postgres-schema/public.ai_builder_temporary_workflow.md @@ -0,0 +1,80 @@ +# public.ai_builder_temporary_workflow + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| createdAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| threadId | uuid | | false | | [public.instance_ai_threads](public.instance_ai_threads.md) | | +| updatedAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| workflowId | varchar(36) | | false | | [public.workflow_entity](public.workflow_entity.md) | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| FK_39b07732e819fb561d74c38763f | FOREIGN KEY | FOREIGN KEY ("threadId") REFERENCES instance_ai_threads(id) ON DELETE CASCADE | +| FK_85a87a1ba0f61999fe11dc56325 | FOREIGN KEY | FOREIGN KEY ("workflowId") REFERENCES workflow_entity(id) ON DELETE CASCADE | +| PK_85a87a1ba0f61999fe11dc56325 | PRIMARY KEY | PRIMARY KEY ("workflowId") | +| ai_builder_temporary_workflow_createdAt_not_null | n | NOT NULL "createdAt" | +| ai_builder_temporary_workflow_threadId_not_null | n | NOT NULL "threadId" | +| ai_builder_temporary_workflow_updatedAt_not_null | n | NOT NULL "updatedAt" | +| ai_builder_temporary_workflow_workflowId_not_null | n | NOT NULL "workflowId" | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_39b07732e819fb561d74c38763 | CREATE INDEX "IDX_39b07732e819fb561d74c38763" ON public.ai_builder_temporary_workflow USING btree ("threadId") | +| PK_85a87a1ba0f61999fe11dc56325 | CREATE UNIQUE INDEX "PK_85a87a1ba0f61999fe11dc56325" ON public.ai_builder_temporary_workflow USING btree ("workflowId") | + +## Relations + +```mermaid +erDiagram + +"public.ai_builder_temporary_workflow" }o--|| "public.instance_ai_threads" : "FOREIGN KEY (#quot;threadId#quot;) REFERENCES instance_ai_threads(id) ON DELETE CASCADE" +"public.ai_builder_temporary_workflow" |o--|| "public.workflow_entity" : "FOREIGN KEY (#quot;workflowId#quot;) REFERENCES workflow_entity(id) ON DELETE CASCADE" + +"public.ai_builder_temporary_workflow" { + timestamp_3__with_time_zone createdAt + uuid threadId FK + timestamp_3__with_time_zone updatedAt + varchar_36_ workflowId FK +} +"public.instance_ai_threads" { + timestamp_3__with_time_zone createdAt + uuid id + json metadata + varchar_36_ projectId FK + varchar_255_ resourceId + text title + timestamp_3__with_time_zone updatedAt +} +"public.workflow_entity" { + boolean active + varchar_36_ activeVersionId FK + json connections + timestamp_3__with_time_zone createdAt + text description + varchar_36_ id + boolean isArchived + json meta + varchar_128_ name + json nodeGroups + json nodes + varchar_36_ parentFolderId FK + json pinData + json settings + varchar sourceWorkflowId + json staticData + integer triggerCount + timestamp_3__with_time_zone updatedAt + integer versionCounter + character_36_ versionId +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/postgres-schema/public.annotation_tag_entity.md b/docs/generated/postgres-schema/public.annotation_tag_entity.md new file mode 100644 index 00000000000..67740581c8d --- /dev/null +++ b/docs/generated/postgres-schema/public.annotation_tag_entity.md @@ -0,0 +1,50 @@ +# public.annotation_tag_entity + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| createdAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| id | varchar(16) | | false | [public.execution_annotation_tags](public.execution_annotation_tags.md) | | | +| name | varchar(24) | | false | | | | +| updatedAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| PK_69dfa041592c30bbc0d4b84aa00 | PRIMARY KEY | PRIMARY KEY (id) | +| annotation_tag_entity_createdAt_not_null | n | NOT NULL "createdAt" | +| annotation_tag_entity_id_not_null | n | NOT NULL id | +| annotation_tag_entity_name_not_null | n | NOT NULL name | +| annotation_tag_entity_updatedAt_not_null | n | NOT NULL "updatedAt" | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_ae51b54c4bb430cf92f48b623f | CREATE UNIQUE INDEX "IDX_ae51b54c4bb430cf92f48b623f" ON public.annotation_tag_entity USING btree (name) | +| PK_69dfa041592c30bbc0d4b84aa00 | CREATE UNIQUE INDEX "PK_69dfa041592c30bbc0d4b84aa00" ON public.annotation_tag_entity USING btree (id) | + +## Relations + +```mermaid +erDiagram + +"public.execution_annotation_tags" }o--|| "public.annotation_tag_entity" : "FOREIGN KEY (#quot;tagId#quot;) REFERENCES annotation_tag_entity(id) ON DELETE CASCADE" + +"public.annotation_tag_entity" { + timestamp_3__with_time_zone createdAt + varchar_16_ id + varchar_24_ name + timestamp_3__with_time_zone updatedAt +} +"public.execution_annotation_tags" { + integer annotationId FK + varchar_24_ tagId FK +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/postgres-schema/public.auth_identity.md b/docs/generated/postgres-schema/public.auth_identity.md new file mode 100644 index 00000000000..d2c3e673434 --- /dev/null +++ b/docs/generated/postgres-schema/public.auth_identity.md @@ -0,0 +1,65 @@ +# public.auth_identity + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| createdAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| providerId | varchar(255) | | false | | | | +| providerType | varchar(32) | | false | | | | +| updatedAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| userId | uuid | | true | | [public.user](public.user.md) | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| auth_identity_createdAt_not_null | n | NOT NULL "createdAt" | +| auth_identity_pkey | PRIMARY KEY | PRIMARY KEY ("providerId", "providerType") | +| auth_identity_providerId_not_null | n | NOT NULL "providerId" | +| auth_identity_providerType_not_null | n | NOT NULL "providerType" | +| auth_identity_updatedAt_not_null | n | NOT NULL "updatedAt" | +| auth_identity_userId_fkey | FOREIGN KEY | FOREIGN KEY ("userId") REFERENCES "user"(id) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| auth_identity_pkey | CREATE UNIQUE INDEX auth_identity_pkey ON public.auth_identity USING btree ("providerId", "providerType") | + +## Relations + +```mermaid +erDiagram + +"public.auth_identity" }o--o| "public.user" : "FOREIGN KEY (#quot;userId#quot;) REFERENCES #quot;user#quot;(id)" + +"public.auth_identity" { + timestamp_3__with_time_zone createdAt + varchar_255_ providerId + varchar_32_ providerType + timestamp_3__with_time_zone updatedAt + uuid userId FK +} +"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 +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/postgres-schema/public.auth_provider_sync_history.md b/docs/generated/postgres-schema/public.auth_provider_sync_history.md new file mode 100644 index 00000000000..0f681cba193 --- /dev/null +++ b/docs/generated/postgres-schema/public.auth_provider_sync_history.md @@ -0,0 +1,64 @@ +# public.auth_provider_sync_history + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| created | integer | | false | | | | +| disabled | integer | | false | | | | +| endedAt | timestamp(3) with time zone | CURRENT_TIMESTAMP | false | | | | +| error | text | | true | | | | +| id | integer | nextval('auth_provider_sync_history_id_seq'::regclass) | false | | | | +| providerType | varchar(32) | | false | | | | +| runMode | text | | false | | | | +| scanned | integer | | false | | | | +| startedAt | timestamp(3) with time zone | CURRENT_TIMESTAMP | false | | | | +| status | text | | false | | | | +| updated | integer | | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| auth_provider_sync_history_created_not_null | n | NOT NULL created | +| auth_provider_sync_history_disabled_not_null | n | NOT NULL disabled | +| auth_provider_sync_history_endedAt_not_null | n | NOT NULL "endedAt" | +| auth_provider_sync_history_id_not_null | n | NOT NULL id | +| auth_provider_sync_history_pkey | PRIMARY KEY | PRIMARY KEY (id) | +| auth_provider_sync_history_providerType_not_null | n | NOT NULL "providerType" | +| auth_provider_sync_history_runMode_not_null | n | NOT NULL "runMode" | +| auth_provider_sync_history_scanned_not_null | n | NOT NULL scanned | +| auth_provider_sync_history_startedAt_not_null | n | NOT NULL "startedAt" | +| auth_provider_sync_history_status_not_null | n | NOT NULL status | +| auth_provider_sync_history_updated_not_null | n | NOT NULL updated | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| auth_provider_sync_history_pkey | CREATE UNIQUE INDEX auth_provider_sync_history_pkey ON public.auth_provider_sync_history USING btree (id) | + +## Relations + +```mermaid +erDiagram + + +"public.auth_provider_sync_history" { + integer created + integer disabled + timestamp_3__with_time_zone endedAt + text error + integer id + varchar_32_ providerType + text runMode + integer scanned + timestamp_3__with_time_zone startedAt + text status + integer updated +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/postgres-schema/public.binary_data.md b/docs/generated/postgres-schema/public.binary_data.md new file mode 100644 index 00000000000..22d62e04692 --- /dev/null +++ b/docs/generated/postgres-schema/public.binary_data.md @@ -0,0 +1,59 @@ +# public.binary_data + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| createdAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| data | bytea | | false | | | Raw, not base64 encoded | +| fileId | uuid | | false | | | | +| fileName | varchar(255) | | true | | | | +| fileSize | integer | | false | | | In bytes | +| mimeType | varchar(255) | | true | | | | +| sourceId | varchar(255) | | false | | | ID of the source, e.g. execution ID | +| sourceType | varchar(50) | | false | | | Source the file belongs to, e.g. 'execution' | +| updatedAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| CHK_binary_data_sourceType | CHECK | CHECK ((("sourceType")::text = ANY ((ARRAY['execution'::character varying, 'chat_message_attachment'::character varying, 'agent_file'::character varying])::text[]))) | +| PK_fc3691585b39408bb0551122af6 | PRIMARY KEY | PRIMARY KEY ("fileId") | +| binary_data_createdAt_not_null | n | NOT NULL "createdAt" | +| binary_data_data_not_null | n | NOT NULL data | +| binary_data_fileId_not_null | n | NOT NULL "fileId" | +| binary_data_fileSize_not_null | n | NOT NULL "fileSize" | +| binary_data_sourceId_not_null | n | NOT NULL "sourceId" | +| binary_data_sourceType_not_null | n | NOT NULL "sourceType" | +| binary_data_updatedAt_not_null | n | NOT NULL "updatedAt" | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_56900edc3cfd16612e2ef2c6a8 | CREATE INDEX "IDX_56900edc3cfd16612e2ef2c6a8" ON public.binary_data USING btree ("sourceType", "sourceId") | +| PK_fc3691585b39408bb0551122af6 | CREATE UNIQUE INDEX "PK_fc3691585b39408bb0551122af6" ON public.binary_data USING btree ("fileId") | + +## Relations + +```mermaid +erDiagram + + +"public.binary_data" { + timestamp_3__with_time_zone createdAt + bytea data + uuid fileId + varchar_255_ fileName + integer fileSize + varchar_255_ mimeType + varchar_255_ sourceId + varchar_50_ sourceType + timestamp_3__with_time_zone updatedAt +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/postgres-schema/public.chat_hub_agent_tools.md b/docs/generated/postgres-schema/public.chat_hub_agent_tools.md new file mode 100644 index 00000000000..a7d6e2e812b --- /dev/null +++ b/docs/generated/postgres-schema/public.chat_hub_agent_tools.md @@ -0,0 +1,68 @@ +# public.chat_hub_agent_tools + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| agentId | uuid | | false | | [public.chat_hub_agents](public.chat_hub_agents.md) | | +| toolId | uuid | | false | | [public.chat_hub_tools](public.chat_hub_tools.md) | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| FK_2b53d796b3dbae91b1a9553c048 | FOREIGN KEY | FOREIGN KEY ("agentId") REFERENCES chat_hub_agents(id) ON DELETE CASCADE | +| FK_43e70f04c53344f82483d0570f6 | FOREIGN KEY | FOREIGN KEY ("toolId") REFERENCES chat_hub_tools(id) ON DELETE CASCADE | +| PK_cc8806fdea48297a7d497035d72 | PRIMARY KEY | PRIMARY KEY ("agentId", "toolId") | +| chat_hub_agent_tools_agentId_not_null | n | NOT NULL "agentId" | +| chat_hub_agent_tools_toolId_not_null | n | NOT NULL "toolId" | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| PK_cc8806fdea48297a7d497035d72 | CREATE UNIQUE INDEX "PK_cc8806fdea48297a7d497035d72" ON public.chat_hub_agent_tools USING btree ("agentId", "toolId") | + +## Relations + +```mermaid +erDiagram + +"public.chat_hub_agent_tools" }o--|| "public.chat_hub_agents" : "FOREIGN KEY (#quot;agentId#quot;) REFERENCES chat_hub_agents(id) ON DELETE CASCADE" +"public.chat_hub_agent_tools" }o--|| "public.chat_hub_tools" : "FOREIGN KEY (#quot;toolId#quot;) REFERENCES chat_hub_tools(id) ON DELETE CASCADE" + +"public.chat_hub_agent_tools" { + uuid agentId FK + uuid toolId FK +} +"public.chat_hub_agents" { + timestamp_3__with_time_zone createdAt + varchar_36_ credentialId FK + varchar_512_ description + json files + json icon + uuid id + varchar_64_ model + varchar_256_ name + uuid ownerId FK + varchar_16_ provider + json suggestedPrompts + text systemPrompt + timestamp_3__with_time_zone updatedAt +} +"public.chat_hub_tools" { + timestamp_3__with_time_zone createdAt + json definition + boolean enabled + uuid id + varchar_255_ name + uuid ownerId FK + varchar_255_ type + double_precision typeVersion + timestamp_3__with_time_zone updatedAt +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/postgres-schema/public.chat_hub_agents.md b/docs/generated/postgres-schema/public.chat_hub_agents.md new file mode 100644 index 00000000000..17276ebaed2 --- /dev/null +++ b/docs/generated/postgres-schema/public.chat_hub_agents.md @@ -0,0 +1,143 @@ +# public.chat_hub_agents + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| createdAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| credentialId | varchar(36) | | true | | [public.credentials_entity](public.credentials_entity.md) | | +| description | varchar(512) | | true | | | | +| files | json | '[]'::json | false | | | | +| icon | json | | true | | | | +| id | uuid | | false | [public.chat_hub_agent_tools](public.chat_hub_agent_tools.md) [public.chat_hub_messages](public.chat_hub_messages.md) [public.chat_hub_sessions](public.chat_hub_sessions.md) | | | +| model | varchar(64) | | false | | | Model name used at the respective Model node, ie. "gpt-4" | +| name | varchar(256) | | false | | | | +| ownerId | uuid | | false | | [public.user](public.user.md) | | +| provider | varchar(16) | | false | | | ChatHubProvider enum: "openai", "anthropic", "google", "n8n" | +| suggestedPrompts | json | '[]'::json | false | | | | +| systemPrompt | text | | false | | | | +| updatedAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| FK_441ba2caba11e077ce3fbfa2cd8 | FOREIGN KEY | FOREIGN KEY ("ownerId") REFERENCES "user"(id) ON DELETE CASCADE | +| FK_9c61ad497dcbae499c96a6a78ba | FOREIGN KEY | FOREIGN KEY ("credentialId") REFERENCES credentials_entity(id) ON DELETE SET NULL | +| PK_f39a3b36bbdf0e2979ddb21cf78 | PRIMARY KEY | PRIMARY KEY (id) | +| chat_hub_agents_createdAt_not_null | n | NOT NULL "createdAt" | +| chat_hub_agents_files_not_null | n | NOT NULL files | +| chat_hub_agents_id_not_null | n | NOT NULL id | +| chat_hub_agents_model_not_null | n | NOT NULL model | +| chat_hub_agents_name_not_null | n | NOT NULL name | +| chat_hub_agents_ownerId_not_null | n | NOT NULL "ownerId" | +| chat_hub_agents_provider_not_null | n | NOT NULL provider | +| chat_hub_agents_suggestedPrompts_not_null | n | NOT NULL "suggestedPrompts" | +| chat_hub_agents_systemPrompt_not_null | n | NOT NULL "systemPrompt" | +| chat_hub_agents_updatedAt_not_null | n | NOT NULL "updatedAt" | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| PK_f39a3b36bbdf0e2979ddb21cf78 | CREATE UNIQUE INDEX "PK_f39a3b36bbdf0e2979ddb21cf78" ON public.chat_hub_agents USING btree (id) | + +## Relations + +```mermaid +erDiagram + +"public.chat_hub_agents" }o--o| "public.credentials_entity" : "FOREIGN KEY (#quot;credentialId#quot;) REFERENCES credentials_entity(id) ON DELETE SET NULL" +"public.chat_hub_agent_tools" }o--|| "public.chat_hub_agents" : "FOREIGN KEY (#quot;agentId#quot;) REFERENCES chat_hub_agents(id) ON DELETE CASCADE" +"public.chat_hub_messages" }o--o| "public.chat_hub_agents" : "FOREIGN KEY (#quot;agentId#quot;) REFERENCES chat_hub_agents(id) ON DELETE SET NULL" +"public.chat_hub_sessions" }o--o| "public.chat_hub_agents" : "FOREIGN KEY (#quot;agentId#quot;) REFERENCES chat_hub_agents(id) ON DELETE SET NULL" +"public.chat_hub_agents" }o--|| "public.user" : "FOREIGN KEY (#quot;ownerId#quot;) REFERENCES #quot;user#quot;(id) ON DELETE CASCADE" + +"public.chat_hub_agents" { + timestamp_3__with_time_zone createdAt + varchar_36_ credentialId FK + varchar_512_ description + json files + json icon + uuid id + varchar_64_ model + varchar_256_ name + uuid ownerId FK + varchar_16_ provider + json suggestedPrompts + text systemPrompt + timestamp_3__with_time_zone updatedAt +} +"public.credentials_entity" { + timestamp_3__with_time_zone createdAt + text data + varchar_36_ id + boolean isGlobal + boolean isManaged + boolean isResolvable + varchar_128_ name + boolean resolvableAllowFallback + varchar_16_ resolverId FK + varchar_128_ type + timestamp_3__with_time_zone updatedAt +} +"public.chat_hub_agent_tools" { + uuid agentId FK + uuid toolId FK +} +"public.chat_hub_messages" { + uuid agentId FK + json attachments + text content + timestamp_3__with_time_zone createdAt + integer executionId FK + uuid id + varchar_256_ model + varchar_128_ name + uuid previousMessageId FK + varchar_16_ provider + uuid retryOfMessageId FK + uuid revisionOfMessageId FK + uuid sessionId FK + varchar_16_ status + varchar_16_ type + timestamp_3__with_time_zone updatedAt + varchar_36_ workflowId FK +} +"public.chat_hub_sessions" { + uuid agentId FK + varchar_128_ agentName + timestamp_3__with_time_zone createdAt + varchar_36_ credentialId FK + uuid id + timestamp_3__with_time_zone lastMessageAt + varchar_256_ model + uuid ownerId FK + varchar_16_ provider + varchar_256_ title + varchar_16_ type + timestamp_3__with_time_zone updatedAt + varchar_36_ workflowId FK +} +"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 +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/postgres-schema/public.chat_hub_messages.md b/docs/generated/postgres-schema/public.chat_hub_messages.md new file mode 100644 index 00000000000..9749ae06860 --- /dev/null +++ b/docs/generated/postgres-schema/public.chat_hub_messages.md @@ -0,0 +1,161 @@ +# public.chat_hub_messages + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| agentId | uuid | | true | | [public.chat_hub_agents](public.chat_hub_agents.md) | ID of the custom agent (if provider is "custom-agent") | +| attachments | json | | true | | | File attachments for the message (if any), stored as JSON. Files are stored as base64-encoded data URLs. | +| content | text | | false | | | | +| createdAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| executionId | integer | | true | | [public.execution_entity](public.execution_entity.md) | | +| id | uuid | | false | [public.chat_hub_messages](public.chat_hub_messages.md) | | | +| model | varchar(256) | | true | | | Model name used at the respective Model node, ie. "gpt-4" | +| name | varchar(128) | | false | | | | +| previousMessageId | uuid | | true | | [public.chat_hub_messages](public.chat_hub_messages.md) | | +| provider | varchar(16) | | true | | | ChatHubProvider enum: "openai", "anthropic", "google", "n8n" | +| retryOfMessageId | uuid | | true | | [public.chat_hub_messages](public.chat_hub_messages.md) | | +| revisionOfMessageId | uuid | | true | | [public.chat_hub_messages](public.chat_hub_messages.md) | | +| sessionId | uuid | | false | | [public.chat_hub_sessions](public.chat_hub_sessions.md) | | +| status | varchar(16) | 'success'::character varying | false | | | ChatHubMessageStatus enum, eg. "success", "error", "running", "cancelled" | +| type | varchar(16) | | false | | | ChatHubMessageType enum: "human", "ai", "system", "tool", "generic" | +| updatedAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| workflowId | varchar(36) | | true | | [public.workflow_entity](public.workflow_entity.md) | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| FK_1f4998c8a7dec9e00a9ab15550e | FOREIGN KEY | FOREIGN KEY ("revisionOfMessageId") REFERENCES chat_hub_messages(id) ON DELETE CASCADE | +| FK_25c9736e7f769f3a005eef4b372 | FOREIGN KEY | FOREIGN KEY ("retryOfMessageId") REFERENCES chat_hub_messages(id) ON DELETE CASCADE | +| FK_6afb260449dd7a9b85355d4e0c9 | FOREIGN KEY | FOREIGN KEY ("executionId") REFERENCES execution_entity(id) ON DELETE SET NULL | +| FK_acf8926098f063cdbbad8497fd1 | FOREIGN KEY | FOREIGN KEY ("workflowId") REFERENCES workflow_entity(id) ON DELETE SET NULL | +| FK_chat_hub_messages_agentId | FOREIGN KEY | FOREIGN KEY ("agentId") REFERENCES chat_hub_agents(id) ON DELETE SET NULL | +| FK_e22538eb50a71a17954cd7e076c | FOREIGN KEY | FOREIGN KEY ("sessionId") REFERENCES chat_hub_sessions(id) ON DELETE CASCADE | +| FK_e5d1fa722c5a8d38ac204746662 | FOREIGN KEY | FOREIGN KEY ("previousMessageId") REFERENCES chat_hub_messages(id) ON DELETE CASCADE | +| PK_7704a5add6baed43eef835f0bfb | PRIMARY KEY | PRIMARY KEY (id) | +| chat_hub_messages_content_not_null | n | NOT NULL content | +| chat_hub_messages_createdAt_not_null | n | NOT NULL "createdAt" | +| chat_hub_messages_id_not_null | n | NOT NULL id | +| chat_hub_messages_name_not_null | n | NOT NULL name | +| chat_hub_messages_sessionId_not_null | n | NOT NULL "sessionId" | +| chat_hub_messages_status_not_null | n | NOT NULL status | +| chat_hub_messages_type_not_null | n | NOT NULL type | +| chat_hub_messages_updatedAt_not_null | n | NOT NULL "updatedAt" | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_chat_hub_messages_sessionId | CREATE INDEX "IDX_chat_hub_messages_sessionId" ON public.chat_hub_messages USING btree ("sessionId") | +| PK_7704a5add6baed43eef835f0bfb | CREATE UNIQUE INDEX "PK_7704a5add6baed43eef835f0bfb" ON public.chat_hub_messages USING btree (id) | + +## Relations + +```mermaid +erDiagram + +"public.chat_hub_messages" }o--o| "public.chat_hub_agents" : "FOREIGN KEY (#quot;agentId#quot;) REFERENCES chat_hub_agents(id) ON DELETE SET NULL" +"public.chat_hub_messages" }o--o| "public.execution_entity" : "FOREIGN KEY (#quot;executionId#quot;) REFERENCES execution_entity(id) ON DELETE SET NULL" +"public.chat_hub_messages" }o--o| "public.chat_hub_messages" : "FOREIGN KEY (#quot;revisionOfMessageId#quot;) REFERENCES chat_hub_messages(id) ON DELETE CASCADE" +"public.chat_hub_messages" }o--o| "public.chat_hub_messages" : "FOREIGN KEY (#quot;retryOfMessageId#quot;) REFERENCES chat_hub_messages(id) ON DELETE CASCADE" +"public.chat_hub_messages" }o--o| "public.chat_hub_messages" : "FOREIGN KEY (#quot;previousMessageId#quot;) REFERENCES chat_hub_messages(id) ON DELETE CASCADE" +"public.chat_hub_messages" }o--|| "public.chat_hub_sessions" : "FOREIGN KEY (#quot;sessionId#quot;) REFERENCES chat_hub_sessions(id) ON DELETE CASCADE" +"public.chat_hub_messages" }o--o| "public.workflow_entity" : "FOREIGN KEY (#quot;workflowId#quot;) REFERENCES workflow_entity(id) ON DELETE SET NULL" + +"public.chat_hub_messages" { + uuid agentId FK + json attachments + text content + timestamp_3__with_time_zone createdAt + integer executionId FK + uuid id + varchar_256_ model + varchar_128_ name + uuid previousMessageId FK + varchar_16_ provider + uuid retryOfMessageId FK + uuid revisionOfMessageId FK + uuid sessionId FK + varchar_16_ status + varchar_16_ type + timestamp_3__with_time_zone updatedAt + varchar_36_ workflowId FK +} +"public.chat_hub_agents" { + timestamp_3__with_time_zone createdAt + varchar_36_ credentialId FK + varchar_512_ description + json files + json icon + uuid id + varchar_64_ model + varchar_256_ name + uuid ownerId FK + varchar_16_ provider + json suggestedPrompts + text systemPrompt + timestamp_3__with_time_zone updatedAt +} +"public.execution_entity" { + bigint binaryDataSizeBytes + timestamp_3__with_time_zone createdAt + varchar_255_ deduplicationKey + timestamp_3__with_time_zone deletedAt + boolean finished + integer id + bigint jsonSizeBytes + varchar mode + varchar retryOf + varchar retrySuccessId + timestamp_3__with_time_zone startedAt + varchar status + timestamp_3__with_time_zone stoppedAt + varchar_2_ storedAt + json tracingContext + timestamp_3__with_time_zone waitTill + varchar_36_ workflowId FK + varchar_36_ workflowVersionId +} +"public.chat_hub_sessions" { + uuid agentId FK + varchar_128_ agentName + timestamp_3__with_time_zone createdAt + varchar_36_ credentialId FK + uuid id + timestamp_3__with_time_zone lastMessageAt + varchar_256_ model + uuid ownerId FK + varchar_16_ provider + varchar_256_ title + varchar_16_ type + timestamp_3__with_time_zone updatedAt + varchar_36_ workflowId FK +} +"public.workflow_entity" { + boolean active + varchar_36_ activeVersionId FK + json connections + timestamp_3__with_time_zone createdAt + text description + varchar_36_ id + boolean isArchived + json meta + varchar_128_ name + json nodeGroups + json nodes + varchar_36_ parentFolderId FK + json pinData + json settings + varchar sourceWorkflowId + json staticData + integer triggerCount + timestamp_3__with_time_zone updatedAt + integer versionCounter + character_36_ versionId +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/postgres-schema/public.chat_hub_session_tools.md b/docs/generated/postgres-schema/public.chat_hub_session_tools.md new file mode 100644 index 00000000000..1a6cb7a1452 --- /dev/null +++ b/docs/generated/postgres-schema/public.chat_hub_session_tools.md @@ -0,0 +1,68 @@ +# public.chat_hub_session_tools + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| sessionId | uuid | | false | | [public.chat_hub_sessions](public.chat_hub_sessions.md) | | +| toolId | uuid | | false | | [public.chat_hub_tools](public.chat_hub_tools.md) | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| FK_6596a328affd8d4967ffb303eee | FOREIGN KEY | FOREIGN KEY ("toolId") REFERENCES chat_hub_tools(id) ON DELETE CASCADE | +| FK_e649bf1295f4ed8d4299ed290f9 | FOREIGN KEY | FOREIGN KEY ("sessionId") REFERENCES chat_hub_sessions(id) ON DELETE CASCADE | +| PK_87aea76ff4c274c4a5ac838ebe3 | PRIMARY KEY | PRIMARY KEY ("sessionId", "toolId") | +| chat_hub_session_tools_sessionId_not_null | n | NOT NULL "sessionId" | +| chat_hub_session_tools_toolId_not_null | n | NOT NULL "toolId" | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| PK_87aea76ff4c274c4a5ac838ebe3 | CREATE UNIQUE INDEX "PK_87aea76ff4c274c4a5ac838ebe3" ON public.chat_hub_session_tools USING btree ("sessionId", "toolId") | + +## Relations + +```mermaid +erDiagram + +"public.chat_hub_session_tools" }o--|| "public.chat_hub_sessions" : "FOREIGN KEY (#quot;sessionId#quot;) REFERENCES chat_hub_sessions(id) ON DELETE CASCADE" +"public.chat_hub_session_tools" }o--|| "public.chat_hub_tools" : "FOREIGN KEY (#quot;toolId#quot;) REFERENCES chat_hub_tools(id) ON DELETE CASCADE" + +"public.chat_hub_session_tools" { + uuid sessionId FK + uuid toolId FK +} +"public.chat_hub_sessions" { + uuid agentId FK + varchar_128_ agentName + timestamp_3__with_time_zone createdAt + varchar_36_ credentialId FK + uuid id + timestamp_3__with_time_zone lastMessageAt + varchar_256_ model + uuid ownerId FK + varchar_16_ provider + varchar_256_ title + varchar_16_ type + timestamp_3__with_time_zone updatedAt + varchar_36_ workflowId FK +} +"public.chat_hub_tools" { + timestamp_3__with_time_zone createdAt + json definition + boolean enabled + uuid id + varchar_255_ name + uuid ownerId FK + varchar_255_ type + double_precision typeVersion + timestamp_3__with_time_zone updatedAt +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/postgres-schema/public.chat_hub_sessions.md b/docs/generated/postgres-schema/public.chat_hub_sessions.md new file mode 100644 index 00000000000..e27222bc539 --- /dev/null +++ b/docs/generated/postgres-schema/public.chat_hub_sessions.md @@ -0,0 +1,167 @@ +# public.chat_hub_sessions + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| agentId | uuid | | true | | [public.chat_hub_agents](public.chat_hub_agents.md) | ID of the custom agent (if provider is "custom-agent") | +| agentName | varchar(128) | | true | | | Cached name of the custom agent (if provider is "custom-agent") | +| createdAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| credentialId | varchar(36) | | true | | [public.credentials_entity](public.credentials_entity.md) | | +| id | uuid | | false | [public.chat_hub_messages](public.chat_hub_messages.md) [public.chat_hub_session_tools](public.chat_hub_session_tools.md) | | | +| lastMessageAt | timestamp(3) with time zone | | false | | | | +| model | varchar(256) | | true | | | Model name used at the respective Model node, ie. "gpt-4" | +| ownerId | uuid | | false | | [public.user](public.user.md) | | +| provider | varchar(16) | | true | | | ChatHubProvider enum: "openai", "anthropic", "google", "n8n" | +| title | varchar(256) | | false | | | | +| type | varchar(16) | 'production'::character varying | false | | | | +| updatedAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| workflowId | varchar(36) | | true | | [public.workflow_entity](public.workflow_entity.md) | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| CHK_chat_hub_sessions_type | CHECK | CHECK (((type)::text = ANY ((ARRAY['production'::character varying, 'manual'::character varying])::text[]))) | +| FK_7bc13b4c7e6afbfaf9be326c189 | FOREIGN KEY | FOREIGN KEY ("credentialId") REFERENCES credentials_entity(id) ON DELETE SET NULL | +| FK_9f9293d9f552496c40e0d1a8f80 | FOREIGN KEY | FOREIGN KEY ("workflowId") REFERENCES workflow_entity(id) ON DELETE SET NULL | +| FK_chat_hub_sessions_agentId | FOREIGN KEY | FOREIGN KEY ("agentId") REFERENCES chat_hub_agents(id) ON DELETE SET NULL | +| FK_e9ecf8ede7d989fcd18790fe36a | FOREIGN KEY | FOREIGN KEY ("ownerId") REFERENCES "user"(id) ON DELETE CASCADE | +| PK_1eafef1273c70e4464fec703412 | PRIMARY KEY | PRIMARY KEY (id) | +| chat_hub_sessions_createdAt_not_null | n | NOT NULL "createdAt" | +| chat_hub_sessions_id_not_null | n | NOT NULL id | +| chat_hub_sessions_lastMessageAt_not_null | n | NOT NULL "lastMessageAt" | +| chat_hub_sessions_ownerId_not_null | n | NOT NULL "ownerId" | +| chat_hub_sessions_title_not_null | n | NOT NULL title | +| chat_hub_sessions_type_not_null | n | NOT NULL type | +| chat_hub_sessions_updatedAt_not_null | n | NOT NULL "updatedAt" | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_chat_hub_sessions_owner_lastmsg_id | CREATE INDEX "IDX_chat_hub_sessions_owner_lastmsg_id" ON public.chat_hub_sessions USING btree ("ownerId", "lastMessageAt" DESC, id) | +| PK_1eafef1273c70e4464fec703412 | CREATE UNIQUE INDEX "PK_1eafef1273c70e4464fec703412" ON public.chat_hub_sessions USING btree (id) | + +## Relations + +```mermaid +erDiagram + +"public.chat_hub_sessions" }o--o| "public.chat_hub_agents" : "FOREIGN KEY (#quot;agentId#quot;) REFERENCES chat_hub_agents(id) ON DELETE SET NULL" +"public.chat_hub_sessions" }o--o| "public.credentials_entity" : "FOREIGN KEY (#quot;credentialId#quot;) REFERENCES credentials_entity(id) ON DELETE SET NULL" +"public.chat_hub_messages" }o--|| "public.chat_hub_sessions" : "FOREIGN KEY (#quot;sessionId#quot;) REFERENCES chat_hub_sessions(id) ON DELETE CASCADE" +"public.chat_hub_session_tools" }o--|| "public.chat_hub_sessions" : "FOREIGN KEY (#quot;sessionId#quot;) REFERENCES chat_hub_sessions(id) ON DELETE CASCADE" +"public.chat_hub_sessions" }o--|| "public.user" : "FOREIGN KEY (#quot;ownerId#quot;) REFERENCES #quot;user#quot;(id) ON DELETE CASCADE" +"public.chat_hub_sessions" }o--o| "public.workflow_entity" : "FOREIGN KEY (#quot;workflowId#quot;) REFERENCES workflow_entity(id) ON DELETE SET NULL" + +"public.chat_hub_sessions" { + uuid agentId FK + varchar_128_ agentName + timestamp_3__with_time_zone createdAt + varchar_36_ credentialId FK + uuid id + timestamp_3__with_time_zone lastMessageAt + varchar_256_ model + uuid ownerId FK + varchar_16_ provider + varchar_256_ title + varchar_16_ type + timestamp_3__with_time_zone updatedAt + varchar_36_ workflowId FK +} +"public.chat_hub_agents" { + timestamp_3__with_time_zone createdAt + varchar_36_ credentialId FK + varchar_512_ description + json files + json icon + uuid id + varchar_64_ model + varchar_256_ name + uuid ownerId FK + varchar_16_ provider + json suggestedPrompts + text systemPrompt + timestamp_3__with_time_zone updatedAt +} +"public.credentials_entity" { + timestamp_3__with_time_zone createdAt + text data + varchar_36_ id + boolean isGlobal + boolean isManaged + boolean isResolvable + varchar_128_ name + boolean resolvableAllowFallback + varchar_16_ resolverId FK + varchar_128_ type + timestamp_3__with_time_zone updatedAt +} +"public.chat_hub_messages" { + uuid agentId FK + json attachments + text content + timestamp_3__with_time_zone createdAt + integer executionId FK + uuid id + varchar_256_ model + varchar_128_ name + uuid previousMessageId FK + varchar_16_ provider + uuid retryOfMessageId FK + uuid revisionOfMessageId FK + uuid sessionId FK + varchar_16_ status + varchar_16_ type + timestamp_3__with_time_zone updatedAt + varchar_36_ workflowId FK +} +"public.chat_hub_session_tools" { + uuid sessionId FK + uuid toolId FK +} +"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.workflow_entity" { + boolean active + varchar_36_ activeVersionId FK + json connections + timestamp_3__with_time_zone createdAt + text description + varchar_36_ id + boolean isArchived + json meta + varchar_128_ name + json nodeGroups + json nodes + varchar_36_ parentFolderId FK + json pinData + json settings + varchar sourceWorkflowId + json staticData + integer triggerCount + timestamp_3__with_time_zone updatedAt + integer versionCounter + character_36_ versionId +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/postgres-schema/public.chat_hub_tools.md b/docs/generated/postgres-schema/public.chat_hub_tools.md new file mode 100644 index 00000000000..05bea5d1a20 --- /dev/null +++ b/docs/generated/postgres-schema/public.chat_hub_tools.md @@ -0,0 +1,89 @@ +# public.chat_hub_tools + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| createdAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| definition | json | | false | | | | +| enabled | boolean | true | false | | | | +| id | uuid | | false | [public.chat_hub_agent_tools](public.chat_hub_agent_tools.md) [public.chat_hub_session_tools](public.chat_hub_session_tools.md) | | | +| name | varchar(255) | | false | | | | +| ownerId | uuid | | false | | [public.user](public.user.md) | | +| type | varchar(255) | | false | | | | +| typeVersion | double precision | | false | | | | +| updatedAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| FK_b8030b47af9213f1fd15450fb7f | FOREIGN KEY | FOREIGN KEY ("ownerId") REFERENCES "user"(id) ON DELETE CASCADE | +| PK_696d26426c704fba79b2c195ef5 | PRIMARY KEY | PRIMARY KEY (id) | +| chat_hub_tools_createdAt_not_null | n | NOT NULL "createdAt" | +| chat_hub_tools_definition_not_null | n | NOT NULL definition | +| chat_hub_tools_enabled_not_null | n | NOT NULL enabled | +| chat_hub_tools_id_not_null | n | NOT NULL id | +| chat_hub_tools_name_not_null | n | NOT NULL name | +| chat_hub_tools_ownerId_not_null | n | NOT NULL "ownerId" | +| chat_hub_tools_typeVersion_not_null | n | NOT NULL "typeVersion" | +| chat_hub_tools_type_not_null | n | NOT NULL type | +| chat_hub_tools_updatedAt_not_null | n | NOT NULL "updatedAt" | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_4c72ebdb265d1775bf61147af0 | CREATE UNIQUE INDEX "IDX_4c72ebdb265d1775bf61147af0" ON public.chat_hub_tools USING btree ("ownerId", name) | +| PK_696d26426c704fba79b2c195ef5 | CREATE UNIQUE INDEX "PK_696d26426c704fba79b2c195ef5" ON public.chat_hub_tools USING btree (id) | + +## Relations + +```mermaid +erDiagram + +"public.chat_hub_agent_tools" }o--|| "public.chat_hub_tools" : "FOREIGN KEY (#quot;toolId#quot;) REFERENCES chat_hub_tools(id) ON DELETE CASCADE" +"public.chat_hub_session_tools" }o--|| "public.chat_hub_tools" : "FOREIGN KEY (#quot;toolId#quot;) REFERENCES chat_hub_tools(id) ON DELETE CASCADE" +"public.chat_hub_tools" }o--|| "public.user" : "FOREIGN KEY (#quot;ownerId#quot;) REFERENCES #quot;user#quot;(id) ON DELETE CASCADE" + +"public.chat_hub_tools" { + timestamp_3__with_time_zone createdAt + json definition + boolean enabled + uuid id + varchar_255_ name + uuid ownerId FK + varchar_255_ type + double_precision typeVersion + timestamp_3__with_time_zone updatedAt +} +"public.chat_hub_agent_tools" { + uuid agentId FK + uuid toolId FK +} +"public.chat_hub_session_tools" { + uuid sessionId FK + uuid toolId FK +} +"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 +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/postgres-schema/public.credential_dependency.md b/docs/generated/postgres-schema/public.credential_dependency.md new file mode 100644 index 00000000000..392925de42d --- /dev/null +++ b/docs/generated/postgres-schema/public.credential_dependency.md @@ -0,0 +1,65 @@ +# public.credential_dependency + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| createdAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| credentialId | varchar(36) | | false | | [public.credentials_entity](public.credentials_entity.md) | | +| dependencyId | varchar(255) | | false | | | | +| dependencyType | varchar(64) | | false | | | | +| id | integer | | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| FK_5ec8e8c8d3539f3696cf73b43bf | FOREIGN KEY | FOREIGN KEY ("credentialId") REFERENCES credentials_entity(id) ON DELETE CASCADE | +| PK_80212729ed0ffa0709417ab28f4 | PRIMARY KEY | PRIMARY KEY (id) | +| credential_dependency_createdAt_not_null | n | NOT NULL "createdAt" | +| credential_dependency_credentialId_not_null | n | NOT NULL "credentialId" | +| credential_dependency_dependencyId_not_null | n | NOT NULL "dependencyId" | +| credential_dependency_dependencyType_not_null | n | NOT NULL "dependencyType" | +| credential_dependency_id_not_null | n | NOT NULL id | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_5ec8e8c8d3539f3696cf73b43b | CREATE INDEX "IDX_5ec8e8c8d3539f3696cf73b43b" ON public.credential_dependency USING btree ("credentialId") | +| IDX_91ee85fa9619dd6776725e117b | CREATE INDEX "IDX_91ee85fa9619dd6776725e117b" ON public.credential_dependency USING btree ("dependencyType", "dependencyId") | +| IDX_credential_dependency_credentialId_dependencyType_dependenc | CREATE UNIQUE INDEX "IDX_credential_dependency_credentialId_dependencyType_dependenc" ON public.credential_dependency USING btree ("credentialId", "dependencyType", "dependencyId") | +| PK_80212729ed0ffa0709417ab28f4 | CREATE UNIQUE INDEX "PK_80212729ed0ffa0709417ab28f4" ON public.credential_dependency USING btree (id) | + +## Relations + +```mermaid +erDiagram + +"public.credential_dependency" }o--|| "public.credentials_entity" : "FOREIGN KEY (#quot;credentialId#quot;) REFERENCES credentials_entity(id) ON DELETE CASCADE" + +"public.credential_dependency" { + timestamp_3__with_time_zone createdAt + varchar_36_ credentialId FK + varchar_255_ dependencyId + varchar_64_ dependencyType + integer id +} +"public.credentials_entity" { + timestamp_3__with_time_zone createdAt + text data + varchar_36_ id + boolean isGlobal + boolean isManaged + boolean isResolvable + varchar_128_ name + boolean resolvableAllowFallback + varchar_16_ resolverId FK + varchar_128_ type + timestamp_3__with_time_zone updatedAt +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/postgres-schema/public.credentials_entity.md b/docs/generated/postgres-schema/public.credentials_entity.md new file mode 100644 index 00000000000..b7088d0f3ce --- /dev/null +++ b/docs/generated/postgres-schema/public.credentials_entity.md @@ -0,0 +1,152 @@ +# public.credentials_entity + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| createdAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| data | text | | false | | | | +| id | varchar(36) | | false | [public.chat_hub_agents](public.chat_hub_agents.md) [public.chat_hub_sessions](public.chat_hub_sessions.md) [public.credential_dependency](public.credential_dependency.md) [public.dynamic_credential_entry](public.dynamic_credential_entry.md) [public.dynamic_credential_user_entry](public.dynamic_credential_user_entry.md) [public.instance_ai_mcp_registry_connections](public.instance_ai_mcp_registry_connections.md) [public.shared_credentials](public.shared_credentials.md) | | | +| isGlobal | boolean | false | false | | | | +| isManaged | boolean | false | false | | | | +| isResolvable | boolean | false | false | | | | +| name | varchar(128) | | false | | | | +| resolvableAllowFallback | boolean | false | false | | | | +| resolverId | varchar(16) | | true | | [public.dynamic_credential_resolver](public.dynamic_credential_resolver.md) | | +| type | varchar(128) | | false | | | | +| updatedAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| credentials_entity_createdAt_not_null | n | NOT NULL "createdAt" | +| credentials_entity_data_not_null | n | NOT NULL data | +| credentials_entity_id_not_null1 | n | NOT NULL id | +| credentials_entity_isGlobal_not_null | n | NOT NULL "isGlobal" | +| credentials_entity_isManaged_not_null | n | NOT NULL "isManaged" | +| credentials_entity_isResolvable_not_null | n | NOT NULL "isResolvable" | +| credentials_entity_name_not_null | n | NOT NULL name | +| credentials_entity_pkey | PRIMARY KEY | PRIMARY KEY (id) | +| credentials_entity_resolvableAllowFallback_not_null | n | NOT NULL "resolvableAllowFallback" | +| credentials_entity_resolverId_foreign | FOREIGN KEY | FOREIGN KEY ("resolverId") REFERENCES dynamic_credential_resolver(id) ON DELETE SET NULL | +| credentials_entity_type_not_null | n | NOT NULL type | +| credentials_entity_updatedAt_not_null | n | NOT NULL "updatedAt" | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| credentials_entity_pkey | CREATE UNIQUE INDEX credentials_entity_pkey ON public.credentials_entity USING btree (id) | +| idx_07fde106c0b471d8cc80a64fc8 | CREATE INDEX idx_07fde106c0b471d8cc80a64fc8 ON public.credentials_entity USING btree (type) | +| pk_credentials_entity_id | CREATE UNIQUE INDEX pk_credentials_entity_id ON public.credentials_entity USING btree (id) | + +## Relations + +```mermaid +erDiagram + +"public.chat_hub_agents" }o--o| "public.credentials_entity" : "FOREIGN KEY (#quot;credentialId#quot;) REFERENCES credentials_entity(id) ON DELETE SET NULL" +"public.chat_hub_sessions" }o--o| "public.credentials_entity" : "FOREIGN KEY (#quot;credentialId#quot;) REFERENCES credentials_entity(id) ON DELETE SET NULL" +"public.credential_dependency" }o--|| "public.credentials_entity" : "FOREIGN KEY (#quot;credentialId#quot;) REFERENCES credentials_entity(id) ON DELETE CASCADE" +"public.dynamic_credential_entry" }o--|| "public.credentials_entity" : "FOREIGN KEY (credential_id) REFERENCES credentials_entity(id) ON DELETE CASCADE" +"public.dynamic_credential_user_entry" }o--|| "public.credentials_entity" : "FOREIGN KEY (#quot;credentialId#quot;) REFERENCES credentials_entity(id) ON DELETE CASCADE" +"public.instance_ai_mcp_registry_connections" }o--|| "public.credentials_entity" : "FOREIGN KEY (#quot;credentialId#quot;) REFERENCES credentials_entity(id) ON DELETE CASCADE" +"public.shared_credentials" }o--|| "public.credentials_entity" : "FOREIGN KEY (#quot;credentialsId#quot;) REFERENCES credentials_entity(id) ON DELETE CASCADE" +"public.credentials_entity" }o--o| "public.dynamic_credential_resolver" : "FOREIGN KEY (#quot;resolverId#quot;) REFERENCES dynamic_credential_resolver(id) ON DELETE SET NULL" + +"public.credentials_entity" { + timestamp_3__with_time_zone createdAt + text data + varchar_36_ id + boolean isGlobal + boolean isManaged + boolean isResolvable + varchar_128_ name + boolean resolvableAllowFallback + varchar_16_ resolverId FK + varchar_128_ type + timestamp_3__with_time_zone updatedAt +} +"public.chat_hub_agents" { + timestamp_3__with_time_zone createdAt + varchar_36_ credentialId FK + varchar_512_ description + json files + json icon + uuid id + varchar_64_ model + varchar_256_ name + uuid ownerId FK + varchar_16_ provider + json suggestedPrompts + text systemPrompt + timestamp_3__with_time_zone updatedAt +} +"public.chat_hub_sessions" { + uuid agentId FK + varchar_128_ agentName + timestamp_3__with_time_zone createdAt + varchar_36_ credentialId FK + uuid id + timestamp_3__with_time_zone lastMessageAt + varchar_256_ model + uuid ownerId FK + varchar_16_ provider + varchar_256_ title + varchar_16_ type + timestamp_3__with_time_zone updatedAt + varchar_36_ workflowId FK +} +"public.credential_dependency" { + timestamp_3__with_time_zone createdAt + varchar_36_ credentialId FK + varchar_255_ dependencyId + varchar_64_ dependencyType + integer id +} +"public.dynamic_credential_entry" { + timestamp_3__with_time_zone createdAt + varchar_16_ credential_id FK + text data + varchar_16_ resolver_id FK + varchar_2048_ subject_id + timestamp_3__with_time_zone updatedAt +} +"public.dynamic_credential_user_entry" { + timestamp_3__with_time_zone createdAt + varchar_16_ credentialId FK + text data + varchar_16_ resolverId FK + timestamp_3__with_time_zone updatedAt + uuid userId FK +} +"public.instance_ai_mcp_registry_connections" { + timestamp_3__with_time_zone createdAt + varchar_36_ credentialId FK + uuid id + varchar_255_ serverSlug FK + json toolFilter + timestamp_3__with_time_zone updatedAt + uuid userId FK +} +"public.shared_credentials" { + timestamp_3__with_time_zone createdAt + varchar_36_ credentialsId FK + varchar_36_ projectId FK + text role + timestamp_3__with_time_zone updatedAt +} +"public.dynamic_credential_resolver" { + text config + timestamp_3__with_time_zone createdAt + varchar_16_ id + varchar_128_ name + varchar_128_ type + timestamp_3__with_time_zone updatedAt +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/postgres-schema/public.data_table.md b/docs/generated/postgres-schema/public.data_table.md new file mode 100644 index 00000000000..05667e6d60f --- /dev/null +++ b/docs/generated/postgres-schema/public.data_table.md @@ -0,0 +1,72 @@ +# public.data_table + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| createdAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| id | varchar(36) | | false | [public.data_table_column](public.data_table_column.md) | | | +| name | varchar(128) | | false | | | | +| projectId | varchar(36) | | false | | [public.project](public.project.md) | | +| updatedAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| FK_c2a794257dee48af7c9abf681de | FOREIGN KEY | FOREIGN KEY ("projectId") REFERENCES project(id) ON DELETE CASCADE | +| PK_e226d0001b9e6097cbfe70617cb | PRIMARY KEY | PRIMARY KEY (id) | +| UQ_b23096ef747281ac944d28e8b0d | UNIQUE | UNIQUE ("projectId", name) | +| data_table_createdAt_not_null | n | NOT NULL "createdAt" | +| data_table_id_not_null | n | NOT NULL id | +| data_table_name_not_null | n | NOT NULL name | +| data_table_projectId_not_null | n | NOT NULL "projectId" | +| data_table_updatedAt_not_null | n | NOT NULL "updatedAt" | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| PK_e226d0001b9e6097cbfe70617cb | CREATE UNIQUE INDEX "PK_e226d0001b9e6097cbfe70617cb" ON public.data_table USING btree (id) | +| UQ_b23096ef747281ac944d28e8b0d | CREATE UNIQUE INDEX "UQ_b23096ef747281ac944d28e8b0d" ON public.data_table USING btree ("projectId", name) | + +## Relations + +```mermaid +erDiagram + +"public.data_table_column" }o--|| "public.data_table" : "FOREIGN KEY (#quot;dataTableId#quot;) REFERENCES data_table(id) ON DELETE CASCADE" +"public.data_table" }o--|| "public.project" : "FOREIGN KEY (#quot;projectId#quot;) REFERENCES project(id) ON DELETE CASCADE" + +"public.data_table" { + timestamp_3__with_time_zone createdAt + varchar_36_ id + varchar_128_ name + varchar_36_ projectId FK + timestamp_3__with_time_zone updatedAt +} +"public.data_table_column" { + timestamp_3__with_time_zone createdAt + varchar_36_ dataTableId FK + varchar_36_ id + integer index + varchar_128_ name + varchar_32_ type + timestamp_3__with_time_zone updatedAt +} +"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.data_table_column.md b/docs/generated/postgres-schema/public.data_table_column.md new file mode 100644 index 00000000000..b79a5701fd6 --- /dev/null +++ b/docs/generated/postgres-schema/public.data_table_column.md @@ -0,0 +1,64 @@ +# public.data_table_column + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| createdAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| dataTableId | varchar(36) | | false | | [public.data_table](public.data_table.md) | | +| id | varchar(36) | | false | | | | +| index | integer | | false | | | Column order, starting from 0 (0 = first column) | +| name | varchar(128) | | false | | | | +| type | varchar(32) | | false | | | Expected: string, number, boolean, or date (not enforced as a constraint) | +| updatedAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| FK_930b6e8faaf88294cef23484160 | FOREIGN KEY | FOREIGN KEY ("dataTableId") REFERENCES data_table(id) ON DELETE CASCADE | +| PK_673cb121ee4a8a5e27850c72c51 | PRIMARY KEY | PRIMARY KEY (id) | +| UQ_8082ec4890f892f0bc77473a123 | UNIQUE | UNIQUE ("dataTableId", name) | +| data_table_column_createdAt_not_null | n | NOT NULL "createdAt" | +| data_table_column_dataTableId_not_null | n | NOT NULL "dataTableId" | +| data_table_column_id_not_null | n | NOT NULL id | +| data_table_column_index_not_null | n | NOT NULL index | +| data_table_column_name_not_null | n | NOT NULL name | +| data_table_column_type_not_null | n | NOT NULL type | +| data_table_column_updatedAt_not_null | n | NOT NULL "updatedAt" | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| PK_673cb121ee4a8a5e27850c72c51 | CREATE UNIQUE INDEX "PK_673cb121ee4a8a5e27850c72c51" ON public.data_table_column USING btree (id) | +| UQ_8082ec4890f892f0bc77473a123 | CREATE UNIQUE INDEX "UQ_8082ec4890f892f0bc77473a123" ON public.data_table_column USING btree ("dataTableId", name) | + +## Relations + +```mermaid +erDiagram + +"public.data_table_column" }o--|| "public.data_table" : "FOREIGN KEY (#quot;dataTableId#quot;) REFERENCES data_table(id) ON DELETE CASCADE" + +"public.data_table_column" { + timestamp_3__with_time_zone createdAt + varchar_36_ dataTableId FK + varchar_36_ id + integer index + varchar_128_ name + varchar_32_ type + timestamp_3__with_time_zone updatedAt +} +"public.data_table" { + timestamp_3__with_time_zone createdAt + varchar_36_ id + varchar_128_ name + varchar_36_ projectId FK + timestamp_3__with_time_zone updatedAt +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/postgres-schema/public.deployment_key.md b/docs/generated/postgres-schema/public.deployment_key.md new file mode 100644 index 00000000000..a4e0c2fccb5 --- /dev/null +++ b/docs/generated/postgres-schema/public.deployment_key.md @@ -0,0 +1,58 @@ +# public.deployment_key + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| algorithm | varchar(20) | | true | | | | +| createdAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| id | varchar(36) | | false | | | | +| status | varchar(20) | | false | | | | +| type | varchar(64) | | false | | | | +| updatedAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| value | text | | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| PK_94bb7aeb5def5a0284a5fe9f9a0 | PRIMARY KEY | PRIMARY KEY (id) | +| deployment_key_createdAt_not_null | n | NOT NULL "createdAt" | +| deployment_key_id_not_null | n | NOT NULL id | +| deployment_key_status_not_null | n | NOT NULL status | +| deployment_key_type_not_null | n | NOT NULL type | +| deployment_key_updatedAt_not_null | n | NOT NULL "updatedAt" | +| deployment_key_value_not_null | n | NOT NULL value | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_deployment_key_data_encryption_active | CREATE UNIQUE INDEX "IDX_deployment_key_data_encryption_active" ON public.deployment_key USING btree (type) WHERE (((status)::text = 'active'::text) AND ((type)::text = 'data_encryption'::text)) | +| IDX_deployment_key_instance_id_active | CREATE UNIQUE INDEX "IDX_deployment_key_instance_id_active" ON public.deployment_key USING btree (type) WHERE (((status)::text = 'active'::text) AND ((type)::text = 'instance.id'::text)) | +| IDX_deployment_key_jwe_private_key_active | CREATE UNIQUE INDEX "IDX_deployment_key_jwe_private_key_active" ON public.deployment_key USING btree (type, algorithm) WHERE (((status)::text = 'active'::text) AND ((type)::text = 'jwe.private-key'::text)) | +| IDX_deployment_key_signing_binary_data_active | CREATE UNIQUE INDEX "IDX_deployment_key_signing_binary_data_active" ON public.deployment_key USING btree (type) WHERE (((status)::text = 'active'::text) AND ((type)::text = 'signing.binary_data'::text)) | +| IDX_deployment_key_signing_hmac_active | CREATE UNIQUE INDEX "IDX_deployment_key_signing_hmac_active" ON public.deployment_key USING btree (type) WHERE (((status)::text = 'active'::text) AND ((type)::text = 'signing.hmac'::text)) | +| IDX_deployment_key_signing_jwt_active | CREATE UNIQUE INDEX "IDX_deployment_key_signing_jwt_active" ON public.deployment_key USING btree (type) WHERE (((status)::text = 'active'::text) AND ((type)::text = 'signing.jwt'::text)) | +| PK_94bb7aeb5def5a0284a5fe9f9a0 | CREATE UNIQUE INDEX "PK_94bb7aeb5def5a0284a5fe9f9a0" ON public.deployment_key USING btree (id) | + +## Relations + +```mermaid +erDiagram + + +"public.deployment_key" { + varchar_20_ algorithm + timestamp_3__with_time_zone createdAt + varchar_36_ id + varchar_20_ status + varchar_64_ type + timestamp_3__with_time_zone updatedAt + text value +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/postgres-schema/public.dynamic_credential_entry.md b/docs/generated/postgres-schema/public.dynamic_credential_entry.md new file mode 100644 index 00000000000..8aa6eaa757d --- /dev/null +++ b/docs/generated/postgres-schema/public.dynamic_credential_entry.md @@ -0,0 +1,77 @@ +# public.dynamic_credential_entry + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| createdAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| credential_id | varchar(16) | | false | | [public.credentials_entity](public.credentials_entity.md) | | +| data | text | | false | | | | +| resolver_id | varchar(16) | | false | | [public.dynamic_credential_resolver](public.dynamic_credential_resolver.md) | | +| subject_id | varchar(2048) | | false | | | | +| updatedAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| FK_a6d1dd080958304a47a02952aab | FOREIGN KEY | FOREIGN KEY (credential_id) REFERENCES credentials_entity(id) ON DELETE CASCADE | +| FK_d61a12235d268a49af6a3c09c13 | FOREIGN KEY | FOREIGN KEY (resolver_id) REFERENCES dynamic_credential_resolver(id) ON DELETE CASCADE | +| PK_5135ffcabecad4727ff6b9b803d | PRIMARY KEY | PRIMARY KEY (credential_id, subject_id, resolver_id) | +| tmp_dynamic_credential_entry_createdAt_not_null | n | NOT NULL "createdAt" | +| tmp_dynamic_credential_entry_credential_id_not_null | n | NOT NULL credential_id | +| tmp_dynamic_credential_entry_data_not_null | n | NOT NULL data | +| tmp_dynamic_credential_entry_resolver_id_not_null | n | NOT NULL resolver_id | +| tmp_dynamic_credential_entry_subject_id_not_null | n | NOT NULL subject_id | +| tmp_dynamic_credential_entry_updatedAt_not_null | n | NOT NULL "updatedAt" | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_62476b94b56d9dc7ed9ed75d3d | CREATE INDEX "IDX_62476b94b56d9dc7ed9ed75d3d" ON public.dynamic_credential_entry USING btree (subject_id) | +| IDX_d61a12235d268a49af6a3c09c1 | CREATE INDEX "IDX_d61a12235d268a49af6a3c09c1" ON public.dynamic_credential_entry USING btree (resolver_id) | +| PK_5135ffcabecad4727ff6b9b803d | CREATE UNIQUE INDEX "PK_5135ffcabecad4727ff6b9b803d" ON public.dynamic_credential_entry USING btree (credential_id, subject_id, resolver_id) | + +## Relations + +```mermaid +erDiagram + +"public.dynamic_credential_entry" }o--|| "public.credentials_entity" : "FOREIGN KEY (credential_id) REFERENCES credentials_entity(id) ON DELETE CASCADE" +"public.dynamic_credential_entry" }o--|| "public.dynamic_credential_resolver" : "FOREIGN KEY (resolver_id) REFERENCES dynamic_credential_resolver(id) ON DELETE CASCADE" + +"public.dynamic_credential_entry" { + timestamp_3__with_time_zone createdAt + varchar_16_ credential_id FK + text data + varchar_16_ resolver_id FK + varchar_2048_ subject_id + timestamp_3__with_time_zone updatedAt +} +"public.credentials_entity" { + timestamp_3__with_time_zone createdAt + text data + varchar_36_ id + boolean isGlobal + boolean isManaged + boolean isResolvable + varchar_128_ name + boolean resolvableAllowFallback + varchar_16_ resolverId FK + varchar_128_ type + timestamp_3__with_time_zone updatedAt +} +"public.dynamic_credential_resolver" { + text config + timestamp_3__with_time_zone createdAt + varchar_16_ id + varchar_128_ name + varchar_128_ type + timestamp_3__with_time_zone updatedAt +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/postgres-schema/public.dynamic_credential_resolver.md b/docs/generated/postgres-schema/public.dynamic_credential_resolver.md new file mode 100644 index 00000000000..10105bf72f9 --- /dev/null +++ b/docs/generated/postgres-schema/public.dynamic_credential_resolver.md @@ -0,0 +1,83 @@ +# public.dynamic_credential_resolver + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| config | text | | false | | | Encrypted resolver configuration (JSON encrypted as string) | +| createdAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| id | varchar(16) | | false | [public.credentials_entity](public.credentials_entity.md) [public.dynamic_credential_entry](public.dynamic_credential_entry.md) [public.dynamic_credential_user_entry](public.dynamic_credential_user_entry.md) | | | +| name | varchar(128) | | false | | | | +| type | varchar(128) | | false | | | | +| updatedAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| PK_b76cfb088dcdaf5275e9980bb64 | PRIMARY KEY | PRIMARY KEY (id) | +| dynamic_credential_resolver_config_not_null | n | NOT NULL config | +| dynamic_credential_resolver_createdAt_not_null | n | NOT NULL "createdAt" | +| dynamic_credential_resolver_id_not_null | n | NOT NULL id | +| dynamic_credential_resolver_name_not_null | n | NOT NULL name | +| dynamic_credential_resolver_type_not_null | n | NOT NULL type | +| dynamic_credential_resolver_updatedAt_not_null | n | NOT NULL "updatedAt" | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_9c9ee9df586e60bb723234e499 | CREATE INDEX "IDX_9c9ee9df586e60bb723234e499" ON public.dynamic_credential_resolver USING btree (type) | +| PK_b76cfb088dcdaf5275e9980bb64 | CREATE UNIQUE INDEX "PK_b76cfb088dcdaf5275e9980bb64" ON public.dynamic_credential_resolver USING btree (id) | + +## Relations + +```mermaid +erDiagram + +"public.credentials_entity" }o--o| "public.dynamic_credential_resolver" : "FOREIGN KEY (#quot;resolverId#quot;) REFERENCES dynamic_credential_resolver(id) ON DELETE SET NULL" +"public.dynamic_credential_entry" }o--|| "public.dynamic_credential_resolver" : "FOREIGN KEY (resolver_id) REFERENCES dynamic_credential_resolver(id) ON DELETE CASCADE" +"public.dynamic_credential_user_entry" }o--|| "public.dynamic_credential_resolver" : "FOREIGN KEY (#quot;resolverId#quot;) REFERENCES dynamic_credential_resolver(id) ON DELETE CASCADE" + +"public.dynamic_credential_resolver" { + text config + timestamp_3__with_time_zone createdAt + varchar_16_ id + varchar_128_ name + varchar_128_ type + timestamp_3__with_time_zone updatedAt +} +"public.credentials_entity" { + timestamp_3__with_time_zone createdAt + text data + varchar_36_ id + boolean isGlobal + boolean isManaged + boolean isResolvable + varchar_128_ name + boolean resolvableAllowFallback + varchar_16_ resolverId FK + varchar_128_ type + timestamp_3__with_time_zone updatedAt +} +"public.dynamic_credential_entry" { + timestamp_3__with_time_zone createdAt + varchar_16_ credential_id FK + text data + varchar_16_ resolver_id FK + varchar_2048_ subject_id + timestamp_3__with_time_zone updatedAt +} +"public.dynamic_credential_user_entry" { + timestamp_3__with_time_zone createdAt + varchar_16_ credentialId FK + text data + varchar_16_ resolverId FK + timestamp_3__with_time_zone updatedAt + uuid userId FK +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/postgres-schema/public.dynamic_credential_user_entry.md b/docs/generated/postgres-schema/public.dynamic_credential_user_entry.md new file mode 100644 index 00000000000..bf62db4025b --- /dev/null +++ b/docs/generated/postgres-schema/public.dynamic_credential_user_entry.md @@ -0,0 +1,96 @@ +# public.dynamic_credential_user_entry + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| createdAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| credentialId | varchar(16) | | false | | [public.credentials_entity](public.credentials_entity.md) | | +| data | text | | false | | | | +| resolverId | varchar(16) | | false | | [public.dynamic_credential_resolver](public.dynamic_credential_resolver.md) | | +| updatedAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| userId | uuid | | false | | [public.user](public.user.md) | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| FK_6edec973a6450990977bb854c38 | FOREIGN KEY | FOREIGN KEY ("resolverId") REFERENCES dynamic_credential_resolver(id) ON DELETE CASCADE | +| FK_945ba70b342a066d1306b12ccd2 | FOREIGN KEY | FOREIGN KEY ("credentialId") REFERENCES credentials_entity(id) ON DELETE CASCADE | +| FK_a36dc616fabc3f736bb82410a22 | FOREIGN KEY | FOREIGN KEY ("userId") REFERENCES "user"(id) ON DELETE CASCADE | +| PK_74f548e633abc66dc27c8f0ca77 | PRIMARY KEY | PRIMARY KEY ("credentialId", "userId", "resolverId") | +| dynamic_credential_user_entry_createdAt_not_null | n | NOT NULL "createdAt" | +| dynamic_credential_user_entry_credentialId_not_null | n | NOT NULL "credentialId" | +| dynamic_credential_user_entry_data_not_null | n | NOT NULL data | +| dynamic_credential_user_entry_resolverId_not_null | n | NOT NULL "resolverId" | +| dynamic_credential_user_entry_updatedAt_not_null | n | NOT NULL "updatedAt" | +| dynamic_credential_user_entry_userId_not_null | n | NOT NULL "userId" | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_6edec973a6450990977bb854c3 | CREATE INDEX "IDX_6edec973a6450990977bb854c3" ON public.dynamic_credential_user_entry USING btree ("resolverId") | +| IDX_a36dc616fabc3f736bb82410a2 | CREATE INDEX "IDX_a36dc616fabc3f736bb82410a2" ON public.dynamic_credential_user_entry USING btree ("userId") | +| PK_74f548e633abc66dc27c8f0ca77 | CREATE UNIQUE INDEX "PK_74f548e633abc66dc27c8f0ca77" ON public.dynamic_credential_user_entry USING btree ("credentialId", "userId", "resolverId") | + +## Relations + +```mermaid +erDiagram + +"public.dynamic_credential_user_entry" }o--|| "public.credentials_entity" : "FOREIGN KEY (#quot;credentialId#quot;) REFERENCES credentials_entity(id) ON DELETE CASCADE" +"public.dynamic_credential_user_entry" }o--|| "public.dynamic_credential_resolver" : "FOREIGN KEY (#quot;resolverId#quot;) REFERENCES dynamic_credential_resolver(id) ON DELETE CASCADE" +"public.dynamic_credential_user_entry" }o--|| "public.user" : "FOREIGN KEY (#quot;userId#quot;) REFERENCES #quot;user#quot;(id) ON DELETE CASCADE" + +"public.dynamic_credential_user_entry" { + timestamp_3__with_time_zone createdAt + varchar_16_ credentialId FK + text data + varchar_16_ resolverId FK + timestamp_3__with_time_zone updatedAt + uuid userId FK +} +"public.credentials_entity" { + timestamp_3__with_time_zone createdAt + text data + varchar_36_ id + boolean isGlobal + boolean isManaged + boolean isResolvable + varchar_128_ name + boolean resolvableAllowFallback + varchar_16_ resolverId FK + varchar_128_ type + timestamp_3__with_time_zone updatedAt +} +"public.dynamic_credential_resolver" { + text config + timestamp_3__with_time_zone createdAt + varchar_16_ id + varchar_128_ name + varchar_128_ type + timestamp_3__with_time_zone updatedAt +} +"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 +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/postgres-schema/public.evaluation_collection.md b/docs/generated/postgres-schema/public.evaluation_collection.md new file mode 100644 index 00000000000..242d8663642 --- /dev/null +++ b/docs/generated/postgres-schema/public.evaluation_collection.md @@ -0,0 +1,136 @@ +# public.evaluation_collection + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| createdAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| createdById | uuid | | true | | [public.user](public.user.md) | | +| description | text | | true | | | | +| evaluationConfigId | varchar(36) | | false | | [public.evaluation_config](public.evaluation_config.md) | | +| id | varchar(36) | | false | [public.test_run](public.test_run.md) | | | +| insightsCache | json | | true | | | | +| name | varchar(128) | | false | | | | +| updatedAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| workflowId | varchar(36) | | false | | [public.workflow_entity](public.workflow_entity.md) | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| FK_a48ce930c3bc7604894b8f0eaad | FOREIGN KEY | FOREIGN KEY ("workflowId") REFERENCES workflow_entity(id) ON DELETE CASCADE | +| FK_d634a0c93fd7de68a87eab951b2 | FOREIGN KEY | FOREIGN KEY ("evaluationConfigId") REFERENCES evaluation_config(id) ON DELETE CASCADE | +| FK_f4561f38b5a22a4f090d5cd3eae | FOREIGN KEY | FOREIGN KEY ("createdById") REFERENCES "user"(id) ON DELETE SET NULL | +| PK_e720b6efc1e45b878ebb0b2ca30 | PRIMARY KEY | PRIMARY KEY (id) | +| evaluation_collection_createdAt_not_null | n | NOT NULL "createdAt" | +| evaluation_collection_evaluationConfigId_not_null | n | NOT NULL "evaluationConfigId" | +| evaluation_collection_id_not_null | n | NOT NULL id | +| evaluation_collection_name_not_null | n | NOT NULL name | +| evaluation_collection_updatedAt_not_null | n | NOT NULL "updatedAt" | +| evaluation_collection_workflowId_not_null | n | NOT NULL "workflowId" | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_a48ce930c3bc7604894b8f0eaa | CREATE INDEX "IDX_a48ce930c3bc7604894b8f0eaa" ON public.evaluation_collection USING btree ("workflowId") | +| IDX_d634a0c93fd7de68a87eab951b | CREATE INDEX "IDX_d634a0c93fd7de68a87eab951b" ON public.evaluation_collection USING btree ("evaluationConfigId") | +| PK_e720b6efc1e45b878ebb0b2ca30 | CREATE UNIQUE INDEX "PK_e720b6efc1e45b878ebb0b2ca30" ON public.evaluation_collection USING btree (id) | + +## Relations + +```mermaid +erDiagram + +"public.evaluation_collection" }o--o| "public.user" : "FOREIGN KEY (#quot;createdById#quot;) REFERENCES #quot;user#quot;(id) ON DELETE SET NULL" +"public.evaluation_collection" }o--|| "public.evaluation_config" : "FOREIGN KEY (#quot;evaluationConfigId#quot;) REFERENCES evaluation_config(id) ON DELETE CASCADE" +"public.test_run" }o--o| "public.evaluation_collection" : "FOREIGN KEY (#quot;collectionId#quot;) REFERENCES evaluation_collection(id) ON DELETE SET NULL" +"public.evaluation_collection" }o--|| "public.workflow_entity" : "FOREIGN KEY (#quot;workflowId#quot;) REFERENCES workflow_entity(id) ON DELETE CASCADE" + +"public.evaluation_collection" { + timestamp_3__with_time_zone createdAt + uuid createdById FK + text description + varchar_36_ evaluationConfigId FK + varchar_36_ id + json insightsCache + varchar_128_ name + timestamp_3__with_time_zone updatedAt + varchar_36_ workflowId FK +} +"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.evaluation_config" { + timestamp_3__with_time_zone createdAt + json datasetRef + varchar_32_ datasetSource + varchar_255_ endNodeName + varchar_36_ id + varchar_64_ invalidReason + json metrics + varchar_128_ name + varchar_255_ startNodeName + varchar_16_ status + timestamp_3__with_time_zone updatedAt + varchar_36_ workflowId FK +} +"public.test_run" { + boolean cancelRequested + varchar_36_ collectionId FK + timestamp_3__with_time_zone completedAt + timestamp_3__with_time_zone createdAt + varchar errorCode + json errorDetails + varchar_36_ evaluationConfigId FK + jsonb evaluationConfigSnapshot + varchar_36_ id + json metrics + timestamp_3__with_time_zone runAt + varchar_255_ runningInstanceId + varchar status + timestamp_3__with_time_zone updatedAt + varchar_36_ workflowId FK + varchar_36_ workflowVersionId +} +"public.workflow_entity" { + boolean active + varchar_36_ activeVersionId FK + json connections + timestamp_3__with_time_zone createdAt + text description + varchar_36_ id + boolean isArchived + json meta + varchar_128_ name + json nodeGroups + json nodes + varchar_36_ parentFolderId FK + json pinData + json settings + varchar sourceWorkflowId + json staticData + integer triggerCount + timestamp_3__with_time_zone updatedAt + integer versionCounter + character_36_ versionId +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/postgres-schema/public.evaluation_config.md b/docs/generated/postgres-schema/public.evaluation_config.md new file mode 100644 index 00000000000..e4f1d4c4b97 --- /dev/null +++ b/docs/generated/postgres-schema/public.evaluation_config.md @@ -0,0 +1,125 @@ +# public.evaluation_config + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| createdAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| datasetRef | json | | false | | | | +| datasetSource | varchar(32) | | false | | | | +| endNodeName | varchar(255) | | false | | | | +| id | varchar(36) | | false | [public.evaluation_collection](public.evaluation_collection.md) [public.test_run](public.test_run.md) | | | +| invalidReason | varchar(64) | | true | | | | +| metrics | json | | false | | | | +| name | varchar(128) | | false | | | | +| startNodeName | varchar(255) | | false | | | | +| status | varchar(16) | 'valid'::character varying | false | | | | +| updatedAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| workflowId | varchar(36) | | false | | [public.workflow_entity](public.workflow_entity.md) | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| FK_fd7542bb123074760285dc1bbf3 | FOREIGN KEY | FOREIGN KEY ("workflowId") REFERENCES workflow_entity(id) ON DELETE CASCADE | +| PK_59c14dccf8989df94070c2dcfda | PRIMARY KEY | PRIMARY KEY (id) | +| UQ_3c3c99a712e971835c52292e44c | UNIQUE | UNIQUE ("workflowId", name) | +| evaluation_config_createdAt_not_null | n | NOT NULL "createdAt" | +| evaluation_config_datasetRef_not_null | n | NOT NULL "datasetRef" | +| evaluation_config_datasetSource_not_null | n | NOT NULL "datasetSource" | +| evaluation_config_endNodeName_not_null | n | NOT NULL "endNodeName" | +| evaluation_config_id_not_null | n | NOT NULL id | +| evaluation_config_metrics_not_null | n | NOT NULL metrics | +| evaluation_config_name_not_null | n | NOT NULL name | +| evaluation_config_startNodeName_not_null | n | NOT NULL "startNodeName" | +| evaluation_config_status_not_null | n | NOT NULL status | +| evaluation_config_updatedAt_not_null | n | NOT NULL "updatedAt" | +| evaluation_config_workflowId_not_null | n | NOT NULL "workflowId" | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_fd7542bb123074760285dc1bbf | CREATE INDEX "IDX_fd7542bb123074760285dc1bbf" ON public.evaluation_config USING btree ("workflowId") | +| PK_59c14dccf8989df94070c2dcfda | CREATE UNIQUE INDEX "PK_59c14dccf8989df94070c2dcfda" ON public.evaluation_config USING btree (id) | +| UQ_3c3c99a712e971835c52292e44c | CREATE UNIQUE INDEX "UQ_3c3c99a712e971835c52292e44c" ON public.evaluation_config USING btree ("workflowId", name) | + +## Relations + +```mermaid +erDiagram + +"public.evaluation_collection" }o--|| "public.evaluation_config" : "FOREIGN KEY (#quot;evaluationConfigId#quot;) REFERENCES evaluation_config(id) ON DELETE CASCADE" +"public.test_run" }o--o| "public.evaluation_config" : "FOREIGN KEY (#quot;evaluationConfigId#quot;) REFERENCES evaluation_config(id) ON DELETE SET NULL" +"public.evaluation_config" }o--|| "public.workflow_entity" : "FOREIGN KEY (#quot;workflowId#quot;) REFERENCES workflow_entity(id) ON DELETE CASCADE" + +"public.evaluation_config" { + timestamp_3__with_time_zone createdAt + json datasetRef + varchar_32_ datasetSource + varchar_255_ endNodeName + varchar_36_ id + varchar_64_ invalidReason + json metrics + varchar_128_ name + varchar_255_ startNodeName + varchar_16_ status + timestamp_3__with_time_zone updatedAt + varchar_36_ workflowId FK +} +"public.evaluation_collection" { + timestamp_3__with_time_zone createdAt + uuid createdById FK + text description + varchar_36_ evaluationConfigId FK + varchar_36_ id + json insightsCache + varchar_128_ name + timestamp_3__with_time_zone updatedAt + varchar_36_ workflowId FK +} +"public.test_run" { + boolean cancelRequested + varchar_36_ collectionId FK + timestamp_3__with_time_zone completedAt + timestamp_3__with_time_zone createdAt + varchar errorCode + json errorDetails + varchar_36_ evaluationConfigId FK + jsonb evaluationConfigSnapshot + varchar_36_ id + json metrics + timestamp_3__with_time_zone runAt + varchar_255_ runningInstanceId + varchar status + timestamp_3__with_time_zone updatedAt + varchar_36_ workflowId FK + varchar_36_ workflowVersionId +} +"public.workflow_entity" { + boolean active + varchar_36_ activeVersionId FK + json connections + timestamp_3__with_time_zone createdAt + text description + varchar_36_ id + boolean isArchived + json meta + varchar_128_ name + json nodeGroups + json nodes + varchar_36_ parentFolderId FK + json pinData + json settings + varchar sourceWorkflowId + json staticData + integer triggerCount + timestamp_3__with_time_zone updatedAt + integer versionCounter + character_36_ versionId +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/postgres-schema/public.event_destinations.md b/docs/generated/postgres-schema/public.event_destinations.md new file mode 100644 index 00000000000..5ee8d2a60d0 --- /dev/null +++ b/docs/generated/postgres-schema/public.event_destinations.md @@ -0,0 +1,44 @@ +# public.event_destinations + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| createdAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| destination | jsonb | | false | | | | +| id | uuid | | false | | | | +| updatedAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| event_destinations_createdAt_not_null | n | NOT NULL "createdAt" | +| event_destinations_destination_not_null | n | NOT NULL destination | +| event_destinations_id_not_null | n | NOT NULL id | +| event_destinations_pkey | PRIMARY KEY | PRIMARY KEY (id) | +| event_destinations_updatedAt_not_null | n | NOT NULL "updatedAt" | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| event_destinations_pkey | CREATE UNIQUE INDEX event_destinations_pkey ON public.event_destinations USING btree (id) | + +## Relations + +```mermaid +erDiagram + + +"public.event_destinations" { + timestamp_3__with_time_zone createdAt + jsonb destination + uuid id + timestamp_3__with_time_zone updatedAt +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/postgres-schema/public.execution_annotation_tags.md b/docs/generated/postgres-schema/public.execution_annotation_tags.md new file mode 100644 index 00000000000..da63cb64ac7 --- /dev/null +++ b/docs/generated/postgres-schema/public.execution_annotation_tags.md @@ -0,0 +1,58 @@ +# public.execution_annotation_tags + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| annotationId | integer | | false | | [public.execution_annotations](public.execution_annotations.md) | | +| tagId | varchar(24) | | false | | [public.annotation_tag_entity](public.annotation_tag_entity.md) | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| FK_a3697779b366e131b2bbdae2976 | FOREIGN KEY | FOREIGN KEY ("tagId") REFERENCES annotation_tag_entity(id) ON DELETE CASCADE | +| FK_c1519757391996eb06064f0e7c8 | FOREIGN KEY | FOREIGN KEY ("annotationId") REFERENCES execution_annotations(id) ON DELETE CASCADE | +| PK_979ec03d31294cca484be65d11f | PRIMARY KEY | PRIMARY KEY ("annotationId", "tagId") | +| execution_annotation_tags_annotationId_not_null | n | NOT NULL "annotationId" | +| execution_annotation_tags_tagId_not_null | n | NOT NULL "tagId" | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_a3697779b366e131b2bbdae297 | CREATE INDEX "IDX_a3697779b366e131b2bbdae297" ON public.execution_annotation_tags USING btree ("tagId") | +| IDX_c1519757391996eb06064f0e7c | CREATE INDEX "IDX_c1519757391996eb06064f0e7c" ON public.execution_annotation_tags USING btree ("annotationId") | +| PK_979ec03d31294cca484be65d11f | CREATE UNIQUE INDEX "PK_979ec03d31294cca484be65d11f" ON public.execution_annotation_tags USING btree ("annotationId", "tagId") | + +## Relations + +```mermaid +erDiagram + +"public.execution_annotation_tags" }o--|| "public.execution_annotations" : "FOREIGN KEY (#quot;annotationId#quot;) REFERENCES execution_annotations(id) ON DELETE CASCADE" +"public.execution_annotation_tags" }o--|| "public.annotation_tag_entity" : "FOREIGN KEY (#quot;tagId#quot;) REFERENCES annotation_tag_entity(id) ON DELETE CASCADE" + +"public.execution_annotation_tags" { + integer annotationId FK + varchar_24_ tagId FK +} +"public.execution_annotations" { + timestamp_3__with_time_zone createdAt + integer executionId FK + integer id + text note + timestamp_3__with_time_zone updatedAt + varchar_6_ vote +} +"public.annotation_tag_entity" { + timestamp_3__with_time_zone createdAt + varchar_16_ id + varchar_24_ name + timestamp_3__with_time_zone updatedAt +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/postgres-schema/public.execution_annotations.md b/docs/generated/postgres-schema/public.execution_annotations.md new file mode 100644 index 00000000000..a2d96c1ba70 --- /dev/null +++ b/docs/generated/postgres-schema/public.execution_annotations.md @@ -0,0 +1,76 @@ +# public.execution_annotations + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| createdAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| executionId | integer | | false | | [public.execution_entity](public.execution_entity.md) | | +| id | integer | nextval('execution_annotations_id_seq'::regclass) | false | [public.execution_annotation_tags](public.execution_annotation_tags.md) | | | +| note | text | | true | | | | +| updatedAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| vote | varchar(6) | | true | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| FK_97f863fa83c4786f19565084960 | FOREIGN KEY | FOREIGN KEY ("executionId") REFERENCES execution_entity(id) ON DELETE CASCADE | +| PK_7afcf93ffa20c4252869a7c6a23 | PRIMARY KEY | PRIMARY KEY (id) | +| execution_annotations_createdAt_not_null | n | NOT NULL "createdAt" | +| execution_annotations_executionId_not_null | n | NOT NULL "executionId" | +| execution_annotations_id_not_null | n | NOT NULL id | +| execution_annotations_updatedAt_not_null | n | NOT NULL "updatedAt" | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_97f863fa83c4786f1956508496 | CREATE UNIQUE INDEX "IDX_97f863fa83c4786f1956508496" ON public.execution_annotations USING btree ("executionId") | +| PK_7afcf93ffa20c4252869a7c6a23 | CREATE UNIQUE INDEX "PK_7afcf93ffa20c4252869a7c6a23" ON public.execution_annotations USING btree (id) | + +## Relations + +```mermaid +erDiagram + +"public.execution_annotations" }o--|| "public.execution_entity" : "FOREIGN KEY (#quot;executionId#quot;) REFERENCES execution_entity(id) ON DELETE CASCADE" +"public.execution_annotation_tags" }o--|| "public.execution_annotations" : "FOREIGN KEY (#quot;annotationId#quot;) REFERENCES execution_annotations(id) ON DELETE CASCADE" + +"public.execution_annotations" { + timestamp_3__with_time_zone createdAt + integer executionId FK + integer id + text note + timestamp_3__with_time_zone updatedAt + varchar_6_ vote +} +"public.execution_entity" { + bigint binaryDataSizeBytes + timestamp_3__with_time_zone createdAt + varchar_255_ deduplicationKey + timestamp_3__with_time_zone deletedAt + boolean finished + integer id + bigint jsonSizeBytes + varchar mode + varchar retryOf + varchar retrySuccessId + timestamp_3__with_time_zone startedAt + varchar status + timestamp_3__with_time_zone stoppedAt + varchar_2_ storedAt + json tracingContext + timestamp_3__with_time_zone waitTill + varchar_36_ workflowId FK + varchar_36_ workflowVersionId +} +"public.execution_annotation_tags" { + integer annotationId FK + varchar_24_ tagId FK +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/postgres-schema/public.execution_data.md b/docs/generated/postgres-schema/public.execution_data.md new file mode 100644 index 00000000000..fcfa9df071b --- /dev/null +++ b/docs/generated/postgres-schema/public.execution_data.md @@ -0,0 +1,65 @@ +# public.execution_data + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| data | text | | false | | | | +| executionId | integer | | false | | [public.execution_entity](public.execution_entity.md) | | +| workflowData | json | | false | | | | +| workflowVersionId | varchar(36) | | true | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| execution_data_data_not_null | n | NOT NULL data | +| execution_data_executionId_not_null | n | NOT NULL "executionId" | +| execution_data_fk | FOREIGN KEY | FOREIGN KEY ("executionId") REFERENCES execution_entity(id) ON DELETE CASCADE | +| execution_data_pkey | PRIMARY KEY | PRIMARY KEY ("executionId") | +| execution_data_workflowData_not_null | n | NOT NULL "workflowData" | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| execution_data_pkey | CREATE UNIQUE INDEX execution_data_pkey ON public.execution_data USING btree ("executionId") | + +## Relations + +```mermaid +erDiagram + +"public.execution_data" |o--|| "public.execution_entity" : "FOREIGN KEY (#quot;executionId#quot;) REFERENCES execution_entity(id) ON DELETE CASCADE" + +"public.execution_data" { + text data + integer executionId FK + json workflowData + varchar_36_ workflowVersionId +} +"public.execution_entity" { + bigint binaryDataSizeBytes + timestamp_3__with_time_zone createdAt + varchar_255_ deduplicationKey + timestamp_3__with_time_zone deletedAt + boolean finished + integer id + bigint jsonSizeBytes + varchar mode + varchar retryOf + varchar retrySuccessId + timestamp_3__with_time_zone startedAt + varchar status + timestamp_3__with_time_zone stoppedAt + varchar_2_ storedAt + json tracingContext + timestamp_3__with_time_zone waitTill + varchar_36_ workflowId FK + varchar_36_ workflowVersionId +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/postgres-schema/public.execution_entity.md b/docs/generated/postgres-schema/public.execution_entity.md new file mode 100644 index 00000000000..20186a87a40 --- /dev/null +++ b/docs/generated/postgres-schema/public.execution_entity.md @@ -0,0 +1,168 @@ +# public.execution_entity + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| binaryDataSizeBytes | bigint | 0 | false | | | Byte size of binary data offloaded to separate storage (db/fs/S3), deduplicated by blob; excludes inline binary counted in jsonSizeBytes. 0 means unknown. | +| createdAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| deduplicationKey | varchar(255) | | true | | | | +| deletedAt | timestamp(3) with time zone | | true | | | | +| finished | boolean | | false | | | | +| id | integer | nextval('execution_entity_id_seq'::regclass) | false | [public.chat_hub_messages](public.chat_hub_messages.md) [public.execution_annotations](public.execution_annotations.md) [public.execution_data](public.execution_data.md) [public.execution_metadata](public.execution_metadata.md) [public.test_case_execution](public.test_case_execution.md) | | | +| jsonSizeBytes | bigint | 0 | false | | | Byte size of the JSON execution data bundle (run data, workflow snapshot, version id); excludes binary data. 0 means unknown. | +| mode | varchar | | false | | | | +| retryOf | varchar | | true | | | | +| retrySuccessId | varchar | | true | | | | +| startedAt | timestamp(3) with time zone | | true | | | | +| status | varchar | | false | | | | +| stoppedAt | timestamp(3) with time zone | | true | | | | +| storedAt | varchar(2) | 'db'::character varying | false | | | | +| tracingContext | json | | true | | | | +| waitTill | timestamp(3) with time zone | | true | | | | +| workflowId | varchar(36) | | false | | [public.workflow_entity](public.workflow_entity.md) | | +| workflowVersionId | varchar(36) | NULL::character varying | true | | | Version id of the workflow run by this execution; denormalized from the data bundle. | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| execution_entity_binaryDataSizeBytes_not_null | n | NOT NULL "binaryDataSizeBytes" | +| execution_entity_createdAt_not_null | n | NOT NULL "createdAt" | +| execution_entity_finished_not_null | n | NOT NULL finished | +| execution_entity_id_not_null | n | NOT NULL id | +| execution_entity_jsonSizeBytes_not_null | n | NOT NULL "jsonSizeBytes" | +| execution_entity_mode_not_null | n | NOT NULL mode | +| execution_entity_status_not_null | n | NOT NULL status | +| execution_entity_storedAt_check | CHECK | CHECK ((("storedAt")::text = ANY ((ARRAY['db'::character varying, 'fs'::character varying, 's3'::character varying])::text[]))) | +| execution_entity_storedAt_not_null | n | NOT NULL "storedAt" | +| execution_entity_workflowId_not_null | n | NOT NULL "workflowId" | +| fk_execution_entity_workflow_id | FOREIGN KEY | FOREIGN KEY ("workflowId") REFERENCES workflow_entity(id) ON DELETE CASCADE | +| pk_e3e63bbf986767844bbe1166d4e | PRIMARY KEY | PRIMARY KEY (id) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_execution_entity_deduplicationKey | CREATE UNIQUE INDEX "IDX_execution_entity_deduplicationKey" ON public.execution_entity USING btree ("deduplicationKey") WHERE ("deduplicationKey" IS NOT NULL) | +| IDX_execution_entity_deletedAt | CREATE INDEX "IDX_execution_entity_deletedAt" ON public.execution_entity USING btree ("deletedAt") | +| IDX_execution_entity_workflowId_status_id | CREATE INDEX "IDX_execution_entity_workflowId_status_id" ON public.execution_entity USING btree ("workflowId", status, id) WHERE ("deletedAt" IS NULL) | +| idx_execution_entity_stopped_at_status_deleted_at | CREATE INDEX idx_execution_entity_stopped_at_status_deleted_at ON public.execution_entity USING btree ("stoppedAt", status, "deletedAt") WHERE (("stoppedAt" IS NOT NULL) AND ("deletedAt" IS NULL)) | +| idx_execution_entity_wait_till_status_deleted_at | CREATE INDEX idx_execution_entity_wait_till_status_deleted_at ON public.execution_entity USING btree ("waitTill", status, "deletedAt") WHERE (("waitTill" IS NOT NULL) AND ("deletedAt" IS NULL)) | +| idx_execution_entity_workflow_id_started_at | CREATE INDEX idx_execution_entity_workflow_id_started_at ON public.execution_entity USING btree ("workflowId", "startedAt") WHERE (("startedAt" IS NOT NULL) AND ("deletedAt" IS NULL)) | +| pk_e3e63bbf986767844bbe1166d4e | CREATE UNIQUE INDEX pk_e3e63bbf986767844bbe1166d4e ON public.execution_entity USING btree (id) | + +## Relations + +```mermaid +erDiagram + +"public.chat_hub_messages" }o--o| "public.execution_entity" : "FOREIGN KEY (#quot;executionId#quot;) REFERENCES execution_entity(id) ON DELETE SET NULL" +"public.execution_annotations" }o--|| "public.execution_entity" : "FOREIGN KEY (#quot;executionId#quot;) REFERENCES execution_entity(id) ON DELETE CASCADE" +"public.execution_data" |o--|| "public.execution_entity" : "FOREIGN KEY (#quot;executionId#quot;) REFERENCES execution_entity(id) ON DELETE CASCADE" +"public.execution_metadata" }o--|| "public.execution_entity" : "FOREIGN KEY (#quot;executionId#quot;) REFERENCES execution_entity(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.execution_entity" }o--|| "public.workflow_entity" : "FOREIGN KEY (#quot;workflowId#quot;) REFERENCES workflow_entity(id) ON DELETE CASCADE" + +"public.execution_entity" { + bigint binaryDataSizeBytes + timestamp_3__with_time_zone createdAt + varchar_255_ deduplicationKey + timestamp_3__with_time_zone deletedAt + boolean finished + integer id + bigint jsonSizeBytes + varchar mode + varchar retryOf + varchar retrySuccessId + timestamp_3__with_time_zone startedAt + varchar status + timestamp_3__with_time_zone stoppedAt + varchar_2_ storedAt + json tracingContext + timestamp_3__with_time_zone waitTill + varchar_36_ workflowId FK + varchar_36_ workflowVersionId +} +"public.chat_hub_messages" { + uuid agentId FK + json attachments + text content + timestamp_3__with_time_zone createdAt + integer executionId FK + uuid id + varchar_256_ model + varchar_128_ name + uuid previousMessageId FK + varchar_16_ provider + uuid retryOfMessageId FK + uuid revisionOfMessageId FK + uuid sessionId FK + varchar_16_ status + varchar_16_ type + timestamp_3__with_time_zone updatedAt + varchar_36_ workflowId FK +} +"public.execution_annotations" { + timestamp_3__with_time_zone createdAt + integer executionId FK + integer id + text note + timestamp_3__with_time_zone updatedAt + varchar_6_ vote +} +"public.execution_data" { + text data + integer executionId FK + json workflowData + varchar_36_ workflowVersionId +} +"public.execution_metadata" { + integer executionId FK + integer id + varchar_255_ key + text value +} +"public.test_case_execution" { + timestamp_3__with_time_zone completedAt + timestamp_3__with_time_zone createdAt + varchar errorCode + json errorDetails + integer executionId FK + varchar_36_ id + json inputs + json metrics + json outputs + timestamp_3__with_time_zone runAt + integer runIndex + varchar status + varchar_36_ testRunId FK + timestamp_3__with_time_zone updatedAt +} +"public.workflow_entity" { + boolean active + varchar_36_ activeVersionId FK + json connections + timestamp_3__with_time_zone createdAt + text description + varchar_36_ id + boolean isArchived + json meta + varchar_128_ name + json nodeGroups + json nodes + varchar_36_ parentFolderId FK + json pinData + json settings + varchar sourceWorkflowId + json staticData + integer triggerCount + timestamp_3__with_time_zone updatedAt + integer versionCounter + character_36_ versionId +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/postgres-schema/public.execution_metadata.md b/docs/generated/postgres-schema/public.execution_metadata.md new file mode 100644 index 00000000000..304a3ab040c --- /dev/null +++ b/docs/generated/postgres-schema/public.execution_metadata.md @@ -0,0 +1,67 @@ +# public.execution_metadata + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| executionId | integer | | false | | [public.execution_entity](public.execution_entity.md) | | +| id | integer | nextval('execution_metadata_temp_id_seq'::regclass) | false | | | | +| key | varchar(255) | | false | | | | +| value | text | | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| FK_31d0b4c93fb85ced26f6005cda3 | FOREIGN KEY | FOREIGN KEY ("executionId") REFERENCES execution_entity(id) ON DELETE CASCADE | +| PK_17a0b6284f8d626aae88e1c16e4 | PRIMARY KEY | PRIMARY KEY (id) | +| execution_metadata_temp_executionId_not_null | n | NOT NULL "executionId" | +| execution_metadata_temp_id_not_null | n | NOT NULL id | +| execution_metadata_temp_key_not_null | n | NOT NULL key | +| execution_metadata_temp_value_not_null | n | NOT NULL value | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_cec8eea3bf49551482ccb4933e | CREATE UNIQUE INDEX "IDX_cec8eea3bf49551482ccb4933e" ON public.execution_metadata USING btree ("executionId", key) | +| PK_17a0b6284f8d626aae88e1c16e4 | CREATE UNIQUE INDEX "PK_17a0b6284f8d626aae88e1c16e4" ON public.execution_metadata USING btree (id) | + +## Relations + +```mermaid +erDiagram + +"public.execution_metadata" }o--|| "public.execution_entity" : "FOREIGN KEY (#quot;executionId#quot;) REFERENCES execution_entity(id) ON DELETE CASCADE" + +"public.execution_metadata" { + integer executionId FK + integer id + varchar_255_ key + text value +} +"public.execution_entity" { + bigint binaryDataSizeBytes + timestamp_3__with_time_zone createdAt + varchar_255_ deduplicationKey + timestamp_3__with_time_zone deletedAt + boolean finished + integer id + bigint jsonSizeBytes + varchar mode + varchar retryOf + varchar retrySuccessId + timestamp_3__with_time_zone startedAt + varchar status + timestamp_3__with_time_zone stoppedAt + varchar_2_ storedAt + json tracingContext + timestamp_3__with_time_zone waitTill + varchar_36_ workflowId FK + varchar_36_ workflowVersionId +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/postgres-schema/public.folder.md b/docs/generated/postgres-schema/public.folder.md new file mode 100644 index 00000000000..ab8fe20d0af --- /dev/null +++ b/docs/generated/postgres-schema/public.folder.md @@ -0,0 +1,93 @@ +# public.folder + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| createdAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| id | varchar(36) | | false | [public.folder](public.folder.md) [public.folder_tag](public.folder_tag.md) [public.workflow_entity](public.workflow_entity.md) | | | +| name | varchar(128) | | false | | | | +| parentFolderId | varchar(36) | | true | | [public.folder](public.folder.md) | | +| projectId | varchar(36) | | false | | [public.project](public.project.md) | | +| updatedAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| FK_804ea52f6729e3940498bd54d78 | FOREIGN KEY | FOREIGN KEY ("parentFolderId") REFERENCES folder(id) ON DELETE CASCADE | +| FK_a8260b0b36939c6247f385b8221 | FOREIGN KEY | FOREIGN KEY ("projectId") REFERENCES project(id) ON DELETE CASCADE | +| PK_6278a41a706740c94c02e288df8 | PRIMARY KEY | PRIMARY KEY (id) | +| folder_createdAt_not_null | n | NOT NULL "createdAt" | +| folder_id_not_null | n | NOT NULL id | +| folder_name_not_null | n | NOT NULL name | +| folder_projectId_not_null | n | NOT NULL "projectId" | +| folder_updatedAt_not_null | n | NOT NULL "updatedAt" | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_14f68deffaf858465715995508 | CREATE UNIQUE INDEX "IDX_14f68deffaf858465715995508" ON public.folder USING btree ("projectId", id) | +| PK_6278a41a706740c94c02e288df8 | CREATE UNIQUE INDEX "PK_6278a41a706740c94c02e288df8" ON public.folder USING btree (id) | + +## Relations + +```mermaid +erDiagram + +"public.folder" }o--o| "public.folder" : "FOREIGN KEY (#quot;parentFolderId#quot;) REFERENCES folder(id) ON DELETE CASCADE" +"public.folder_tag" }o--|| "public.folder" : "FOREIGN KEY (#quot;folderId#quot;) REFERENCES folder(id) ON DELETE CASCADE" +"public.workflow_entity" }o--o| "public.folder" : "FOREIGN KEY (#quot;parentFolderId#quot;) REFERENCES folder(id) ON DELETE CASCADE" +"public.folder" }o--|| "public.project" : "FOREIGN KEY (#quot;projectId#quot;) REFERENCES project(id) ON DELETE CASCADE" + +"public.folder" { + timestamp_3__with_time_zone createdAt + varchar_36_ id + varchar_128_ name + varchar_36_ parentFolderId FK + varchar_36_ projectId FK + timestamp_3__with_time_zone updatedAt +} +"public.folder_tag" { + varchar_36_ folderId FK + varchar_36_ tagId FK +} +"public.workflow_entity" { + boolean active + varchar_36_ activeVersionId FK + json connections + timestamp_3__with_time_zone createdAt + text description + varchar_36_ id + boolean isArchived + json meta + varchar_128_ name + json nodeGroups + json nodes + varchar_36_ parentFolderId FK + json pinData + json settings + varchar sourceWorkflowId + json staticData + integer triggerCount + timestamp_3__with_time_zone updatedAt + integer versionCounter + character_36_ versionId +} +"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.folder_tag.md b/docs/generated/postgres-schema/public.folder_tag.md new file mode 100644 index 00000000000..acbefa092a3 --- /dev/null +++ b/docs/generated/postgres-schema/public.folder_tag.md @@ -0,0 +1,56 @@ +# public.folder_tag + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| folderId | varchar(36) | | false | | [public.folder](public.folder.md) | | +| tagId | varchar(36) | | false | | [public.tag_entity](public.tag_entity.md) | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| FK_94a60854e06f2897b2e0d39edba | FOREIGN KEY | FOREIGN KEY ("folderId") REFERENCES folder(id) ON DELETE CASCADE | +| FK_dc88164176283de80af47621746 | FOREIGN KEY | FOREIGN KEY ("tagId") REFERENCES tag_entity(id) ON DELETE CASCADE | +| PK_27e4e00852f6b06a925a4d83a3e | PRIMARY KEY | PRIMARY KEY ("folderId", "tagId") | +| folder_tag_folderId_not_null | n | NOT NULL "folderId" | +| folder_tag_tagId_not_null | n | NOT NULL "tagId" | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| PK_27e4e00852f6b06a925a4d83a3e | CREATE UNIQUE INDEX "PK_27e4e00852f6b06a925a4d83a3e" ON public.folder_tag USING btree ("folderId", "tagId") | + +## Relations + +```mermaid +erDiagram + +"public.folder_tag" }o--|| "public.folder" : "FOREIGN KEY (#quot;folderId#quot;) REFERENCES folder(id) ON DELETE CASCADE" +"public.folder_tag" }o--|| "public.tag_entity" : "FOREIGN KEY (#quot;tagId#quot;) REFERENCES tag_entity(id) ON DELETE CASCADE" + +"public.folder_tag" { + varchar_36_ folderId FK + varchar_36_ tagId FK +} +"public.folder" { + timestamp_3__with_time_zone createdAt + varchar_36_ id + varchar_128_ name + varchar_36_ parentFolderId FK + varchar_36_ projectId FK + timestamp_3__with_time_zone updatedAt +} +"public.tag_entity" { + timestamp_3__with_time_zone createdAt + varchar_36_ id + varchar_24_ name + timestamp_3__with_time_zone updatedAt +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/postgres-schema/public.insights_by_period.md b/docs/generated/postgres-schema/public.insights_by_period.md new file mode 100644 index 00000000000..50963b40ba1 --- /dev/null +++ b/docs/generated/postgres-schema/public.insights_by_period.md @@ -0,0 +1,59 @@ +# public.insights_by_period + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| id | integer | | false | | | | +| metaId | integer | | false | | [public.insights_metadata](public.insights_metadata.md) | | +| periodStart | timestamp(0) with time zone | CURRENT_TIMESTAMP | true | | | | +| periodUnit | integer | | false | | | 0: hour, 1: day, 2: week | +| type | integer | | false | | | 0: time_saved_minutes, 1: runtime_milliseconds, 2: success, 3: failure | +| value | bigint | | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| FK_6414cfed98daabbfdd61a1cfbc0 | FOREIGN KEY | FOREIGN KEY ("metaId") REFERENCES insights_metadata("metaId") ON DELETE CASCADE | +| PK_b606942249b90cc39b0265f0575 | PRIMARY KEY | PRIMARY KEY (id) | +| insights_by_period_id_not_null | n | NOT NULL id | +| insights_by_period_metaId_not_null | n | NOT NULL "metaId" | +| insights_by_period_periodUnit_not_null | n | NOT NULL "periodUnit" | +| insights_by_period_type_not_null | n | NOT NULL type | +| insights_by_period_value_not_null | n | NOT NULL value | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_60b6a84299eeb3f671dfec7693 | CREATE UNIQUE INDEX "IDX_60b6a84299eeb3f671dfec7693" ON public.insights_by_period USING btree ("periodStart", type, "periodUnit", "metaId") | +| PK_b606942249b90cc39b0265f0575 | CREATE UNIQUE INDEX "PK_b606942249b90cc39b0265f0575" ON public.insights_by_period USING btree (id) | + +## Relations + +```mermaid +erDiagram + +"public.insights_by_period" }o--|| "public.insights_metadata" : "FOREIGN KEY (#quot;metaId#quot;) REFERENCES insights_metadata(#quot;metaId#quot;) ON DELETE CASCADE" + +"public.insights_by_period" { + integer id + integer metaId FK + timestamp_0__with_time_zone periodStart + integer periodUnit + integer type + bigint value +} +"public.insights_metadata" { + integer metaId + varchar_36_ projectId FK + varchar_255_ projectName + varchar_36_ workflowId FK + varchar_128_ workflowName +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/postgres-schema/public.insights_metadata.md b/docs/generated/postgres-schema/public.insights_metadata.md new file mode 100644 index 00000000000..51626443d14 --- /dev/null +++ b/docs/generated/postgres-schema/public.insights_metadata.md @@ -0,0 +1,100 @@ +# public.insights_metadata + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| metaId | integer | | false | [public.insights_by_period](public.insights_by_period.md) [public.insights_raw](public.insights_raw.md) | | | +| projectId | varchar(36) | | true | | [public.project](public.project.md) | | +| projectName | varchar(255) | | false | | | | +| workflowId | varchar(36) | | true | | [public.workflow_entity](public.workflow_entity.md) | | +| workflowName | varchar(128) | | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| FK_1d8ab99d5861c9388d2dc1cf733 | FOREIGN KEY | FOREIGN KEY ("workflowId") REFERENCES workflow_entity(id) ON DELETE SET NULL | +| FK_2375a1eda085adb16b24615b69c | FOREIGN KEY | FOREIGN KEY ("projectId") REFERENCES project(id) ON DELETE SET NULL | +| PK_f448a94c35218b6208ce20cf5a1 | PRIMARY KEY | PRIMARY KEY ("metaId") | +| insights_metadata_metaId_not_null | n | NOT NULL "metaId" | +| insights_metadata_projectName_not_null | n | NOT NULL "projectName" | +| insights_metadata_workflowName_not_null | n | NOT NULL "workflowName" | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_1d8ab99d5861c9388d2dc1cf73 | CREATE UNIQUE INDEX "IDX_1d8ab99d5861c9388d2dc1cf73" ON public.insights_metadata USING btree ("workflowId") | +| PK_f448a94c35218b6208ce20cf5a1 | CREATE UNIQUE INDEX "PK_f448a94c35218b6208ce20cf5a1" ON public.insights_metadata USING btree ("metaId") | + +## Relations + +```mermaid +erDiagram + +"public.insights_by_period" }o--|| "public.insights_metadata" : "FOREIGN KEY (#quot;metaId#quot;) REFERENCES insights_metadata(#quot;metaId#quot;) ON DELETE CASCADE" +"public.insights_raw" }o--|| "public.insights_metadata" : "FOREIGN KEY (#quot;metaId#quot;) REFERENCES insights_metadata(#quot;metaId#quot;) ON DELETE CASCADE" +"public.insights_metadata" }o--o| "public.project" : "FOREIGN KEY (#quot;projectId#quot;) REFERENCES project(id) ON DELETE SET NULL" +"public.insights_metadata" }o--o| "public.workflow_entity" : "FOREIGN KEY (#quot;workflowId#quot;) REFERENCES workflow_entity(id) ON DELETE SET NULL" + +"public.insights_metadata" { + integer metaId + varchar_36_ projectId FK + varchar_255_ projectName + varchar_36_ workflowId FK + varchar_128_ workflowName +} +"public.insights_by_period" { + integer id + integer metaId FK + timestamp_0__with_time_zone periodStart + integer periodUnit + integer type + bigint value +} +"public.insights_raw" { + integer id + integer metaId FK + timestamp_0__with_time_zone timestamp + integer type + bigint value +} +"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 +} +"public.workflow_entity" { + boolean active + varchar_36_ activeVersionId FK + json connections + timestamp_3__with_time_zone createdAt + text description + varchar_36_ id + boolean isArchived + json meta + varchar_128_ name + json nodeGroups + json nodes + varchar_36_ parentFolderId FK + json pinData + json settings + varchar sourceWorkflowId + json staticData + integer triggerCount + timestamp_3__with_time_zone updatedAt + integer versionCounter + character_36_ versionId +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/postgres-schema/public.insights_raw.md b/docs/generated/postgres-schema/public.insights_raw.md new file mode 100644 index 00000000000..c422bfb1e37 --- /dev/null +++ b/docs/generated/postgres-schema/public.insights_raw.md @@ -0,0 +1,57 @@ +# public.insights_raw + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| id | integer | | false | | | | +| metaId | integer | | false | | [public.insights_metadata](public.insights_metadata.md) | | +| timestamp | timestamp(0) with time zone | CURRENT_TIMESTAMP | false | | | | +| type | integer | | false | | | 0: time_saved_minutes, 1: runtime_milliseconds, 2: success, 3: failure | +| value | bigint | | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| FK_6e2e33741adef2a7c5d66befa4e | FOREIGN KEY | FOREIGN KEY ("metaId") REFERENCES insights_metadata("metaId") ON DELETE CASCADE | +| PK_ec15125755151e3a7e00e00014f | PRIMARY KEY | PRIMARY KEY (id) | +| insights_raw_id_not_null | n | NOT NULL id | +| insights_raw_metaId_not_null | n | NOT NULL "metaId" | +| insights_raw_timestamp_not_null | n | NOT NULL "timestamp" | +| insights_raw_type_not_null | n | NOT NULL type | +| insights_raw_value_not_null | n | NOT NULL value | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_insights_raw_timestamp_id | CREATE INDEX "IDX_insights_raw_timestamp_id" ON public.insights_raw USING btree ("timestamp", id) | +| PK_ec15125755151e3a7e00e00014f | CREATE UNIQUE INDEX "PK_ec15125755151e3a7e00e00014f" ON public.insights_raw USING btree (id) | + +## Relations + +```mermaid +erDiagram + +"public.insights_raw" }o--|| "public.insights_metadata" : "FOREIGN KEY (#quot;metaId#quot;) REFERENCES insights_metadata(#quot;metaId#quot;) ON DELETE CASCADE" + +"public.insights_raw" { + integer id + integer metaId FK + timestamp_0__with_time_zone timestamp + integer type + bigint value +} +"public.insights_metadata" { + integer metaId + varchar_36_ projectId FK + varchar_255_ projectName + varchar_36_ workflowId FK + varchar_128_ workflowName +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/postgres-schema/public.installed_nodes.md b/docs/generated/postgres-schema/public.installed_nodes.md new file mode 100644 index 00000000000..fccae9ff3d1 --- /dev/null +++ b/docs/generated/postgres-schema/public.installed_nodes.md @@ -0,0 +1,54 @@ +# public.installed_nodes + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| latestVersion | integer | 1 | false | | | | +| name | varchar(200) | | false | | | | +| package | varchar(241) | | false | | [public.installed_packages](public.installed_packages.md) | | +| type | varchar(200) | | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| FK_73f857fc5dce682cef8a99c11dbddbc969618951 | FOREIGN KEY | FOREIGN KEY (package) REFERENCES installed_packages("packageName") ON UPDATE CASCADE ON DELETE CASCADE | +| PK_8ebd28194e4f792f96b5933423fc439df97d9689 | PRIMARY KEY | PRIMARY KEY (name) | +| installed_nodes_latestVersion_not_null | n | NOT NULL "latestVersion" | +| installed_nodes_name_not_null | n | NOT NULL name | +| installed_nodes_package_not_null | n | NOT NULL package | +| installed_nodes_type_not_null | n | NOT NULL type | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| PK_8ebd28194e4f792f96b5933423fc439df97d9689 | CREATE UNIQUE INDEX "PK_8ebd28194e4f792f96b5933423fc439df97d9689" ON public.installed_nodes USING btree (name) | + +## Relations + +```mermaid +erDiagram + +"public.installed_nodes" }o--|| "public.installed_packages" : "FOREIGN KEY (package) REFERENCES installed_packages(#quot;packageName#quot;) ON UPDATE CASCADE ON DELETE CASCADE" + +"public.installed_nodes" { + integer latestVersion + varchar_200_ name + varchar_241_ package FK + varchar_200_ type +} +"public.installed_packages" { + varchar_70_ authorEmail + varchar_70_ authorName + timestamp_3__with_time_zone createdAt + varchar_50_ installedVersion + varchar_214_ packageName + timestamp_3__with_time_zone updatedAt +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/postgres-schema/public.installed_packages.md b/docs/generated/postgres-schema/public.installed_packages.md new file mode 100644 index 00000000000..8ab4de8802a --- /dev/null +++ b/docs/generated/postgres-schema/public.installed_packages.md @@ -0,0 +1,55 @@ +# public.installed_packages + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| authorEmail | varchar(70) | | true | | | | +| authorName | varchar(70) | | true | | | | +| createdAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| installedVersion | varchar(50) | | false | | | | +| packageName | varchar(214) | | false | [public.installed_nodes](public.installed_nodes.md) | | | +| updatedAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| PK_08cc9197c39b028c1e9beca225940576fd1a5804 | PRIMARY KEY | PRIMARY KEY ("packageName") | +| installed_packages_createdAt_not_null | n | NOT NULL "createdAt" | +| installed_packages_installedVersion_not_null | n | NOT NULL "installedVersion" | +| installed_packages_packageName_not_null | n | NOT NULL "packageName" | +| installed_packages_updatedAt_not_null | n | NOT NULL "updatedAt" | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| PK_08cc9197c39b028c1e9beca225940576fd1a5804 | CREATE UNIQUE INDEX "PK_08cc9197c39b028c1e9beca225940576fd1a5804" ON public.installed_packages USING btree ("packageName") | + +## Relations + +```mermaid +erDiagram + +"public.installed_nodes" }o--|| "public.installed_packages" : "FOREIGN KEY (package) REFERENCES installed_packages(#quot;packageName#quot;) ON UPDATE CASCADE ON DELETE CASCADE" + +"public.installed_packages" { + varchar_70_ authorEmail + varchar_70_ authorName + timestamp_3__with_time_zone createdAt + varchar_50_ installedVersion + varchar_214_ packageName + timestamp_3__with_time_zone updatedAt +} +"public.installed_nodes" { + integer latestVersion + varchar_200_ name + varchar_241_ package FK + varchar_200_ type +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/postgres-schema/public.instance_ai_checkpoints.md b/docs/generated/postgres-schema/public.instance_ai_checkpoints.md new file mode 100644 index 00000000000..fccf53564d5 --- /dev/null +++ b/docs/generated/postgres-schema/public.instance_ai_checkpoints.md @@ -0,0 +1,82 @@ +# public.instance_ai_checkpoints + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| createdAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| expiredAt | timestamp(3) with time zone | | true | | | Soft-delete timestamp: null means live; non-null marks the row as a tombstone. | +| key | varchar(255) | | false | [public.instance_ai_pending_confirmations](public.instance_ai_pending_confirmations.md) | | Opaque checkpoint key from the agent runtime. | +| resourceId | varchar(255) | | true | | | Resource ID recorded by the agent runtime. | +| runId | varchar(255) | | true | | | Run ID parsed from the checkpoint key when available. | +| state | json | | true | | | Serializable agent state snapshot stored as JSON. | +| threadId | uuid | | false | | [public.instance_ai_threads](public.instance_ai_threads.md) | Instance AI thread that owns the checkpoint. | +| updatedAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| FK_2b23f3f24a70bebb990203b011e | FOREIGN KEY | FOREIGN KEY ("threadId") REFERENCES instance_ai_threads(id) ON DELETE CASCADE | +| PK_5315a45f0846d1f9d128c18a2ed | PRIMARY KEY | PRIMARY KEY (key) | +| instance_ai_checkpoints_createdAt_not_null | n | NOT NULL "createdAt" | +| instance_ai_checkpoints_key_not_null | n | NOT NULL key | +| instance_ai_checkpoints_state_tombstone_check | CHECK | CHECK (((("expiredAt" IS NOT NULL) AND (state IS NULL)) OR ("expiredAt" IS NULL))) | +| instance_ai_checkpoints_threadId_not_null | n | NOT NULL "threadId" | +| instance_ai_checkpoints_updatedAt_not_null | n | NOT NULL "updatedAt" | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_2b23f3f24a70bebb990203b011 | CREATE INDEX "IDX_2b23f3f24a70bebb990203b011" ON public.instance_ai_checkpoints USING btree ("threadId") | +| IDX_768189b506cc26c4fe878b87cb | CREATE INDEX "IDX_768189b506cc26c4fe878b87cb" ON public.instance_ai_checkpoints USING btree ("runId") | +| IDX_be9d0eca0b19fb93d4eb74b327 | CREATE INDEX "IDX_be9d0eca0b19fb93d4eb74b327" ON public.instance_ai_checkpoints USING btree ("resourceId") | +| PK_5315a45f0846d1f9d128c18a2ed | CREATE UNIQUE INDEX "PK_5315a45f0846d1f9d128c18a2ed" ON public.instance_ai_checkpoints USING btree (key) | + +## Relations + +```mermaid +erDiagram + +"public.instance_ai_pending_confirmations" }o--o| "public.instance_ai_checkpoints" : "FOREIGN KEY (#quot;checkpointKey#quot;) REFERENCES instance_ai_checkpoints(key) ON DELETE CASCADE" +"public.instance_ai_checkpoints" }o--|| "public.instance_ai_threads" : "FOREIGN KEY (#quot;threadId#quot;) REFERENCES instance_ai_threads(id) ON DELETE CASCADE" + +"public.instance_ai_checkpoints" { + timestamp_3__with_time_zone createdAt + timestamp_3__with_time_zone expiredAt + varchar_255_ key + varchar_255_ resourceId + varchar_255_ runId + json state + uuid threadId FK + timestamp_3__with_time_zone updatedAt +} +"public.instance_ai_pending_confirmations" { + varchar_255_ checkpointKey FK + varchar_36_ checkpointTaskId + timestamp_3__with_time_zone createdAt + timestamp_3__with_time_zone expiresAt + varchar_16_ kind + varchar_36_ messageGroupId + varchar_36_ requestId + varchar_36_ runId + uuid threadId FK + varchar_64_ toolCallId + timestamp_3__with_time_zone updatedAt + uuid userId FK +} +"public.instance_ai_threads" { + timestamp_3__with_time_zone createdAt + uuid id + json metadata + varchar_36_ projectId FK + varchar_255_ resourceId + text title + timestamp_3__with_time_zone updatedAt +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/postgres-schema/public.instance_ai_iteration_logs.md b/docs/generated/postgres-schema/public.instance_ai_iteration_logs.md new file mode 100644 index 00000000000..896d6c8c2ce --- /dev/null +++ b/docs/generated/postgres-schema/public.instance_ai_iteration_logs.md @@ -0,0 +1,62 @@ +# public.instance_ai_iteration_logs + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| createdAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| entry | text | | false | | | | +| id | varchar(36) | | false | | | | +| taskKey | varchar | | false | | | | +| threadId | uuid | | false | | [public.instance_ai_threads](public.instance_ai_threads.md) | | +| updatedAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| FK_8bfcc6c51fd3d69b1eae8aebd49 | FOREIGN KEY | FOREIGN KEY ("threadId") REFERENCES instance_ai_threads(id) ON DELETE CASCADE | +| PK_21c2b214b44bc6c34a6d3551c90 | PRIMARY KEY | PRIMARY KEY (id) | +| instance_ai_iteration_logs_createdAt_not_null | n | NOT NULL "createdAt" | +| instance_ai_iteration_logs_entry_not_null | n | NOT NULL entry | +| instance_ai_iteration_logs_id_not_null | n | NOT NULL id | +| instance_ai_iteration_logs_taskKey_not_null | n | NOT NULL "taskKey" | +| instance_ai_iteration_logs_threadId_not_null | n | NOT NULL "threadId" | +| instance_ai_iteration_logs_updatedAt_not_null | n | NOT NULL "updatedAt" | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_02751202c9a2ad75f2d8e14f5e | CREATE INDEX "IDX_02751202c9a2ad75f2d8e14f5e" ON public.instance_ai_iteration_logs USING btree ("threadId", "taskKey", "createdAt") | +| PK_21c2b214b44bc6c34a6d3551c90 | CREATE UNIQUE INDEX "PK_21c2b214b44bc6c34a6d3551c90" ON public.instance_ai_iteration_logs USING btree (id) | + +## Relations + +```mermaid +erDiagram + +"public.instance_ai_iteration_logs" }o--|| "public.instance_ai_threads" : "FOREIGN KEY (#quot;threadId#quot;) REFERENCES instance_ai_threads(id) ON DELETE CASCADE" + +"public.instance_ai_iteration_logs" { + timestamp_3__with_time_zone createdAt + text entry + varchar_36_ id + varchar taskKey + uuid threadId FK + timestamp_3__with_time_zone updatedAt +} +"public.instance_ai_threads" { + timestamp_3__with_time_zone createdAt + uuid id + json metadata + varchar_36_ projectId FK + varchar_255_ resourceId + text title + timestamp_3__with_time_zone updatedAt +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/postgres-schema/public.instance_ai_mcp_registry_connections.md b/docs/generated/postgres-schema/public.instance_ai_mcp_registry_connections.md new file mode 100644 index 00000000000..d8e14dd0e31 --- /dev/null +++ b/docs/generated/postgres-schema/public.instance_ai_mcp_registry_connections.md @@ -0,0 +1,98 @@ +# public.instance_ai_mcp_registry_connections + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| createdAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| credentialId | varchar(36) | | false | | [public.credentials_entity](public.credentials_entity.md) | | +| id | uuid | | false | | | | +| serverSlug | varchar(255) | | false | | [public.mcp_registry_server](public.mcp_registry_server.md) | | +| toolFilter | json | | true | | | Optional MCP tool filter per registry connection: { mode: "allow" \| "exclude", tools: string[] } | +| updatedAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| userId | uuid | | false | | [public.user](public.user.md) | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| FK_1d25707354d2012da256eb2ec0a | FOREIGN KEY | FOREIGN KEY ("serverSlug") REFERENCES mcp_registry_server(slug) ON DELETE CASCADE | +| FK_1e826120e7e53ebc4681f026de8 | FOREIGN KEY | FOREIGN KEY ("credentialId") REFERENCES credentials_entity(id) ON DELETE CASCADE | +| FK_8b42c08a531d76410980c639a5b | FOREIGN KEY | FOREIGN KEY ("userId") REFERENCES "user"(id) ON DELETE CASCADE | +| PK_e34e4d15d78eabbe8217e33ef03 | PRIMARY KEY | PRIMARY KEY (id) | +| instance_ai_mcp_registry_connections_createdAt_not_null | n | NOT NULL "createdAt" | +| instance_ai_mcp_registry_connections_credentialId_not_null | n | NOT NULL "credentialId" | +| instance_ai_mcp_registry_connections_id_not_null | n | NOT NULL id | +| instance_ai_mcp_registry_connections_serverSlug_not_null | n | NOT NULL "serverSlug" | +| instance_ai_mcp_registry_connections_updatedAt_not_null | n | NOT NULL "updatedAt" | +| instance_ai_mcp_registry_connections_userId_not_null | n | NOT NULL "userId" | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_16db3adb7b19df1ee55ff06b27 | CREATE UNIQUE INDEX "IDX_16db3adb7b19df1ee55ff06b27" ON public.instance_ai_mcp_registry_connections USING btree ("userId", "serverSlug", "credentialId") | +| PK_e34e4d15d78eabbe8217e33ef03 | CREATE UNIQUE INDEX "PK_e34e4d15d78eabbe8217e33ef03" ON public.instance_ai_mcp_registry_connections USING btree (id) | + +## Relations + +```mermaid +erDiagram + +"public.instance_ai_mcp_registry_connections" }o--|| "public.credentials_entity" : "FOREIGN KEY (#quot;credentialId#quot;) REFERENCES credentials_entity(id) ON DELETE CASCADE" +"public.instance_ai_mcp_registry_connections" }o--|| "public.mcp_registry_server" : "FOREIGN KEY (#quot;serverSlug#quot;) REFERENCES mcp_registry_server(slug) ON DELETE CASCADE" +"public.instance_ai_mcp_registry_connections" }o--|| "public.user" : "FOREIGN KEY (#quot;userId#quot;) REFERENCES #quot;user#quot;(id) ON DELETE CASCADE" + +"public.instance_ai_mcp_registry_connections" { + timestamp_3__with_time_zone createdAt + varchar_36_ credentialId FK + uuid id + varchar_255_ serverSlug FK + json toolFilter + timestamp_3__with_time_zone updatedAt + uuid userId FK +} +"public.credentials_entity" { + timestamp_3__with_time_zone createdAt + text data + varchar_36_ id + boolean isGlobal + boolean isManaged + boolean isResolvable + varchar_128_ name + boolean resolvableAllowFallback + varchar_16_ resolverId FK + varchar_128_ type + timestamp_3__with_time_zone updatedAt +} +"public.mcp_registry_server" { + timestamp_3__with_time_zone createdAt + json data + timestamp_3__without_time_zone registryUpdatedAt + varchar_255_ slug + varchar_50_ status + timestamp_3__with_time_zone updatedAt + varchar_50_ 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 +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/postgres-schema/public.instance_ai_messages.md b/docs/generated/postgres-schema/public.instance_ai_messages.md new file mode 100644 index 00000000000..735349b2f55 --- /dev/null +++ b/docs/generated/postgres-schema/public.instance_ai_messages.md @@ -0,0 +1,67 @@ +# public.instance_ai_messages + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| content | text | | false | | | | +| createdAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| id | varchar(36) | | false | | | | +| resourceId | varchar(255) | | true | | | | +| role | varchar(16) | | false | | | | +| threadId | uuid | | false | | [public.instance_ai_threads](public.instance_ai_threads.md) | | +| type | varchar(32) | | true | | | | +| updatedAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| FK_1eeb64cb9d66a927988de759e6e | FOREIGN KEY | FOREIGN KEY ("threadId") REFERENCES instance_ai_threads(id) ON DELETE CASCADE | +| PK_156c6f287225e9befe0181bb02b | PRIMARY KEY | PRIMARY KEY (id) | +| instance_ai_messages_content_not_null | n | NOT NULL content | +| instance_ai_messages_createdAt_not_null | n | NOT NULL "createdAt" | +| instance_ai_messages_id_not_null | n | NOT NULL id | +| instance_ai_messages_role_not_null | n | NOT NULL role | +| instance_ai_messages_threadId_not_null | n | NOT NULL "threadId" | +| instance_ai_messages_updatedAt_not_null | n | NOT NULL "updatedAt" | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_1eeb64cb9d66a927988de759e6 | CREATE INDEX "IDX_1eeb64cb9d66a927988de759e6" ON public.instance_ai_messages USING btree ("threadId") | +| IDX_76e212c6867fbaa06bf0decd6f | CREATE INDEX "IDX_76e212c6867fbaa06bf0decd6f" ON public.instance_ai_messages USING btree ("resourceId") | +| PK_156c6f287225e9befe0181bb02b | CREATE UNIQUE INDEX "PK_156c6f287225e9befe0181bb02b" ON public.instance_ai_messages USING btree (id) | + +## Relations + +```mermaid +erDiagram + +"public.instance_ai_messages" }o--|| "public.instance_ai_threads" : "FOREIGN KEY (#quot;threadId#quot;) REFERENCES instance_ai_threads(id) ON DELETE CASCADE" + +"public.instance_ai_messages" { + text content + timestamp_3__with_time_zone createdAt + varchar_36_ id + varchar_255_ resourceId + varchar_16_ role + uuid threadId FK + varchar_32_ type + timestamp_3__with_time_zone updatedAt +} +"public.instance_ai_threads" { + timestamp_3__with_time_zone createdAt + uuid id + json metadata + varchar_36_ projectId FK + varchar_255_ resourceId + text title + timestamp_3__with_time_zone updatedAt +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/postgres-schema/public.instance_ai_observation_cursors.md b/docs/generated/postgres-schema/public.instance_ai_observation_cursors.md new file mode 100644 index 00000000000..d3b95998f7e --- /dev/null +++ b/docs/generated/postgres-schema/public.instance_ai_observation_cursors.md @@ -0,0 +1,58 @@ +# public.instance_ai_observation_cursors + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| createdAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| lastObservedAt | timestamp(3) with time zone | | false | | | | +| lastObservedMessageId | varchar(36) | | false | | | | +| observationScopeId | uuid | | false | | [public.instance_ai_threads](public.instance_ai_threads.md) | instance_ai_threads.id source stream checkpointed by this cursor | +| updatedAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| FK_5b6319b2e9a37c1064a72428f9a | FOREIGN KEY | FOREIGN KEY ("observationScopeId") REFERENCES instance_ai_threads(id) ON DELETE CASCADE | +| PK_5b6319b2e9a37c1064a72428f9a | PRIMARY KEY | PRIMARY KEY ("observationScopeId") | +| instance_ai_observation_cursors_createdAt_not_null | n | NOT NULL "createdAt" | +| instance_ai_observation_cursors_lastObservedAt_not_null | n | NOT NULL "lastObservedAt" | +| instance_ai_observation_cursors_lastObservedMessageId_not_null | n | NOT NULL "lastObservedMessageId" | +| instance_ai_observation_cursors_observationScopeId_not_null | n | NOT NULL "observationScopeId" | +| instance_ai_observation_cursors_updatedAt_not_null | n | NOT NULL "updatedAt" | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| PK_5b6319b2e9a37c1064a72428f9a | CREATE UNIQUE INDEX "PK_5b6319b2e9a37c1064a72428f9a" ON public.instance_ai_observation_cursors USING btree ("observationScopeId") | + +## Relations + +```mermaid +erDiagram + +"public.instance_ai_observation_cursors" |o--|| "public.instance_ai_threads" : "FOREIGN KEY (#quot;observationScopeId#quot;) REFERENCES instance_ai_threads(id) ON DELETE CASCADE" + +"public.instance_ai_observation_cursors" { + timestamp_3__with_time_zone createdAt + timestamp_3__with_time_zone lastObservedAt + varchar_36_ lastObservedMessageId + uuid observationScopeId FK + timestamp_3__with_time_zone updatedAt +} +"public.instance_ai_threads" { + timestamp_3__with_time_zone createdAt + uuid id + json metadata + varchar_36_ projectId FK + varchar_255_ resourceId + text title + timestamp_3__with_time_zone updatedAt +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/postgres-schema/public.instance_ai_observation_locks.md b/docs/generated/postgres-schema/public.instance_ai_observation_locks.md new file mode 100644 index 00000000000..c6c7da52fd6 --- /dev/null +++ b/docs/generated/postgres-schema/public.instance_ai_observation_locks.md @@ -0,0 +1,62 @@ +# public.instance_ai_observation_locks + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| createdAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| heldUntil | timestamp(3) with time zone | | false | | | | +| holderId | varchar(64) | | false | | | Ephemeral background-task lock owner token, not a user ID | +| observationScopeId | uuid | | false | | [public.instance_ai_threads](public.instance_ai_threads.md) | instance_ai_threads.id source stream locked for observation tasks | +| taskKind | varchar(20) | | false | | | | +| updatedAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| CHK_instance_ai_observation_locks_taskKind | CHECK | CHECK ((("taskKind")::text = ANY ((ARRAY['observer'::character varying, 'reflector'::character varying])::text[]))) | +| FK_103e2e5f454860b28ea05a82c74 | FOREIGN KEY | FOREIGN KEY ("observationScopeId") REFERENCES instance_ai_threads(id) ON DELETE CASCADE | +| PK_fc491dd378b9448655c3c683f85 | PRIMARY KEY | PRIMARY KEY ("observationScopeId", "taskKind") | +| instance_ai_observation_locks_createdAt_not_null | n | NOT NULL "createdAt" | +| instance_ai_observation_locks_heldUntil_not_null | n | NOT NULL "heldUntil" | +| instance_ai_observation_locks_holderId_not_null | n | NOT NULL "holderId" | +| instance_ai_observation_locks_observationScopeId_not_null | n | NOT NULL "observationScopeId" | +| instance_ai_observation_locks_taskKind_not_null | n | NOT NULL "taskKind" | +| instance_ai_observation_locks_updatedAt_not_null | n | NOT NULL "updatedAt" | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| PK_fc491dd378b9448655c3c683f85 | CREATE UNIQUE INDEX "PK_fc491dd378b9448655c3c683f85" ON public.instance_ai_observation_locks USING btree ("observationScopeId", "taskKind") | + +## Relations + +```mermaid +erDiagram + +"public.instance_ai_observation_locks" }o--|| "public.instance_ai_threads" : "FOREIGN KEY (#quot;observationScopeId#quot;) REFERENCES instance_ai_threads(id) ON DELETE CASCADE" + +"public.instance_ai_observation_locks" { + timestamp_3__with_time_zone createdAt + timestamp_3__with_time_zone heldUntil + varchar_64_ holderId + uuid observationScopeId FK + varchar_20_ taskKind + timestamp_3__with_time_zone updatedAt +} +"public.instance_ai_threads" { + timestamp_3__with_time_zone createdAt + uuid id + json metadata + varchar_36_ projectId FK + varchar_255_ resourceId + text title + timestamp_3__with_time_zone updatedAt +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/postgres-schema/public.instance_ai_observational_memory.md b/docs/generated/postgres-schema/public.instance_ai_observational_memory.md new file mode 100644 index 00000000000..76b1bd765f7 --- /dev/null +++ b/docs/generated/postgres-schema/public.instance_ai_observational_memory.md @@ -0,0 +1,127 @@ +# public.instance_ai_observational_memory + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| activeObservations | text | ''::text | false | | | | +| bufferedMessageIds | json | | true | | | | +| bufferedObservationChunks | json | | true | | | | +| bufferedObservationTokens | integer | | true | | | | +| bufferedObservations | text | | true | | | | +| bufferedReflection | text | | true | | | | +| bufferedReflectionInputTokens | integer | | true | | | | +| bufferedReflectionTokens | integer | | true | | | | +| config | text | | false | | | | +| createdAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| generationCount | integer | 0 | false | | | | +| id | varchar(36) | | false | | | | +| isBufferingObservation | boolean | false | false | | | | +| isBufferingReflection | boolean | false | false | | | | +| isObserving | boolean | false | false | | | | +| isReflecting | boolean | false | false | | | | +| lastBufferedAtTime | timestamp(3) with time zone | | true | | | | +| lastBufferedAtTokens | integer | 0 | false | | | | +| lastObservedAt | timestamp(3) with time zone | | true | | | | +| lookupKey | varchar(255) | | false | | | | +| metadata | json | | true | | | | +| observationTokenCount | integer | 0 | false | | | | +| observedMessageIds | json | | true | | | | +| observedTimezone | varchar | | true | | | | +| originType | varchar(32) | | false | | | | +| pendingMessageTokens | integer | 0 | false | | | | +| reflectedObservationLineCount | integer | | true | | | | +| resourceId | varchar(255) | | false | | | | +| scope | varchar(16) | | false | | | | +| threadId | uuid | | true | | [public.instance_ai_threads](public.instance_ai_threads.md) | | +| totalTokensObserved | integer | 0 | false | | | | +| updatedAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| FK_34018c303885cd37093458e6409 | FOREIGN KEY | FOREIGN KEY ("threadId") REFERENCES instance_ai_threads(id) ON DELETE SET NULL | +| PK_7192dd00cddba039bf1d3e6a098 | PRIMARY KEY | PRIMARY KEY (id) | +| instance_ai_observational_memor_isBufferingObservation_not_null | n | NOT NULL "isBufferingObservation" | +| instance_ai_observational_memory_activeObservations_not_null | n | NOT NULL "activeObservations" | +| instance_ai_observational_memory_config_not_null | n | NOT NULL config | +| instance_ai_observational_memory_createdAt_not_null | n | NOT NULL "createdAt" | +| instance_ai_observational_memory_generationCount_not_null | n | NOT NULL "generationCount" | +| instance_ai_observational_memory_id_not_null | n | NOT NULL id | +| instance_ai_observational_memory_isBufferingReflection_not_null | n | NOT NULL "isBufferingReflection" | +| instance_ai_observational_memory_isObserving_not_null | n | NOT NULL "isObserving" | +| instance_ai_observational_memory_isReflecting_not_null | n | NOT NULL "isReflecting" | +| instance_ai_observational_memory_lastBufferedAtTokens_not_null | n | NOT NULL "lastBufferedAtTokens" | +| instance_ai_observational_memory_lookupKey_not_null | n | NOT NULL "lookupKey" | +| instance_ai_observational_memory_observationTokenCount_not_null | n | NOT NULL "observationTokenCount" | +| instance_ai_observational_memory_originType_not_null | n | NOT NULL "originType" | +| instance_ai_observational_memory_pendingMessageTokens_not_null | n | NOT NULL "pendingMessageTokens" | +| instance_ai_observational_memory_resourceId_not_null | n | NOT NULL "resourceId" | +| instance_ai_observational_memory_scope_not_null | n | NOT NULL scope | +| instance_ai_observational_memory_totalTokensObserved_not_null | n | NOT NULL "totalTokensObserved" | +| instance_ai_observational_memory_updatedAt_not_null | n | NOT NULL "updatedAt" | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_92f13cb6bc694227e069447f7b | CREATE INDEX "IDX_92f13cb6bc694227e069447f7b" ON public.instance_ai_observational_memory USING btree ("lookupKey") | +| IDX_a680ac96aae02dc887bbaac512 | CREATE UNIQUE INDEX "IDX_a680ac96aae02dc887bbaac512" ON public.instance_ai_observational_memory USING btree (scope, "threadId", "resourceId") | +| PK_7192dd00cddba039bf1d3e6a098 | CREATE UNIQUE INDEX "PK_7192dd00cddba039bf1d3e6a098" ON public.instance_ai_observational_memory USING btree (id) | + +## Relations + +```mermaid +erDiagram + +"public.instance_ai_observational_memory" }o--o| "public.instance_ai_threads" : "FOREIGN KEY (#quot;threadId#quot;) REFERENCES instance_ai_threads(id) ON DELETE SET NULL" + +"public.instance_ai_observational_memory" { + text activeObservations + json bufferedMessageIds + json bufferedObservationChunks + integer bufferedObservationTokens + text bufferedObservations + text bufferedReflection + integer bufferedReflectionInputTokens + integer bufferedReflectionTokens + text config + timestamp_3__with_time_zone createdAt + integer generationCount + varchar_36_ id + boolean isBufferingObservation + boolean isBufferingReflection + boolean isObserving + boolean isReflecting + timestamp_3__with_time_zone lastBufferedAtTime + integer lastBufferedAtTokens + timestamp_3__with_time_zone lastObservedAt + varchar_255_ lookupKey + json metadata + integer observationTokenCount + json observedMessageIds + varchar observedTimezone + varchar_32_ originType + integer pendingMessageTokens + integer reflectedObservationLineCount + varchar_255_ resourceId + varchar_16_ scope + uuid threadId FK + integer totalTokensObserved + timestamp_3__with_time_zone updatedAt +} +"public.instance_ai_threads" { + timestamp_3__with_time_zone createdAt + uuid id + json metadata + varchar_36_ projectId FK + varchar_255_ resourceId + text title + timestamp_3__with_time_zone updatedAt +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/postgres-schema/public.instance_ai_observations.md b/docs/generated/postgres-schema/public.instance_ai_observations.md new file mode 100644 index 00000000000..644bf8a37c1 --- /dev/null +++ b/docs/generated/postgres-schema/public.instance_ai_observations.md @@ -0,0 +1,80 @@ +# public.instance_ai_observations + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| createdAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| id | varchar(36) | | false | [public.instance_ai_observations](public.instance_ai_observations.md) | | Application-generated n8n string ID, not a database UUID | +| marker | varchar(16) | | false | | | | +| observationScopeId | uuid | | false | | [public.instance_ai_threads](public.instance_ai_threads.md) | instance_ai_threads.id source stream for this observation log | +| parentId | varchar(36) | | true | | [public.instance_ai_observations](public.instance_ai_observations.md) | | +| status | varchar(16) | | false | | | | +| supersededBy | varchar(36) | | true | | [public.instance_ai_observations](public.instance_ai_observations.md) | | +| text | text | | false | | | | +| tokenCount | integer | 0 | false | | | | +| updatedAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| CHK_instance_ai_observations_marker | CHECK | CHECK (((marker)::text = ANY ((ARRAY['critical'::character varying, 'important'::character varying, 'info'::character varying, 'completion'::character varying])::text[]))) | +| CHK_instance_ai_observations_status | CHECK | CHECK (((status)::text = ANY ((ARRAY['active'::character varying, 'superseded'::character varying, 'dropped'::character varying])::text[]))) | +| FK_a80e0ee839a2f10ba4b86e19998 | FOREIGN KEY | FOREIGN KEY ("supersededBy") REFERENCES instance_ai_observations(id) | +| FK_d54fc84a6c8ac91b5e0db0378a4 | FOREIGN KEY | FOREIGN KEY ("observationScopeId") REFERENCES instance_ai_threads(id) ON DELETE CASCADE | +| FK_daef2195a4a846eb70eed15e039 | FOREIGN KEY | FOREIGN KEY ("parentId") REFERENCES instance_ai_observations(id) | +| PK_4d9b514cdf0f0b577650caf2ac2 | PRIMARY KEY | PRIMARY KEY (id) | +| instance_ai_observations_createdAt_not_null | n | NOT NULL "createdAt" | +| instance_ai_observations_id_not_null | n | NOT NULL id | +| instance_ai_observations_marker_not_null | n | NOT NULL marker | +| instance_ai_observations_observationScopeId_not_null | n | NOT NULL "observationScopeId" | +| instance_ai_observations_status_not_null | n | NOT NULL status | +| instance_ai_observations_text_not_null | n | NOT NULL text | +| instance_ai_observations_tokenCount_not_null | n | NOT NULL "tokenCount" | +| instance_ai_observations_updatedAt_not_null | n | NOT NULL "updatedAt" | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_0d5db648188d338df7fb2a8064 | CREATE INDEX "IDX_0d5db648188d338df7fb2a8064" ON public.instance_ai_observations USING btree ("observationScopeId", status, "createdAt", id) | +| IDX_a80e0ee839a2f10ba4b86e1999 | CREATE INDEX "IDX_a80e0ee839a2f10ba4b86e1999" ON public.instance_ai_observations USING btree ("supersededBy") | +| IDX_daef2195a4a846eb70eed15e03 | CREATE INDEX "IDX_daef2195a4a846eb70eed15e03" ON public.instance_ai_observations USING btree ("parentId") | +| PK_4d9b514cdf0f0b577650caf2ac2 | CREATE UNIQUE INDEX "PK_4d9b514cdf0f0b577650caf2ac2" ON public.instance_ai_observations USING btree (id) | + +## Relations + +```mermaid +erDiagram + +"public.instance_ai_observations" }o--o| "public.instance_ai_observations" : "FOREIGN KEY (#quot;supersededBy#quot;) REFERENCES instance_ai_observations(id)" +"public.instance_ai_observations" }o--o| "public.instance_ai_observations" : "FOREIGN KEY (#quot;parentId#quot;) REFERENCES instance_ai_observations(id)" +"public.instance_ai_observations" }o--|| "public.instance_ai_threads" : "FOREIGN KEY (#quot;observationScopeId#quot;) REFERENCES instance_ai_threads(id) ON DELETE CASCADE" + +"public.instance_ai_observations" { + timestamp_3__with_time_zone createdAt + varchar_36_ id + varchar_16_ marker + uuid observationScopeId FK + varchar_36_ parentId FK + varchar_16_ status + varchar_36_ supersededBy FK + text text + integer tokenCount + timestamp_3__with_time_zone updatedAt +} +"public.instance_ai_threads" { + timestamp_3__with_time_zone createdAt + uuid id + json metadata + varchar_36_ projectId FK + varchar_255_ resourceId + text title + timestamp_3__with_time_zone updatedAt +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/postgres-schema/public.instance_ai_pending_confirmations.md b/docs/generated/postgres-schema/public.instance_ai_pending_confirmations.md new file mode 100644 index 00000000000..36e06f0ff2b --- /dev/null +++ b/docs/generated/postgres-schema/public.instance_ai_pending_confirmations.md @@ -0,0 +1,110 @@ +# public.instance_ai_pending_confirmations + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| checkpointKey | varchar(255) | | true | | [public.instance_ai_checkpoints](public.instance_ai_checkpoints.md) | FK to instance_ai_checkpoints.key; also the SDK runId used to resume. | +| checkpointTaskId | varchar(36) | | true | | | Set when the suspended run was a planned-task checkpoint follow-up. | +| createdAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| expiresAt | timestamp(3) with time zone | | true | | | TTL for the leader-only sweep; null disables auto-expiry. | +| kind | varchar(16) | | false | | | 'suspended' (resumable from checkpoint) or 'inline' (orchestrator-held Promise). | +| messageGroupId | varchar(36) | | true | | | SSE event correlation group. | +| requestId | varchar(36) | | false | | | HITL confirmation request identifier. | +| runId | varchar(36) | | false | | | External run ID; reused on resume for SSE correlation. | +| threadId | uuid | | false | | [public.instance_ai_threads](public.instance_ai_threads.md) | Instance AI thread that owns the confirmation. | +| toolCallId | varchar(64) | | true | | | Suspended tool call awaiting confirmation. | +| updatedAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| userId | uuid | | false | | [public.user](public.user.md) | User who is expected to confirm or cancel. | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| CHK_instance_ai_pending_confirmations_kind | CHECK | CHECK (((kind)::text = ANY ((ARRAY['suspended'::character varying, 'inline'::character varying])::text[]))) | +| FK_0babdf6e3b897a86fe4678355eb | FOREIGN KEY | FOREIGN KEY ("checkpointKey") REFERENCES instance_ai_checkpoints(key) ON DELETE CASCADE | +| FK_ba67ee8dc311830a2eea89b6e96 | FOREIGN KEY | FOREIGN KEY ("threadId") REFERENCES instance_ai_threads(id) ON DELETE CASCADE | +| FK_df5fd25c8bbfd2b042602600d8e | FOREIGN KEY | FOREIGN KEY ("userId") REFERENCES "user"(id) ON DELETE CASCADE | +| PK_25c38179c8d45095b168adfff80 | PRIMARY KEY | PRIMARY KEY ("requestId") | +| instance_ai_pending_confirmations_createdAt_not_null | n | NOT NULL "createdAt" | +| instance_ai_pending_confirmations_kind_not_null | n | NOT NULL kind | +| instance_ai_pending_confirmations_requestId_not_null | n | NOT NULL "requestId" | +| instance_ai_pending_confirmations_runId_not_null | n | NOT NULL "runId" | +| instance_ai_pending_confirmations_threadId_not_null | n | NOT NULL "threadId" | +| instance_ai_pending_confirmations_updatedAt_not_null | n | NOT NULL "updatedAt" | +| instance_ai_pending_confirmations_userId_not_null | n | NOT NULL "userId" | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_0babdf6e3b897a86fe4678355e | CREATE INDEX "IDX_0babdf6e3b897a86fe4678355e" ON public.instance_ai_pending_confirmations USING btree ("checkpointKey") | +| IDX_ba67ee8dc311830a2eea89b6e9 | CREATE INDEX "IDX_ba67ee8dc311830a2eea89b6e9" ON public.instance_ai_pending_confirmations USING btree ("threadId") | +| IDX_d7a4aba7440449865e2b924377 | CREATE INDEX "IDX_d7a4aba7440449865e2b924377" ON public.instance_ai_pending_confirmations USING btree ("expiresAt") | +| IDX_df5fd25c8bbfd2b042602600d8 | CREATE INDEX "IDX_df5fd25c8bbfd2b042602600d8" ON public.instance_ai_pending_confirmations USING btree ("userId") | +| PK_25c38179c8d45095b168adfff80 | CREATE UNIQUE INDEX "PK_25c38179c8d45095b168adfff80" ON public.instance_ai_pending_confirmations USING btree ("requestId") | + +## Relations + +```mermaid +erDiagram + +"public.instance_ai_pending_confirmations" }o--o| "public.instance_ai_checkpoints" : "FOREIGN KEY (#quot;checkpointKey#quot;) REFERENCES instance_ai_checkpoints(key) ON DELETE CASCADE" +"public.instance_ai_pending_confirmations" }o--|| "public.instance_ai_threads" : "FOREIGN KEY (#quot;threadId#quot;) REFERENCES instance_ai_threads(id) ON DELETE CASCADE" +"public.instance_ai_pending_confirmations" }o--|| "public.user" : "FOREIGN KEY (#quot;userId#quot;) REFERENCES #quot;user#quot;(id) ON DELETE CASCADE" + +"public.instance_ai_pending_confirmations" { + varchar_255_ checkpointKey FK + varchar_36_ checkpointTaskId + timestamp_3__with_time_zone createdAt + timestamp_3__with_time_zone expiresAt + varchar_16_ kind + varchar_36_ messageGroupId + varchar_36_ requestId + varchar_36_ runId + uuid threadId FK + varchar_64_ toolCallId + timestamp_3__with_time_zone updatedAt + uuid userId FK +} +"public.instance_ai_checkpoints" { + timestamp_3__with_time_zone createdAt + timestamp_3__with_time_zone expiredAt + varchar_255_ key + varchar_255_ resourceId + varchar_255_ runId + json state + uuid threadId FK + timestamp_3__with_time_zone updatedAt +} +"public.instance_ai_threads" { + timestamp_3__with_time_zone createdAt + uuid id + json metadata + varchar_36_ projectId FK + varchar_255_ resourceId + text title + timestamp_3__with_time_zone updatedAt +} +"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 +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/postgres-schema/public.instance_ai_resources.md b/docs/generated/postgres-schema/public.instance_ai_resources.md new file mode 100644 index 00000000000..bfe1ec00b2c --- /dev/null +++ b/docs/generated/postgres-schema/public.instance_ai_resources.md @@ -0,0 +1,45 @@ +# public.instance_ai_resources + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| createdAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| id | varchar(255) | | false | | | | +| metadata | json | | true | | | | +| updatedAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| workingMemory | text | | true | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| PK_45b5b0b6f715dae4292b86603d8 | PRIMARY KEY | PRIMARY KEY (id) | +| instance_ai_resources_createdAt_not_null | n | NOT NULL "createdAt" | +| instance_ai_resources_id_not_null | n | NOT NULL id | +| instance_ai_resources_updatedAt_not_null | n | NOT NULL "updatedAt" | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| PK_45b5b0b6f715dae4292b86603d8 | CREATE UNIQUE INDEX "PK_45b5b0b6f715dae4292b86603d8" ON public.instance_ai_resources USING btree (id) | + +## Relations + +```mermaid +erDiagram + + +"public.instance_ai_resources" { + timestamp_3__with_time_zone createdAt + varchar_255_ id + json metadata + timestamp_3__with_time_zone updatedAt + text workingMemory +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/postgres-schema/public.instance_ai_run_snapshots.md b/docs/generated/postgres-schema/public.instance_ai_run_snapshots.md new file mode 100644 index 00000000000..bfa6db30318 --- /dev/null +++ b/docs/generated/postgres-schema/public.instance_ai_run_snapshots.md @@ -0,0 +1,72 @@ +# public.instance_ai_run_snapshots + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| createdAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| langsmithRunId | varchar(36) | | true | | | LangSmith run ID (UUID v4, e.g. "f47ac10b-58cc-4372-a567-0e02b2c3d479"). | +| langsmithTraceId | varchar(36) | | true | | | LangSmith trace ID (UUID v4, e.g. "f47ac10b-58cc-4372-a567-0e02b2c3d479"). | +| messageGroupId | varchar(36) | | true | | | | +| runId | varchar(36) | | false | | | | +| runIds | json | | true | | | | +| spanId | varchar(64) | | true | | | OpenTelemetry span ID for the root Instance AI run. | +| threadId | uuid | | false | | [public.instance_ai_threads](public.instance_ai_threads.md) | | +| traceId | varchar(64) | | true | | | OpenTelemetry trace ID for the root Instance AI run. | +| tree | text | | false | | | | +| updatedAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| FK_2f63fa21d09d7918f347ddbdf70 | FOREIGN KEY | FOREIGN KEY ("threadId") REFERENCES instance_ai_threads(id) ON DELETE CASCADE | +| PK_0a5fc9690a84950ebf1416fb146 | PRIMARY KEY | PRIMARY KEY ("threadId", "runId") | +| instance_ai_run_snapshots_createdAt_not_null | n | NOT NULL "createdAt" | +| instance_ai_run_snapshots_runId_not_null | n | NOT NULL "runId" | +| instance_ai_run_snapshots_threadId_not_null | n | NOT NULL "threadId" | +| instance_ai_run_snapshots_tree_not_null | n | NOT NULL tree | +| instance_ai_run_snapshots_updatedAt_not_null | n | NOT NULL "updatedAt" | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_d3a2bc880e7a8626802e5474ad | CREATE INDEX "IDX_d3a2bc880e7a8626802e5474ad" ON public.instance_ai_run_snapshots USING btree ("threadId", "createdAt") | +| IDX_d926c16c2ad9728cb9a81790c0 | CREATE INDEX "IDX_d926c16c2ad9728cb9a81790c0" ON public.instance_ai_run_snapshots USING btree ("threadId", "messageGroupId") | +| PK_0a5fc9690a84950ebf1416fb146 | CREATE UNIQUE INDEX "PK_0a5fc9690a84950ebf1416fb146" ON public.instance_ai_run_snapshots USING btree ("threadId", "runId") | + +## Relations + +```mermaid +erDiagram + +"public.instance_ai_run_snapshots" }o--|| "public.instance_ai_threads" : "FOREIGN KEY (#quot;threadId#quot;) REFERENCES instance_ai_threads(id) ON DELETE CASCADE" + +"public.instance_ai_run_snapshots" { + timestamp_3__with_time_zone createdAt + varchar_36_ langsmithRunId + varchar_36_ langsmithTraceId + varchar_36_ messageGroupId + varchar_36_ runId + json runIds + varchar_64_ spanId + uuid threadId FK + varchar_64_ traceId + text tree + timestamp_3__with_time_zone updatedAt +} +"public.instance_ai_threads" { + timestamp_3__with_time_zone createdAt + uuid id + json metadata + varchar_36_ projectId FK + varchar_255_ resourceId + text title + timestamp_3__with_time_zone updatedAt +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/postgres-schema/public.instance_ai_threads.md b/docs/generated/postgres-schema/public.instance_ai_threads.md new file mode 100644 index 00000000000..627e3ab5da0 --- /dev/null +++ b/docs/generated/postgres-schema/public.instance_ai_threads.md @@ -0,0 +1,199 @@ +# public.instance_ai_threads + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| createdAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| id | uuid | | false | [public.ai_builder_temporary_workflow](public.ai_builder_temporary_workflow.md) [public.instance_ai_checkpoints](public.instance_ai_checkpoints.md) [public.instance_ai_iteration_logs](public.instance_ai_iteration_logs.md) [public.instance_ai_messages](public.instance_ai_messages.md) [public.instance_ai_observation_cursors](public.instance_ai_observation_cursors.md) [public.instance_ai_observation_locks](public.instance_ai_observation_locks.md) [public.instance_ai_observational_memory](public.instance_ai_observational_memory.md) [public.instance_ai_observations](public.instance_ai_observations.md) [public.instance_ai_pending_confirmations](public.instance_ai_pending_confirmations.md) [public.instance_ai_run_snapshots](public.instance_ai_run_snapshots.md) | | | +| metadata | json | | true | | | | +| projectId | varchar(36) | | false | | [public.project](public.project.md) | Project this thread is scoped to | +| resourceId | varchar(255) | | false | | | | +| title | text | ''::text | false | | | | +| updatedAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| FK_instance_ai_threads_projectId | FOREIGN KEY | FOREIGN KEY ("projectId") REFERENCES project(id) ON DELETE CASCADE | +| PK_35575100e45cdedeb89ae0643e9 | PRIMARY KEY | PRIMARY KEY (id) | +| instance_ai_threads_createdAt_not_null | n | NOT NULL "createdAt" | +| instance_ai_threads_id_not_null | n | NOT NULL id | +| instance_ai_threads_projectId_not_null | n | NOT NULL "projectId" | +| instance_ai_threads_resourceId_not_null | n | NOT NULL "resourceId" | +| instance_ai_threads_title_not_null | n | NOT NULL title | +| instance_ai_threads_updatedAt_not_null | n | NOT NULL "updatedAt" | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_f36dea4d38fe92e0e8f44d5a56 | CREATE INDEX "IDX_f36dea4d38fe92e0e8f44d5a56" ON public.instance_ai_threads USING btree ("resourceId") | +| IDX_instance_ai_threads_projectId | CREATE INDEX "IDX_instance_ai_threads_projectId" ON public.instance_ai_threads USING btree ("projectId") | +| PK_35575100e45cdedeb89ae0643e9 | CREATE UNIQUE INDEX "PK_35575100e45cdedeb89ae0643e9" ON public.instance_ai_threads USING btree (id) | + +## Relations + +```mermaid +erDiagram + +"public.ai_builder_temporary_workflow" }o--|| "public.instance_ai_threads" : "FOREIGN KEY (#quot;threadId#quot;) REFERENCES instance_ai_threads(id) ON DELETE CASCADE" +"public.instance_ai_checkpoints" }o--|| "public.instance_ai_threads" : "FOREIGN KEY (#quot;threadId#quot;) REFERENCES instance_ai_threads(id) ON DELETE CASCADE" +"public.instance_ai_iteration_logs" }o--|| "public.instance_ai_threads" : "FOREIGN KEY (#quot;threadId#quot;) REFERENCES instance_ai_threads(id) ON DELETE CASCADE" +"public.instance_ai_messages" }o--|| "public.instance_ai_threads" : "FOREIGN KEY (#quot;threadId#quot;) REFERENCES instance_ai_threads(id) ON DELETE CASCADE" +"public.instance_ai_observation_cursors" |o--|| "public.instance_ai_threads" : "FOREIGN KEY (#quot;observationScopeId#quot;) REFERENCES instance_ai_threads(id) ON DELETE CASCADE" +"public.instance_ai_observation_locks" }o--|| "public.instance_ai_threads" : "FOREIGN KEY (#quot;observationScopeId#quot;) REFERENCES instance_ai_threads(id) ON DELETE CASCADE" +"public.instance_ai_observational_memory" }o--o| "public.instance_ai_threads" : "FOREIGN KEY (#quot;threadId#quot;) REFERENCES instance_ai_threads(id) ON DELETE SET NULL" +"public.instance_ai_observations" }o--|| "public.instance_ai_threads" : "FOREIGN KEY (#quot;observationScopeId#quot;) REFERENCES instance_ai_threads(id) ON DELETE CASCADE" +"public.instance_ai_pending_confirmations" }o--|| "public.instance_ai_threads" : "FOREIGN KEY (#quot;threadId#quot;) REFERENCES instance_ai_threads(id) ON DELETE CASCADE" +"public.instance_ai_run_snapshots" }o--|| "public.instance_ai_threads" : "FOREIGN KEY (#quot;threadId#quot;) REFERENCES instance_ai_threads(id) ON DELETE CASCADE" +"public.instance_ai_threads" }o--|| "public.project" : "FOREIGN KEY (#quot;projectId#quot;) REFERENCES project(id) ON DELETE CASCADE" + +"public.instance_ai_threads" { + timestamp_3__with_time_zone createdAt + uuid id + json metadata + varchar_36_ projectId FK + varchar_255_ resourceId + text title + timestamp_3__with_time_zone updatedAt +} +"public.ai_builder_temporary_workflow" { + timestamp_3__with_time_zone createdAt + uuid threadId FK + timestamp_3__with_time_zone updatedAt + varchar_36_ workflowId FK +} +"public.instance_ai_checkpoints" { + timestamp_3__with_time_zone createdAt + timestamp_3__with_time_zone expiredAt + varchar_255_ key + varchar_255_ resourceId + varchar_255_ runId + json state + uuid threadId FK + timestamp_3__with_time_zone updatedAt +} +"public.instance_ai_iteration_logs" { + timestamp_3__with_time_zone createdAt + text entry + varchar_36_ id + varchar taskKey + uuid threadId FK + timestamp_3__with_time_zone updatedAt +} +"public.instance_ai_messages" { + text content + timestamp_3__with_time_zone createdAt + varchar_36_ id + varchar_255_ resourceId + varchar_16_ role + uuid threadId FK + varchar_32_ type + timestamp_3__with_time_zone updatedAt +} +"public.instance_ai_observation_cursors" { + timestamp_3__with_time_zone createdAt + timestamp_3__with_time_zone lastObservedAt + varchar_36_ lastObservedMessageId + uuid observationScopeId FK + timestamp_3__with_time_zone updatedAt +} +"public.instance_ai_observation_locks" { + timestamp_3__with_time_zone createdAt + timestamp_3__with_time_zone heldUntil + varchar_64_ holderId + uuid observationScopeId FK + varchar_20_ taskKind + timestamp_3__with_time_zone updatedAt +} +"public.instance_ai_observational_memory" { + text activeObservations + json bufferedMessageIds + json bufferedObservationChunks + integer bufferedObservationTokens + text bufferedObservations + text bufferedReflection + integer bufferedReflectionInputTokens + integer bufferedReflectionTokens + text config + timestamp_3__with_time_zone createdAt + integer generationCount + varchar_36_ id + boolean isBufferingObservation + boolean isBufferingReflection + boolean isObserving + boolean isReflecting + timestamp_3__with_time_zone lastBufferedAtTime + integer lastBufferedAtTokens + timestamp_3__with_time_zone lastObservedAt + varchar_255_ lookupKey + json metadata + integer observationTokenCount + json observedMessageIds + varchar observedTimezone + varchar_32_ originType + integer pendingMessageTokens + integer reflectedObservationLineCount + varchar_255_ resourceId + varchar_16_ scope + uuid threadId FK + integer totalTokensObserved + timestamp_3__with_time_zone updatedAt +} +"public.instance_ai_observations" { + timestamp_3__with_time_zone createdAt + varchar_36_ id + varchar_16_ marker + uuid observationScopeId FK + varchar_36_ parentId FK + varchar_16_ status + varchar_36_ supersededBy FK + text text + integer tokenCount + timestamp_3__with_time_zone updatedAt +} +"public.instance_ai_pending_confirmations" { + varchar_255_ checkpointKey FK + varchar_36_ checkpointTaskId + timestamp_3__with_time_zone createdAt + timestamp_3__with_time_zone expiresAt + varchar_16_ kind + varchar_36_ messageGroupId + varchar_36_ requestId + varchar_36_ runId + uuid threadId FK + varchar_64_ toolCallId + timestamp_3__with_time_zone updatedAt + uuid userId FK +} +"public.instance_ai_run_snapshots" { + timestamp_3__with_time_zone createdAt + varchar_36_ langsmithRunId + varchar_36_ langsmithTraceId + varchar_36_ messageGroupId + varchar_36_ runId + json runIds + varchar_64_ spanId + uuid threadId FK + varchar_64_ traceId + text tree + timestamp_3__with_time_zone updatedAt +} +"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.instance_ai_workflow_snapshots.md b/docs/generated/postgres-schema/public.instance_ai_workflow_snapshots.md new file mode 100644 index 00000000000..fe173d917cd --- /dev/null +++ b/docs/generated/postgres-schema/public.instance_ai_workflow_snapshots.md @@ -0,0 +1,52 @@ +# public.instance_ai_workflow_snapshots + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| createdAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| resourceId | varchar(255) | | true | | | | +| runId | varchar(36) | | false | | | | +| snapshot | text | | false | | | | +| status | varchar | | true | | | | +| updatedAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| workflowName | varchar(255) | | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| PK_93f2696eb321dfe1d7defe7073f | PRIMARY KEY | PRIMARY KEY ("runId", "workflowName") | +| instance_ai_workflow_snapshots_createdAt_not_null | n | NOT NULL "createdAt" | +| instance_ai_workflow_snapshots_runId_not_null | n | NOT NULL "runId" | +| instance_ai_workflow_snapshots_snapshot_not_null | n | NOT NULL snapshot | +| instance_ai_workflow_snapshots_updatedAt_not_null | n | NOT NULL "updatedAt" | +| instance_ai_workflow_snapshots_workflowName_not_null | n | NOT NULL "workflowName" | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_a371ee6b8e0ebb5635f8baa46d | CREATE INDEX "IDX_a371ee6b8e0ebb5635f8baa46d" ON public.instance_ai_workflow_snapshots USING btree ("workflowName", status) | +| PK_93f2696eb321dfe1d7defe7073f | CREATE UNIQUE INDEX "PK_93f2696eb321dfe1d7defe7073f" ON public.instance_ai_workflow_snapshots USING btree ("runId", "workflowName") | + +## Relations + +```mermaid +erDiagram + + +"public.instance_ai_workflow_snapshots" { + timestamp_3__with_time_zone createdAt + varchar_255_ resourceId + varchar_36_ runId + text snapshot + varchar status + timestamp_3__with_time_zone updatedAt + varchar_255_ workflowName +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/postgres-schema/public.instance_version_history.md b/docs/generated/postgres-schema/public.instance_version_history.md new file mode 100644 index 00000000000..36a4dd579e1 --- /dev/null +++ b/docs/generated/postgres-schema/public.instance_version_history.md @@ -0,0 +1,47 @@ +# public.instance_version_history + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| createdAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| id | integer | nextval('instance_version_history_id_seq'::regclass) | false | | | | +| major | integer | | false | | | | +| minor | integer | | false | | | | +| patch | integer | | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| PK_874f58cb616935bf49d9dbd67e9 | PRIMARY KEY | PRIMARY KEY (id) | +| instance_version_history_createdAt_not_null | n | NOT NULL "createdAt" | +| instance_version_history_id_not_null | n | NOT NULL id | +| instance_version_history_major_not_null | n | NOT NULL major | +| instance_version_history_minor_not_null | n | NOT NULL minor | +| instance_version_history_patch_not_null | n | NOT NULL patch | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| PK_874f58cb616935bf49d9dbd67e9 | CREATE UNIQUE INDEX "PK_874f58cb616935bf49d9dbd67e9" ON public.instance_version_history USING btree (id) | + +## Relations + +```mermaid +erDiagram + + +"public.instance_version_history" { + timestamp_3__with_time_zone createdAt + integer id + integer major + integer minor + integer patch +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/postgres-schema/public.invalid_auth_token.md b/docs/generated/postgres-schema/public.invalid_auth_token.md new file mode 100644 index 00000000000..e7be5289387 --- /dev/null +++ b/docs/generated/postgres-schema/public.invalid_auth_token.md @@ -0,0 +1,38 @@ +# public.invalid_auth_token + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| expiresAt | timestamp(3) with time zone | | false | | | | +| token | varchar(512) | | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| PK_5779069b7235b256d91f7af1a15 | PRIMARY KEY | PRIMARY KEY (token) | +| invalid_auth_token_expiresAt_not_null | n | NOT NULL "expiresAt" | +| invalid_auth_token_token_not_null | n | NOT NULL token | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| PK_5779069b7235b256d91f7af1a15 | CREATE UNIQUE INDEX "PK_5779069b7235b256d91f7af1a15" ON public.invalid_auth_token USING btree (token) | + +## Relations + +```mermaid +erDiagram + + +"public.invalid_auth_token" { + timestamp_3__with_time_zone expiresAt + varchar_512_ token +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/postgres-schema/public.mcp_registry_server.md b/docs/generated/postgres-schema/public.mcp_registry_server.md new file mode 100644 index 00000000000..b179f373334 --- /dev/null +++ b/docs/generated/postgres-schema/public.mcp_registry_server.md @@ -0,0 +1,64 @@ +# public.mcp_registry_server + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| createdAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| data | json | '{}'::json | false | | | JSON object containing server metadata (icons, remotes, tools, etc.) | +| registryUpdatedAt | timestamp(3) without time zone | | false | | | | +| slug | varchar(255) | | false | [public.instance_ai_mcp_registry_connections](public.instance_ai_mcp_registry_connections.md) | | | +| status | varchar(50) | | false | | | Server status in the MCP registry. Deprecated servers are not surfaced to users. | +| updatedAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| version | varchar(50) | | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| CHK_tmp_mcp_registry_server_status | CHECK | CHECK (((status)::text = ANY ((ARRAY['active'::character varying, 'deprecated'::character varying])::text[]))) | +| PK_12fd89a1fb8489513b0a91f5d31 | PRIMARY KEY | PRIMARY KEY (slug) | +| tmp_mcp_registry_server_createdAt_not_null | n | NOT NULL "createdAt" | +| tmp_mcp_registry_server_data_not_null | n | NOT NULL data | +| tmp_mcp_registry_server_registryUpdatedAt_not_null | n | NOT NULL "registryUpdatedAt" | +| tmp_mcp_registry_server_slug_not_null | n | NOT NULL slug | +| tmp_mcp_registry_server_status_not_null | n | NOT NULL status | +| tmp_mcp_registry_server_updatedAt_not_null | n | NOT NULL "updatedAt" | +| tmp_mcp_registry_server_version_not_null | n | NOT NULL version | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| PK_12fd89a1fb8489513b0a91f5d31 | CREATE UNIQUE INDEX "PK_12fd89a1fb8489513b0a91f5d31" ON public.mcp_registry_server USING btree (slug) | + +## Relations + +```mermaid +erDiagram + +"public.instance_ai_mcp_registry_connections" }o--|| "public.mcp_registry_server" : "FOREIGN KEY (#quot;serverSlug#quot;) REFERENCES mcp_registry_server(slug) ON DELETE CASCADE" + +"public.mcp_registry_server" { + timestamp_3__with_time_zone createdAt + json data + timestamp_3__without_time_zone registryUpdatedAt + varchar_255_ slug + varchar_50_ status + timestamp_3__with_time_zone updatedAt + varchar_50_ version +} +"public.instance_ai_mcp_registry_connections" { + timestamp_3__with_time_zone createdAt + varchar_36_ credentialId FK + uuid id + varchar_255_ serverSlug FK + json toolFilter + timestamp_3__with_time_zone updatedAt + uuid userId FK +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/postgres-schema/public.oauth_access_tokens.md b/docs/generated/postgres-schema/public.oauth_access_tokens.md new file mode 100644 index 00000000000..fca472ccbd9 --- /dev/null +++ b/docs/generated/postgres-schema/public.oauth_access_tokens.md @@ -0,0 +1,73 @@ +# public.oauth_access_tokens + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| clientId | varchar | | false | | [public.oauth_clients](public.oauth_clients.md) | | +| token | varchar | | false | | | | +| userId | uuid | | false | | [public.user](public.user.md) | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| FK_7234a36d8e49a1fa85095328845 | FOREIGN KEY | FOREIGN KEY ("userId") REFERENCES "user"(id) ON DELETE CASCADE | +| FK_78b26968132b7e5e45b75876481 | FOREIGN KEY | FOREIGN KEY ("clientId") REFERENCES oauth_clients(id) ON DELETE CASCADE | +| PK_dcd71f96a5d5f4bf79e67d322bf | PRIMARY KEY | PRIMARY KEY (token) | +| oauth_access_tokens_clientId_not_null | n | NOT NULL "clientId" | +| oauth_access_tokens_token_not_null | n | NOT NULL token | +| oauth_access_tokens_userId_not_null | n | NOT NULL "userId" | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| PK_dcd71f96a5d5f4bf79e67d322bf | CREATE UNIQUE INDEX "PK_dcd71f96a5d5f4bf79e67d322bf" ON public.oauth_access_tokens USING btree (token) | + +## Relations + +```mermaid +erDiagram + +"public.oauth_access_tokens" }o--|| "public.oauth_clients" : "FOREIGN KEY (#quot;clientId#quot;) REFERENCES oauth_clients(id) ON DELETE CASCADE" +"public.oauth_access_tokens" }o--|| "public.user" : "FOREIGN KEY (#quot;userId#quot;) REFERENCES #quot;user#quot;(id) ON DELETE CASCADE" + +"public.oauth_access_tokens" { + varchar clientId FK + varchar token + uuid userId FK +} +"public.oauth_clients" { + varchar_255_ clientSecret + bigint clientSecretExpiresAt + timestamp_3__with_time_zone createdAt + json grantTypes + varchar id + varchar_255_ name + json redirectUris + varchar_255_ tokenEndpointAuthMethod + timestamp_3__with_time_zone updatedAt +} +"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 +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/postgres-schema/public.oauth_authorization_codes.md b/docs/generated/postgres-schema/public.oauth_authorization_codes.md new file mode 100644 index 00000000000..6ee13ccbf37 --- /dev/null +++ b/docs/generated/postgres-schema/public.oauth_authorization_codes.md @@ -0,0 +1,101 @@ +# public.oauth_authorization_codes + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| clientId | varchar | | false | | [public.oauth_clients](public.oauth_clients.md) | | +| code | varchar(255) | | false | | | | +| codeChallenge | varchar | | false | | | | +| codeChallengeMethod | varchar(255) | | false | | | | +| createdAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| expiresAt | bigint | | false | | | Unix timestamp in milliseconds | +| redirectUri | varchar | | false | | | | +| resource | varchar | | true | | | RFC 8707 resource indicator URI (e.g. https://n8n.example.com/mcp-server/http). NULL = legacy flow predating resource indicator support; defaults to the instance canonical MCP resource URL. | +| scope | json | '["tool:listWorkflows","tool:getWorkflowDetails"]'::json | false | | | OAuth scopes granted for this authorization code | +| state | varchar | | true | | | | +| updatedAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| used | boolean | false | false | | | | +| userId | uuid | | false | | [public.user](public.user.md) | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| FK_64d965bd072ea24fb6da55468cd | FOREIGN KEY | FOREIGN KEY ("clientId") REFERENCES oauth_clients(id) ON DELETE CASCADE | +| FK_aa8d3560484944c19bdf79ffa16 | FOREIGN KEY | FOREIGN KEY ("userId") REFERENCES "user"(id) ON DELETE CASCADE | +| PK_fb91ab932cfbd694061501cc20f | PRIMARY KEY | PRIMARY KEY (code) | +| oauth_authorization_codes_clientId_not_null | n | NOT NULL "clientId" | +| oauth_authorization_codes_codeChallengeMethod_not_null | n | NOT NULL "codeChallengeMethod" | +| oauth_authorization_codes_codeChallenge_not_null | n | NOT NULL "codeChallenge" | +| oauth_authorization_codes_code_not_null | n | NOT NULL code | +| oauth_authorization_codes_createdAt_not_null | n | NOT NULL "createdAt" | +| oauth_authorization_codes_expiresAt_not_null | n | NOT NULL "expiresAt" | +| oauth_authorization_codes_redirectUri_not_null | n | NOT NULL "redirectUri" | +| oauth_authorization_codes_scope_not_null | n | NOT NULL scope | +| oauth_authorization_codes_updatedAt_not_null | n | NOT NULL "updatedAt" | +| oauth_authorization_codes_used_not_null | n | NOT NULL used | +| oauth_authorization_codes_userId_not_null | n | NOT NULL "userId" | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| PK_fb91ab932cfbd694061501cc20f | CREATE UNIQUE INDEX "PK_fb91ab932cfbd694061501cc20f" ON public.oauth_authorization_codes USING btree (code) | + +## Relations + +```mermaid +erDiagram + +"public.oauth_authorization_codes" }o--|| "public.oauth_clients" : "FOREIGN KEY (#quot;clientId#quot;) REFERENCES oauth_clients(id) ON DELETE CASCADE" +"public.oauth_authorization_codes" }o--|| "public.user" : "FOREIGN KEY (#quot;userId#quot;) REFERENCES #quot;user#quot;(id) ON DELETE CASCADE" + +"public.oauth_authorization_codes" { + varchar clientId FK + varchar_255_ code + varchar codeChallenge + varchar_255_ codeChallengeMethod + timestamp_3__with_time_zone createdAt + bigint expiresAt + varchar redirectUri + varchar resource + json scope + varchar state + timestamp_3__with_time_zone updatedAt + boolean used + uuid userId FK +} +"public.oauth_clients" { + varchar_255_ clientSecret + bigint clientSecretExpiresAt + timestamp_3__with_time_zone createdAt + json grantTypes + varchar id + varchar_255_ name + json redirectUris + varchar_255_ tokenEndpointAuthMethod + timestamp_3__with_time_zone updatedAt +} +"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 +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/postgres-schema/public.oauth_clients.md b/docs/generated/postgres-schema/public.oauth_clients.md new file mode 100644 index 00000000000..048d6174523 --- /dev/null +++ b/docs/generated/postgres-schema/public.oauth_clients.md @@ -0,0 +1,96 @@ +# public.oauth_clients + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| clientSecret | varchar(255) | | true | | | | +| clientSecretExpiresAt | bigint | | true | | | | +| createdAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| grantTypes | json | | false | | | | +| id | varchar | | false | [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) | | | +| name | varchar(255) | | false | | | | +| redirectUris | json | | false | | | | +| tokenEndpointAuthMethod | varchar(255) | 'none'::character varying | false | | | Possible values: none, client_secret_basic or client_secret_post | +| updatedAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| PK_c4759172d3431bae6f04e678e0d | PRIMARY KEY | PRIMARY KEY (id) | +| oauth_clients_createdAt_not_null | n | NOT NULL "createdAt" | +| oauth_clients_grantTypes_not_null | n | NOT NULL "grantTypes" | +| oauth_clients_id_not_null | n | NOT NULL id | +| oauth_clients_name_not_null | n | NOT NULL name | +| oauth_clients_redirectUris_not_null | n | NOT NULL "redirectUris" | +| oauth_clients_tokenEndpointAuthMethod_not_null | n | NOT NULL "tokenEndpointAuthMethod" | +| oauth_clients_updatedAt_not_null | n | NOT NULL "updatedAt" | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| PK_c4759172d3431bae6f04e678e0d | CREATE UNIQUE INDEX "PK_c4759172d3431bae6f04e678e0d" ON public.oauth_clients USING btree (id) | + +## Relations + +```mermaid +erDiagram + +"public.oauth_access_tokens" }o--|| "public.oauth_clients" : "FOREIGN KEY (#quot;clientId#quot;) REFERENCES oauth_clients(id) ON DELETE CASCADE" +"public.oauth_authorization_codes" }o--|| "public.oauth_clients" : "FOREIGN KEY (#quot;clientId#quot;) REFERENCES oauth_clients(id) ON DELETE CASCADE" +"public.oauth_refresh_tokens" }o--|| "public.oauth_clients" : "FOREIGN KEY (#quot;clientId#quot;) REFERENCES oauth_clients(id) ON DELETE CASCADE" +"public.oauth_user_consents" }o--|| "public.oauth_clients" : "FOREIGN KEY (#quot;clientId#quot;) REFERENCES oauth_clients(id) ON DELETE CASCADE" + +"public.oauth_clients" { + varchar_255_ clientSecret + bigint clientSecretExpiresAt + timestamp_3__with_time_zone createdAt + json grantTypes + varchar id + varchar_255_ name + json redirectUris + varchar_255_ tokenEndpointAuthMethod + timestamp_3__with_time_zone updatedAt +} +"public.oauth_access_tokens" { + varchar clientId FK + varchar token + uuid userId FK +} +"public.oauth_authorization_codes" { + varchar clientId FK + varchar_255_ code + varchar codeChallenge + varchar_255_ codeChallengeMethod + timestamp_3__with_time_zone createdAt + bigint expiresAt + varchar redirectUri + varchar resource + json scope + varchar state + timestamp_3__with_time_zone updatedAt + boolean used + uuid userId FK +} +"public.oauth_refresh_tokens" { + varchar clientId FK + timestamp_3__with_time_zone createdAt + bigint expiresAt + json scope + varchar_255_ token + timestamp_3__with_time_zone updatedAt + uuid userId FK +} +"public.oauth_user_consents" { + varchar clientId FK + bigint grantedAt + integer id + uuid userId FK +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/postgres-schema/public.oauth_refresh_tokens.md b/docs/generated/postgres-schema/public.oauth_refresh_tokens.md new file mode 100644 index 00000000000..cafa6fe353d --- /dev/null +++ b/docs/generated/postgres-schema/public.oauth_refresh_tokens.md @@ -0,0 +1,85 @@ +# public.oauth_refresh_tokens + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| clientId | varchar | | false | | [public.oauth_clients](public.oauth_clients.md) | | +| createdAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| expiresAt | bigint | | false | | | Unix timestamp in milliseconds | +| scope | json | '["tool:listWorkflows","tool:getWorkflowDetails"]'::json | false | | | OAuth scopes granted for this refresh token | +| token | varchar(255) | | false | | | | +| updatedAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| userId | uuid | | false | | [public.user](public.user.md) | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| FK_a699f3ed9fd0c1b19bc2608ac53 | FOREIGN KEY | FOREIGN KEY ("userId") REFERENCES "user"(id) ON DELETE CASCADE | +| FK_b388696ce4d8be7ffbe8d3e4b69 | FOREIGN KEY | FOREIGN KEY ("clientId") REFERENCES oauth_clients(id) ON DELETE CASCADE | +| PK_74abaed0b30711b6532598b0392 | PRIMARY KEY | PRIMARY KEY (token) | +| oauth_refresh_tokens_clientId_not_null | n | NOT NULL "clientId" | +| oauth_refresh_tokens_createdAt_not_null | n | NOT NULL "createdAt" | +| oauth_refresh_tokens_expiresAt_not_null | n | NOT NULL "expiresAt" | +| oauth_refresh_tokens_scope_not_null | n | NOT NULL scope | +| oauth_refresh_tokens_token_not_null | n | NOT NULL token | +| oauth_refresh_tokens_updatedAt_not_null | n | NOT NULL "updatedAt" | +| oauth_refresh_tokens_userId_not_null | n | NOT NULL "userId" | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| PK_74abaed0b30711b6532598b0392 | CREATE UNIQUE INDEX "PK_74abaed0b30711b6532598b0392" ON public.oauth_refresh_tokens USING btree (token) | + +## Relations + +```mermaid +erDiagram + +"public.oauth_refresh_tokens" }o--|| "public.oauth_clients" : "FOREIGN KEY (#quot;clientId#quot;) REFERENCES oauth_clients(id) ON DELETE CASCADE" +"public.oauth_refresh_tokens" }o--|| "public.user" : "FOREIGN KEY (#quot;userId#quot;) REFERENCES #quot;user#quot;(id) ON DELETE CASCADE" + +"public.oauth_refresh_tokens" { + varchar clientId FK + timestamp_3__with_time_zone createdAt + bigint expiresAt + json scope + varchar_255_ token + timestamp_3__with_time_zone updatedAt + uuid userId FK +} +"public.oauth_clients" { + varchar_255_ clientSecret + bigint clientSecretExpiresAt + timestamp_3__with_time_zone createdAt + json grantTypes + varchar id + varchar_255_ name + json redirectUris + varchar_255_ tokenEndpointAuthMethod + timestamp_3__with_time_zone updatedAt +} +"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 +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/postgres-schema/public.oauth_user_consents.md b/docs/generated/postgres-schema/public.oauth_user_consents.md new file mode 100644 index 00000000000..941d21584a1 --- /dev/null +++ b/docs/generated/postgres-schema/public.oauth_user_consents.md @@ -0,0 +1,78 @@ +# public.oauth_user_consents + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| clientId | varchar | | false | | [public.oauth_clients](public.oauth_clients.md) | | +| grantedAt | bigint | | false | | | Unix timestamp in milliseconds | +| id | integer | | false | | | | +| userId | uuid | | false | | [public.user](public.user.md) | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| FK_21e6c3c2d78a097478fae6aaefa | FOREIGN KEY | FOREIGN KEY ("userId") REFERENCES "user"(id) ON DELETE CASCADE | +| FK_a651acea2f6c97f8c4514935486 | FOREIGN KEY | FOREIGN KEY ("clientId") REFERENCES oauth_clients(id) ON DELETE CASCADE | +| PK_85b9ada746802c8993103470f05 | PRIMARY KEY | PRIMARY KEY (id) | +| UQ_083721d99ce8db4033e2958ebb4 | UNIQUE | UNIQUE ("userId", "clientId") | +| oauth_user_consents_clientId_not_null | n | NOT NULL "clientId" | +| oauth_user_consents_grantedAt_not_null | n | NOT NULL "grantedAt" | +| oauth_user_consents_id_not_null | n | NOT NULL id | +| oauth_user_consents_userId_not_null | n | NOT NULL "userId" | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| PK_85b9ada746802c8993103470f05 | CREATE UNIQUE INDEX "PK_85b9ada746802c8993103470f05" ON public.oauth_user_consents USING btree (id) | +| UQ_083721d99ce8db4033e2958ebb4 | CREATE UNIQUE INDEX "UQ_083721d99ce8db4033e2958ebb4" ON public.oauth_user_consents USING btree ("userId", "clientId") | + +## Relations + +```mermaid +erDiagram + +"public.oauth_user_consents" }o--|| "public.oauth_clients" : "FOREIGN KEY (#quot;clientId#quot;) REFERENCES oauth_clients(id) ON DELETE CASCADE" +"public.oauth_user_consents" }o--|| "public.user" : "FOREIGN KEY (#quot;userId#quot;) REFERENCES #quot;user#quot;(id) ON DELETE CASCADE" + +"public.oauth_user_consents" { + varchar clientId FK + bigint grantedAt + integer id + uuid userId FK +} +"public.oauth_clients" { + varchar_255_ clientSecret + bigint clientSecretExpiresAt + timestamp_3__with_time_zone createdAt + json grantTypes + varchar id + varchar_255_ name + json redirectUris + varchar_255_ tokenEndpointAuthMethod + timestamp_3__with_time_zone updatedAt +} +"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 +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/postgres-schema/public.processed_data.md b/docs/generated/postgres-schema/public.processed_data.md new file mode 100644 index 00000000000..c2a34513103 --- /dev/null +++ b/docs/generated/postgres-schema/public.processed_data.md @@ -0,0 +1,71 @@ +# public.processed_data + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| context | varchar(255) | | false | | | | +| createdAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| updatedAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| value | text | | false | | | | +| workflowId | varchar(36) | | false | | [public.workflow_entity](public.workflow_entity.md) | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| FK_06a69a7032c97a763c2c7599464 | FOREIGN KEY | FOREIGN KEY ("workflowId") REFERENCES workflow_entity(id) ON DELETE CASCADE | +| PK_ca04b9d8dc72de268fe07a65773 | PRIMARY KEY | PRIMARY KEY ("workflowId", context) | +| processed_data_context_not_null | n | NOT NULL context | +| processed_data_createdAt_not_null | n | NOT NULL "createdAt" | +| processed_data_updatedAt_not_null | n | NOT NULL "updatedAt" | +| processed_data_value_not_null | n | NOT NULL value | +| processed_data_workflowId_not_null | n | NOT NULL "workflowId" | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| PK_ca04b9d8dc72de268fe07a65773 | CREATE UNIQUE INDEX "PK_ca04b9d8dc72de268fe07a65773" ON public.processed_data USING btree ("workflowId", context) | + +## Relations + +```mermaid +erDiagram + +"public.processed_data" }o--|| "public.workflow_entity" : "FOREIGN KEY (#quot;workflowId#quot;) REFERENCES workflow_entity(id) ON DELETE CASCADE" + +"public.processed_data" { + varchar_255_ context + timestamp_3__with_time_zone createdAt + timestamp_3__with_time_zone updatedAt + text value + varchar_36_ workflowId FK +} +"public.workflow_entity" { + boolean active + varchar_36_ activeVersionId FK + json connections + timestamp_3__with_time_zone createdAt + text description + varchar_36_ id + boolean isArchived + json meta + varchar_128_ name + json nodeGroups + json nodes + varchar_36_ parentFolderId FK + json pinData + json settings + varchar sourceWorkflowId + json staticData + integer triggerCount + timestamp_3__with_time_zone updatedAt + integer versionCounter + character_36_ versionId +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/postgres-schema/public.project.md b/docs/generated/postgres-schema/public.project.md new file mode 100644 index 00000000000..62d17ac49ba --- /dev/null +++ b/docs/generated/postgres-schema/public.project.md @@ -0,0 +1,190 @@ +# public.project + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| createdAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| creatorId | uuid | | true | | [public.user](public.user.md) | ID of the user who created the project | +| customTelemetryTags | json | '[]'::json | false | | | | +| description | varchar(512) | | true | | | | +| icon | json | | true | | | | +| id | varchar(36) | | false | [public.agent_execution_threads](public.agent_execution_threads.md) [public.agents](public.agents.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_relation](public.project_relation.md) [public.project_secrets_provider_access](public.project_secrets_provider_access.md) [public.role_mapping_rule_project](public.role_mapping_rule_project.md) [public.shared_credentials](public.shared_credentials.md) [public.shared_workflow](public.shared_workflow.md) [public.variables](public.variables.md) | | | +| name | varchar(255) | | false | | | | +| type | varchar(36) | | false | | | | +| updatedAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| PK_4d68b1358bb5b766d3e78f32f57 | PRIMARY KEY | PRIMARY KEY (id) | +| project_createdAt_not_null | n | NOT NULL "createdAt" | +| project_customTelemetryTags_not_null | n | NOT NULL "customTelemetryTags" | +| project_id_not_null | n | NOT NULL id | +| project_name_not_null | n | NOT NULL name | +| project_type_not_null | n | NOT NULL type | +| project_updatedAt_not_null | n | NOT NULL "updatedAt" | +| projects_creatorId_foreign | FOREIGN KEY | FOREIGN KEY ("creatorId") REFERENCES "user"(id) ON DELETE SET NULL | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| PK_4d68b1358bb5b766d3e78f32f57 | CREATE UNIQUE INDEX "PK_4d68b1358bb5b766d3e78f32f57" ON public.project USING btree (id) | + +## Relations + +```mermaid +erDiagram + +"public.project" }o--o| "public.user" : "FOREIGN KEY (#quot;creatorId#quot;) REFERENCES #quot;user#quot;(id) ON DELETE SET NULL" +"public.agent_execution_threads" }o--|| "public.project" : "FOREIGN KEY (#quot;projectId#quot;) REFERENCES project(id) ON DELETE CASCADE" +"public.agents" }o--|| "public.project" : "FOREIGN KEY (#quot;projectId#quot;) REFERENCES project(id) ON DELETE CASCADE" +"public.data_table" }o--|| "public.project" : "FOREIGN KEY (#quot;projectId#quot;) REFERENCES project(id) ON DELETE CASCADE" +"public.folder" }o--|| "public.project" : "FOREIGN KEY (#quot;projectId#quot;) REFERENCES project(id) ON DELETE CASCADE" +"public.insights_metadata" }o--o| "public.project" : "FOREIGN KEY (#quot;projectId#quot;) REFERENCES project(id) ON DELETE SET NULL" +"public.instance_ai_threads" }o--|| "public.project" : "FOREIGN KEY (#quot;projectId#quot;) REFERENCES project(id) ON DELETE CASCADE" +"public.project_relation" }o--|| "public.project" : "FOREIGN KEY (#quot;projectId#quot;) REFERENCES project(id) ON DELETE CASCADE" +"public.project_secrets_provider_access" }o--|| "public.project" : "FOREIGN KEY (#quot;projectId#quot;) REFERENCES project(id) ON DELETE CASCADE" +"public.role_mapping_rule_project" }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.variables" }o--o| "public.project" : "FOREIGN KEY (#quot;projectId#quot;) REFERENCES project(id) ON DELETE CASCADE" + +"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 +} +"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_execution_threads" { + varchar_36_ agentId FK + varchar_255_ agentName + timestamp_3__with_time_zone createdAt + varchar_8_ emoji + varchar_128_ id + varchar_36_ parentAgentId + varchar_128_ parentThreadId + varchar_255_ projectId FK + integer sessionNumber + varchar_32_ taskId + varchar_36_ taskVersionId FK + varchar_255_ title + integer totalCompletionTokens + double_precision totalCost + integer totalDuration + integer totalPromptTokens + timestamp_3__with_time_zone updatedAt +} +"public.agents" { + varchar_36_ activeVersionId FK + timestamp_3__with_time_zone createdAt + varchar_512_ description + varchar_36_ id + json integrations + varchar_128_ name + varchar_255_ projectId FK + json schema + json skills + json tools + timestamp_3__with_time_zone updatedAt + varchar_36_ versionId +} +"public.data_table" { + timestamp_3__with_time_zone createdAt + varchar_36_ id + varchar_128_ name + varchar_36_ projectId FK + timestamp_3__with_time_zone updatedAt +} +"public.folder" { + timestamp_3__with_time_zone createdAt + varchar_36_ id + varchar_128_ name + varchar_36_ parentFolderId FK + varchar_36_ projectId FK + timestamp_3__with_time_zone updatedAt +} +"public.insights_metadata" { + integer metaId + varchar_36_ projectId FK + varchar_255_ projectName + varchar_36_ workflowId FK + varchar_128_ workflowName +} +"public.instance_ai_threads" { + timestamp_3__with_time_zone createdAt + uuid id + json metadata + varchar_36_ projectId FK + varchar_255_ resourceId + text title + timestamp_3__with_time_zone updatedAt +} +"public.project_relation" { + timestamp_3__with_time_zone createdAt + varchar_36_ projectId FK + varchar role FK + timestamp_3__with_time_zone updatedAt + uuid userId FK +} +"public.project_secrets_provider_access" { + timestamp_3__with_time_zone createdAt + varchar_36_ projectId FK + varchar_128_ role + integer secretsProviderConnectionId FK + timestamp_3__with_time_zone updatedAt +} +"public.role_mapping_rule_project" { + varchar_36_ projectId FK + varchar_16_ roleMappingRuleId FK +} +"public.shared_credentials" { + timestamp_3__with_time_zone createdAt + varchar_36_ credentialsId FK + varchar_36_ projectId FK + text role + timestamp_3__with_time_zone updatedAt +} +"public.shared_workflow" { + timestamp_3__with_time_zone createdAt + varchar_36_ projectId FK + text role + timestamp_3__with_time_zone updatedAt + varchar_36_ workflowId FK +} +"public.variables" { + varchar_36_ id + varchar_50_ key + varchar_36_ projectId FK + varchar_50_ type + text value +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/postgres-schema/public.project_relation.md b/docs/generated/postgres-schema/public.project_relation.md new file mode 100644 index 00000000000..d6e00a2bcb7 --- /dev/null +++ b/docs/generated/postgres-schema/public.project_relation.md @@ -0,0 +1,94 @@ +# public.project_relation + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| createdAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| projectId | varchar(36) | | false | | [public.project](public.project.md) | | +| role | varchar | | false | | [public.role](public.role.md) | | +| updatedAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| userId | uuid | | false | | [public.user](public.user.md) | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| FK_5f0643f6717905a05164090dde7 | FOREIGN KEY | FOREIGN KEY ("userId") REFERENCES "user"(id) ON DELETE CASCADE | +| FK_61448d56d61802b5dfde5cdb002 | FOREIGN KEY | FOREIGN KEY ("projectId") REFERENCES project(id) ON DELETE CASCADE | +| FK_c6b99592dc96b0d836d7a21db91 | FOREIGN KEY | FOREIGN KEY (role) REFERENCES role(slug) | +| PK_1caaa312a5d7184a003be0f0cb6 | PRIMARY KEY | PRIMARY KEY ("projectId", "userId") | +| project_relation_createdAt_not_null | n | NOT NULL "createdAt" | +| project_relation_projectId_not_null | n | NOT NULL "projectId" | +| project_relation_role_not_null | n | NOT NULL role | +| project_relation_updatedAt_not_null | n | NOT NULL "updatedAt" | +| project_relation_userId_not_null | n | NOT NULL "userId" | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_5f0643f6717905a05164090dde | CREATE INDEX "IDX_5f0643f6717905a05164090dde" ON public.project_relation USING btree ("userId") | +| IDX_61448d56d61802b5dfde5cdb00 | CREATE INDEX "IDX_61448d56d61802b5dfde5cdb00" ON public.project_relation USING btree ("projectId") | +| PK_1caaa312a5d7184a003be0f0cb6 | CREATE UNIQUE INDEX "PK_1caaa312a5d7184a003be0f0cb6" ON public.project_relation USING btree ("projectId", "userId") | +| project_relation_role_idx | CREATE INDEX project_relation_role_idx ON public.project_relation USING btree (role) | +| project_relation_role_project_idx | CREATE INDEX project_relation_role_project_idx ON public.project_relation USING btree ("projectId", role) | + +## Relations + +```mermaid +erDiagram + +"public.project_relation" }o--|| "public.project" : "FOREIGN KEY (#quot;projectId#quot;) REFERENCES project(id) ON DELETE CASCADE" +"public.project_relation" }o--|| "public.role" : "FOREIGN KEY (role) REFERENCES role(slug)" +"public.project_relation" }o--|| "public.user" : "FOREIGN KEY (#quot;userId#quot;) REFERENCES #quot;user#quot;(id) ON DELETE CASCADE" + +"public.project_relation" { + timestamp_3__with_time_zone createdAt + varchar_36_ projectId FK + varchar role FK + timestamp_3__with_time_zone updatedAt + uuid userId FK +} +"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 +} +"public.role" { + timestamp_3__with_time_zone createdAt + text description + text displayName + text roleType + varchar_128_ slug + boolean systemRole + timestamp_3__with_time_zone updatedAt +} +"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 +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/postgres-schema/public.project_secrets_provider_access.md b/docs/generated/postgres-schema/public.project_secrets_provider_access.md new file mode 100644 index 00000000000..c26f934b93f --- /dev/null +++ b/docs/generated/postgres-schema/public.project_secrets_provider_access.md @@ -0,0 +1,72 @@ +# public.project_secrets_provider_access + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| createdAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| projectId | varchar(36) | | false | | [public.project](public.project.md) | | +| role | varchar(128) | 'secretsProviderConnection:user'::character varying | false | | | | +| secretsProviderConnectionId | integer | | false | | [public.secrets_provider_connection](public.secrets_provider_connection.md) | | +| updatedAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| CHK_project_secrets_provider_access_role | CHECK | CHECK (((role)::text = ANY ((ARRAY['secretsProviderConnection:owner'::character varying, 'secretsProviderConnection:user'::character varying])::text[]))) | +| FK_18e5c27d2524b1638b292904e48 | FOREIGN KEY | FOREIGN KEY ("secretsProviderConnectionId") REFERENCES secrets_provider_connection(id) ON DELETE CASCADE | +| FK_bd264b81209355b543878deedb1 | FOREIGN KEY | FOREIGN KEY ("projectId") REFERENCES project(id) ON DELETE CASCADE | +| PK_0402b7fcec5415246656f102f83 | PRIMARY KEY | PRIMARY KEY ("secretsProviderConnectionId", "projectId") | +| project_secrets_provider_ac_secretsProviderConnectionI_not_null | n | NOT NULL "secretsProviderConnectionId" | +| project_secrets_provider_access_createdAt_not_null | n | NOT NULL "createdAt" | +| project_secrets_provider_access_projectId_not_null | n | NOT NULL "projectId" | +| project_secrets_provider_access_role_not_null | n | NOT NULL role | +| project_secrets_provider_access_updatedAt_not_null | n | NOT NULL "updatedAt" | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| PK_0402b7fcec5415246656f102f83 | CREATE UNIQUE INDEX "PK_0402b7fcec5415246656f102f83" ON public.project_secrets_provider_access USING btree ("secretsProviderConnectionId", "projectId") | + +## Relations + +```mermaid +erDiagram + +"public.project_secrets_provider_access" }o--|| "public.project" : "FOREIGN KEY (#quot;projectId#quot;) REFERENCES project(id) ON DELETE CASCADE" +"public.project_secrets_provider_access" }o--|| "public.secrets_provider_connection" : "FOREIGN KEY (#quot;secretsProviderConnectionId#quot;) REFERENCES secrets_provider_connection(id) ON DELETE CASCADE" + +"public.project_secrets_provider_access" { + timestamp_3__with_time_zone createdAt + varchar_36_ projectId FK + varchar_128_ role + integer secretsProviderConnectionId FK + timestamp_3__with_time_zone updatedAt +} +"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 +} +"public.secrets_provider_connection" { + timestamp_3__with_time_zone createdAt + text encryptedSettings + integer id + boolean isEnabled + varchar_128_ providerKey + 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.role.md b/docs/generated/postgres-schema/public.role.md new file mode 100644 index 00000000000..2a6792b2453 --- /dev/null +++ b/docs/generated/postgres-schema/public.role.md @@ -0,0 +1,92 @@ +# public.role + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| createdAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| description | text | | true | | | Text describing the scope in more detail of users | +| displayName | text | | true | | | Name used to display in the UI | +| roleType | text | | true | | | Type of the role, e.g., global, project, or workflow | +| slug | varchar(128) | | false | [public.project_relation](public.project_relation.md) [public.role_mapping_rule](public.role_mapping_rule.md) [public.role_scope](public.role_scope.md) [public.user](public.user.md) | | Unique identifier of the role for example: "global:owner" | +| systemRole | boolean | false | false | | | Indicates if the role is managed by the system and cannot be edited | +| updatedAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| PK_35c9b140caaf6da09cfabb0d675 | PRIMARY KEY | PRIMARY KEY (slug) | +| role_createdAt_not_null | n | NOT NULL "createdAt" | +| role_slug_not_null | n | NOT NULL slug | +| role_systemRole_not_null | n | NOT NULL "systemRole" | +| role_updatedAt_not_null | n | NOT NULL "updatedAt" | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_UniqueRoleDisplayName | CREATE UNIQUE INDEX "IDX_UniqueRoleDisplayName" ON public.role USING btree ("displayName") | +| PK_35c9b140caaf6da09cfabb0d675 | CREATE UNIQUE INDEX "PK_35c9b140caaf6da09cfabb0d675" ON public.role USING btree (slug) | + +## Relations + +```mermaid +erDiagram + +"public.project_relation" }o--|| "public.role" : "FOREIGN KEY (role) REFERENCES role(slug)" +"public.role_mapping_rule" }o--|| "public.role" : "FOREIGN KEY (role) REFERENCES role(slug) ON UPDATE CASCADE ON DELETE CASCADE" +"public.role_scope" }o--|| "public.role" : "FOREIGN KEY (#quot;roleSlug#quot;) REFERENCES role(slug) ON UPDATE CASCADE ON DELETE CASCADE" +"public.user" }o--|| "public.role" : "FOREIGN KEY (#quot;roleSlug#quot;) REFERENCES role(slug)" + +"public.role" { + timestamp_3__with_time_zone createdAt + text description + text displayName + text roleType + varchar_128_ slug + boolean systemRole + timestamp_3__with_time_zone updatedAt +} +"public.project_relation" { + timestamp_3__with_time_zone createdAt + varchar_36_ projectId FK + varchar role FK + timestamp_3__with_time_zone updatedAt + uuid userId FK +} +"public.role_mapping_rule" { + timestamp_3__with_time_zone createdAt + text expression + varchar_16_ id + integer order + varchar_128_ role FK + varchar_64_ type + timestamp_3__with_time_zone updatedAt +} +"public.role_scope" { + varchar_128_ roleSlug FK + varchar_128_ scopeSlug FK +} +"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 +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/postgres-schema/public.role_mapping_rule.md b/docs/generated/postgres-schema/public.role_mapping_rule.md new file mode 100644 index 00000000000..b5ababde582 --- /dev/null +++ b/docs/generated/postgres-schema/public.role_mapping_rule.md @@ -0,0 +1,72 @@ +# public.role_mapping_rule + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| createdAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| expression | text | | false | | | | +| id | varchar(16) | | false | [public.role_mapping_rule_project](public.role_mapping_rule_project.md) | | | +| order | integer | | false | | | | +| role | varchar(128) | | false | | [public.role](public.role.md) | | +| type | varchar(64) | | false | | | Expected values: 'instance' (maps to a global role) or 'project' (maps to a project role; projects linked via role_mapping_rule_project). | +| updatedAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| FK_bb66e404c35996b0d6946177501 | FOREIGN KEY | FOREIGN KEY (role) REFERENCES role(slug) ON UPDATE CASCADE ON DELETE CASCADE | +| PK_d772c8ec1a89b52d31c882bc560 | PRIMARY KEY | PRIMARY KEY (id) | +| UQ_b33ac896ad3099fc8de36fdc1c4 | UNIQUE | UNIQUE (type, "order") | +| role_mapping_rule_createdAt_not_null | n | NOT NULL "createdAt" | +| role_mapping_rule_expression_not_null | n | NOT NULL expression | +| role_mapping_rule_id_not_null | n | NOT NULL id | +| role_mapping_rule_order_not_null | n | NOT NULL "order" | +| role_mapping_rule_role_not_null | n | NOT NULL role | +| role_mapping_rule_type_not_null | n | NOT NULL type | +| role_mapping_rule_updatedAt_not_null | n | NOT NULL "updatedAt" | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_bb66e404c35996b0d694617750 | CREATE INDEX "IDX_bb66e404c35996b0d694617750" ON public.role_mapping_rule USING btree (role) | +| PK_d772c8ec1a89b52d31c882bc560 | CREATE UNIQUE INDEX "PK_d772c8ec1a89b52d31c882bc560" ON public.role_mapping_rule USING btree (id) | +| UQ_b33ac896ad3099fc8de36fdc1c4 | CREATE UNIQUE INDEX "UQ_b33ac896ad3099fc8de36fdc1c4" ON public.role_mapping_rule USING btree (type, "order") | + +## Relations + +```mermaid +erDiagram + +"public.role_mapping_rule_project" }o--|| "public.role_mapping_rule" : "FOREIGN KEY (#quot;roleMappingRuleId#quot;) REFERENCES role_mapping_rule(id) ON DELETE CASCADE" +"public.role_mapping_rule" }o--|| "public.role" : "FOREIGN KEY (role) REFERENCES role(slug) ON UPDATE CASCADE ON DELETE CASCADE" + +"public.role_mapping_rule" { + timestamp_3__with_time_zone createdAt + text expression + varchar_16_ id + integer order + varchar_128_ role FK + varchar_64_ type + timestamp_3__with_time_zone updatedAt +} +"public.role_mapping_rule_project" { + varchar_36_ projectId FK + varchar_16_ roleMappingRuleId FK +} +"public.role" { + timestamp_3__with_time_zone createdAt + text description + text displayName + text roleType + varchar_128_ slug + boolean systemRole + timestamp_3__with_time_zone updatedAt +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/postgres-schema/public.role_mapping_rule_project.md b/docs/generated/postgres-schema/public.role_mapping_rule_project.md new file mode 100644 index 00000000000..7d8b4899277 --- /dev/null +++ b/docs/generated/postgres-schema/public.role_mapping_rule_project.md @@ -0,0 +1,63 @@ +# public.role_mapping_rule_project + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| projectId | varchar(36) | | false | | [public.project](public.project.md) | | +| roleMappingRuleId | varchar(16) | | false | | [public.role_mapping_rule](public.role_mapping_rule.md) | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| FK_35a78869286c65d9330d02b88f5 | FOREIGN KEY | FOREIGN KEY ("projectId") REFERENCES project(id) ON DELETE CASCADE | +| FK_dd7ce4dfa09e95b36a626bd9de3 | FOREIGN KEY | FOREIGN KEY ("roleMappingRuleId") REFERENCES role_mapping_rule(id) ON DELETE CASCADE | +| PK_198c5b5aea509d139274efcaf9a | PRIMARY KEY | PRIMARY KEY ("roleMappingRuleId", "projectId") | +| role_mapping_rule_project_projectId_not_null | n | NOT NULL "projectId" | +| role_mapping_rule_project_roleMappingRuleId_not_null | n | NOT NULL "roleMappingRuleId" | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_35a78869286c65d9330d02b88f | CREATE INDEX "IDX_35a78869286c65d9330d02b88f" ON public.role_mapping_rule_project USING btree ("projectId") | +| PK_198c5b5aea509d139274efcaf9a | CREATE UNIQUE INDEX "PK_198c5b5aea509d139274efcaf9a" ON public.role_mapping_rule_project USING btree ("roleMappingRuleId", "projectId") | + +## Relations + +```mermaid +erDiagram + +"public.role_mapping_rule_project" }o--|| "public.project" : "FOREIGN KEY (#quot;projectId#quot;) REFERENCES project(id) ON DELETE CASCADE" +"public.role_mapping_rule_project" }o--|| "public.role_mapping_rule" : "FOREIGN KEY (#quot;roleMappingRuleId#quot;) REFERENCES role_mapping_rule(id) ON DELETE CASCADE" + +"public.role_mapping_rule_project" { + varchar_36_ projectId FK + varchar_16_ roleMappingRuleId FK +} +"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 +} +"public.role_mapping_rule" { + timestamp_3__with_time_zone createdAt + text expression + varchar_16_ id + integer order + varchar_128_ role FK + varchar_64_ type + timestamp_3__with_time_zone updatedAt +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/postgres-schema/public.role_scope.md b/docs/generated/postgres-schema/public.role_scope.md new file mode 100644 index 00000000000..4a587a2259c --- /dev/null +++ b/docs/generated/postgres-schema/public.role_scope.md @@ -0,0 +1,57 @@ +# public.role_scope + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| roleSlug | varchar(128) | | false | | [public.role](public.role.md) | | +| scopeSlug | varchar(128) | | false | | [public.scope](public.scope.md) | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| FK_role | FOREIGN KEY | FOREIGN KEY ("roleSlug") REFERENCES role(slug) ON UPDATE CASCADE ON DELETE CASCADE | +| FK_scope | FOREIGN KEY | FOREIGN KEY ("scopeSlug") REFERENCES scope(slug) ON UPDATE CASCADE ON DELETE CASCADE | +| PK_role_scope | PRIMARY KEY | PRIMARY KEY ("roleSlug", "scopeSlug") | +| role_scope_roleSlug_not_null | n | NOT NULL "roleSlug" | +| role_scope_scopeSlug_not_null | n | NOT NULL "scopeSlug" | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_role_scope_scopeSlug | CREATE INDEX "IDX_role_scope_scopeSlug" ON public.role_scope USING btree ("scopeSlug") | +| PK_role_scope | CREATE UNIQUE INDEX "PK_role_scope" ON public.role_scope USING btree ("roleSlug", "scopeSlug") | + +## Relations + +```mermaid +erDiagram + +"public.role_scope" }o--|| "public.role" : "FOREIGN KEY (#quot;roleSlug#quot;) REFERENCES role(slug) ON UPDATE CASCADE ON DELETE CASCADE" +"public.role_scope" }o--|| "public.scope" : "FOREIGN KEY (#quot;scopeSlug#quot;) REFERENCES scope(slug) ON UPDATE CASCADE ON DELETE CASCADE" + +"public.role_scope" { + varchar_128_ roleSlug FK + varchar_128_ scopeSlug FK +} +"public.role" { + timestamp_3__with_time_zone createdAt + text description + text displayName + text roleType + varchar_128_ slug + boolean systemRole + timestamp_3__with_time_zone updatedAt +} +"public.scope" { + text description + text displayName + varchar_128_ slug +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/postgres-schema/public.scope.md b/docs/generated/postgres-schema/public.scope.md new file mode 100644 index 00000000000..208e447d5ea --- /dev/null +++ b/docs/generated/postgres-schema/public.scope.md @@ -0,0 +1,44 @@ +# public.scope + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| description | text | | true | | | Text describing the scope in more detail of users | +| displayName | text | | true | | | Name used to display in the UI | +| slug | varchar(128) | | false | [public.role_scope](public.role_scope.md) | | Unique identifier of the scope for example: "project:create" | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| PK_bfc45df0481abd7f355d6187da1 | PRIMARY KEY | PRIMARY KEY (slug) | +| scope_slug_not_null | n | NOT NULL slug | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| PK_bfc45df0481abd7f355d6187da1 | CREATE UNIQUE INDEX "PK_bfc45df0481abd7f355d6187da1" ON public.scope USING btree (slug) | + +## Relations + +```mermaid +erDiagram + +"public.role_scope" }o--|| "public.scope" : "FOREIGN KEY (#quot;scopeSlug#quot;) REFERENCES scope(slug) ON UPDATE CASCADE ON DELETE CASCADE" + +"public.scope" { + text description + text displayName + varchar_128_ slug +} +"public.role_scope" { + varchar_128_ roleSlug FK + varchar_128_ scopeSlug FK +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/postgres-schema/public.secrets_provider_connection.md b/docs/generated/postgres-schema/public.secrets_provider_connection.md new file mode 100644 index 00000000000..960d145a80d --- /dev/null +++ b/docs/generated/postgres-schema/public.secrets_provider_connection.md @@ -0,0 +1,62 @@ +# public.secrets_provider_connection + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| createdAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| encryptedSettings | text | | false | | | | +| id | integer | | false | [public.project_secrets_provider_access](public.project_secrets_provider_access.md) | | | +| isEnabled | boolean | false | false | | | | +| providerKey | varchar(128) | | false | | | | +| type | varchar(36) | | false | | | Type of secrets provider. Possible values: awsSecretsManager, gcpSecretsManager, vault, azureKeyVault, infisical | +| updatedAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| PK_4350ae85e76f9ba7df1370acb5d | PRIMARY KEY | PRIMARY KEY (id) | +| secrets_provider_connection_createdAt_not_null | n | NOT NULL "createdAt" | +| secrets_provider_connection_encryptedSettings_not_null | n | NOT NULL "encryptedSettings" | +| secrets_provider_connection_id_not_null | n | NOT NULL id | +| secrets_provider_connection_isEnabled_not_null | n | NOT NULL "isEnabled" | +| secrets_provider_connection_providerKey_not_null | n | NOT NULL "providerKey" | +| secrets_provider_connection_type_not_null | n | NOT NULL type | +| secrets_provider_connection_updatedAt_not_null | n | NOT NULL "updatedAt" | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_secrets_provider_connection_providerKey | CREATE UNIQUE INDEX "IDX_secrets_provider_connection_providerKey" ON public.secrets_provider_connection USING btree ("providerKey") | +| PK_4350ae85e76f9ba7df1370acb5d | CREATE UNIQUE INDEX "PK_4350ae85e76f9ba7df1370acb5d" ON public.secrets_provider_connection USING btree (id) | + +## Relations + +```mermaid +erDiagram + +"public.project_secrets_provider_access" }o--|| "public.secrets_provider_connection" : "FOREIGN KEY (#quot;secretsProviderConnectionId#quot;) REFERENCES secrets_provider_connection(id) ON DELETE CASCADE" + +"public.secrets_provider_connection" { + timestamp_3__with_time_zone createdAt + text encryptedSettings + integer id + boolean isEnabled + varchar_128_ providerKey + varchar_36_ type + timestamp_3__with_time_zone updatedAt +} +"public.project_secrets_provider_access" { + timestamp_3__with_time_zone createdAt + varchar_36_ projectId FK + varchar_128_ role + integer secretsProviderConnectionId FK + timestamp_3__with_time_zone updatedAt +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/postgres-schema/public.settings.md b/docs/generated/postgres-schema/public.settings.md new file mode 100644 index 00000000000..ca703d8d6a8 --- /dev/null +++ b/docs/generated/postgres-schema/public.settings.md @@ -0,0 +1,41 @@ +# public.settings + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| key | varchar(255) | | false | | | | +| loadOnStartup | boolean | false | false | | | | +| value | text | | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| PK_dc0fe14e6d9943f268e7b119f69ab8bd | PRIMARY KEY | PRIMARY KEY (key) | +| settings_key_not_null | n | NOT NULL key | +| settings_loadOnStartup_not_null | n | NOT NULL "loadOnStartup" | +| settings_value_not_null | n | NOT NULL value | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| PK_dc0fe14e6d9943f268e7b119f69ab8bd | CREATE UNIQUE INDEX "PK_dc0fe14e6d9943f268e7b119f69ab8bd" ON public.settings USING btree (key) | + +## Relations + +```mermaid +erDiagram + + +"public.settings" { + varchar_255_ key + boolean loadOnStartup + text value +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/postgres-schema/public.shared_credentials.md b/docs/generated/postgres-schema/public.shared_credentials.md new file mode 100644 index 00000000000..dce378cf39b --- /dev/null +++ b/docs/generated/postgres-schema/public.shared_credentials.md @@ -0,0 +1,75 @@ +# public.shared_credentials + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| createdAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| credentialsId | varchar(36) | | false | | [public.credentials_entity](public.credentials_entity.md) | | +| projectId | varchar(36) | | false | | [public.project](public.project.md) | | +| role | text | | false | | | | +| updatedAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| FK_416f66fc846c7c442970c094ccf | FOREIGN KEY | FOREIGN KEY ("credentialsId") REFERENCES credentials_entity(id) ON DELETE CASCADE | +| FK_812c2852270da1247756e77f5a4 | FOREIGN KEY | FOREIGN KEY ("projectId") REFERENCES project(id) ON DELETE CASCADE | +| PK_8ef3a59796a228913f251779cff | PRIMARY KEY | PRIMARY KEY ("credentialsId", "projectId") | +| shared_credentials_2_createdAt_not_null | n | NOT NULL "createdAt" | +| shared_credentials_2_credentialsId_not_null | n | NOT NULL "credentialsId" | +| shared_credentials_2_projectId_not_null | n | NOT NULL "projectId" | +| shared_credentials_2_role_not_null | n | NOT NULL role | +| shared_credentials_2_updatedAt_not_null | n | NOT NULL "updatedAt" | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| PK_8ef3a59796a228913f251779cff | CREATE UNIQUE INDEX "PK_8ef3a59796a228913f251779cff" ON public.shared_credentials USING btree ("credentialsId", "projectId") | + +## Relations + +```mermaid +erDiagram + +"public.shared_credentials" }o--|| "public.credentials_entity" : "FOREIGN KEY (#quot;credentialsId#quot;) REFERENCES credentials_entity(id) ON DELETE CASCADE" +"public.shared_credentials" }o--|| "public.project" : "FOREIGN KEY (#quot;projectId#quot;) REFERENCES project(id) ON DELETE CASCADE" + +"public.shared_credentials" { + timestamp_3__with_time_zone createdAt + varchar_36_ credentialsId FK + varchar_36_ projectId FK + text role + timestamp_3__with_time_zone updatedAt +} +"public.credentials_entity" { + timestamp_3__with_time_zone createdAt + text data + varchar_36_ id + boolean isGlobal + boolean isManaged + boolean isResolvable + varchar_128_ name + boolean resolvableAllowFallback + varchar_16_ resolverId FK + varchar_128_ type + timestamp_3__with_time_zone updatedAt +} +"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.shared_workflow.md b/docs/generated/postgres-schema/public.shared_workflow.md new file mode 100644 index 00000000000..dcec3824f72 --- /dev/null +++ b/docs/generated/postgres-schema/public.shared_workflow.md @@ -0,0 +1,85 @@ +# public.shared_workflow + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| createdAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| projectId | varchar(36) | | false | | [public.project](public.project.md) | | +| role | text | | false | | | | +| updatedAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| workflowId | varchar(36) | | false | | [public.workflow_entity](public.workflow_entity.md) | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| FK_a45ea5f27bcfdc21af9b4188560 | FOREIGN KEY | FOREIGN KEY ("projectId") REFERENCES project(id) ON DELETE CASCADE | +| FK_daa206a04983d47d0a9c34649ce | FOREIGN KEY | FOREIGN KEY ("workflowId") REFERENCES workflow_entity(id) ON DELETE CASCADE | +| PK_5ba87620386b847201c9531c58f | PRIMARY KEY | PRIMARY KEY ("workflowId", "projectId") | +| shared_workflow_2_createdAt_not_null | n | NOT NULL "createdAt" | +| shared_workflow_2_projectId_not_null | n | NOT NULL "projectId" | +| shared_workflow_2_role_not_null | n | NOT NULL role | +| shared_workflow_2_updatedAt_not_null | n | NOT NULL "updatedAt" | +| shared_workflow_2_workflowId_not_null | n | NOT NULL "workflowId" | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_shared_workflow_projectId | CREATE INDEX "IDX_shared_workflow_projectId" ON public.shared_workflow USING btree ("projectId") | +| PK_5ba87620386b847201c9531c58f | CREATE UNIQUE INDEX "PK_5ba87620386b847201c9531c58f" ON public.shared_workflow USING btree ("workflowId", "projectId") | + +## Relations + +```mermaid +erDiagram + +"public.shared_workflow" }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" { + timestamp_3__with_time_zone createdAt + varchar_36_ projectId FK + text role + timestamp_3__with_time_zone updatedAt + varchar_36_ workflowId FK +} +"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 +} +"public.workflow_entity" { + boolean active + varchar_36_ activeVersionId FK + json connections + timestamp_3__with_time_zone createdAt + text description + varchar_36_ id + boolean isArchived + json meta + varchar_128_ name + json nodeGroups + json nodes + varchar_36_ parentFolderId FK + json pinData + json settings + varchar sourceWorkflowId + json staticData + integer triggerCount + timestamp_3__with_time_zone updatedAt + integer versionCounter + character_36_ versionId +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/postgres-schema/public.tag_entity.md b/docs/generated/postgres-schema/public.tag_entity.md new file mode 100644 index 00000000000..726e98a298e --- /dev/null +++ b/docs/generated/postgres-schema/public.tag_entity.md @@ -0,0 +1,56 @@ +# public.tag_entity + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| createdAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| id | varchar(36) | | false | [public.folder_tag](public.folder_tag.md) [public.workflows_tags](public.workflows_tags.md) | | | +| name | varchar(24) | | false | | | | +| updatedAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| tag_entity_createdAt_not_null | n | NOT NULL "createdAt" | +| tag_entity_id_not_null1 | n | NOT NULL id | +| tag_entity_name_not_null | n | NOT NULL name | +| tag_entity_pkey | PRIMARY KEY | PRIMARY KEY (id) | +| tag_entity_updatedAt_not_null | n | NOT NULL "updatedAt" | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| idx_812eb05f7451ca757fb98444ce | CREATE UNIQUE INDEX idx_812eb05f7451ca757fb98444ce ON public.tag_entity USING btree (name) | +| pk_tag_entity_id | CREATE UNIQUE INDEX pk_tag_entity_id ON public.tag_entity USING btree (id) | +| tag_entity_pkey | CREATE UNIQUE INDEX tag_entity_pkey ON public.tag_entity USING btree (id) | + +## Relations + +```mermaid +erDiagram + +"public.folder_tag" }o--|| "public.tag_entity" : "FOREIGN KEY (#quot;tagId#quot;) REFERENCES tag_entity(id) ON DELETE CASCADE" +"public.workflows_tags" }o--|| "public.tag_entity" : "FOREIGN KEY (#quot;tagId#quot;) REFERENCES tag_entity(id) ON DELETE CASCADE" + +"public.tag_entity" { + timestamp_3__with_time_zone createdAt + varchar_36_ id + varchar_24_ name + timestamp_3__with_time_zone updatedAt +} +"public.folder_tag" { + varchar_36_ folderId FK + varchar_36_ tagId FK +} +"public.workflows_tags" { + varchar_36_ tagId FK + varchar_36_ workflowId FK +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/postgres-schema/public.test_case_execution.md b/docs/generated/postgres-schema/public.test_case_execution.md new file mode 100644 index 00000000000..aa566a5a612 --- /dev/null +++ b/docs/generated/postgres-schema/public.test_case_execution.md @@ -0,0 +1,108 @@ +# public.test_case_execution + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| completedAt | timestamp(3) with time zone | | true | | | | +| createdAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| errorCode | varchar | | true | | | | +| errorDetails | json | | true | | | | +| executionId | integer | | true | | [public.execution_entity](public.execution_entity.md) | | +| id | varchar(36) | | false | | | | +| inputs | json | | true | | | | +| metrics | json | | true | | | | +| outputs | json | | true | | | | +| runAt | timestamp(3) with time zone | | true | | | | +| runIndex | integer | | true | | | | +| status | varchar | | false | | | | +| testRunId | varchar(36) | | false | | [public.test_run](public.test_run.md) | | +| updatedAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| FK_8e4b4774db42f1e6dda3452b2af | FOREIGN KEY | FOREIGN KEY ("testRunId") REFERENCES test_run(id) ON DELETE CASCADE | +| FK_e48965fac35d0f5b9e7f51d8c44 | FOREIGN KEY | FOREIGN KEY ("executionId") REFERENCES execution_entity(id) ON DELETE SET NULL | +| PK_90c121f77a78a6580e94b794bce | PRIMARY KEY | PRIMARY KEY (id) | +| test_case_execution_createdAt_not_null | n | NOT NULL "createdAt" | +| test_case_execution_id_not_null | n | NOT NULL id | +| test_case_execution_status_not_null | n | NOT NULL status | +| test_case_execution_testRunId_not_null | n | NOT NULL "testRunId" | +| test_case_execution_updatedAt_not_null | n | NOT NULL "updatedAt" | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_8e4b4774db42f1e6dda3452b2a | CREATE INDEX "IDX_8e4b4774db42f1e6dda3452b2a" ON public.test_case_execution USING btree ("testRunId") | +| PK_90c121f77a78a6580e94b794bce | CREATE UNIQUE INDEX "PK_90c121f77a78a6580e94b794bce" ON public.test_case_execution USING btree (id) | + +## Relations + +```mermaid +erDiagram + +"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_case_execution" { + timestamp_3__with_time_zone completedAt + timestamp_3__with_time_zone createdAt + varchar errorCode + json errorDetails + integer executionId FK + varchar_36_ id + json inputs + json metrics + json outputs + timestamp_3__with_time_zone runAt + integer runIndex + varchar status + varchar_36_ testRunId FK + timestamp_3__with_time_zone updatedAt +} +"public.execution_entity" { + bigint binaryDataSizeBytes + timestamp_3__with_time_zone createdAt + varchar_255_ deduplicationKey + timestamp_3__with_time_zone deletedAt + boolean finished + integer id + bigint jsonSizeBytes + varchar mode + varchar retryOf + varchar retrySuccessId + timestamp_3__with_time_zone startedAt + varchar status + timestamp_3__with_time_zone stoppedAt + varchar_2_ storedAt + json tracingContext + timestamp_3__with_time_zone waitTill + varchar_36_ workflowId FK + varchar_36_ workflowVersionId +} +"public.test_run" { + boolean cancelRequested + varchar_36_ collectionId FK + timestamp_3__with_time_zone completedAt + timestamp_3__with_time_zone createdAt + varchar errorCode + json errorDetails + varchar_36_ evaluationConfigId FK + jsonb evaluationConfigSnapshot + varchar_36_ id + json metrics + timestamp_3__with_time_zone runAt + varchar_255_ runningInstanceId + varchar status + timestamp_3__with_time_zone updatedAt + varchar_36_ workflowId FK + varchar_36_ workflowVersionId +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/postgres-schema/public.test_run.md b/docs/generated/postgres-schema/public.test_run.md new file mode 100644 index 00000000000..636103eb3da --- /dev/null +++ b/docs/generated/postgres-schema/public.test_run.md @@ -0,0 +1,143 @@ +# public.test_run + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| cancelRequested | boolean | false | false | | | | +| collectionId | varchar(36) | | true | | [public.evaluation_collection](public.evaluation_collection.md) | | +| completedAt | timestamp(3) with time zone | | true | | | | +| createdAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| errorCode | varchar | | true | | | | +| errorDetails | json | | true | | | | +| evaluationConfigId | varchar(36) | | true | | [public.evaluation_config](public.evaluation_config.md) | | +| evaluationConfigSnapshot | jsonb | | true | | | | +| id | varchar(36) | | false | [public.test_case_execution](public.test_case_execution.md) | | | +| metrics | json | | true | | | | +| runAt | timestamp(3) with time zone | | true | | | | +| runningInstanceId | varchar(255) | | true | | | | +| status | varchar | | false | | | | +| updatedAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| workflowId | varchar(36) | | false | | [public.workflow_entity](public.workflow_entity.md) | | +| workflowVersionId | varchar(36) | | true | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| FK_d6870d3b6e4c185d33926f423c8 | FOREIGN KEY | FOREIGN KEY ("workflowId") REFERENCES workflow_entity(id) ON DELETE CASCADE | +| FK_test_run_collection_id | FOREIGN KEY | FOREIGN KEY ("collectionId") REFERENCES evaluation_collection(id) ON DELETE SET NULL | +| FK_test_run_evaluation_config_id | FOREIGN KEY | FOREIGN KEY ("evaluationConfigId") REFERENCES evaluation_config(id) ON DELETE SET NULL | +| PK_011c050f566e9db509a0fadb9b9 | PRIMARY KEY | PRIMARY KEY (id) | +| test_run_cancelRequested_not_null | n | NOT NULL "cancelRequested" | +| test_run_createdAt_not_null | n | NOT NULL "createdAt" | +| test_run_id_not_null | n | NOT NULL id | +| test_run_status_not_null | n | NOT NULL status | +| test_run_updatedAt_not_null | n | NOT NULL "updatedAt" | +| test_run_workflowId_not_null | n | NOT NULL "workflowId" | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_d6870d3b6e4c185d33926f423c | CREATE INDEX "IDX_d6870d3b6e4c185d33926f423c" ON public.test_run USING btree ("workflowId") | +| IDX_test_run_collectionId | CREATE INDEX "IDX_test_run_collectionId" ON public.test_run USING btree ("collectionId") | +| IDX_test_run_evaluationConfigId | CREATE INDEX "IDX_test_run_evaluationConfigId" ON public.test_run USING btree ("evaluationConfigId") | +| PK_011c050f566e9db509a0fadb9b9 | CREATE UNIQUE INDEX "PK_011c050f566e9db509a0fadb9b9" ON public.test_run USING btree (id) | + +## Relations + +```mermaid +erDiagram + +"public.test_run" }o--o| "public.evaluation_collection" : "FOREIGN KEY (#quot;collectionId#quot;) REFERENCES evaluation_collection(id) ON DELETE SET NULL" +"public.test_run" }o--o| "public.evaluation_config" : "FOREIGN KEY (#quot;evaluationConfigId#quot;) REFERENCES evaluation_config(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" + +"public.test_run" { + boolean cancelRequested + varchar_36_ collectionId FK + timestamp_3__with_time_zone completedAt + timestamp_3__with_time_zone createdAt + varchar errorCode + json errorDetails + varchar_36_ evaluationConfigId FK + jsonb evaluationConfigSnapshot + varchar_36_ id + json metrics + timestamp_3__with_time_zone runAt + varchar_255_ runningInstanceId + varchar status + timestamp_3__with_time_zone updatedAt + varchar_36_ workflowId FK + varchar_36_ workflowVersionId +} +"public.evaluation_collection" { + timestamp_3__with_time_zone createdAt + uuid createdById FK + text description + varchar_36_ evaluationConfigId FK + varchar_36_ id + json insightsCache + varchar_128_ name + timestamp_3__with_time_zone updatedAt + varchar_36_ workflowId FK +} +"public.evaluation_config" { + timestamp_3__with_time_zone createdAt + json datasetRef + varchar_32_ datasetSource + varchar_255_ endNodeName + varchar_36_ id + varchar_64_ invalidReason + json metrics + varchar_128_ name + varchar_255_ startNodeName + varchar_16_ status + timestamp_3__with_time_zone updatedAt + varchar_36_ workflowId FK +} +"public.test_case_execution" { + timestamp_3__with_time_zone completedAt + timestamp_3__with_time_zone createdAt + varchar errorCode + json errorDetails + integer executionId FK + varchar_36_ id + json inputs + json metrics + json outputs + timestamp_3__with_time_zone runAt + integer runIndex + varchar status + varchar_36_ testRunId FK + timestamp_3__with_time_zone updatedAt +} +"public.workflow_entity" { + boolean active + varchar_36_ activeVersionId FK + json connections + timestamp_3__with_time_zone createdAt + text description + varchar_36_ id + boolean isArchived + json meta + varchar_128_ name + json nodeGroups + json nodes + varchar_36_ parentFolderId FK + json pinData + json settings + varchar sourceWorkflowId + json staticData + integer triggerCount + timestamp_3__with_time_zone updatedAt + integer versionCounter + character_36_ versionId +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/postgres-schema/public.token_exchange_jti.md b/docs/generated/postgres-schema/public.token_exchange_jti.md new file mode 100644 index 00000000000..68528411898 --- /dev/null +++ b/docs/generated/postgres-schema/public.token_exchange_jti.md @@ -0,0 +1,41 @@ +# public.token_exchange_jti + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| createdAt | timestamp(3) with time zone | | false | | | | +| expiresAt | timestamp(3) with time zone | | false | | | | +| jti | varchar(255) | | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| PK_d8e8a6f737d530fdd2dd716e89c | PRIMARY KEY | PRIMARY KEY (jti) | +| token_exchange_jti_createdAt_not_null | n | NOT NULL "createdAt" | +| token_exchange_jti_expiresAt_not_null | n | NOT NULL "expiresAt" | +| token_exchange_jti_jti_not_null | n | NOT NULL jti | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| PK_d8e8a6f737d530fdd2dd716e89c | CREATE UNIQUE INDEX "PK_d8e8a6f737d530fdd2dd716e89c" ON public.token_exchange_jti USING btree (jti) | + +## Relations + +```mermaid +erDiagram + + +"public.token_exchange_jti" { + timestamp_3__with_time_zone createdAt + timestamp_3__with_time_zone expiresAt + varchar_255_ jti +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/postgres-schema/public.trusted_key.md b/docs/generated/postgres-schema/public.trusted_key.md new file mode 100644 index 00000000000..99477e77837 --- /dev/null +++ b/docs/generated/postgres-schema/public.trusted_key.md @@ -0,0 +1,56 @@ +# public.trusted_key + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| createdAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| data | text | | false | | | | +| kid | varchar(255) | | false | | | | +| sourceId | varchar(36) | | false | | [public.trusted_key_source](public.trusted_key_source.md) | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| FK_8c2938d746943dd8f608d23c891 | FOREIGN KEY | FOREIGN KEY ("sourceId") REFERENCES trusted_key_source(id) ON DELETE CASCADE | +| PK_dc7d93798f3dbb6959f974c97e1 | PRIMARY KEY | PRIMARY KEY ("sourceId", kid) | +| trusted_key_createdAt_not_null | n | NOT NULL "createdAt" | +| trusted_key_data_not_null | n | NOT NULL data | +| trusted_key_kid_not_null | n | NOT NULL kid | +| trusted_key_sourceId_not_null | n | NOT NULL "sourceId" | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| PK_dc7d93798f3dbb6959f974c97e1 | CREATE UNIQUE INDEX "PK_dc7d93798f3dbb6959f974c97e1" ON public.trusted_key USING btree ("sourceId", kid) | + +## Relations + +```mermaid +erDiagram + +"public.trusted_key" }o--|| "public.trusted_key_source" : "FOREIGN KEY (#quot;sourceId#quot;) REFERENCES trusted_key_source(id) ON DELETE CASCADE" + +"public.trusted_key" { + timestamp_3__with_time_zone createdAt + text data + varchar_255_ kid + varchar_36_ sourceId FK +} +"public.trusted_key_source" { + text config + timestamp_3__with_time_zone createdAt + varchar_36_ id + text lastError + timestamp_3__with_time_zone lastRefreshedAt + varchar_32_ status + varchar_32_ type + timestamp_3__with_time_zone updatedAt +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/postgres-schema/public.trusted_key_source.md b/docs/generated/postgres-schema/public.trusted_key_source.md new file mode 100644 index 00000000000..053221e3bb6 --- /dev/null +++ b/docs/generated/postgres-schema/public.trusted_key_source.md @@ -0,0 +1,61 @@ +# public.trusted_key_source + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| config | text | | false | | | | +| createdAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| id | varchar(36) | | false | [public.trusted_key](public.trusted_key.md) | | | +| lastError | text | | true | | | | +| lastRefreshedAt | timestamp(3) with time zone | | true | | | | +| status | varchar(32) | 'pending'::character varying | false | | | | +| type | varchar(32) | | false | | | | +| updatedAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| PK_99e8908ce2c2cdccce487db7fc6 | PRIMARY KEY | PRIMARY KEY (id) | +| trusted_key_source_config_not_null | n | NOT NULL config | +| trusted_key_source_createdAt_not_null | n | NOT NULL "createdAt" | +| trusted_key_source_id_not_null | n | NOT NULL id | +| trusted_key_source_status_not_null | n | NOT NULL status | +| trusted_key_source_type_not_null | n | NOT NULL type | +| trusted_key_source_updatedAt_not_null | n | NOT NULL "updatedAt" | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| PK_99e8908ce2c2cdccce487db7fc6 | CREATE UNIQUE INDEX "PK_99e8908ce2c2cdccce487db7fc6" ON public.trusted_key_source USING btree (id) | + +## Relations + +```mermaid +erDiagram + +"public.trusted_key" }o--|| "public.trusted_key_source" : "FOREIGN KEY (#quot;sourceId#quot;) REFERENCES trusted_key_source(id) ON DELETE CASCADE" + +"public.trusted_key_source" { + text config + timestamp_3__with_time_zone createdAt + varchar_36_ id + text lastError + timestamp_3__with_time_zone lastRefreshedAt + varchar_32_ status + varchar_32_ type + timestamp_3__with_time_zone updatedAt +} +"public.trusted_key" { + timestamp_3__with_time_zone createdAt + text data + varchar_255_ kid + varchar_36_ sourceId FK +} +``` + +--- + +> 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 new file mode 100644 index 00000000000..a6fa4a685cd --- /dev/null +++ b/docs/generated/postgres-schema/public.user.md @@ -0,0 +1,291 @@ +# public.user + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| createdAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| disabled | boolean | false | false | | | | +| email | varchar(255) | | true | | | | +| firstName | varchar(32) | | true | | | | +| id | uuid | gen_random_uuid() | false | [public.agent_history](public.agent_history.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.instance_ai_mcp_registry_connections](public.instance_ai_mcp_registry_connections.md) [public.instance_ai_pending_confirmations](public.instance_ai_pending_confirmations.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.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) | | | +| lastActiveAt | date | | true | | | | +| lastName | varchar(32) | | true | | | | +| mfaEnabled | boolean | false | false | | | | +| mfaRecoveryCodes | text | | true | | | | +| mfaSecret | text | | true | | | | +| password | varchar(255) | | true | | | | +| personalizationAnswers | json | | true | | | | +| roleSlug | varchar(128) | 'global:member'::character varying | false | | [public.role](public.role.md) | | +| settings | json | | true | | | | +| updatedAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| FK_eaea92ee7bfb9c1b6cd01505d56 | FOREIGN KEY | FOREIGN KEY ("roleSlug") REFERENCES role(slug) | +| PK_ea8f538c94b6e352418254ed6474a81f | PRIMARY KEY | PRIMARY KEY (id) | +| UQ_e12875dfb3b1d92d7d7c5377e2 | UNIQUE | UNIQUE (email) | +| user_createdAt_not_null | n | NOT NULL "createdAt" | +| user_disabled_not_null | n | NOT NULL disabled | +| user_id_not_null | n | NOT NULL id | +| user_mfaEnabled_not_null | n | NOT NULL "mfaEnabled" | +| user_roleSlug_not_null | n | NOT NULL "roleSlug" | +| user_updatedAt_not_null | n | NOT NULL "updatedAt" | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| PK_ea8f538c94b6e352418254ed6474a81f | CREATE UNIQUE INDEX "PK_ea8f538c94b6e352418254ed6474a81f" ON public."user" USING btree (id) | +| UQ_e12875dfb3b1d92d7d7c5377e2 | CREATE UNIQUE INDEX "UQ_e12875dfb3b1d92d7d7c5377e2" ON public."user" USING btree (email) | +| user_role_idx | CREATE INDEX user_role_idx ON public."user" USING btree ("roleSlug") | + +## Relations + +```mermaid +erDiagram + +"public.agent_history" }o--o| "public.user" : "FOREIGN KEY (#quot;publishedById#quot;) REFERENCES #quot;user#quot;(id) ON DELETE SET NULL" +"public.auth_identity" }o--o| "public.user" : "FOREIGN KEY (#quot;userId#quot;) REFERENCES #quot;user#quot;(id)" +"public.chat_hub_agents" }o--|| "public.user" : "FOREIGN KEY (#quot;ownerId#quot;) REFERENCES #quot;user#quot;(id) ON DELETE CASCADE" +"public.chat_hub_sessions" }o--|| "public.user" : "FOREIGN KEY (#quot;ownerId#quot;) REFERENCES #quot;user#quot;(id) ON DELETE CASCADE" +"public.chat_hub_tools" }o--|| "public.user" : "FOREIGN KEY (#quot;ownerId#quot;) REFERENCES #quot;user#quot;(id) ON DELETE CASCADE" +"public.dynamic_credential_user_entry" }o--|| "public.user" : "FOREIGN KEY (#quot;userId#quot;) REFERENCES #quot;user#quot;(id) ON DELETE CASCADE" +"public.evaluation_collection" }o--o| "public.user" : "FOREIGN KEY (#quot;createdById#quot;) REFERENCES #quot;user#quot;(id) ON DELETE SET NULL" +"public.instance_ai_mcp_registry_connections" }o--|| "public.user" : "FOREIGN KEY (#quot;userId#quot;) REFERENCES #quot;user#quot;(id) ON DELETE CASCADE" +"public.instance_ai_pending_confirmations" }o--|| "public.user" : "FOREIGN KEY (#quot;userId#quot;) REFERENCES #quot;user#quot;(id) ON DELETE CASCADE" +"public.oauth_access_tokens" }o--|| "public.user" : "FOREIGN KEY (#quot;userId#quot;) REFERENCES #quot;user#quot;(id) ON DELETE CASCADE" +"public.oauth_authorization_codes" }o--|| "public.user" : "FOREIGN KEY (#quot;userId#quot;) REFERENCES #quot;user#quot;(id) ON DELETE CASCADE" +"public.oauth_refresh_tokens" }o--|| "public.user" : "FOREIGN KEY (#quot;userId#quot;) REFERENCES #quot;user#quot;(id) ON DELETE CASCADE" +"public.oauth_user_consents" }o--|| "public.user" : "FOREIGN KEY (#quot;userId#quot;) REFERENCES #quot;user#quot;(id) ON DELETE CASCADE" +"public.project" }o--o| "public.user" : "FOREIGN KEY (#quot;creatorId#quot;) REFERENCES #quot;user#quot;(id) ON DELETE SET NULL" +"public.project_relation" }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" +"public.workflow_builder_session" }o--|| "public.user" : "FOREIGN KEY (#quot;userId#quot;) REFERENCES #quot;user#quot;(id) ON DELETE CASCADE" +"public.workflow_publish_history" }o--o| "public.user" : "FOREIGN KEY (#quot;userId#quot;) REFERENCES #quot;user#quot;(id) ON DELETE SET NULL" +"public.user" }o--|| "public.role" : "FOREIGN KEY (#quot;roleSlug#quot;) REFERENCES role(slug)" + +"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_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.auth_identity" { + timestamp_3__with_time_zone createdAt + varchar_255_ providerId + varchar_32_ providerType + timestamp_3__with_time_zone updatedAt + uuid userId FK +} +"public.chat_hub_agents" { + timestamp_3__with_time_zone createdAt + varchar_36_ credentialId FK + varchar_512_ description + json files + json icon + uuid id + varchar_64_ model + varchar_256_ name + uuid ownerId FK + varchar_16_ provider + json suggestedPrompts + text systemPrompt + timestamp_3__with_time_zone updatedAt +} +"public.chat_hub_sessions" { + uuid agentId FK + varchar_128_ agentName + timestamp_3__with_time_zone createdAt + varchar_36_ credentialId FK + uuid id + timestamp_3__with_time_zone lastMessageAt + varchar_256_ model + uuid ownerId FK + varchar_16_ provider + varchar_256_ title + varchar_16_ type + timestamp_3__with_time_zone updatedAt + varchar_36_ workflowId FK +} +"public.chat_hub_tools" { + timestamp_3__with_time_zone createdAt + json definition + boolean enabled + uuid id + varchar_255_ name + uuid ownerId FK + varchar_255_ type + double_precision typeVersion + timestamp_3__with_time_zone updatedAt +} +"public.dynamic_credential_user_entry" { + timestamp_3__with_time_zone createdAt + varchar_16_ credentialId FK + text data + varchar_16_ resolverId FK + timestamp_3__with_time_zone updatedAt + uuid userId FK +} +"public.evaluation_collection" { + timestamp_3__with_time_zone createdAt + uuid createdById FK + text description + varchar_36_ evaluationConfigId FK + varchar_36_ id + json insightsCache + varchar_128_ name + timestamp_3__with_time_zone updatedAt + varchar_36_ workflowId FK +} +"public.instance_ai_mcp_registry_connections" { + timestamp_3__with_time_zone createdAt + varchar_36_ credentialId FK + uuid id + varchar_255_ serverSlug FK + json toolFilter + timestamp_3__with_time_zone updatedAt + uuid userId FK +} +"public.instance_ai_pending_confirmations" { + varchar_255_ checkpointKey FK + varchar_36_ checkpointTaskId + timestamp_3__with_time_zone createdAt + timestamp_3__with_time_zone expiresAt + varchar_16_ kind + varchar_36_ messageGroupId + varchar_36_ requestId + varchar_36_ runId + uuid threadId FK + varchar_64_ toolCallId + timestamp_3__with_time_zone updatedAt + uuid userId FK +} +"public.oauth_access_tokens" { + varchar clientId FK + varchar token + uuid userId FK +} +"public.oauth_authorization_codes" { + varchar clientId FK + varchar_255_ code + varchar codeChallenge + varchar_255_ codeChallengeMethod + timestamp_3__with_time_zone createdAt + bigint expiresAt + varchar redirectUri + varchar resource + json scope + varchar state + timestamp_3__with_time_zone updatedAt + boolean used + uuid userId FK +} +"public.oauth_refresh_tokens" { + varchar clientId FK + timestamp_3__with_time_zone createdAt + bigint expiresAt + json scope + varchar_255_ token + timestamp_3__with_time_zone updatedAt + uuid userId FK +} +"public.oauth_user_consents" { + varchar clientId FK + bigint grantedAt + integer id + uuid userId FK +} +"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 +} +"public.project_relation" { + timestamp_3__with_time_zone createdAt + varchar_36_ projectId FK + varchar role FK + timestamp_3__with_time_zone updatedAt + uuid userId FK +} +"public.user_api_keys" { + varchar apiKey + varchar audience + timestamp_3__with_time_zone createdAt + varchar_36_ id + varchar_100_ label + timestamp_3__with_time_zone lastUsedAt + json scopes + timestamp_3__with_time_zone updatedAt + uuid userId FK +} +"public.user_favorites" { + integer id + varchar_255_ resourceId + varchar_64_ resourceType + uuid userId FK +} +"public.workflow_builder_session" { + varchar_255_ activeVersionCardId + timestamp_3__with_time_zone createdAt + uuid id + json messages + text previousSummary + varchar_255_ resumeAfterRestoreMessageId + timestamp_3__with_time_zone updatedAt + uuid userId FK + varchar_36_ workflowId FK +} +"public.workflow_publish_history" { + timestamp_3__with_time_zone createdAt + varchar_36_ event + integer id + uuid userId FK + varchar_36_ versionId FK + varchar_36_ workflowId FK +} +"public.role" { + timestamp_3__with_time_zone createdAt + text description + text displayName + text roleType + varchar_128_ slug + boolean systemRole + timestamp_3__with_time_zone updatedAt +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/postgres-schema/public.user_api_keys.md b/docs/generated/postgres-schema/public.user_api_keys.md new file mode 100644 index 00000000000..947de36e556 --- /dev/null +++ b/docs/generated/postgres-schema/public.user_api_keys.md @@ -0,0 +1,78 @@ +# public.user_api_keys + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| apiKey | varchar | | false | | | | +| audience | varchar | 'public-api'::character varying | false | | | | +| createdAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| id | varchar(36) | | false | | | | +| label | varchar(100) | | false | | | | +| lastUsedAt | timestamp(3) with time zone | | true | | | | +| scopes | json | | true | | | | +| updatedAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| userId | uuid | | false | | [public.user](public.user.md) | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| FK_e131705cbbc8fb589889b02d457 | FOREIGN KEY | FOREIGN KEY ("userId") REFERENCES "user"(id) ON DELETE CASCADE | +| PK_978fa5caa3468f463dac9d92e69 | PRIMARY KEY | PRIMARY KEY (id) | +| user_api_keys_apiKey_not_null | n | NOT NULL "apiKey" | +| user_api_keys_audience_not_null | n | NOT NULL audience | +| user_api_keys_createdAt_not_null | n | NOT NULL "createdAt" | +| user_api_keys_id_not_null | n | NOT NULL id | +| user_api_keys_label_not_null | n | NOT NULL label | +| user_api_keys_updatedAt_not_null | n | NOT NULL "updatedAt" | +| user_api_keys_userId_not_null | n | NOT NULL "userId" | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_1ef35bac35d20bdae979d917a3 | CREATE UNIQUE INDEX "IDX_1ef35bac35d20bdae979d917a3" ON public.user_api_keys USING btree ("apiKey") | +| IDX_63d7bbae72c767cf162d459fcc | CREATE UNIQUE INDEX "IDX_63d7bbae72c767cf162d459fcc" ON public.user_api_keys USING btree ("userId", label) | +| PK_978fa5caa3468f463dac9d92e69 | CREATE UNIQUE INDEX "PK_978fa5caa3468f463dac9d92e69" ON public.user_api_keys USING btree (id) | + +## Relations + +```mermaid +erDiagram + +"public.user_api_keys" }o--|| "public.user" : "FOREIGN KEY (#quot;userId#quot;) REFERENCES #quot;user#quot;(id) ON DELETE CASCADE" + +"public.user_api_keys" { + varchar apiKey + varchar audience + timestamp_3__with_time_zone createdAt + varchar_36_ id + varchar_100_ label + timestamp_3__with_time_zone lastUsedAt + json scopes + timestamp_3__with_time_zone updatedAt + uuid userId FK +} +"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 +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/postgres-schema/public.user_favorites.md b/docs/generated/postgres-schema/public.user_favorites.md new file mode 100644 index 00000000000..e41f2dcc634 --- /dev/null +++ b/docs/generated/postgres-schema/public.user_favorites.md @@ -0,0 +1,67 @@ +# public.user_favorites + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| id | integer | | false | | | | +| resourceId | varchar(255) | | false | | | | +| resourceType | varchar(64) | | false | | | | +| userId | uuid | | false | | [public.user](public.user.md) | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| FK_1dd5c393ad0517be3c31a7af836 | FOREIGN KEY | FOREIGN KEY ("userId") REFERENCES "user"(id) ON DELETE CASCADE | +| PK_6c472a19a7423cfbbf6b7c75939 | PRIMARY KEY | PRIMARY KEY (id) | +| UQ_cf6ae658ead9ffc124723413c65 | UNIQUE | UNIQUE ("userId", "resourceId", "resourceType") | +| user_favorites_id_not_null | n | NOT NULL id | +| user_favorites_resourceId_not_null | n | NOT NULL "resourceId" | +| user_favorites_resourceType_not_null | n | NOT NULL "resourceType" | +| user_favorites_userId_not_null | n | NOT NULL "userId" | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_1d11050a381548c42c32cc25c4 | CREATE INDEX "IDX_1d11050a381548c42c32cc25c4" ON public.user_favorites USING btree ("resourceType", "resourceId") | +| IDX_1dd5c393ad0517be3c31a7af83 | CREATE INDEX "IDX_1dd5c393ad0517be3c31a7af83" ON public.user_favorites USING btree ("userId") | +| PK_6c472a19a7423cfbbf6b7c75939 | CREATE UNIQUE INDEX "PK_6c472a19a7423cfbbf6b7c75939" ON public.user_favorites USING btree (id) | +| UQ_cf6ae658ead9ffc124723413c65 | CREATE UNIQUE INDEX "UQ_cf6ae658ead9ffc124723413c65" ON public.user_favorites USING btree ("userId", "resourceId", "resourceType") | + +## Relations + +```mermaid +erDiagram + +"public.user_favorites" }o--|| "public.user" : "FOREIGN KEY (#quot;userId#quot;) REFERENCES #quot;user#quot;(id) ON DELETE CASCADE" + +"public.user_favorites" { + integer id + varchar_255_ resourceId + varchar_64_ resourceType + uuid userId FK +} +"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 +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/postgres-schema/public.variables.md b/docs/generated/postgres-schema/public.variables.md new file mode 100644 index 00000000000..08b5db36b52 --- /dev/null +++ b/docs/generated/postgres-schema/public.variables.md @@ -0,0 +1,61 @@ +# public.variables + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| id | varchar(36) | | false | | | | +| key | varchar(50) | | false | | | | +| projectId | varchar(36) | | true | | [public.project](public.project.md) | | +| type | varchar(50) | 'string'::character varying | false | | | | +| value | text | | true | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| FK_42f6c766f9f9d2edcc15bdd6e9b | FOREIGN KEY | FOREIGN KEY ("projectId") REFERENCES project(id) ON DELETE CASCADE | +| variables_id_not_null1 | n | NOT NULL id | +| variables_key_not_null | n | NOT NULL key | +| variables_pkey | PRIMARY KEY | PRIMARY KEY (id) | +| variables_type_not_null | n | NOT NULL type | +| variables_value_max_len | CHECK | CHECK (((value IS NULL) OR (char_length(value) <= 1000))) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| variables_global_key_unique | CREATE UNIQUE INDEX variables_global_key_unique ON public.variables USING btree (key) WHERE ("projectId" IS NULL) | +| variables_pkey | CREATE UNIQUE INDEX variables_pkey ON public.variables USING btree (id) | +| variables_project_key_unique | CREATE UNIQUE INDEX variables_project_key_unique ON public.variables USING btree ("projectId", key) WHERE ("projectId" IS NOT NULL) | + +## Relations + +```mermaid +erDiagram + +"public.variables" }o--o| "public.project" : "FOREIGN KEY (#quot;projectId#quot;) REFERENCES project(id) ON DELETE CASCADE" + +"public.variables" { + varchar_36_ id + varchar_50_ key + varchar_36_ projectId FK + varchar_50_ type + text value +} +"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.webhook_entity.md b/docs/generated/postgres-schema/public.webhook_entity.md new file mode 100644 index 00000000000..eb0f2a6087b --- /dev/null +++ b/docs/generated/postgres-schema/public.webhook_entity.md @@ -0,0 +1,73 @@ +# public.webhook_entity + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| method | varchar | | false | | | | +| node | varchar | | false | | | | +| pathLength | integer | | true | | | | +| webhookId | varchar | | true | | | | +| webhookPath | varchar | | false | | | | +| workflowId | varchar(36) | | false | | [public.workflow_entity](public.workflow_entity.md) | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| PK_b21ace2e13596ccd87dc9bf4ea6 | PRIMARY KEY | PRIMARY KEY ("webhookPath", method) | +| fk_webhook_entity_workflow_id | FOREIGN KEY | FOREIGN KEY ("workflowId") REFERENCES workflow_entity(id) ON DELETE CASCADE | +| webhook_entity_method_not_null | n | NOT NULL method | +| webhook_entity_node_not_null | n | NOT NULL node | +| webhook_entity_webhookPath_not_null | n | NOT NULL "webhookPath" | +| webhook_entity_workflowId_not_null1 | n | NOT NULL "workflowId" | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| PK_b21ace2e13596ccd87dc9bf4ea6 | CREATE UNIQUE INDEX "PK_b21ace2e13596ccd87dc9bf4ea6" ON public.webhook_entity USING btree ("webhookPath", method) | +| idx_16f4436789e804e3e1c9eeb240 | CREATE INDEX idx_16f4436789e804e3e1c9eeb240 ON public.webhook_entity USING btree ("webhookId", method, "pathLength") | + +## Relations + +```mermaid +erDiagram + +"public.webhook_entity" }o--|| "public.workflow_entity" : "FOREIGN KEY (#quot;workflowId#quot;) REFERENCES workflow_entity(id) ON DELETE CASCADE" + +"public.webhook_entity" { + varchar method + varchar node + integer pathLength + varchar webhookId + varchar webhookPath + varchar_36_ workflowId FK +} +"public.workflow_entity" { + boolean active + varchar_36_ activeVersionId FK + json connections + timestamp_3__with_time_zone createdAt + text description + varchar_36_ id + boolean isArchived + json meta + varchar_128_ name + json nodeGroups + json nodes + varchar_36_ parentFolderId FK + json pinData + json settings + varchar sourceWorkflowId + json staticData + integer triggerCount + timestamp_3__with_time_zone updatedAt + integer versionCounter + character_36_ versionId +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/postgres-schema/public.workflow_builder_session.md b/docs/generated/postgres-schema/public.workflow_builder_session.md new file mode 100644 index 00000000000..5952dc14580 --- /dev/null +++ b/docs/generated/postgres-schema/public.workflow_builder_session.md @@ -0,0 +1,101 @@ +# public.workflow_builder_session + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| activeVersionCardId | varchar(255) | | true | | | | +| createdAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| id | uuid | | false | | | | +| messages | json | '[]'::json | false | | | | +| previousSummary | text | | true | | | Summary of prior conversation from compaction (/compact or auto-compact) | +| resumeAfterRestoreMessageId | varchar(255) | | true | | | | +| updatedAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| userId | uuid | | false | | [public.user](public.user.md) | | +| workflowId | varchar(36) | | false | | [public.workflow_entity](public.workflow_entity.md) | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| FK_00290cdeee4d4d7db84709be936 | FOREIGN KEY | FOREIGN KEY ("userId") REFERENCES "user"(id) ON DELETE CASCADE | +| FK_7983c618db48f47bf5a4cc1e1e4 | FOREIGN KEY | FOREIGN KEY ("workflowId") REFERENCES workflow_entity(id) ON DELETE CASCADE | +| PK_e69ef0d385986e273423b0e8695 | PRIMARY KEY | PRIMARY KEY (id) | +| UQ_ec2aa73632932d485a1d5192ce1 | UNIQUE | UNIQUE ("workflowId", "userId") | +| workflow_builder_session_createdAt_not_null | n | NOT NULL "createdAt" | +| workflow_builder_session_id_not_null | n | NOT NULL id | +| workflow_builder_session_messages_not_null | n | NOT NULL messages | +| workflow_builder_session_updatedAt_not_null | n | NOT NULL "updatedAt" | +| workflow_builder_session_userId_not_null | n | NOT NULL "userId" | +| workflow_builder_session_workflowId_not_null | n | NOT NULL "workflowId" | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| PK_e69ef0d385986e273423b0e8695 | CREATE UNIQUE INDEX "PK_e69ef0d385986e273423b0e8695" ON public.workflow_builder_session USING btree (id) | +| UQ_ec2aa73632932d485a1d5192ce1 | CREATE UNIQUE INDEX "UQ_ec2aa73632932d485a1d5192ce1" ON public.workflow_builder_session USING btree ("workflowId", "userId") | + +## Relations + +```mermaid +erDiagram + +"public.workflow_builder_session" }o--|| "public.user" : "FOREIGN KEY (#quot;userId#quot;) REFERENCES #quot;user#quot;(id) ON DELETE CASCADE" +"public.workflow_builder_session" }o--|| "public.workflow_entity" : "FOREIGN KEY (#quot;workflowId#quot;) REFERENCES workflow_entity(id) ON DELETE CASCADE" + +"public.workflow_builder_session" { + varchar_255_ activeVersionCardId + timestamp_3__with_time_zone createdAt + uuid id + json messages + text previousSummary + varchar_255_ resumeAfterRestoreMessageId + timestamp_3__with_time_zone updatedAt + uuid userId FK + varchar_36_ workflowId FK +} +"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.workflow_entity" { + boolean active + varchar_36_ activeVersionId FK + json connections + timestamp_3__with_time_zone createdAt + text description + varchar_36_ id + boolean isArchived + json meta + varchar_128_ name + json nodeGroups + json nodes + varchar_36_ parentFolderId FK + json pinData + json settings + varchar sourceWorkflowId + json staticData + integer triggerCount + timestamp_3__with_time_zone updatedAt + integer versionCounter + character_36_ versionId +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/postgres-schema/public.workflow_dependency.md b/docs/generated/postgres-schema/public.workflow_dependency.md new file mode 100644 index 00000000000..525c5b8e358 --- /dev/null +++ b/docs/generated/postgres-schema/public.workflow_dependency.md @@ -0,0 +1,85 @@ +# public.workflow_dependency + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| createdAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| dependencyInfo | json | | true | | | Additional info about the dependency, interpreted based on type | +| dependencyKey | varchar(255) | | false | | | ID or name of the dependency | +| dependencyType | varchar(32) | | false | | | Type of dependency: "credential", "nodeType", "webhookPath", or "workflowCall" | +| id | integer | | false | | | | +| indexVersionId | smallint | 1 | false | | | Version of the index structure | +| publishedVersionId | varchar(36) | | true | | | | +| workflowId | varchar(36) | | false | | [public.workflow_entity](public.workflow_entity.md) | | +| workflowVersionId | integer | | false | | | Version of the workflow | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| FK_a4ff2d9b9628ea988fa9e7d0bf8 | FOREIGN KEY | FOREIGN KEY ("workflowId") REFERENCES workflow_entity(id) ON DELETE CASCADE | +| PK_52325e34cd7a2f0f67b0f3cad65 | PRIMARY KEY | PRIMARY KEY (id) | +| workflow_dependency_createdAt_not_null | n | NOT NULL "createdAt" | +| workflow_dependency_dependencyKey_not_null | n | NOT NULL "dependencyKey" | +| workflow_dependency_dependencyType_not_null | n | NOT NULL "dependencyType" | +| workflow_dependency_id_not_null | n | NOT NULL id | +| workflow_dependency_indexVersionId_not_null | n | NOT NULL "indexVersionId" | +| workflow_dependency_workflowId_not_null | n | NOT NULL "workflowId" | +| workflow_dependency_workflowVersionId_not_null | n | NOT NULL "workflowVersionId" | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_a4ff2d9b9628ea988fa9e7d0bf | CREATE INDEX "IDX_a4ff2d9b9628ea988fa9e7d0bf" ON public.workflow_dependency USING btree ("workflowId") | +| IDX_e48a201071ab85d9d09119d640 | CREATE INDEX "IDX_e48a201071ab85d9d09119d640" ON public.workflow_dependency USING btree ("dependencyKey") | +| IDX_e7fe1cfda990c14a445937d0b9 | CREATE INDEX "IDX_e7fe1cfda990c14a445937d0b9" ON public.workflow_dependency USING btree ("dependencyType") | +| IDX_workflow_dependency_publishedVersionId | CREATE INDEX "IDX_workflow_dependency_publishedVersionId" ON public.workflow_dependency USING btree ("publishedVersionId") | +| PK_52325e34cd7a2f0f67b0f3cad65 | CREATE UNIQUE INDEX "PK_52325e34cd7a2f0f67b0f3cad65" ON public.workflow_dependency USING btree (id) | + +## Relations + +```mermaid +erDiagram + +"public.workflow_dependency" }o--|| "public.workflow_entity" : "FOREIGN KEY (#quot;workflowId#quot;) REFERENCES workflow_entity(id) ON DELETE CASCADE" + +"public.workflow_dependency" { + timestamp_3__with_time_zone createdAt + json dependencyInfo + varchar_255_ dependencyKey + varchar_32_ dependencyType + integer id + smallint indexVersionId + varchar_36_ publishedVersionId + varchar_36_ workflowId FK + integer workflowVersionId +} +"public.workflow_entity" { + boolean active + varchar_36_ activeVersionId FK + json connections + timestamp_3__with_time_zone createdAt + text description + varchar_36_ id + boolean isArchived + json meta + varchar_128_ name + json nodeGroups + json nodes + varchar_36_ parentFolderId FK + json pinData + json settings + varchar sourceWorkflowId + json staticData + integer triggerCount + timestamp_3__with_time_zone updatedAt + integer versionCounter + character_36_ versionId +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/postgres-schema/public.workflow_entity.md b/docs/generated/postgres-schema/public.workflow_entity.md new file mode 100644 index 00000000000..d4669e00a45 --- /dev/null +++ b/docs/generated/postgres-schema/public.workflow_entity.md @@ -0,0 +1,307 @@ +# public.workflow_entity + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| active | boolean | | false | | | | +| activeVersionId | varchar(36) | | true | | [public.workflow_history](public.workflow_history.md) | | +| connections | json | | false | | | | +| createdAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| description | text | | true | | | | +| id | varchar(36) | | false | [public.ai_builder_temporary_workflow](public.ai_builder_temporary_workflow.md) [public.chat_hub_messages](public.chat_hub_messages.md) [public.chat_hub_sessions](public.chat_hub_sessions.md) [public.evaluation_collection](public.evaluation_collection.md) [public.evaluation_config](public.evaluation_config.md) [public.execution_entity](public.execution_entity.md) [public.insights_metadata](public.insights_metadata.md) [public.processed_data](public.processed_data.md) [public.shared_workflow](public.shared_workflow.md) [public.test_run](public.test_run.md) [public.webhook_entity](public.webhook_entity.md) [public.workflow_builder_session](public.workflow_builder_session.md) [public.workflow_dependency](public.workflow_dependency.md) [public.workflow_history](public.workflow_history.md) [public.workflow_publish_history](public.workflow_publish_history.md) [public.workflow_published_version](public.workflow_published_version.md) [public.workflows_tags](public.workflows_tags.md) | | | +| isArchived | boolean | false | false | | | | +| meta | json | | true | | | | +| name | varchar(128) | | false | | | | +| nodeGroups | json | '[]'::json | false | | | | +| nodes | json | | false | | | | +| parentFolderId | varchar(36) | NULL::character varying | true | | [public.folder](public.folder.md) | | +| pinData | json | | true | | | | +| settings | json | | true | | | | +| sourceWorkflowId | varchar | | true | | | | +| staticData | json | | true | | | | +| triggerCount | integer | 0 | false | | | | +| updatedAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| versionCounter | integer | 1 | false | | | | +| versionId | character(36) | | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| FK_08d6c67b7f722b0039d9d5ed620 | FOREIGN KEY | FOREIGN KEY ("activeVersionId") REFERENCES workflow_history("versionId") ON DELETE RESTRICT | +| fk_workflow_parent_folder | FOREIGN KEY | FOREIGN KEY ("parentFolderId") REFERENCES folder(id) ON DELETE CASCADE | +| workflow_entity_active_not_null | n | NOT NULL active | +| workflow_entity_connections_not_null | n | NOT NULL connections | +| workflow_entity_createdAt_not_null | n | NOT NULL "createdAt" | +| workflow_entity_id_not_null1 | n | NOT NULL id | +| workflow_entity_isArchived_not_null | n | NOT NULL "isArchived" | +| workflow_entity_name_not_null | n | NOT NULL name | +| workflow_entity_nodeGroups_not_null | n | NOT NULL "nodeGroups" | +| workflow_entity_nodes_not_null | n | NOT NULL nodes | +| workflow_entity_pkey | PRIMARY KEY | PRIMARY KEY (id) | +| workflow_entity_triggerCount_not_null | n | NOT NULL "triggerCount" | +| workflow_entity_updatedAt_not_null | n | NOT NULL "updatedAt" | +| workflow_entity_versionCounter_not_null | n | NOT NULL "versionCounter" | +| workflow_entity_versionId_not_null | n | NOT NULL "versionId" | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_workflow_entity_name | CREATE INDEX "IDX_workflow_entity_name" ON public.workflow_entity USING btree (name) | +| IDX_workflow_entity_sourceWorkflowId | CREATE INDEX "IDX_workflow_entity_sourceWorkflowId" ON public.workflow_entity USING btree ("sourceWorkflowId") WHERE ("sourceWorkflowId" IS NOT NULL) | +| pk_workflow_entity_id | CREATE UNIQUE INDEX pk_workflow_entity_id ON public.workflow_entity USING btree (id) | +| workflow_entity_pkey | CREATE UNIQUE INDEX workflow_entity_pkey ON public.workflow_entity USING btree (id) | + +## Triggers + +| Name | Definition | +| ---- | ---------- | +| workflow_version_increment | CREATE TRIGGER workflow_version_increment BEFORE UPDATE ON public.workflow_entity FOR EACH ROW EXECUTE FUNCTION increment_workflow_version() | + +## Relations + +```mermaid +erDiagram + +"public.workflow_entity" }o--o| "public.workflow_history" : "FOREIGN KEY (#quot;activeVersionId#quot;) REFERENCES workflow_history(#quot;versionId#quot;) ON DELETE RESTRICT" +"public.ai_builder_temporary_workflow" |o--|| "public.workflow_entity" : "FOREIGN KEY (#quot;workflowId#quot;) REFERENCES workflow_entity(id) ON DELETE CASCADE" +"public.chat_hub_messages" }o--o| "public.workflow_entity" : "FOREIGN KEY (#quot;workflowId#quot;) REFERENCES workflow_entity(id) ON DELETE SET NULL" +"public.chat_hub_sessions" }o--o| "public.workflow_entity" : "FOREIGN KEY (#quot;workflowId#quot;) REFERENCES workflow_entity(id) ON DELETE SET NULL" +"public.evaluation_collection" }o--|| "public.workflow_entity" : "FOREIGN KEY (#quot;workflowId#quot;) REFERENCES workflow_entity(id) ON DELETE CASCADE" +"public.evaluation_config" }o--|| "public.workflow_entity" : "FOREIGN KEY (#quot;workflowId#quot;) REFERENCES workflow_entity(id) ON DELETE CASCADE" +"public.execution_entity" }o--|| "public.workflow_entity" : "FOREIGN KEY (#quot;workflowId#quot;) REFERENCES workflow_entity(id) ON DELETE CASCADE" +"public.insights_metadata" }o--o| "public.workflow_entity" : "FOREIGN KEY (#quot;workflowId#quot;) REFERENCES workflow_entity(id) ON DELETE SET NULL" +"public.processed_data" }o--|| "public.workflow_entity" : "FOREIGN KEY (#quot;workflowId#quot;) REFERENCES workflow_entity(id) ON DELETE CASCADE" +"public.shared_workflow" }o--|| "public.workflow_entity" : "FOREIGN KEY (#quot;workflowId#quot;) REFERENCES workflow_entity(id) ON DELETE CASCADE" +"public.test_run" }o--|| "public.workflow_entity" : "FOREIGN KEY (#quot;workflowId#quot;) REFERENCES workflow_entity(id) ON DELETE CASCADE" +"public.webhook_entity" }o--|| "public.workflow_entity" : "FOREIGN KEY (#quot;workflowId#quot;) REFERENCES workflow_entity(id) ON DELETE CASCADE" +"public.workflow_builder_session" }o--|| "public.workflow_entity" : "FOREIGN KEY (#quot;workflowId#quot;) REFERENCES workflow_entity(id) ON DELETE CASCADE" +"public.workflow_dependency" }o--|| "public.workflow_entity" : "FOREIGN KEY (#quot;workflowId#quot;) REFERENCES workflow_entity(id) ON DELETE CASCADE" +"public.workflow_history" }o--|| "public.workflow_entity" : "FOREIGN KEY (#quot;workflowId#quot;) REFERENCES workflow_entity(id) ON DELETE CASCADE" +"public.workflow_publish_history" }o--|| "public.workflow_entity" : "FOREIGN KEY (#quot;workflowId#quot;) REFERENCES workflow_entity(id) ON DELETE CASCADE" +"public.workflow_published_version" |o--|| "public.workflow_entity" : "FOREIGN KEY (#quot;workflowId#quot;) REFERENCES workflow_entity(id) ON DELETE RESTRICT" +"public.workflows_tags" }o--|| "public.workflow_entity" : "FOREIGN KEY (#quot;workflowId#quot;) REFERENCES workflow_entity(id) ON DELETE CASCADE" +"public.workflow_entity" }o--o| "public.folder" : "FOREIGN KEY (#quot;parentFolderId#quot;) REFERENCES folder(id) ON DELETE CASCADE" + +"public.workflow_entity" { + boolean active + varchar_36_ activeVersionId FK + json connections + timestamp_3__with_time_zone createdAt + text description + varchar_36_ id + boolean isArchived + json meta + varchar_128_ name + json nodeGroups + json nodes + varchar_36_ parentFolderId FK + json pinData + json settings + varchar sourceWorkflowId + json staticData + integer triggerCount + timestamp_3__with_time_zone updatedAt + integer versionCounter + character_36_ versionId +} +"public.workflow_history" { + varchar_255_ authors + boolean autosaved + json connections + timestamp_3__with_time_zone createdAt + text description + varchar_128_ name + json nodeGroups + json nodes + timestamp_3__with_time_zone updatedAt + varchar_36_ versionId + varchar_36_ workflowId FK +} +"public.ai_builder_temporary_workflow" { + timestamp_3__with_time_zone createdAt + uuid threadId FK + timestamp_3__with_time_zone updatedAt + varchar_36_ workflowId FK +} +"public.chat_hub_messages" { + uuid agentId FK + json attachments + text content + timestamp_3__with_time_zone createdAt + integer executionId FK + uuid id + varchar_256_ model + varchar_128_ name + uuid previousMessageId FK + varchar_16_ provider + uuid retryOfMessageId FK + uuid revisionOfMessageId FK + uuid sessionId FK + varchar_16_ status + varchar_16_ type + timestamp_3__with_time_zone updatedAt + varchar_36_ workflowId FK +} +"public.chat_hub_sessions" { + uuid agentId FK + varchar_128_ agentName + timestamp_3__with_time_zone createdAt + varchar_36_ credentialId FK + uuid id + timestamp_3__with_time_zone lastMessageAt + varchar_256_ model + uuid ownerId FK + varchar_16_ provider + varchar_256_ title + varchar_16_ type + timestamp_3__with_time_zone updatedAt + varchar_36_ workflowId FK +} +"public.evaluation_collection" { + timestamp_3__with_time_zone createdAt + uuid createdById FK + text description + varchar_36_ evaluationConfigId FK + varchar_36_ id + json insightsCache + varchar_128_ name + timestamp_3__with_time_zone updatedAt + varchar_36_ workflowId FK +} +"public.evaluation_config" { + timestamp_3__with_time_zone createdAt + json datasetRef + varchar_32_ datasetSource + varchar_255_ endNodeName + varchar_36_ id + varchar_64_ invalidReason + json metrics + varchar_128_ name + varchar_255_ startNodeName + varchar_16_ status + timestamp_3__with_time_zone updatedAt + varchar_36_ workflowId FK +} +"public.execution_entity" { + bigint binaryDataSizeBytes + timestamp_3__with_time_zone createdAt + varchar_255_ deduplicationKey + timestamp_3__with_time_zone deletedAt + boolean finished + integer id + bigint jsonSizeBytes + varchar mode + varchar retryOf + varchar retrySuccessId + timestamp_3__with_time_zone startedAt + varchar status + timestamp_3__with_time_zone stoppedAt + varchar_2_ storedAt + json tracingContext + timestamp_3__with_time_zone waitTill + varchar_36_ workflowId FK + varchar_36_ workflowVersionId +} +"public.insights_metadata" { + integer metaId + varchar_36_ projectId FK + varchar_255_ projectName + varchar_36_ workflowId FK + varchar_128_ workflowName +} +"public.processed_data" { + varchar_255_ context + timestamp_3__with_time_zone createdAt + timestamp_3__with_time_zone updatedAt + text value + varchar_36_ workflowId FK +} +"public.shared_workflow" { + timestamp_3__with_time_zone createdAt + varchar_36_ projectId FK + text role + timestamp_3__with_time_zone updatedAt + varchar_36_ workflowId FK +} +"public.test_run" { + boolean cancelRequested + varchar_36_ collectionId FK + timestamp_3__with_time_zone completedAt + timestamp_3__with_time_zone createdAt + varchar errorCode + json errorDetails + varchar_36_ evaluationConfigId FK + jsonb evaluationConfigSnapshot + varchar_36_ id + json metrics + timestamp_3__with_time_zone runAt + varchar_255_ runningInstanceId + varchar status + timestamp_3__with_time_zone updatedAt + varchar_36_ workflowId FK + varchar_36_ workflowVersionId +} +"public.webhook_entity" { + varchar method + varchar node + integer pathLength + varchar webhookId + varchar webhookPath + varchar_36_ workflowId FK +} +"public.workflow_builder_session" { + varchar_255_ activeVersionCardId + timestamp_3__with_time_zone createdAt + uuid id + json messages + text previousSummary + varchar_255_ resumeAfterRestoreMessageId + timestamp_3__with_time_zone updatedAt + uuid userId FK + varchar_36_ workflowId FK +} +"public.workflow_dependency" { + timestamp_3__with_time_zone createdAt + json dependencyInfo + varchar_255_ dependencyKey + varchar_32_ dependencyType + integer id + smallint indexVersionId + varchar_36_ publishedVersionId + varchar_36_ workflowId FK + integer workflowVersionId +} +"public.workflow_publish_history" { + timestamp_3__with_time_zone createdAt + varchar_36_ event + integer id + uuid userId FK + varchar_36_ versionId FK + varchar_36_ workflowId FK +} +"public.workflow_published_version" { + timestamp_3__with_time_zone createdAt + varchar_36_ publishedVersionId FK + timestamp_3__with_time_zone updatedAt + varchar_36_ workflowId FK +} +"public.workflows_tags" { + varchar_36_ tagId FK + varchar_36_ workflowId FK +} +"public.folder" { + timestamp_3__with_time_zone createdAt + varchar_36_ id + varchar_128_ name + varchar_36_ parentFolderId FK + varchar_36_ projectId FK + timestamp_3__with_time_zone updatedAt +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/postgres-schema/public.workflow_history.md b/docs/generated/postgres-schema/public.workflow_history.md new file mode 100644 index 00000000000..e832f5883a1 --- /dev/null +++ b/docs/generated/postgres-schema/public.workflow_history.md @@ -0,0 +1,105 @@ +# public.workflow_history + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| authors | varchar(255) | | false | | | | +| autosaved | boolean | false | false | | | | +| connections | json | | false | | | | +| createdAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| description | text | | true | | | | +| name | varchar(128) | | true | | | | +| nodeGroups | json | '[]'::json | false | | | | +| nodes | json | | false | | | | +| updatedAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| versionId | varchar(36) | | false | [public.workflow_entity](public.workflow_entity.md) [public.workflow_publish_history](public.workflow_publish_history.md) [public.workflow_published_version](public.workflow_published_version.md) | | | +| workflowId | varchar(36) | | false | | [public.workflow_entity](public.workflow_entity.md) | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| FK_1e31657f5fe46816c34be7c1b4b | FOREIGN KEY | FOREIGN KEY ("workflowId") REFERENCES workflow_entity(id) ON DELETE CASCADE | +| PK_b6572dd6173e4cd06fe79937b58 | PRIMARY KEY | PRIMARY KEY ("versionId") | +| workflow_history_authors_not_null | n | NOT NULL authors | +| workflow_history_autosaved_not_null | n | NOT NULL autosaved | +| workflow_history_connections_not_null | n | NOT NULL connections | +| workflow_history_createdAt_not_null | n | NOT NULL "createdAt" | +| workflow_history_nodeGroups_not_null | n | NOT NULL "nodeGroups" | +| workflow_history_nodes_not_null | n | NOT NULL nodes | +| workflow_history_updatedAt_not_null | n | NOT NULL "updatedAt" | +| workflow_history_versionId_not_null | n | NOT NULL "versionId" | +| workflow_history_workflowId_not_null | n | NOT NULL "workflowId" | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_1e31657f5fe46816c34be7c1b4 | CREATE INDEX "IDX_1e31657f5fe46816c34be7c1b4" ON public.workflow_history USING btree ("workflowId") | +| PK_b6572dd6173e4cd06fe79937b58 | CREATE UNIQUE INDEX "PK_b6572dd6173e4cd06fe79937b58" ON public.workflow_history USING btree ("versionId") | + +## Relations + +```mermaid +erDiagram + +"public.workflow_entity" }o--o| "public.workflow_history" : "FOREIGN KEY (#quot;activeVersionId#quot;) REFERENCES workflow_history(#quot;versionId#quot;) ON DELETE RESTRICT" +"public.workflow_publish_history" }o--o| "public.workflow_history" : "FOREIGN KEY (#quot;versionId#quot;) REFERENCES workflow_history(#quot;versionId#quot;) ON DELETE SET NULL" +"public.workflow_published_version" }o--|| "public.workflow_history" : "FOREIGN KEY (#quot;publishedVersionId#quot;) REFERENCES workflow_history(#quot;versionId#quot;) ON DELETE RESTRICT" +"public.workflow_history" }o--|| "public.workflow_entity" : "FOREIGN KEY (#quot;workflowId#quot;) REFERENCES workflow_entity(id) ON DELETE CASCADE" + +"public.workflow_history" { + varchar_255_ authors + boolean autosaved + json connections + timestamp_3__with_time_zone createdAt + text description + varchar_128_ name + json nodeGroups + json nodes + timestamp_3__with_time_zone updatedAt + varchar_36_ versionId + varchar_36_ workflowId FK +} +"public.workflow_entity" { + boolean active + varchar_36_ activeVersionId FK + json connections + timestamp_3__with_time_zone createdAt + text description + varchar_36_ id + boolean isArchived + json meta + varchar_128_ name + json nodeGroups + json nodes + varchar_36_ parentFolderId FK + json pinData + json settings + varchar sourceWorkflowId + json staticData + integer triggerCount + timestamp_3__with_time_zone updatedAt + integer versionCounter + character_36_ versionId +} +"public.workflow_publish_history" { + timestamp_3__with_time_zone createdAt + varchar_36_ event + integer id + uuid userId FK + varchar_36_ versionId FK + varchar_36_ workflowId FK +} +"public.workflow_published_version" { + timestamp_3__with_time_zone createdAt + varchar_36_ publishedVersionId FK + timestamp_3__with_time_zone updatedAt + varchar_36_ workflowId FK +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/postgres-schema/public.workflow_publication_outbox.md b/docs/generated/postgres-schema/public.workflow_publication_outbox.md new file mode 100644 index 00000000000..ad7fa1c44f9 --- /dev/null +++ b/docs/generated/postgres-schema/public.workflow_publication_outbox.md @@ -0,0 +1,54 @@ +# public.workflow_publication_outbox + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| createdAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| errorMessage | text | | true | | | Error details for surfacing failed publications to the user. | +| id | integer | | false | | | | +| publishedVersionId | varchar(36) | | false | | | References workflow_history.versionId. | +| status | varchar(20) | | false | | | | +| updatedAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| workflowId | varchar(36) | | false | | | References workflow_entity.id. | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| CHK_workflow_publication_outbox_status | CHECK | CHECK (((status)::text = ANY ((ARRAY['pending'::character varying, 'in_progress'::character varying, 'completed'::character varying, 'partial_success'::character varying, 'failed'::character varying])::text[]))) | +| PK_b3e2eeee36a4bd044d56468d311 | PRIMARY KEY | PRIMARY KEY (id) | +| workflow_publication_outbox_createdAt_not_null | n | NOT NULL "createdAt" | +| workflow_publication_outbox_id_not_null | n | NOT NULL id | +| workflow_publication_outbox_publishedVersionId_not_null | n | NOT NULL "publishedVersionId" | +| workflow_publication_outbox_status_not_null | n | NOT NULL status | +| workflow_publication_outbox_updatedAt_not_null | n | NOT NULL "updatedAt" | +| workflow_publication_outbox_workflowId_not_null | n | NOT NULL "workflowId" | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_workflow_publication_outbox_active_workflow_status | CREATE UNIQUE INDEX "IDX_workflow_publication_outbox_active_workflow_status" ON public.workflow_publication_outbox USING btree ("workflowId", status) WHERE ((status)::text = ANY ((ARRAY['pending'::character varying, 'in_progress'::character varying])::text[])) | +| PK_b3e2eeee36a4bd044d56468d311 | CREATE UNIQUE INDEX "PK_b3e2eeee36a4bd044d56468d311" ON public.workflow_publication_outbox USING btree (id) | + +## Relations + +```mermaid +erDiagram + + +"public.workflow_publication_outbox" { + timestamp_3__with_time_zone createdAt + text errorMessage + integer id + varchar_36_ publishedVersionId + varchar_20_ status + timestamp_3__with_time_zone updatedAt + varchar_36_ workflowId +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/postgres-schema/public.workflow_publish_history.md b/docs/generated/postgres-schema/public.workflow_publish_history.md new file mode 100644 index 00000000000..2c4f0341c3b --- /dev/null +++ b/docs/generated/postgres-schema/public.workflow_publish_history.md @@ -0,0 +1,108 @@ +# public.workflow_publish_history + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| createdAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| event | varchar(36) | | false | | | Type of history record: activated (workflow is now active), deactivated (workflow is now inactive) | +| id | integer | | false | | | | +| userId | uuid | | true | | [public.user](public.user.md) | | +| versionId | varchar(36) | | true | | [public.workflow_history](public.workflow_history.md) | | +| workflowId | varchar(36) | | false | | [public.workflow_entity](public.workflow_entity.md) | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| CHK_workflow_publish_history_event | CHECK | CHECK (((event)::text = ANY ((ARRAY['activated'::character varying, 'deactivated'::character varying])::text[]))) | +| FK_6eab5bd9eedabe9c54bd879fc40 | FOREIGN KEY | FOREIGN KEY ("userId") REFERENCES "user"(id) ON DELETE SET NULL | +| FK_b4cfbc7556d07f36ca177f5e473 | FOREIGN KEY | FOREIGN KEY ("versionId") REFERENCES workflow_history("versionId") ON DELETE SET NULL | +| FK_c01316f8c2d7101ec4fa9809267 | FOREIGN KEY | FOREIGN KEY ("workflowId") REFERENCES workflow_entity(id) ON DELETE CASCADE | +| PK_c788f7caf88e91e365c97d6d04a | PRIMARY KEY | PRIMARY KEY (id) | +| workflow_publish_history_createdAt_not_null | n | NOT NULL "createdAt" | +| workflow_publish_history_event_not_null | n | NOT NULL event | +| workflow_publish_history_id_not_null | n | NOT NULL id | +| workflow_publish_history_workflowId_not_null | n | NOT NULL "workflowId" | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_070b5de842ece9ccdda0d9738b | CREATE INDEX "IDX_070b5de842ece9ccdda0d9738b" ON public.workflow_publish_history USING btree ("workflowId", "versionId") | +| PK_c788f7caf88e91e365c97d6d04a | CREATE UNIQUE INDEX "PK_c788f7caf88e91e365c97d6d04a" ON public.workflow_publish_history USING btree (id) | + +## Relations + +```mermaid +erDiagram + +"public.workflow_publish_history" }o--o| "public.user" : "FOREIGN KEY (#quot;userId#quot;) REFERENCES #quot;user#quot;(id) ON DELETE SET NULL" +"public.workflow_publish_history" }o--o| "public.workflow_history" : "FOREIGN KEY (#quot;versionId#quot;) REFERENCES workflow_history(#quot;versionId#quot;) ON DELETE SET NULL" +"public.workflow_publish_history" }o--|| "public.workflow_entity" : "FOREIGN KEY (#quot;workflowId#quot;) REFERENCES workflow_entity(id) ON DELETE CASCADE" + +"public.workflow_publish_history" { + timestamp_3__with_time_zone createdAt + varchar_36_ event + integer id + uuid userId FK + varchar_36_ versionId FK + varchar_36_ workflowId FK +} +"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.workflow_history" { + varchar_255_ authors + boolean autosaved + json connections + timestamp_3__with_time_zone createdAt + text description + varchar_128_ name + json nodeGroups + json nodes + timestamp_3__with_time_zone updatedAt + varchar_36_ versionId + varchar_36_ workflowId FK +} +"public.workflow_entity" { + boolean active + varchar_36_ activeVersionId FK + json connections + timestamp_3__with_time_zone createdAt + text description + varchar_36_ id + boolean isArchived + json meta + varchar_128_ name + json nodeGroups + json nodes + varchar_36_ parentFolderId FK + json pinData + json settings + varchar sourceWorkflowId + json staticData + integer triggerCount + timestamp_3__with_time_zone updatedAt + integer versionCounter + character_36_ versionId +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/postgres-schema/public.workflow_published_version.md b/docs/generated/postgres-schema/public.workflow_published_version.md new file mode 100644 index 00000000000..63cd6bad5d6 --- /dev/null +++ b/docs/generated/postgres-schema/public.workflow_published_version.md @@ -0,0 +1,83 @@ +# public.workflow_published_version + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| createdAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| publishedVersionId | varchar(36) | | false | | [public.workflow_history](public.workflow_history.md) | | +| updatedAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| workflowId | varchar(36) | | false | | [public.workflow_entity](public.workflow_entity.md) | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| FK_5c76fb7ee939fe2530374d3f75a | FOREIGN KEY | FOREIGN KEY ("workflowId") REFERENCES workflow_entity(id) ON DELETE RESTRICT | +| FK_df3428a541b802d6a63ac56e330 | FOREIGN KEY | FOREIGN KEY ("publishedVersionId") REFERENCES workflow_history("versionId") ON DELETE RESTRICT | +| PK_5c76fb7ee939fe2530374d3f75a | PRIMARY KEY | PRIMARY KEY ("workflowId") | +| workflow_published_version_createdAt_not_null | n | NOT NULL "createdAt" | +| workflow_published_version_publishedVersionId_not_null | n | NOT NULL "publishedVersionId" | +| workflow_published_version_updatedAt_not_null | n | NOT NULL "updatedAt" | +| workflow_published_version_workflowId_not_null | n | NOT NULL "workflowId" | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| PK_5c76fb7ee939fe2530374d3f75a | CREATE UNIQUE INDEX "PK_5c76fb7ee939fe2530374d3f75a" ON public.workflow_published_version USING btree ("workflowId") | + +## Relations + +```mermaid +erDiagram + +"public.workflow_published_version" }o--|| "public.workflow_history" : "FOREIGN KEY (#quot;publishedVersionId#quot;) REFERENCES workflow_history(#quot;versionId#quot;) ON DELETE RESTRICT" +"public.workflow_published_version" |o--|| "public.workflow_entity" : "FOREIGN KEY (#quot;workflowId#quot;) REFERENCES workflow_entity(id) ON DELETE RESTRICT" + +"public.workflow_published_version" { + timestamp_3__with_time_zone createdAt + varchar_36_ publishedVersionId FK + timestamp_3__with_time_zone updatedAt + varchar_36_ workflowId FK +} +"public.workflow_history" { + varchar_255_ authors + boolean autosaved + json connections + timestamp_3__with_time_zone createdAt + text description + varchar_128_ name + json nodeGroups + json nodes + timestamp_3__with_time_zone updatedAt + varchar_36_ versionId + varchar_36_ workflowId FK +} +"public.workflow_entity" { + boolean active + varchar_36_ activeVersionId FK + json connections + timestamp_3__with_time_zone createdAt + text description + varchar_36_ id + boolean isArchived + json meta + varchar_128_ name + json nodeGroups + json nodes + varchar_36_ parentFolderId FK + json pinData + json settings + varchar sourceWorkflowId + json staticData + integer triggerCount + timestamp_3__with_time_zone updatedAt + integer versionCounter + character_36_ versionId +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/postgres-schema/public.workflow_statistics.md b/docs/generated/postgres-schema/public.workflow_statistics.md new file mode 100644 index 00000000000..19687528fe6 --- /dev/null +++ b/docs/generated/postgres-schema/public.workflow_statistics.md @@ -0,0 +1,50 @@ +# public.workflow_statistics + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| count | bigint | 0 | true | | | | +| id | integer | nextval('workflow_statistics_id_seq'::regclass) | false | | | | +| latestEvent | timestamp(3) with time zone | | true | | | | +| name | varchar(128) | | false | | | | +| rootCount | bigint | 0 | true | | | | +| workflowId | varchar(36) | | false | | | | +| workflowName | varchar(128) | | true | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| workflow_statistics_id_not_null | n | NOT NULL id | +| workflow_statistics_name_not_null | n | NOT NULL name | +| workflow_statistics_pkey | PRIMARY KEY | PRIMARY KEY (id) | +| workflow_statistics_workflowId_not_null1 | n | NOT NULL "workflowId" | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_workflow_statistics_workflow_name | CREATE UNIQUE INDEX "IDX_workflow_statistics_workflow_name" ON public.workflow_statistics USING btree ("workflowId", name) | +| workflow_statistics_pkey | CREATE UNIQUE INDEX workflow_statistics_pkey ON public.workflow_statistics USING btree (id) | + +## Relations + +```mermaid +erDiagram + + +"public.workflow_statistics" { + bigint count + integer id + timestamp_3__with_time_zone latestEvent + varchar_128_ name + bigint rootCount + varchar_36_ workflowId + varchar_128_ workflowName +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/postgres-schema/public.workflows_tags.md b/docs/generated/postgres-schema/public.workflows_tags.md new file mode 100644 index 00000000000..e5b96380794 --- /dev/null +++ b/docs/generated/postgres-schema/public.workflows_tags.md @@ -0,0 +1,71 @@ +# public.workflows_tags + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| tagId | varchar(36) | | false | | [public.tag_entity](public.tag_entity.md) | | +| workflowId | varchar(36) | | false | | [public.workflow_entity](public.workflow_entity.md) | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| fk_workflows_tags_tag_id | FOREIGN KEY | FOREIGN KEY ("tagId") REFERENCES tag_entity(id) ON DELETE CASCADE | +| fk_workflows_tags_workflow_id | FOREIGN KEY | FOREIGN KEY ("workflowId") REFERENCES workflow_entity(id) ON DELETE CASCADE | +| pk_workflows_tags | PRIMARY KEY | PRIMARY KEY ("workflowId", "tagId") | +| workflows_tags_tagId_not_null1 | n | NOT NULL "tagId" | +| workflows_tags_workflowId_not_null1 | n | NOT NULL "workflowId" | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| idx_workflows_tags_workflow_id | CREATE INDEX idx_workflows_tags_workflow_id ON public.workflows_tags USING btree ("workflowId") | +| pk_workflows_tags | CREATE UNIQUE INDEX pk_workflows_tags ON public.workflows_tags USING btree ("workflowId", "tagId") | + +## Relations + +```mermaid +erDiagram + +"public.workflows_tags" }o--|| "public.tag_entity" : "FOREIGN KEY (#quot;tagId#quot;) REFERENCES tag_entity(id) ON DELETE CASCADE" +"public.workflows_tags" }o--|| "public.workflow_entity" : "FOREIGN KEY (#quot;workflowId#quot;) REFERENCES workflow_entity(id) ON DELETE CASCADE" + +"public.workflows_tags" { + varchar_36_ tagId FK + varchar_36_ workflowId FK +} +"public.tag_entity" { + timestamp_3__with_time_zone createdAt + varchar_36_ id + varchar_24_ name + timestamp_3__with_time_zone updatedAt +} +"public.workflow_entity" { + boolean active + varchar_36_ activeVersionId FK + json connections + timestamp_3__with_time_zone createdAt + text description + varchar_36_ id + boolean isArchived + json meta + varchar_128_ name + json nodeGroups + json nodes + varchar_36_ parentFolderId FK + json pinData + json settings + varchar sourceWorkflowId + json staticData + integer triggerCount + timestamp_3__with_time_zone updatedAt + integer versionCounter + character_36_ versionId +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/sqlite-schema/README.md b/docs/generated/sqlite-schema/README.md new file mode 100644 index 00000000000..49775702016 --- /dev/null +++ b/docs/generated/sqlite-schema/README.md @@ -0,0 +1,1312 @@ +# n8n database schema (SQLite) + +## Description + +Auto-generated from the SQLite migrations in @n8n/db. Do not edit by hand. + +## Tables + +| Name | Columns | Comment | Type | +| ---- | ------- | ------- | ---- | +| [agent_chat_subscriptions](agent_chat_subscriptions.md) | 6 | | table | +| [agent_checkpoints](agent_checkpoints.md) | 6 | | table | +| [agent_execution](agent_execution.md) | 20 | | table | +| [agent_execution_threads](agent_execution_threads.md) | 17 | | table | +| [agent_files](agent_files.md) | 8 | | table | +| [agent_history](agent_history.md) | 9 | | table | +| [agent_task_definition](agent_task_definition.md) | 7 | | table | +| [agent_task_run_lock](agent_task_run_lock.md) | 6 | | table | +| [agent_task_snapshot](agent_task_snapshot.md) | 8 | | table | +| [agents](agents.md) | 12 | | table | +| [agents_memory_entries](agents_memory_entries.md) | 13 | | table | +| [agents_memory_entry_cursors](agents_memory_entry_cursors.md) | 6 | | table | +| [agents_memory_entry_locks](agents_memory_entry_locks.md) | 6 | | table | +| [agents_memory_entry_sources](agents_memory_entry_sources.md) | 9 | | table | +| [agents_messages](agents_messages.md) | 8 | | table | +| [agents_observation_cursors](agents_observation_cursors.md) | 6 | | table | +| [agents_observation_locks](agents_observation_locks.md) | 7 | | table | +| [agents_observations](agents_observations.md) | 11 | | table | +| [agents_resources](agents_resources.md) | 4 | | table | +| [agents_threads](agents_threads.md) | 6 | | table | +| [ai_builder_temporary_workflow](ai_builder_temporary_workflow.md) | 4 | | table | +| [annotation_tag_entity](annotation_tag_entity.md) | 4 | | table | +| [auth_identity](auth_identity.md) | 5 | | table | +| [auth_provider_sync_history](auth_provider_sync_history.md) | 11 | | table | +| [binary_data](binary_data.md) | 9 | | table | +| [chat_hub_agent_tools](chat_hub_agent_tools.md) | 2 | | table | +| [chat_hub_agents](chat_hub_agents.md) | 13 | | table | +| [chat_hub_messages](chat_hub_messages.md) | 17 | | table | +| [chat_hub_session_tools](chat_hub_session_tools.md) | 2 | | table | +| [chat_hub_sessions](chat_hub_sessions.md) | 13 | | table | +| [chat_hub_tools](chat_hub_tools.md) | 9 | | table | +| [credential_dependency](credential_dependency.md) | 5 | | table | +| [credentials_entity](credentials_entity.md) | 11 | | table | +| [data_table](data_table.md) | 5 | | table | +| [data_table_column](data_table_column.md) | 7 | | table | +| [deployment_key](deployment_key.md) | 7 | | table | +| [dynamic_credential_entry](dynamic_credential_entry.md) | 6 | | table | +| [dynamic_credential_resolver](dynamic_credential_resolver.md) | 6 | | table | +| [dynamic_credential_user_entry](dynamic_credential_user_entry.md) | 6 | | table | +| [evaluation_collection](evaluation_collection.md) | 9 | | table | +| [evaluation_config](evaluation_config.md) | 12 | | table | +| [event_destinations](event_destinations.md) | 4 | | table | +| [execution_annotation_tags](execution_annotation_tags.md) | 2 | | table | +| [execution_annotations](execution_annotations.md) | 6 | | table | +| [execution_data](execution_data.md) | 4 | | table | +| [execution_entity](execution_entity.md) | 18 | | table | +| [execution_metadata](execution_metadata.md) | 4 | | table | +| [folder](folder.md) | 6 | | table | +| [folder_tag](folder_tag.md) | 2 | | table | +| [insights_by_period](insights_by_period.md) | 6 | | table | +| [insights_metadata](insights_metadata.md) | 5 | | table | +| [insights_raw](insights_raw.md) | 5 | | table | +| [installed_nodes](installed_nodes.md) | 4 | | table | +| [installed_packages](installed_packages.md) | 6 | | table | +| [instance_ai_checkpoints](instance_ai_checkpoints.md) | 8 | | table | +| [instance_ai_iteration_logs](instance_ai_iteration_logs.md) | 6 | | table | +| [instance_ai_mcp_registry_connections](instance_ai_mcp_registry_connections.md) | 7 | | table | +| [instance_ai_messages](instance_ai_messages.md) | 8 | | table | +| [instance_ai_observation_cursors](instance_ai_observation_cursors.md) | 5 | | table | +| [instance_ai_observation_locks](instance_ai_observation_locks.md) | 6 | | table | +| [instance_ai_observational_memory](instance_ai_observational_memory.md) | 32 | | table | +| [instance_ai_observations](instance_ai_observations.md) | 10 | | table | +| [instance_ai_pending_confirmations](instance_ai_pending_confirmations.md) | 12 | | table | +| [instance_ai_resources](instance_ai_resources.md) | 5 | | table | +| [instance_ai_run_snapshots](instance_ai_run_snapshots.md) | 11 | | table | +| [instance_ai_threads](instance_ai_threads.md) | 7 | | table | +| [instance_ai_workflow_snapshots](instance_ai_workflow_snapshots.md) | 7 | | table | +| [instance_version_history](instance_version_history.md) | 5 | | table | +| [invalid_auth_token](invalid_auth_token.md) | 2 | | table | +| [mcp_registry_server](mcp_registry_server.md) | 7 | | table | +| [oauth_access_tokens](oauth_access_tokens.md) | 3 | | table | +| [oauth_authorization_codes](oauth_authorization_codes.md) | 13 | | table | +| [oauth_clients](oauth_clients.md) | 9 | | table | +| [oauth_refresh_tokens](oauth_refresh_tokens.md) | 7 | | table | +| [oauth_user_consents](oauth_user_consents.md) | 4 | | table | +| [processed_data](processed_data.md) | 5 | | table | +| [project](project.md) | 9 | | table | +| [project_relation](project_relation.md) | 5 | | table | +| [project_secrets_provider_access](project_secrets_provider_access.md) | 5 | | table | +| [role](role.md) | 7 | | table | +| [role_mapping_rule](role_mapping_rule.md) | 7 | | table | +| [role_mapping_rule_project](role_mapping_rule_project.md) | 2 | | table | +| [role_scope](role_scope.md) | 2 | | table | +| [scope](scope.md) | 3 | | table | +| [secrets_provider_connection](secrets_provider_connection.md) | 7 | | table | +| [settings](settings.md) | 3 | | table | +| [shared_credentials](shared_credentials.md) | 5 | | table | +| [shared_workflow](shared_workflow.md) | 5 | | table | +| [tag_entity](tag_entity.md) | 4 | | table | +| [test_case_execution](test_case_execution.md) | 16 | | table | +| [test_run](test_run.md) | 16 | | table | +| [token_exchange_jti](token_exchange_jti.md) | 3 | | table | +| [trusted_key](trusted_key.md) | 4 | | table | +| [trusted_key_source](trusted_key_source.md) | 8 | | table | +| [user](user.md) | 15 | | table | +| [user_api_keys](user_api_keys.md) | 9 | | table | +| [user_favorites](user_favorites.md) | 4 | | table | +| [variables](variables.md) | 5 | | table | +| [webhook_entity](webhook_entity.md) | 6 | | table | +| [workflow_builder_session](workflow_builder_session.md) | 9 | | table | +| [workflow_dependency](workflow_dependency.md) | 9 | | table | +| [workflow_entity](workflow_entity.md) | 20 | | table | +| [workflow_history](workflow_history.md) | 11 | | table | +| [workflow_publication_outbox](workflow_publication_outbox.md) | 7 | | table | +| [workflow_publish_history](workflow_publish_history.md) | 6 | | table | +| [workflow_published_version](workflow_published_version.md) | 4 | | table | +| [workflow_statistics](workflow_statistics.md) | 7 | | table | +| [workflows_tags](workflows_tags.md) | 2 | | table | + +## Relations + +```mermaid +erDiagram + +"agent_chat_subscriptions" |o--|| "agents" : "FOREIGN KEY (agentId) REFERENCES agents (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"agent_checkpoints" }o--o| "agents" : "FOREIGN KEY (agentId) REFERENCES agents (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"agent_execution" }o--|| "agent_execution_threads" : "FOREIGN KEY (threadId) REFERENCES agent_execution_threads (id) ON UPDATE NO ACTION ON DELETE CASCADE 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_execution_threads" }o--|| "agents" : "FOREIGN KEY (agentId) REFERENCES agents (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"agent_execution_threads" }o--|| "project" : "FOREIGN KEY (projectId) REFERENCES project (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--o| "user" : "FOREIGN KEY (publishedById) REFERENCES user (id) ON UPDATE NO ACTION ON DELETE SET NULL MATCH NONE" +"agent_history" }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" +"agents" }o--o| "agent_history" : "FOREIGN KEY (activeVersionId) REFERENCES agent_history (versionId) ON UPDATE NO ACTION ON DELETE SET NULL MATCH NONE" +"agents" }o--|| "project" : "FOREIGN KEY (projectId) REFERENCES project (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"agents_memory_entries" }o--o| "agents_memory_entries" : "FOREIGN KEY (supersededBy) REFERENCES agents_memory_entries (id) ON UPDATE NO ACTION ON DELETE NO ACTION MATCH NONE" +"agents_memory_entries" }o--|| "agents_resources" : "FOREIGN KEY (resourceId) REFERENCES agents_resources (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"agents_memory_entries" }o--|| "agents" : "FOREIGN KEY (agentId) REFERENCES agents (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"agents_memory_entry_cursors" |o--|| "agents_threads" : "FOREIGN KEY (observationScopeId) REFERENCES agents_threads (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"agents_memory_entry_cursors" |o--|| "agents" : "FOREIGN KEY (agentId) REFERENCES agents (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"agents_memory_entry_locks" |o--|| "agents_resources" : "FOREIGN KEY (resourceId) REFERENCES agents_resources (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"agents_memory_entry_locks" |o--|| "agents" : "FOREIGN KEY (agentId) REFERENCES agents (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"agents_memory_entry_sources" }o--|| "agents_threads" : "FOREIGN KEY (threadId) REFERENCES agents_threads (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"agents_memory_entry_sources" }o--|| "agents_observations" : "FOREIGN KEY (observationId) REFERENCES agents_observations (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"agents_memory_entry_sources" }o--|| "agents_memory_entries" : "FOREIGN KEY (memoryEntryId) REFERENCES agents_memory_entries (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"agents_memory_entry_sources" }o--|| "agents" : "FOREIGN KEY (agentId) REFERENCES agents (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"agents_messages" }o--|| "agents_threads" : "FOREIGN KEY (threadId) REFERENCES agents_threads (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"agents_observation_cursors" |o--|| "agents_threads" : "FOREIGN KEY (observationScopeId) REFERENCES agents_threads (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"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_threads" : "FOREIGN KEY (observationScopeId) REFERENCES agents_threads (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--o| "agents_observations" : "FOREIGN KEY (supersededBy) REFERENCES agents_observations (id) ON UPDATE NO ACTION ON DELETE NO ACTION MATCH NONE" +"agents_observations" }o--o| "agents_observations" : "FOREIGN KEY (parentId) REFERENCES agents_observations (id) ON UPDATE NO ACTION ON DELETE NO ACTION MATCH NONE" +"agents_observations" }o--|| "agents_threads" : "FOREIGN KEY (observationScopeId) REFERENCES agents_threads (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" +"ai_builder_temporary_workflow" }o--|| "instance_ai_threads" : "FOREIGN KEY (threadId) REFERENCES instance_ai_threads (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"ai_builder_temporary_workflow" |o--|| "workflow_entity" : "FOREIGN KEY (workflowId) REFERENCES workflow_entity (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"auth_identity" }o--o| "user" : "FOREIGN KEY (userId) REFERENCES user (id) ON UPDATE NO ACTION ON DELETE NO ACTION MATCH NONE" +"chat_hub_agent_tools" |o--|| "chat_hub_tools" : "FOREIGN KEY (toolId) REFERENCES chat_hub_tools (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"chat_hub_agent_tools" |o--|| "chat_hub_agents" : "FOREIGN KEY (agentId) REFERENCES chat_hub_agents (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"chat_hub_agents" }o--|| "user" : "FOREIGN KEY (ownerId) REFERENCES user (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"chat_hub_agents" }o--o| "credentials_entity" : "FOREIGN KEY (credentialId) REFERENCES credentials_entity (id) ON UPDATE NO ACTION ON DELETE SET NULL MATCH NONE" +"chat_hub_messages" }o--o| "chat_hub_agents" : "FOREIGN KEY (agentId) REFERENCES chat_hub_agents (id) ON UPDATE NO ACTION ON DELETE SET NULL MATCH NONE" +"chat_hub_messages" }o--o| "execution_entity" : "FOREIGN KEY (executionId) REFERENCES execution_entity (id) ON UPDATE NO ACTION ON DELETE SET NULL MATCH NONE" +"chat_hub_messages" }o--o| "chat_hub_messages" : "FOREIGN KEY (revisionOfMessageId) REFERENCES chat_hub_messages (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"chat_hub_messages" }o--o| "chat_hub_messages" : "FOREIGN KEY (retryOfMessageId) REFERENCES chat_hub_messages (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"chat_hub_messages" }o--o| "workflow_entity" : "FOREIGN KEY (workflowId) REFERENCES workflow_entity (id) ON UPDATE NO ACTION ON DELETE SET NULL MATCH NONE" +"chat_hub_messages" }o--o| "chat_hub_messages" : "FOREIGN KEY (previousMessageId) REFERENCES chat_hub_messages (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"chat_hub_messages" }o--|| "chat_hub_sessions" : "FOREIGN KEY (sessionId) REFERENCES chat_hub_sessions (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"chat_hub_session_tools" |o--|| "chat_hub_tools" : "FOREIGN KEY (toolId) REFERENCES chat_hub_tools (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"chat_hub_session_tools" |o--|| "chat_hub_sessions" : "FOREIGN KEY (sessionId) REFERENCES chat_hub_sessions (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"chat_hub_sessions" }o--|| "user" : "FOREIGN KEY (ownerId) REFERENCES user (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"chat_hub_sessions" }o--o| "credentials_entity" : "FOREIGN KEY (credentialId) REFERENCES credentials_entity (id) ON UPDATE NO ACTION ON DELETE SET NULL MATCH NONE" +"chat_hub_sessions" }o--o| "workflow_entity" : "FOREIGN KEY (workflowId) REFERENCES workflow_entity (id) ON UPDATE NO ACTION ON DELETE SET NULL MATCH NONE" +"chat_hub_sessions" }o--o| "chat_hub_agents" : "FOREIGN KEY (agentId) REFERENCES chat_hub_agents (id) ON UPDATE NO ACTION ON DELETE SET NULL MATCH NONE" +"chat_hub_tools" }o--|| "user" : "FOREIGN KEY (ownerId) REFERENCES user (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"credential_dependency" }o--|| "credentials_entity" : "FOREIGN KEY (credentialId) REFERENCES credentials_entity (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"credentials_entity" }o--o| "dynamic_credential_resolver" : "FOREIGN KEY (resolverId) REFERENCES dynamic_credential_resolver (id) ON UPDATE NO ACTION ON DELETE SET NULL MATCH NONE" +"data_table" }o--|| "project" : "FOREIGN KEY (projectId) REFERENCES project (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"data_table_column" }o--|| "data_table" : "FOREIGN KEY (dataTableId) REFERENCES data_table (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"dynamic_credential_entry" |o--|| "dynamic_credential_resolver" : "FOREIGN KEY (resolver_id) REFERENCES dynamic_credential_resolver (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"dynamic_credential_entry" |o--|| "credentials_entity" : "FOREIGN KEY (credential_id) REFERENCES credentials_entity (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"dynamic_credential_user_entry" |o--|| "user" : "FOREIGN KEY (userId) REFERENCES user (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"dynamic_credential_user_entry" |o--|| "dynamic_credential_resolver" : "FOREIGN KEY (resolverId) REFERENCES dynamic_credential_resolver (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"dynamic_credential_user_entry" |o--|| "credentials_entity" : "FOREIGN KEY (credentialId) REFERENCES credentials_entity (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"evaluation_collection" }o--o| "user" : "FOREIGN KEY (createdById) REFERENCES user (id) ON UPDATE NO ACTION ON DELETE SET NULL MATCH NONE" +"evaluation_collection" }o--|| "evaluation_config" : "FOREIGN KEY (evaluationConfigId) REFERENCES evaluation_config (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"evaluation_collection" }o--|| "workflow_entity" : "FOREIGN KEY (workflowId) REFERENCES workflow_entity (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"evaluation_config" }o--|| "workflow_entity" : "FOREIGN KEY (workflowId) REFERENCES workflow_entity (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"execution_annotation_tags" |o--|| "annotation_tag_entity" : "FOREIGN KEY (tagId) REFERENCES annotation_tag_entity (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"execution_annotation_tags" |o--|| "execution_annotations" : "FOREIGN KEY (annotationId) REFERENCES execution_annotations (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"execution_annotations" }o--|| "execution_entity" : "FOREIGN KEY (executionId) REFERENCES execution_entity (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"execution_data" |o--|| "execution_entity" : "FOREIGN KEY (executionId) REFERENCES execution_entity (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"execution_entity" }o--|| "workflow_entity" : "FOREIGN KEY (workflowId) REFERENCES workflow_entity (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"execution_metadata" }o--|| "execution_entity" : "FOREIGN KEY (executionId) REFERENCES execution_entity (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"folder" }o--o| "folder" : "FOREIGN KEY (parentFolderId) REFERENCES folder (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"folder" }o--|| "project" : "FOREIGN KEY (projectId) REFERENCES project (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"folder_tag" |o--|| "tag_entity" : "FOREIGN KEY (tagId) REFERENCES tag_entity (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"folder_tag" |o--|| "folder" : "FOREIGN KEY (folderId) REFERENCES folder (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"insights_by_period" }o--|| "insights_metadata" : "FOREIGN KEY (metaId) REFERENCES insights_metadata (metaId) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"insights_metadata" }o--o| "project" : "FOREIGN KEY (projectId) REFERENCES project (id) ON UPDATE NO ACTION ON DELETE SET NULL MATCH NONE" +"insights_metadata" }o--o| "workflow_entity" : "FOREIGN KEY (workflowId) REFERENCES workflow_entity (id) ON UPDATE NO ACTION ON DELETE SET NULL MATCH NONE" +"insights_raw" }o--|| "insights_metadata" : "FOREIGN KEY (metaId) REFERENCES insights_metadata (metaId) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"installed_nodes" }o--|| "installed_packages" : "FOREIGN KEY (package) REFERENCES installed_packages (packageName) ON UPDATE CASCADE ON DELETE CASCADE MATCH NONE" +"instance_ai_checkpoints" }o--|| "instance_ai_threads" : "FOREIGN KEY (threadId) REFERENCES instance_ai_threads (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"instance_ai_iteration_logs" }o--|| "instance_ai_threads" : "FOREIGN KEY (threadId) REFERENCES instance_ai_threads (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"instance_ai_mcp_registry_connections" }o--|| "user" : "FOREIGN KEY (userId) REFERENCES user (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"instance_ai_mcp_registry_connections" }o--|| "mcp_registry_server" : "FOREIGN KEY (serverSlug) REFERENCES mcp_registry_server (slug) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"instance_ai_mcp_registry_connections" }o--|| "credentials_entity" : "FOREIGN KEY (credentialId) REFERENCES credentials_entity (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"instance_ai_messages" }o--|| "instance_ai_threads" : "FOREIGN KEY (threadId) REFERENCES instance_ai_threads (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"instance_ai_observation_cursors" |o--|| "instance_ai_threads" : "FOREIGN KEY (observationScopeId) REFERENCES instance_ai_threads (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"instance_ai_observation_locks" |o--|| "instance_ai_threads" : "FOREIGN KEY (observationScopeId) REFERENCES instance_ai_threads (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"instance_ai_observational_memory" }o--o| "instance_ai_threads" : "FOREIGN KEY (threadId) REFERENCES instance_ai_threads (id) ON UPDATE NO ACTION ON DELETE SET NULL MATCH NONE" +"instance_ai_observations" }o--o| "instance_ai_observations" : "FOREIGN KEY (supersededBy) REFERENCES instance_ai_observations (id) ON UPDATE NO ACTION ON DELETE NO ACTION MATCH NONE" +"instance_ai_observations" }o--o| "instance_ai_observations" : "FOREIGN KEY (parentId) REFERENCES instance_ai_observations (id) ON UPDATE NO ACTION ON DELETE NO ACTION MATCH NONE" +"instance_ai_observations" }o--|| "instance_ai_threads" : "FOREIGN KEY (observationScopeId) REFERENCES instance_ai_threads (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"instance_ai_pending_confirmations" }o--o| "instance_ai_checkpoints" : "FOREIGN KEY (checkpointKey) REFERENCES instance_ai_checkpoints (key) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"instance_ai_pending_confirmations" }o--|| "user" : "FOREIGN KEY (userId) REFERENCES user (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"instance_ai_pending_confirmations" }o--|| "instance_ai_threads" : "FOREIGN KEY (threadId) REFERENCES instance_ai_threads (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"instance_ai_run_snapshots" |o--|| "instance_ai_threads" : "FOREIGN KEY (threadId) REFERENCES instance_ai_threads (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"instance_ai_threads" }o--|| "project" : "FOREIGN KEY (projectId) REFERENCES project (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"oauth_access_tokens" }o--|| "user" : "FOREIGN KEY (userId) REFERENCES user (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"oauth_access_tokens" }o--|| "oauth_clients" : "FOREIGN KEY (clientId) REFERENCES oauth_clients (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"oauth_authorization_codes" }o--|| "oauth_clients" : "FOREIGN KEY (clientId) REFERENCES oauth_clients (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"oauth_authorization_codes" }o--|| "user" : "FOREIGN KEY (userId) REFERENCES user (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"oauth_refresh_tokens" }o--|| "oauth_clients" : "FOREIGN KEY (clientId) REFERENCES oauth_clients (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"oauth_refresh_tokens" }o--|| "user" : "FOREIGN KEY (userId) REFERENCES user (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"oauth_user_consents" }o--|| "user" : "FOREIGN KEY (userId) REFERENCES user (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"oauth_user_consents" }o--|| "oauth_clients" : "FOREIGN KEY (clientId) REFERENCES oauth_clients (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"processed_data" |o--|| "workflow_entity" : "FOREIGN KEY (workflowId) REFERENCES workflow_entity (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"project" }o--o| "user" : "FOREIGN KEY (creatorId) REFERENCES user (id) ON UPDATE NO ACTION ON DELETE SET NULL MATCH NONE" +"project_relation" }o--|| "role" : "FOREIGN KEY (role) REFERENCES role (slug) ON UPDATE NO ACTION ON DELETE NO ACTION MATCH NONE" +"project_relation" |o--|| "project" : "FOREIGN KEY (projectId) REFERENCES project (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"project_relation" |o--|| "user" : "FOREIGN KEY (userId) REFERENCES user (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"project_secrets_provider_access" |o--|| "secrets_provider_connection" : "FOREIGN KEY (secretsProviderConnectionId) REFERENCES secrets_provider_connection (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"project_secrets_provider_access" |o--|| "project" : "FOREIGN KEY (projectId) REFERENCES project (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"role_mapping_rule" }o--|| "role" : "FOREIGN KEY (role) REFERENCES role (slug) ON UPDATE CASCADE ON DELETE CASCADE MATCH NONE" +"role_mapping_rule_project" |o--|| "project" : "FOREIGN KEY (projectId) REFERENCES project (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"role_mapping_rule_project" |o--|| "role_mapping_rule" : "FOREIGN KEY (roleMappingRuleId) REFERENCES role_mapping_rule (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"role_scope" |o--|| "scope" : "FOREIGN KEY (scopeSlug) REFERENCES scope (slug) ON UPDATE CASCADE ON DELETE CASCADE MATCH NONE" +"role_scope" |o--|| "role" : "FOREIGN KEY (roleSlug) REFERENCES role (slug) ON UPDATE CASCADE 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_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" +"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" +"test_case_execution" }o--o| "execution_entity" : "FOREIGN KEY (evaluationExecutionId) REFERENCES execution_entity (id) ON UPDATE NO ACTION ON DELETE SET NULL MATCH NONE" +"test_run" }o--o| "evaluation_collection" : "FOREIGN KEY (collectionId) REFERENCES evaluation_collection (id) ON UPDATE NO ACTION ON DELETE SET NULL MATCH NONE" +"test_run" }o--|| "workflow_entity" : "FOREIGN KEY (workflowId) REFERENCES workflow_entity (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"test_run" }o--o| "evaluation_config" : "FOREIGN KEY (evaluationConfigId) REFERENCES evaluation_config (id) ON UPDATE NO ACTION ON DELETE SET NULL MATCH NONE" +"trusted_key" |o--|| "trusted_key_source" : "FOREIGN KEY (sourceId) REFERENCES trusted_key_source (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"user" }o--|| "role" : "FOREIGN KEY (roleSlug) REFERENCES role (slug) ON UPDATE NO ACTION ON DELETE NO ACTION 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" +"variables" }o--o| "project" : "FOREIGN KEY (projectId) REFERENCES project (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"workflow_builder_session" }o--|| "workflow_entity" : "FOREIGN KEY (workflowId) REFERENCES workflow_entity (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"workflow_builder_session" }o--|| "user" : "FOREIGN KEY (userId) REFERENCES user (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"workflow_dependency" }o--|| "workflow_entity" : "FOREIGN KEY (workflowId) REFERENCES workflow_entity (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"workflow_entity" }o--o| "workflow_history" : "FOREIGN KEY (activeVersionId) REFERENCES workflow_history (versionId) ON UPDATE NO ACTION ON DELETE RESTRICT MATCH NONE" +"workflow_entity" }o--o| "folder" : "FOREIGN KEY (parentFolderId) REFERENCES folder (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"workflow_history" }o--|| "workflow_entity" : "FOREIGN KEY (workflowId) REFERENCES workflow_entity (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"workflow_publish_history" }o--o| "workflow_history" : "FOREIGN KEY (versionId) REFERENCES workflow_history (versionId) ON UPDATE NO ACTION ON DELETE SET NULL MATCH NONE" +"workflow_publish_history" }o--o| "user" : "FOREIGN KEY (userId) REFERENCES user (id) ON UPDATE NO ACTION ON DELETE SET NULL MATCH NONE" +"workflow_publish_history" }o--o| "workflow_history" : "FOREIGN KEY (versionId) REFERENCES workflow_history (versionId) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"workflow_publish_history" }o--|| "workflow_entity" : "FOREIGN KEY (workflowId) REFERENCES workflow_entity (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"workflow_published_version" }o--|| "workflow_history" : "FOREIGN KEY (publishedVersionId) REFERENCES workflow_history (versionId) ON UPDATE NO ACTION ON DELETE RESTRICT MATCH NONE" +"workflow_published_version" |o--|| "workflow_entity" : "FOREIGN KEY (workflowId) REFERENCES workflow_entity (id) ON UPDATE NO ACTION ON DELETE RESTRICT MATCH NONE" +"workflow_published_version" |o--|| "workflow_entity" : "FOREIGN KEY (workflowId) REFERENCES workflow_entity (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"workflow_published_version" }o--|| "workflow_history" : "FOREIGN KEY (publishedVersionId) REFERENCES workflow_history (versionId) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"workflows_tags" |o--|| "tag_entity" : "FOREIGN KEY (tagId) REFERENCES tag_entity (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"workflows_tags" |o--|| "workflow_entity" : "FOREIGN KEY (workflowId) REFERENCES workflow_entity (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" + +"agent_chat_subscriptions" { + varchar_36_ agentId PK + datetime_3_ createdAt + varchar_255_ credentialId PK + varchar_64_ integrationType PK + varchar_255_ threadId PK + datetime_3_ updatedAt +} +"agent_checkpoints" { + varchar_255_ agentId FK + datetime_3_ createdAt + boolean expired + varchar_255_ runId PK + TEXT state + datetime_3_ updatedAt +} +"agent_execution" { + TEXT assistantResponse + INTEGER completionTokens + REAL cost + datetime_3_ createdAt + INTEGER duration + TEXT error + varchar_16_ hitlStatus + varchar_36_ id PK + varchar_255_ model + INTEGER promptTokens + varchar_32_ source + datetime_3_ startedAt + varchar_16_ status + datetime_3_ stoppedAt + varchar_128_ threadId FK + TEXT timeline + TEXT toolCalls + INTEGER totalTokens + datetime_3_ updatedAt + TEXT userMessage +} +"agent_execution_threads" { + varchar_36_ agentId FK + varchar_255_ agentName + datetime_3_ createdAt + varchar_8_ emoji + varchar_128_ id PK + varchar_36_ parentAgentId + varchar_128_ parentThreadId + varchar_255_ projectId FK + INTEGER sessionNumber + varchar_32_ taskId + varchar_36_ taskVersionId FK + varchar_255_ title + INTEGER totalCompletionTokens + REAL totalCost + INTEGER totalDuration + INTEGER totalPromptTokens + datetime_3_ updatedAt +} +"agent_files" { + varchar_36_ agentId FK + TEXT binaryDataId + datetime_3_ createdAt + varchar_255_ fileName + INTEGER fileSizeBytes + varchar_16_ id PK + varchar_255_ mimeType + datetime_3_ updatedAt +} +"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 +} +"agent_task_definition" { + varchar_36_ agentId FK + datetime_3_ createdAt + varchar_128_ cronExpression + varchar_32_ id PK + varchar_128_ name + TEXT objective + datetime_3_ updatedAt +} +"agent_task_run_lock" { + varchar_36_ agentId PK + datetime_3_ createdAt + datetime_3_ heldUntil + varchar holderId + varchar_32_ taskId PK + datetime_3_ updatedAt +} +"agent_task_snapshot" { + datetime_3_ createdAt + varchar_128_ cronExpression + boolean enabled + varchar_128_ name + TEXT objective + varchar_32_ taskId PK + datetime_3_ updatedAt + varchar_36_ versionId PK +} +"agents" { + varchar_36_ activeVersionId FK + datetime_3_ createdAt + varchar_512_ description + varchar_36_ id PK + TEXT integrations + varchar_128_ name + varchar_255_ projectId FK + TEXT schema + TEXT skills + TEXT tools + datetime_3_ updatedAt + varchar_36_ versionId +} +"agents_memory_entries" { + varchar_36_ agentId FK + TEXT content + varchar_64_ contentHash + datetime_3_ createdAt + TEXT embedding + varchar_128_ embeddingModel + varchar_36_ id PK + datetime_3_ lastSeenAt + TEXT metadata + varchar_255_ resourceId FK + varchar_16_ status + varchar_36_ supersededBy FK + datetime_3_ updatedAt +} +"agents_memory_entry_cursors" { + varchar_36_ agentId PK + datetime_3_ createdAt + datetime_3_ lastIndexedObservationCreatedAt + varchar_36_ lastIndexedObservationId + varchar_255_ observationScopeId PK + datetime_3_ updatedAt +} +"agents_memory_entry_locks" { + varchar_36_ agentId PK + datetime_3_ createdAt + datetime_3_ heldUntil + varchar_64_ holderId + varchar_255_ resourceId PK + datetime_3_ updatedAt +} +"agents_memory_entry_sources" { + varchar_36_ agentId FK + datetime_3_ createdAt + varchar_64_ evidenceHash + TEXT evidenceText + varchar_36_ id PK + varchar_36_ memoryEntryId FK + varchar_36_ observationId FK + varchar_255_ threadId FK + datetime_3_ updatedAt +} +"agents_messages" { + TEXT content + datetime_3_ createdAt + varchar_36_ id PK + varchar_255_ resourceId + varchar_36_ role + varchar_255_ threadId FK + varchar_36_ type + datetime_3_ updatedAt +} +"agents_observation_cursors" { + varchar_36_ agentId PK + datetime_3_ createdAt + datetime_3_ lastObservedAt + varchar_36_ lastObservedMessageId + varchar_255_ observationScopeId PK + datetime_3_ updatedAt +} +"agents_observation_locks" { + varchar_36_ agentId PK + datetime_3_ createdAt + datetime_3_ heldUntil + varchar_64_ holderId + varchar_255_ observationScopeId PK + varchar_20_ taskKind PK + datetime_3_ updatedAt +} +"agents_observations" { + varchar_36_ agentId FK + datetime_3_ createdAt + varchar_36_ id PK + varchar_16_ marker + varchar_255_ observationScopeId FK + varchar_36_ parentId FK + varchar_16_ status + varchar_36_ supersededBy FK + TEXT text + INTEGER tokenCount + datetime_3_ updatedAt +} +"agents_resources" { + datetime_3_ createdAt + varchar_255_ id PK + TEXT metadata + datetime_3_ updatedAt +} +"agents_threads" { + datetime_3_ createdAt + varchar_128_ id PK + TEXT metadata + varchar_255_ resourceId + varchar_255_ title + datetime_3_ updatedAt +} +"ai_builder_temporary_workflow" { + datetime_3_ createdAt + varchar threadId FK + datetime_3_ updatedAt + varchar_36_ workflowId PK +} +"annotation_tag_entity" { + datetime_3_ createdAt + varchar_16_ id PK + varchar_24_ name + datetime_3_ updatedAt +} +"auth_identity" { + timestamp createdAt + VARCHAR_64_ providerId PK + VARCHAR_32_ providerType PK + timestamp updatedAt + VARCHAR_36_ userId FK +} +"auth_provider_sync_history" { + INTEGER created + INTEGER disabled + DATETIME endedAt + TEXT error + INTEGER id + VARCHAR_32_ providerType + TEXT runMode + INTEGER scanned + DATETIME startedAt + TEXT status + INTEGER updated +} +"binary_data" { + datetime_3_ createdAt + BLOB data + varchar fileId PK + varchar_255_ fileName + INTEGER fileSize + varchar_255_ mimeType + varchar_255_ sourceId + varchar_50_ sourceType + datetime_3_ updatedAt +} +"chat_hub_agent_tools" { + varchar agentId PK + varchar toolId PK +} +"chat_hub_agents" { + datetime_3_ createdAt + varchar_36_ credentialId FK + varchar_512_ description + TEXT files + TEXT icon + varchar id PK + varchar_64_ model + varchar_256_ name + varchar ownerId FK + varchar_16_ provider + TEXT suggestedPrompts + TEXT systemPrompt + datetime_3_ updatedAt +} +"chat_hub_messages" { + varchar_36_ agentId FK + TEXT attachments + TEXT content + datetime_3_ createdAt + INTEGER executionId FK + varchar id PK + VARCHAR_256_ model + varchar_128_ name + varchar previousMessageId FK + varchar_16_ provider + varchar retryOfMessageId FK + varchar revisionOfMessageId FK + varchar sessionId FK + varchar_16_ status + varchar_16_ type + datetime_3_ updatedAt + varchar_36_ workflowId FK +} +"chat_hub_session_tools" { + varchar sessionId PK + varchar toolId PK +} +"chat_hub_sessions" { + varchar_36_ agentId FK + varchar_128_ agentName + datetime_3_ createdAt + varchar_36_ credentialId FK + varchar id PK + datetime_3_ lastMessageAt + varchar_64_ model + varchar ownerId FK + varchar_16_ provider + varchar_256_ title + varchar_16_ type + datetime_3_ updatedAt + varchar_36_ workflowId FK +} +"chat_hub_tools" { + datetime_3_ createdAt + TEXT definition + boolean enabled + varchar id PK + varchar_255_ name + varchar ownerId FK + varchar_255_ type + REAL typeVersion + datetime_3_ updatedAt +} +"credential_dependency" { + datetime_3_ createdAt + varchar_36_ credentialId FK + varchar_255_ dependencyId + varchar_64_ dependencyType + INTEGER id +} +"credentials_entity" { + datetime_3_ createdAt + TEXT data + varchar_36_ id PK + boolean isGlobal + boolean isManaged + boolean isResolvable + varchar_128_ name + boolean resolvableAllowFallback + varchar_16_ resolverId FK + varchar_32_ type + datetime_3_ updatedAt +} +"data_table" { + datetime_3_ createdAt + varchar_36_ id PK + varchar_128_ name + varchar_36_ projectId FK + datetime_3_ updatedAt +} +"data_table_column" { + datetime_3_ createdAt + varchar_36_ dataTableId FK + varchar_36_ id PK + INTEGER index + varchar_128_ name + varchar_32_ type + datetime_3_ updatedAt +} +"deployment_key" { + varchar_20_ algorithm + datetime_3_ createdAt + varchar_36_ id PK + varchar_20_ status + varchar_64_ type + datetime_3_ updatedAt + TEXT value +} +"dynamic_credential_entry" { + datetime_3_ createdAt + varchar_16_ credential_id PK + TEXT data + varchar_16_ resolver_id PK + varchar_2048_ subject_id PK + datetime_3_ updatedAt +} +"dynamic_credential_resolver" { + TEXT config + datetime_3_ createdAt + varchar_16_ id PK + varchar_128_ name + varchar_128_ type + datetime_3_ updatedAt +} +"dynamic_credential_user_entry" { + datetime_3_ createdAt + varchar_16_ credentialId PK + TEXT data + varchar_16_ resolverId PK + datetime_3_ updatedAt + varchar userId PK +} +"evaluation_collection" { + datetime_3_ createdAt + varchar createdById FK + TEXT description + varchar_36_ evaluationConfigId FK + varchar_36_ id PK + TEXT insightsCache + varchar_128_ name + datetime_3_ updatedAt + varchar_36_ workflowId FK +} +"evaluation_config" { + datetime_3_ createdAt + TEXT datasetRef + varchar_32_ datasetSource + varchar_255_ endNodeName + varchar_36_ id PK + varchar_64_ invalidReason + TEXT metrics + varchar_128_ name + varchar_255_ startNodeName + varchar_16_ status + datetime_3_ updatedAt + varchar_36_ workflowId FK +} +"event_destinations" { + datetime_3_ createdAt + TEXT destination + varchar_36_ id PK + datetime_3_ updatedAt +} +"execution_annotation_tags" { + INTEGER annotationId PK + varchar_24_ tagId PK +} +"execution_annotations" { + datetime_3_ createdAt + INTEGER executionId FK + INTEGER id + TEXT note + datetime_3_ updatedAt + varchar_6_ vote +} +"execution_data" { + TEXT data + INT executionId PK + TEXT workflowData + VARCHAR_36_ workflowVersionId +} +"execution_entity" { + BIGINT binaryDataSizeBytes + datetime_3_ createdAt + varchar_255_ deduplicationKey + datetime_3_ deletedAt + boolean finished + INTEGER id + BIGINT jsonSizeBytes + varchar mode + varchar retryOf + varchar retrySuccessId + datetime startedAt + varchar status + datetime stoppedAt + varchar_2_ storedAt + TEXT tracingContext + datetime waitTill + varchar_36_ workflowId FK + VARCHAR_36_ workflowVersionId +} +"execution_metadata" { + INTEGER executionId FK + INTEGER id + varchar_255_ key + TEXT value +} +"folder" { + datetime_3_ createdAt + varchar_36_ id PK + varchar_128_ name + varchar_36_ parentFolderId FK + varchar_36_ projectId FK + datetime_3_ updatedAt +} +"folder_tag" { + varchar_36_ folderId PK + varchar_36_ tagId PK +} +"insights_by_period" { + INTEGER id + INTEGER metaId FK + datetime_0_ periodStart + INTEGER periodUnit + INTEGER type + bigint value +} +"insights_metadata" { + INTEGER metaId + varchar_36_ projectId FK + varchar_255_ projectName + varchar_16_ workflowId FK + varchar_128_ workflowName +} +"insights_raw" { + INTEGER id + INTEGER metaId FK + datetime_0_ timestamp + INTEGER type + bigint value +} +"installed_nodes" { + INTEGER latestVersion + char_200_ name PK + char_214_ package FK + char_200_ type +} +"installed_packages" { + char_70_ authorEmail + char_70_ authorName + datetime_3_ createdAt + char_50_ installedVersion + char_214_ packageName PK + datetime_3_ updatedAt +} +"instance_ai_checkpoints" { + datetime_3_ createdAt + datetime_3_ expiredAt + varchar_255_ key PK + varchar_255_ resourceId + varchar_255_ runId + TEXT state + varchar threadId FK + datetime_3_ updatedAt +} +"instance_ai_iteration_logs" { + datetime_3_ createdAt + TEXT entry + varchar_36_ id PK + varchar taskKey + varchar threadId FK + datetime_3_ updatedAt +} +"instance_ai_mcp_registry_connections" { + datetime_3_ createdAt + varchar_36_ credentialId FK + varchar id PK + varchar_255_ serverSlug FK + TEXT toolFilter + datetime_3_ updatedAt + varchar userId FK +} +"instance_ai_messages" { + TEXT content + datetime_3_ createdAt + varchar_36_ id PK + varchar_255_ resourceId + varchar_16_ role + varchar threadId FK + varchar_32_ type + datetime_3_ updatedAt +} +"instance_ai_observation_cursors" { + datetime_3_ createdAt + datetime_3_ lastObservedAt + varchar_36_ lastObservedMessageId + varchar observationScopeId PK + datetime_3_ updatedAt +} +"instance_ai_observation_locks" { + datetime_3_ createdAt + datetime_3_ heldUntil + varchar_64_ holderId + varchar observationScopeId PK + varchar_20_ taskKind PK + datetime_3_ updatedAt +} +"instance_ai_observational_memory" { + TEXT activeObservations + TEXT bufferedMessageIds + TEXT bufferedObservationChunks + INTEGER bufferedObservationTokens + TEXT bufferedObservations + TEXT bufferedReflection + INTEGER bufferedReflectionInputTokens + INTEGER bufferedReflectionTokens + TEXT config + datetime_3_ createdAt + INTEGER generationCount + varchar_36_ id PK + boolean isBufferingObservation + boolean isBufferingReflection + boolean isObserving + boolean isReflecting + datetime_3_ lastBufferedAtTime + INTEGER lastBufferedAtTokens + datetime_3_ lastObservedAt + varchar_255_ lookupKey + TEXT metadata + INTEGER observationTokenCount + TEXT observedMessageIds + varchar observedTimezone + varchar_32_ originType + INTEGER pendingMessageTokens + INTEGER reflectedObservationLineCount + varchar_255_ resourceId + varchar_16_ scope + varchar threadId FK + INTEGER totalTokensObserved + datetime_3_ updatedAt +} +"instance_ai_observations" { + datetime_3_ createdAt + varchar_36_ id PK + varchar_16_ marker + varchar observationScopeId FK + varchar_36_ parentId FK + varchar_16_ status + varchar_36_ supersededBy FK + TEXT text + INTEGER tokenCount + datetime_3_ updatedAt +} +"instance_ai_pending_confirmations" { + varchar_255_ checkpointKey FK + varchar_36_ checkpointTaskId + datetime_3_ createdAt + datetime_3_ expiresAt + varchar_16_ kind + varchar_36_ messageGroupId + varchar_36_ requestId PK + varchar_36_ runId + varchar threadId FK + varchar_64_ toolCallId + datetime_3_ updatedAt + varchar userId FK +} +"instance_ai_resources" { + datetime_3_ createdAt + varchar_255_ id PK + TEXT metadata + datetime_3_ updatedAt + TEXT workingMemory +} +"instance_ai_run_snapshots" { + datetime_3_ createdAt + varchar_36_ langsmithRunId + varchar_36_ langsmithTraceId + varchar_36_ messageGroupId + varchar_36_ runId PK + TEXT runIds + varchar_64_ spanId + varchar threadId PK + varchar_64_ traceId + TEXT tree + datetime_3_ updatedAt +} +"instance_ai_threads" { + datetime_3_ createdAt + varchar id PK + TEXT metadata + varchar_36_ projectId FK + varchar_255_ resourceId + TEXT title + datetime_3_ updatedAt +} +"instance_ai_workflow_snapshots" { + datetime_3_ createdAt + varchar_255_ resourceId + varchar_36_ runId PK + TEXT snapshot + varchar status + datetime_3_ updatedAt + varchar_255_ workflowName PK +} +"instance_version_history" { + datetime_3_ createdAt + INTEGER id + INTEGER major + INTEGER minor + INTEGER patch +} +"invalid_auth_token" { + datetime_3_ expiresAt + varchar_512_ token PK +} +"mcp_registry_server" { + datetime_3_ createdAt + TEXT data + datetime_3_ registryUpdatedAt + varchar_255_ slug PK + varchar_50_ status + datetime_3_ updatedAt + varchar_50_ version +} +"oauth_access_tokens" { + varchar clientId FK + varchar token PK + varchar userId FK +} +"oauth_authorization_codes" { + varchar clientId FK + varchar_255_ code PK + varchar codeChallenge + varchar_255_ codeChallengeMethod + datetime_3_ createdAt + bigint expiresAt + varchar redirectUri + varchar resource + TEXT scope + varchar state + datetime_3_ updatedAt + boolean used + varchar userId FK +} +"oauth_clients" { + varchar_255_ clientSecret + bigint clientSecretExpiresAt + datetime_3_ createdAt + TEXT grantTypes + varchar id PK + varchar_255_ name + TEXT redirectUris + varchar_255_ tokenEndpointAuthMethod + datetime_3_ updatedAt +} +"oauth_refresh_tokens" { + varchar clientId FK + datetime_3_ createdAt + bigint expiresAt + TEXT scope + varchar_255_ token PK + datetime_3_ updatedAt + varchar userId FK +} +"oauth_user_consents" { + varchar clientId FK + bigint grantedAt + INTEGER id + varchar userId FK +} +"processed_data" { + varchar_255_ context PK + datetime_3_ createdAt + datetime_3_ updatedAt + TEXT value + varchar_36_ workflowId PK +} +"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 +} +"project_relation" { + datetime_3_ createdAt + varchar_36_ projectId PK + varchar role FK + datetime_3_ updatedAt + varchar userId PK +} +"project_secrets_provider_access" { + datetime_3_ createdAt + varchar_36_ projectId PK + varchar_128_ role + INTEGER secretsProviderConnectionId PK + datetime_3_ updatedAt +} +"role" { + datetime_3_ createdAt + TEXT description + TEXT displayName + TEXT roleType + varchar_128_ slug PK + boolean systemRole + datetime_3_ updatedAt +} +"role_mapping_rule" { + datetime_3_ createdAt + TEXT expression + varchar_16_ id PK + INTEGER order + varchar_128_ role FK + varchar_64_ type + datetime_3_ updatedAt +} +"role_mapping_rule_project" { + varchar_36_ projectId PK + varchar_16_ roleMappingRuleId PK +} +"role_scope" { + VARCHAR_128_ roleSlug PK + VARCHAR_128_ scopeSlug PK +} +"scope" { + TEXT description + TEXT displayName + varchar_128_ slug PK +} +"secrets_provider_connection" { + datetime_3_ createdAt + TEXT encryptedSettings + INTEGER id + boolean isEnabled + varchar_128_ providerKey + varchar_36_ type + datetime_3_ updatedAt +} +"settings" { + TEXT key PK + boolean loadOnStartup + TEXT value +} +"shared_credentials" { + datetime_3_ createdAt + varchar_36_ credentialsId PK + varchar_36_ projectId PK + TEXT role + datetime_3_ updatedAt +} +"shared_workflow" { + datetime_3_ createdAt + varchar_36_ projectId PK + TEXT role + datetime_3_ updatedAt + varchar_36_ workflowId PK +} +"tag_entity" { + datetime_3_ createdAt + varchar_36_ id PK + varchar_24_ name + datetime_3_ updatedAt +} +"test_case_execution" { + datetime_3_ completedAt + datetime_3_ createdAt + varchar errorCode + TEXT errorDetails + INTEGER evaluationExecutionId FK + INTEGER executionId FK + varchar_36_ id PK + TEXT inputs + TEXT metrics + TEXT outputs + INTEGER pastExecutionId FK + datetime_3_ runAt + INTEGER runIndex + varchar status + varchar_36_ testRunId FK + datetime_3_ updatedAt +} +"test_run" { + boolean cancelRequested + varchar_36_ collectionId FK + datetime_3_ completedAt + datetime_3_ createdAt + varchar errorCode + TEXT errorDetails + varchar_36_ evaluationConfigId FK + TEXT evaluationConfigSnapshot + varchar_36_ id PK + TEXT metrics + datetime_3_ runAt + varchar_255_ runningInstanceId + varchar status + datetime_3_ updatedAt + varchar_36_ workflowId FK + varchar_36_ workflowVersionId +} +"token_exchange_jti" { + datetime_3_ createdAt + datetime_3_ expiresAt + varchar_255_ jti PK +} +"trusted_key" { + datetime_3_ createdAt + TEXT data + varchar_255_ kid PK + varchar_36_ sourceId PK +} +"trusted_key_source" { + TEXT config + datetime_3_ createdAt + varchar_36_ id PK + TEXT lastError + datetime_3_ lastRefreshedAt + varchar_32_ status + varchar_32_ type + datetime_3_ updatedAt +} +"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 +} +"user_api_keys" { + varchar apiKey + varchar audience + datetime_3_ createdAt + varchar_36_ id PK + varchar_100_ label + datetime_3_ lastUsedAt + TEXT scopes + datetime_3_ updatedAt + varchar userId FK +} +"user_favorites" { + INTEGER id + varchar_255_ resourceId + varchar_64_ resourceType + varchar userId FK +} +"variables" { + varchar_36_ id PK + TEXT key + varchar_36_ projectId FK + TEXT type + TEXT value +} +"webhook_entity" { + varchar method PK + varchar node + INTEGER pathLength + varchar webhookId + varchar webhookPath PK + varchar_36_ workflowId +} +"workflow_builder_session" { + varchar_255_ activeVersionCardId + datetime_3_ createdAt + varchar id PK + TEXT messages + TEXT previousSummary + varchar_255_ resumeAfterRestoreMessageId + datetime_3_ updatedAt + varchar userId FK + varchar_36_ workflowId FK +} +"workflow_dependency" { + datetime_3_ createdAt + TEXT dependencyInfo + varchar_255_ dependencyKey + varchar_32_ dependencyType + INTEGER id + smallint indexVersionId + varchar_36_ publishedVersionId + varchar_36_ workflowId FK + INTEGER workflowVersionId +} +"workflow_entity" { + boolean active + varchar_36_ activeVersionId FK + TEXT connections + datetime_3_ createdAt + TEXT description + varchar_36_ id PK + boolean isArchived + TEXT meta + varchar_128_ name + TEXT nodeGroups + TEXT nodes + varchar_36_ parentFolderId FK + TEXT pinData + TEXT settings + varchar sourceWorkflowId + TEXT staticData + INTEGER triggerCount + datetime_3_ updatedAt + INTEGER versionCounter + varchar_36_ versionId +} +"workflow_history" { + varchar_255_ authors + boolean autosaved + TEXT connections + datetime_3_ createdAt + TEXT description + varchar_128_ name + TEXT nodeGroups + TEXT nodes + datetime_3_ updatedAt + varchar_36_ versionId PK + varchar_36_ workflowId FK +} +"workflow_publication_outbox" { + datetime_3_ createdAt + TEXT errorMessage + INTEGER id + varchar_36_ publishedVersionId + varchar_20_ status + datetime_3_ updatedAt + varchar_36_ workflowId +} +"workflow_publish_history" { + datetime_3_ createdAt + varchar_36_ event + INTEGER id + varchar userId FK + varchar_36_ versionId FK + varchar_36_ workflowId FK +} +"workflow_published_version" { + datetime_3_ createdAt + varchar_36_ publishedVersionId FK + datetime_3_ updatedAt + varchar_36_ workflowId PK +} +"workflow_statistics" { + INTEGER count + INTEGER id + DATETIME latestEvent + VARCHAR_128_ name + INTEGER rootCount + VARCHAR_36_ workflowId + VARCHAR_128_ workflowName +} +"workflows_tags" { + INTEGER tagId PK + varchar_36_ workflowId PK +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/sqlite-schema/agent_chat_subscriptions.md b/docs/generated/sqlite-schema/agent_chat_subscriptions.md new file mode 100644 index 00000000000..f6a868a0aae --- /dev/null +++ b/docs/generated/sqlite-schema/agent_chat_subscriptions.md @@ -0,0 +1,76 @@ +# agent_chat_subscriptions + +## Description + +<details> +<summary><strong>Table Definition</strong></summary> + +```sql +CREATE TABLE "agent_chat_subscriptions" ("agentId" varchar(36) NOT NULL, "integrationType" varchar(64) NOT NULL, "credentialId" varchar(255) NOT NULL, "threadId" varchar(255) 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 "CHK_agent_chat_subscriptions_integrationType" CHECK ("integrationType" IN ('telegram', 'slack', 'linear')), CONSTRAINT "FK_e79153bd179c011e779d5016796" FOREIGN KEY ("agentId") REFERENCES "agents" ("id") ON DELETE CASCADE, PRIMARY KEY ("agentId", "integrationType", "credentialId", "threadId")) +``` + +</details> + +## 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 | | | | +| credentialId | varchar(255) | | false | | | | +| integrationType | varchar(64) | | false | | | | +| threadId | varchar(255) | | false | | | | +| updatedAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| - | CHECK | CHECK ("integrationType" IN ('telegram', 'slack', 'linear')) | +| - (Foreign key ID: 0) | FOREIGN KEY | FOREIGN KEY (agentId) REFERENCES agents (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| agentId | PRIMARY KEY | PRIMARY KEY (agentId) | +| credentialId | PRIMARY KEY | PRIMARY KEY (credentialId) | +| integrationType | PRIMARY KEY | PRIMARY KEY (integrationType) | +| sqlite_autoindex_agent_chat_subscriptions_1 | PRIMARY KEY | PRIMARY KEY (agentId, integrationType, credentialId, threadId) | +| threadId | PRIMARY KEY | PRIMARY KEY (threadId) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| sqlite_autoindex_agent_chat_subscriptions_1 | PRIMARY KEY (agentId, integrationType, credentialId, threadId) | + +## Relations + +```mermaid +erDiagram + +"agent_chat_subscriptions" |o--|| "agents" : "FOREIGN KEY (agentId) REFERENCES agents (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" + +"agent_chat_subscriptions" { + varchar_36_ agentId PK + datetime_3_ createdAt + varchar_255_ credentialId PK + varchar_64_ integrationType PK + varchar_255_ threadId PK + datetime_3_ updatedAt +} +"agents" { + varchar_36_ activeVersionId FK + datetime_3_ createdAt + varchar_512_ description + varchar_36_ id PK + TEXT integrations + varchar_128_ name + varchar_255_ projectId FK + TEXT schema + TEXT skills + TEXT tools + datetime_3_ updatedAt + varchar_36_ versionId +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/sqlite-schema/agent_checkpoints.md b/docs/generated/sqlite-schema/agent_checkpoints.md new file mode 100644 index 00000000000..702a987f48b --- /dev/null +++ b/docs/generated/sqlite-schema/agent_checkpoints.md @@ -0,0 +1,73 @@ +# agent_checkpoints + +## Description + +<details> +<summary><strong>Table Definition</strong></summary> + +```sql +CREATE TABLE "agent_checkpoints" ("runId" varchar(255) PRIMARY KEY NOT NULL, "agentId" varchar(255), "state" text, "expired" boolean NOT NULL DEFAULT (false), "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_5e31c210f896d539964bf99fe32" FOREIGN KEY ("agentId") REFERENCES "agents" ("id") ON DELETE CASCADE) +``` + +</details> + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| agentId | varchar(255) | | true | | [agents](agents.md) | | +| createdAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | +| expired | boolean | false | false | | | | +| runId | varchar(255) | | false | | | | +| state | TEXT | | true | | | | +| updatedAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| - (Foreign key ID: 0) | FOREIGN KEY | FOREIGN KEY (agentId) REFERENCES agents (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| runId | PRIMARY KEY | PRIMARY KEY (runId) | +| sqlite_autoindex_agent_checkpoints_1 | PRIMARY KEY | PRIMARY KEY (runId) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_5e31c210f896d539964bf99fe3 | CREATE INDEX "IDX_5e31c210f896d539964bf99fe3" ON "agent_checkpoints" ("agentId") | +| sqlite_autoindex_agent_checkpoints_1 | PRIMARY KEY (runId) | + +## Relations + +```mermaid +erDiagram + +"agent_checkpoints" }o--o| "agents" : "FOREIGN KEY (agentId) REFERENCES agents (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" + +"agent_checkpoints" { + varchar_255_ agentId FK + datetime_3_ createdAt + boolean expired + varchar_255_ runId PK + TEXT state + datetime_3_ updatedAt +} +"agents" { + varchar_36_ activeVersionId FK + datetime_3_ createdAt + varchar_512_ description + varchar_36_ id PK + TEXT integrations + varchar_128_ name + varchar_255_ projectId FK + TEXT schema + TEXT skills + TEXT tools + datetime_3_ updatedAt + varchar_36_ versionId +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/sqlite-schema/agent_execution.md b/docs/generated/sqlite-schema/agent_execution.md new file mode 100644 index 00000000000..12afc2f1b7a --- /dev/null +++ b/docs/generated/sqlite-schema/agent_execution.md @@ -0,0 +1,108 @@ +# agent_execution + +## Description + +<details> +<summary><strong>Table Definition</strong></summary> + +```sql +CREATE TABLE "agent_execution" ("id" varchar(36) PRIMARY KEY NOT NULL, "threadId" varchar(128) NOT NULL, "status" varchar(16) NOT NULL, "startedAt" datetime(3), "stoppedAt" datetime(3), "duration" integer NOT NULL DEFAULT (0), "userMessage" text NOT NULL, "assistantResponse" text NOT NULL, "model" varchar(255), "promptTokens" integer, "completionTokens" integer, "totalTokens" integer, "cost" real, "toolCalls" text, "timeline" text, "error" text, "hitlStatus" varchar(16), "source" varchar(32), "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_agent_execution_status" CHECK (("status" IN ('success', 'error'))), CONSTRAINT "CHK_agent_execution_hitlStatus" CHECK (("hitlStatus" IN ('suspended', 'resumed'))), CONSTRAINT "FK_add2432fb6034cc18b6af299dce" FOREIGN KEY ("threadId") REFERENCES "agent_execution_threads" ("id") ON DELETE CASCADE ON UPDATE NO ACTION) +``` + +</details> + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| assistantResponse | TEXT | | false | | | | +| completionTokens | INTEGER | | true | | | | +| cost | REAL | | true | | | | +| createdAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | +| duration | INTEGER | 0 | false | | | | +| error | TEXT | | true | | | | +| hitlStatus | varchar(16) | | true | | | | +| id | varchar(36) | | false | | | | +| model | varchar(255) | | true | | | | +| promptTokens | INTEGER | | true | | | | +| source | varchar(32) | | true | | | | +| startedAt | datetime(3) | | true | | | | +| status | varchar(16) | | false | | | | +| stoppedAt | datetime(3) | | true | | | | +| threadId | varchar(128) | | false | | [agent_execution_threads](agent_execution_threads.md) | | +| timeline | TEXT | | true | | | | +| toolCalls | TEXT | | true | | | | +| totalTokens | INTEGER | | true | | | | +| updatedAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | +| userMessage | TEXT | | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| - | CHECK | CHECK (("status" IN ('success', 'error'))) | +| - | CHECK | CHECK (("hitlStatus" IN ('suspended', 'resumed'))) | +| - (Foreign key ID: 0) | FOREIGN KEY | FOREIGN KEY (threadId) REFERENCES agent_execution_threads (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| id | PRIMARY KEY | PRIMARY KEY (id) | +| sqlite_autoindex_agent_execution_1 | PRIMARY KEY | PRIMARY KEY (id) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_63d3c3a68b9cebf05f967f0b1c | CREATE INDEX "IDX_63d3c3a68b9cebf05f967f0b1c" ON "agent_execution" ("threadId", "createdAt") | +| sqlite_autoindex_agent_execution_1 | PRIMARY KEY (id) | + +## Relations + +```mermaid +erDiagram + +"agent_execution" }o--|| "agent_execution_threads" : "FOREIGN KEY (threadId) REFERENCES agent_execution_threads (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" + +"agent_execution" { + TEXT assistantResponse + INTEGER completionTokens + REAL cost + datetime_3_ createdAt + INTEGER duration + TEXT error + varchar_16_ hitlStatus + varchar_36_ id PK + varchar_255_ model + INTEGER promptTokens + varchar_32_ source + datetime_3_ startedAt + varchar_16_ status + datetime_3_ stoppedAt + varchar_128_ threadId FK + TEXT timeline + TEXT toolCalls + INTEGER totalTokens + datetime_3_ updatedAt + TEXT userMessage +} +"agent_execution_threads" { + varchar_36_ agentId FK + varchar_255_ agentName + datetime_3_ createdAt + varchar_8_ emoji + varchar_128_ id PK + varchar_36_ parentAgentId + varchar_128_ parentThreadId + varchar_255_ projectId FK + INTEGER sessionNumber + varchar_32_ taskId + varchar_36_ taskVersionId FK + varchar_255_ title + INTEGER totalCompletionTokens + REAL totalCost + INTEGER totalDuration + INTEGER totalPromptTokens + datetime_3_ updatedAt +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/sqlite-schema/agent_execution_threads.md b/docs/generated/sqlite-schema/agent_execution_threads.md new file mode 100644 index 00000000000..5ed2f18f936 --- /dev/null +++ b/docs/generated/sqlite-schema/agent_execution_threads.md @@ -0,0 +1,146 @@ +# agent_execution_threads + +## Description + +<details> +<summary><strong>Table Definition</strong></summary> + +```sql +CREATE TABLE "agent_execution_threads" ("id" varchar(128) PRIMARY KEY NOT NULL, "agentId" varchar(36) NOT NULL, "agentName" varchar(255) NOT NULL, "projectId" varchar(255) NOT NULL, "sessionNumber" integer NOT NULL DEFAULT (0), "totalPromptTokens" integer NOT NULL DEFAULT (0), "totalCompletionTokens" integer NOT NULL DEFAULT (0), "totalCost" real NOT NULL DEFAULT (0), "totalDuration" integer NOT NULL DEFAULT (0), "title" varchar(255), "emoji" varchar(8), "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')), "taskId" varchar(32), "taskVersionId" varchar(36), "parentThreadId" varchar(128), "parentAgentId" varchar(36), CONSTRAINT "FK_0e2f8bf92a7a9c88b89670f701c" FOREIGN KEY ("projectId") REFERENCES "project" ("id") ON DELETE CASCADE ON UPDATE NO ACTION, CONSTRAINT "FK_0468a9dc35597314e641d4722aa" FOREIGN KEY ("agentId") REFERENCES "agents" ("id") ON DELETE CASCADE ON UPDATE NO ACTION, CONSTRAINT "FK_f00b52d74fe11838e1fe086deea" FOREIGN KEY ("taskVersionId") REFERENCES "agent_history" ("versionId") ON DELETE SET NULL) +``` + +</details> + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| agentId | varchar(36) | | false | | [agents](agents.md) | | +| agentName | varchar(255) | | false | | | | +| createdAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | +| emoji | varchar(8) | | true | | | | +| id | varchar(128) | | false | [agent_execution](agent_execution.md) | | | +| parentAgentId | varchar(36) | | true | | | | +| parentThreadId | varchar(128) | | true | | | | +| projectId | varchar(255) | | false | | [project](project.md) | | +| sessionNumber | INTEGER | 0 | false | | | | +| taskId | varchar(32) | | true | | | | +| taskVersionId | varchar(36) | | true | | [agent_history](agent_history.md) | | +| title | varchar(255) | | true | | | | +| totalCompletionTokens | INTEGER | 0 | false | | | | +| totalCost | REAL | 0 | false | | | | +| totalDuration | INTEGER | 0 | false | | | | +| totalPromptTokens | INTEGER | 0 | false | | | | +| updatedAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| - (Foreign key ID: 0) | FOREIGN KEY | FOREIGN KEY (taskVersionId) REFERENCES agent_history (versionId) 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_agent_execution_threads_1 | PRIMARY KEY | PRIMARY KEY (id) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_0468a9dc35597314e641d4722a | CREATE INDEX "IDX_0468a9dc35597314e641d4722a" ON "agent_execution_threads" ("agentId") | +| IDX_0e2f8bf92a7a9c88b89670f701 | CREATE INDEX "IDX_0e2f8bf92a7a9c88b89670f701" ON "agent_execution_threads" ("projectId") | +| IDX_agent_execution_threads_taskVersionId | CREATE INDEX "IDX_agent_execution_threads_taskVersionId" ON "agent_execution_threads" ("taskVersionId") | +| sqlite_autoindex_agent_execution_threads_1 | PRIMARY KEY (id) | + +## Relations + +```mermaid +erDiagram + +"agent_execution_threads" }o--|| "agents" : "FOREIGN KEY (agentId) REFERENCES agents (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"agent_execution" }o--|| "agent_execution_threads" : "FOREIGN KEY (threadId) REFERENCES agent_execution_threads (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"agent_execution_threads" }o--|| "project" : "FOREIGN KEY (projectId) REFERENCES project (id) ON UPDATE NO ACTION ON DELETE CASCADE 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_execution_threads" { + varchar_36_ agentId FK + varchar_255_ agentName + datetime_3_ createdAt + varchar_8_ emoji + varchar_128_ id PK + varchar_36_ parentAgentId + varchar_128_ parentThreadId + varchar_255_ projectId FK + INTEGER sessionNumber + varchar_32_ taskId + varchar_36_ taskVersionId FK + varchar_255_ title + INTEGER totalCompletionTokens + REAL totalCost + INTEGER totalDuration + INTEGER totalPromptTokens + datetime_3_ updatedAt +} +"agents" { + varchar_36_ activeVersionId FK + datetime_3_ createdAt + varchar_512_ description + varchar_36_ id PK + TEXT integrations + varchar_128_ name + varchar_255_ projectId FK + TEXT schema + TEXT skills + TEXT tools + datetime_3_ updatedAt + varchar_36_ versionId +} +"agent_execution" { + TEXT assistantResponse + INTEGER completionTokens + REAL cost + datetime_3_ createdAt + INTEGER duration + TEXT error + varchar_16_ hitlStatus + varchar_36_ id PK + varchar_255_ model + INTEGER promptTokens + varchar_32_ source + datetime_3_ startedAt + varchar_16_ status + datetime_3_ stoppedAt + varchar_128_ threadId FK + TEXT timeline + TEXT toolCalls + INTEGER totalTokens + datetime_3_ updatedAt + TEXT userMessage +} +"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 +} +"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 +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/sqlite-schema/agent_files.md b/docs/generated/sqlite-schema/agent_files.md new file mode 100644 index 00000000000..ceec4f76093 --- /dev/null +++ b/docs/generated/sqlite-schema/agent_files.md @@ -0,0 +1,77 @@ +# agent_files + +## Description + +<details> +<summary><strong>Table Definition</strong></summary> + +```sql +CREATE TABLE "agent_files" ("id" varchar(16) PRIMARY KEY NOT NULL, "agentId" varchar(36) NOT NULL, "binaryDataId" text NOT NULL, "fileName" varchar(255) NOT NULL, "mimeType" varchar(255) NOT NULL, "fileSizeBytes" integer 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_aca4514cb500494b64356c2e164" FOREIGN KEY ("agentId") REFERENCES "agents" ("id") ON DELETE CASCADE) +``` + +</details> + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| agentId | varchar(36) | | false | | [agents](agents.md) | | +| binaryDataId | TEXT | | false | | | | +| createdAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | +| fileName | varchar(255) | | false | | | | +| fileSizeBytes | INTEGER | | false | | | | +| id | varchar(16) | | false | | | | +| mimeType | varchar(255) | | false | | | | +| updatedAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| - (Foreign key ID: 0) | FOREIGN KEY | FOREIGN KEY (agentId) REFERENCES agents (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| id | PRIMARY KEY | PRIMARY KEY (id) | +| sqlite_autoindex_agent_files_1 | PRIMARY KEY | PRIMARY KEY (id) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_45dafc48fe2ce95eac30fc8ffd | CREATE INDEX "IDX_45dafc48fe2ce95eac30fc8ffd" ON "agent_files" ("agentId", "createdAt") | +| sqlite_autoindex_agent_files_1 | PRIMARY KEY (id) | + +## Relations + +```mermaid +erDiagram + +"agent_files" }o--|| "agents" : "FOREIGN KEY (agentId) REFERENCES agents (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" + +"agent_files" { + varchar_36_ agentId FK + TEXT binaryDataId + datetime_3_ createdAt + varchar_255_ fileName + INTEGER fileSizeBytes + varchar_16_ id PK + varchar_255_ mimeType + datetime_3_ updatedAt +} +"agents" { + varchar_36_ activeVersionId FK + datetime_3_ createdAt + varchar_512_ description + varchar_36_ id PK + TEXT integrations + varchar_128_ name + varchar_255_ projectId FK + TEXT schema + TEXT skills + TEXT tools + datetime_3_ updatedAt + varchar_36_ versionId +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/sqlite-schema/agent_history.md b/docs/generated/sqlite-schema/agent_history.md new file mode 100644 index 00000000000..d6bea1466bd --- /dev/null +++ b/docs/generated/sqlite-schema/agent_history.md @@ -0,0 +1,130 @@ +# agent_history + +## Description + +<details> +<summary><strong>Table Definition</strong></summary> + +```sql +CREATE TABLE "agent_history" ("versionId" varchar(36) PRIMARY KEY NOT NULL, "agentId" varchar(36) NOT NULL, "schema" text, "tools" text, "skills" text, "publishedById" varchar, "author" varchar(255) 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_87cd5a8da20304b089ea2f83fec" FOREIGN KEY ("agentId") REFERENCES "agents" ("id") ON DELETE CASCADE, CONSTRAINT "FK_8771675f44c58fb40e0feb9ee35" FOREIGN KEY ("publishedById") REFERENCES "user" ("id") ON DELETE SET NULL) +``` + +</details> + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| agentId | varchar(36) | | false | | [agents](agents.md) | | +| author | varchar(255) | | false | | | | +| createdAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | +| publishedById | varchar | | true | | [user](user.md) | | +| schema | TEXT | | true | | | | +| 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) | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| - (Foreign key ID: 0) | FOREIGN KEY | FOREIGN KEY (publishedById) 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 | +| sqlite_autoindex_agent_history_1 | PRIMARY KEY | PRIMARY KEY (versionId) | +| versionId | PRIMARY KEY | PRIMARY KEY (versionId) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_87cd5a8da20304b089ea2f83fe | CREATE INDEX "IDX_87cd5a8da20304b089ea2f83fe" ON "agent_history" ("agentId") | +| sqlite_autoindex_agent_history_1 | PRIMARY KEY (versionId) | + +## Relations + +```mermaid +erDiagram + +"agent_history" }o--|| "agents" : "FOREIGN KEY (agentId) REFERENCES agents (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"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" +"agents" }o--o| "agent_history" : "FOREIGN KEY (activeVersionId) REFERENCES agent_history (versionId) ON UPDATE NO ACTION ON DELETE SET NULL MATCH NONE" + +"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 +} +"agents" { + varchar_36_ activeVersionId FK + datetime_3_ createdAt + varchar_512_ description + varchar_36_ id PK + TEXT integrations + varchar_128_ name + varchar_255_ projectId FK + TEXT schema + 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_execution_threads" { + varchar_36_ agentId FK + varchar_255_ agentName + datetime_3_ createdAt + varchar_8_ emoji + varchar_128_ id PK + varchar_36_ parentAgentId + varchar_128_ parentThreadId + varchar_255_ projectId FK + INTEGER sessionNumber + varchar_32_ taskId + varchar_36_ taskVersionId FK + varchar_255_ title + INTEGER totalCompletionTokens + REAL totalCost + INTEGER totalDuration + INTEGER totalPromptTokens + datetime_3_ updatedAt +} +"agent_task_snapshot" { + datetime_3_ createdAt + varchar_128_ cronExpression + boolean enabled + varchar_128_ name + TEXT objective + varchar_32_ taskId PK + datetime_3_ updatedAt + varchar_36_ versionId PK +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/sqlite-schema/agent_task_definition.md b/docs/generated/sqlite-schema/agent_task_definition.md new file mode 100644 index 00000000000..91f700e1e37 --- /dev/null +++ b/docs/generated/sqlite-schema/agent_task_definition.md @@ -0,0 +1,75 @@ +# agent_task_definition + +## Description + +<details> +<summary><strong>Table Definition</strong></summary> + +```sql +CREATE TABLE "agent_task_definition" ("id" varchar(32) PRIMARY KEY NOT NULL, "agentId" varchar(36) NOT NULL, "name" varchar(128) NOT NULL, "objective" text NOT NULL, "cronExpression" varchar(128) 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_f45d0535a2ed59b6c2dd6da98a0" FOREIGN KEY ("agentId") REFERENCES "agents" ("id") ON DELETE CASCADE) +``` + +</details> + +## 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 | | | | +| cronExpression | varchar(128) | | false | | | | +| id | varchar(32) | | false | | | | +| name | varchar(128) | | false | | | | +| objective | TEXT | | false | | | | +| updatedAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| - (Foreign key ID: 0) | FOREIGN KEY | FOREIGN KEY (agentId) REFERENCES agents (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| id | PRIMARY KEY | PRIMARY KEY (id) | +| sqlite_autoindex_agent_task_definition_1 | PRIMARY KEY | PRIMARY KEY (id) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_f45d0535a2ed59b6c2dd6da98a | CREATE INDEX "IDX_f45d0535a2ed59b6c2dd6da98a" ON "agent_task_definition" ("agentId") | +| sqlite_autoindex_agent_task_definition_1 | PRIMARY KEY (id) | + +## Relations + +```mermaid +erDiagram + +"agent_task_definition" }o--|| "agents" : "FOREIGN KEY (agentId) REFERENCES agents (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" + +"agent_task_definition" { + varchar_36_ agentId FK + datetime_3_ createdAt + varchar_128_ cronExpression + varchar_32_ id PK + varchar_128_ name + TEXT objective + datetime_3_ updatedAt +} +"agents" { + varchar_36_ activeVersionId FK + datetime_3_ createdAt + varchar_512_ description + varchar_36_ id PK + TEXT integrations + varchar_128_ name + varchar_255_ projectId FK + TEXT schema + TEXT skills + TEXT tools + datetime_3_ updatedAt + varchar_36_ versionId +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/sqlite-schema/agent_task_run_lock.md b/docs/generated/sqlite-schema/agent_task_run_lock.md new file mode 100644 index 00000000000..f236f8bbdef --- /dev/null +++ b/docs/generated/sqlite-schema/agent_task_run_lock.md @@ -0,0 +1,73 @@ +# agent_task_run_lock + +## Description + +<details> +<summary><strong>Table Definition</strong></summary> + +```sql +CREATE TABLE "agent_task_run_lock" ("agentId" varchar(36) NOT NULL, "taskId" varchar(32) NOT NULL, "holderId" varchar NOT NULL, "heldUntil" datetime(3) 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_b57a2862ae869aab24e54cefd48" FOREIGN KEY ("agentId") REFERENCES "agents" ("id") ON DELETE CASCADE, PRIMARY KEY ("agentId", "taskId")) +``` + +</details> + +## 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 | | | | +| heldUntil | datetime(3) | | false | | | | +| holderId | varchar | | false | | | | +| taskId | varchar(32) | | false | | | | +| updatedAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| - (Foreign key ID: 0) | FOREIGN KEY | FOREIGN KEY (agentId) REFERENCES agents (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| agentId | PRIMARY KEY | PRIMARY KEY (agentId) | +| sqlite_autoindex_agent_task_run_lock_1 | PRIMARY KEY | PRIMARY KEY (agentId, taskId) | +| taskId | PRIMARY KEY | PRIMARY KEY (taskId) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| sqlite_autoindex_agent_task_run_lock_1 | PRIMARY KEY (agentId, taskId) | + +## Relations + +```mermaid +erDiagram + +"agent_task_run_lock" |o--|| "agents" : "FOREIGN KEY (agentId) REFERENCES agents (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" + +"agent_task_run_lock" { + varchar_36_ agentId PK + datetime_3_ createdAt + datetime_3_ heldUntil + varchar holderId + varchar_32_ taskId PK + datetime_3_ updatedAt +} +"agents" { + varchar_36_ activeVersionId FK + datetime_3_ createdAt + varchar_512_ description + varchar_36_ id PK + TEXT integrations + varchar_128_ name + varchar_255_ projectId FK + TEXT schema + TEXT skills + TEXT tools + datetime_3_ updatedAt + varchar_36_ versionId +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/sqlite-schema/agent_task_snapshot.md b/docs/generated/sqlite-schema/agent_task_snapshot.md new file mode 100644 index 00000000000..96801b8dd5f --- /dev/null +++ b/docs/generated/sqlite-schema/agent_task_snapshot.md @@ -0,0 +1,74 @@ +# agent_task_snapshot + +## Description + +<details> +<summary><strong>Table Definition</strong></summary> + +```sql +CREATE TABLE "agent_task_snapshot" ("versionId" varchar(36) NOT NULL, "taskId" varchar(32) NOT NULL, "enabled" boolean NOT NULL, "name" varchar(128) NOT NULL, "objective" text NOT NULL, "cronExpression" varchar(128) 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_1acedce6690392ef1611cca8b88" FOREIGN KEY ("versionId") REFERENCES "agent_history" ("versionId") ON DELETE CASCADE, PRIMARY KEY ("versionId", "taskId")) +``` + +</details> + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| createdAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | +| cronExpression | varchar(128) | | false | | | | +| enabled | boolean | | false | | | | +| name | varchar(128) | | false | | | | +| objective | TEXT | | false | | | | +| taskId | varchar(32) | | false | | | | +| updatedAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | +| versionId | varchar(36) | | false | | [agent_history](agent_history.md) | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| - (Foreign key ID: 0) | FOREIGN KEY | FOREIGN KEY (versionId) REFERENCES agent_history (versionId) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| sqlite_autoindex_agent_task_snapshot_1 | PRIMARY KEY | PRIMARY KEY (versionId, taskId) | +| taskId | PRIMARY KEY | PRIMARY KEY (taskId) | +| versionId | PRIMARY KEY | PRIMARY KEY (versionId) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| sqlite_autoindex_agent_task_snapshot_1 | PRIMARY KEY (versionId, taskId) | + +## Relations + +```mermaid +erDiagram + +"agent_task_snapshot" |o--|| "agent_history" : "FOREIGN KEY (versionId) REFERENCES agent_history (versionId) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" + +"agent_task_snapshot" { + datetime_3_ createdAt + varchar_128_ cronExpression + boolean enabled + varchar_128_ name + TEXT objective + varchar_32_ taskId PK + datetime_3_ updatedAt + varchar_36_ versionId PK +} +"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 +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/sqlite-schema/agents.md b/docs/generated/sqlite-schema/agents.md new file mode 100644 index 00000000000..0fadf6464d4 --- /dev/null +++ b/docs/generated/sqlite-schema/agents.md @@ -0,0 +1,244 @@ +# agents + +## Description + +<details> +<summary><strong>Table Definition</strong></summary> + +```sql +CREATE TABLE "agents" ("id" varchar(36) PRIMARY KEY NOT NULL, "name" varchar(128) NOT NULL, "description" varchar(512), "projectId" varchar(255) NOT NULL, "integrations" text NOT NULL DEFAULT ('[]'), "schema" text, "tools" text NOT NULL DEFAULT ('{}'), "skills" text NOT NULL DEFAULT ('{}'), "versionId" varchar(36), "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')), "activeVersionId" varchar(36), CONSTRAINT "FK_a30d560207c4071d98aa03c179c" FOREIGN KEY ("projectId") REFERENCES "project" ("id") ON DELETE CASCADE ON UPDATE NO ACTION, CONSTRAINT "FK_940597dfe9753375309ce6aeea0" FOREIGN KEY ("activeVersionId") REFERENCES "agent_history" ("versionId") ON DELETE SET NULL) +``` + +</details> + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| activeVersionId | varchar(36) | | true | | [agent_history](agent_history.md) | | +| createdAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | +| description | varchar(512) | | true | | | | +| id | varchar(36) | | false | [agent_chat_subscriptions](agent_chat_subscriptions.md) [agent_checkpoints](agent_checkpoints.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) [agents_memory_entries](agents_memory_entries.md) [agents_memory_entry_cursors](agents_memory_entry_cursors.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) | | | +| integrations | TEXT | '[]' | false | | | | +| name | varchar(128) | | false | | | | +| projectId | varchar(255) | | false | | [project](project.md) | | +| schema | TEXT | | true | | | | +| skills | TEXT | '{}' | false | | | | +| tools | TEXT | '{}' | false | | | | +| updatedAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | +| versionId | varchar(36) | | true | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| - (Foreign key ID: 0) | FOREIGN KEY | FOREIGN KEY (activeVersionId) REFERENCES agent_history (versionId) ON UPDATE NO ACTION ON DELETE SET NULL MATCH NONE | +| - (Foreign key ID: 1) | 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_agents_1 | PRIMARY KEY | PRIMARY KEY (id) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_a30d560207c4071d98aa03c179 | CREATE INDEX "IDX_a30d560207c4071d98aa03c179" ON "agents" ("projectId") | +| IDX_agents_projectId | CREATE INDEX "IDX_agents_projectId" ON "agents" ("projectId") | +| sqlite_autoindex_agents_1 | PRIMARY KEY (id) | + +## Relations + +```mermaid +erDiagram + +"agents" }o--o| "agent_history" : "FOREIGN KEY (activeVersionId) REFERENCES agent_history (versionId) ON UPDATE NO ACTION ON DELETE SET NULL MATCH NONE" +"agent_chat_subscriptions" |o--|| "agents" : "FOREIGN KEY (agentId) REFERENCES agents (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"agent_checkpoints" }o--o| "agents" : "FOREIGN KEY (agentId) REFERENCES agents (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"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_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" +"agents_memory_entries" }o--|| "agents" : "FOREIGN KEY (agentId) REFERENCES agents (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"agents_memory_entry_cursors" |o--|| "agents" : "FOREIGN KEY (agentId) REFERENCES agents (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"agents_memory_entry_locks" |o--|| "agents" : "FOREIGN KEY (agentId) REFERENCES agents (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"agents_memory_entry_sources" }o--|| "agents" : "FOREIGN KEY (agentId) REFERENCES agents (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"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" +"agents" }o--|| "project" : "FOREIGN KEY (projectId) REFERENCES project (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" + +"agents" { + varchar_36_ activeVersionId FK + datetime_3_ createdAt + varchar_512_ description + varchar_36_ id PK + TEXT integrations + varchar_128_ name + varchar_255_ projectId FK + TEXT schema + TEXT skills + TEXT tools + datetime_3_ updatedAt + varchar_36_ versionId +} +"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 +} +"agent_chat_subscriptions" { + varchar_36_ agentId PK + datetime_3_ createdAt + varchar_255_ credentialId PK + varchar_64_ integrationType PK + varchar_255_ threadId PK + datetime_3_ updatedAt +} +"agent_checkpoints" { + varchar_255_ agentId FK + datetime_3_ createdAt + boolean expired + varchar_255_ runId PK + TEXT state + datetime_3_ updatedAt +} +"agent_execution_threads" { + varchar_36_ agentId FK + varchar_255_ agentName + datetime_3_ createdAt + varchar_8_ emoji + varchar_128_ id PK + varchar_36_ parentAgentId + varchar_128_ parentThreadId + varchar_255_ projectId FK + INTEGER sessionNumber + varchar_32_ taskId + varchar_36_ taskVersionId FK + varchar_255_ title + INTEGER totalCompletionTokens + REAL totalCost + INTEGER totalDuration + INTEGER totalPromptTokens + datetime_3_ updatedAt +} +"agent_files" { + varchar_36_ agentId FK + TEXT binaryDataId + datetime_3_ createdAt + varchar_255_ fileName + INTEGER fileSizeBytes + varchar_16_ id PK + varchar_255_ mimeType + datetime_3_ updatedAt +} +"agent_task_definition" { + varchar_36_ agentId FK + datetime_3_ createdAt + varchar_128_ cronExpression + varchar_32_ id PK + varchar_128_ name + TEXT objective + datetime_3_ updatedAt +} +"agent_task_run_lock" { + varchar_36_ agentId PK + datetime_3_ createdAt + datetime_3_ heldUntil + varchar holderId + varchar_32_ taskId PK + datetime_3_ updatedAt +} +"agents_memory_entries" { + varchar_36_ agentId FK + TEXT content + varchar_64_ contentHash + datetime_3_ createdAt + TEXT embedding + varchar_128_ embeddingModel + varchar_36_ id PK + datetime_3_ lastSeenAt + TEXT metadata + varchar_255_ resourceId FK + varchar_16_ status + varchar_36_ supersededBy FK + datetime_3_ updatedAt +} +"agents_memory_entry_cursors" { + varchar_36_ agentId PK + datetime_3_ createdAt + datetime_3_ lastIndexedObservationCreatedAt + varchar_36_ lastIndexedObservationId + varchar_255_ observationScopeId PK + datetime_3_ updatedAt +} +"agents_memory_entry_locks" { + varchar_36_ agentId PK + datetime_3_ createdAt + datetime_3_ heldUntil + varchar_64_ holderId + varchar_255_ resourceId PK + datetime_3_ updatedAt +} +"agents_memory_entry_sources" { + varchar_36_ agentId FK + datetime_3_ createdAt + varchar_64_ evidenceHash + TEXT evidenceText + varchar_36_ id PK + varchar_36_ memoryEntryId FK + varchar_36_ observationId FK + varchar_255_ threadId FK + datetime_3_ updatedAt +} +"agents_observation_cursors" { + varchar_36_ agentId PK + datetime_3_ createdAt + datetime_3_ lastObservedAt + varchar_36_ lastObservedMessageId + varchar_255_ observationScopeId PK + datetime_3_ updatedAt +} +"agents_observation_locks" { + varchar_36_ agentId PK + datetime_3_ createdAt + datetime_3_ heldUntil + varchar_64_ holderId + varchar_255_ observationScopeId PK + varchar_20_ taskKind PK + datetime_3_ updatedAt +} +"agents_observations" { + varchar_36_ agentId FK + datetime_3_ createdAt + varchar_36_ id PK + varchar_16_ marker + varchar_255_ observationScopeId FK + varchar_36_ parentId FK + varchar_16_ status + varchar_36_ supersededBy FK + TEXT text + INTEGER tokenCount + datetime_3_ updatedAt +} +"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/agents_memory_entries.md b/docs/generated/sqlite-schema/agents_memory_entries.md new file mode 100644 index 00000000000..997002e466a --- /dev/null +++ b/docs/generated/sqlite-schema/agents_memory_entries.md @@ -0,0 +1,113 @@ +# agents_memory_entries + +## Description + +<details> +<summary><strong>Table Definition</strong></summary> + +```sql +CREATE TABLE "agents_memory_entries" ("id" varchar(36) PRIMARY KEY NOT NULL, "agentId" varchar(36) NOT NULL, "resourceId" varchar(255) NOT NULL, "content" text NOT NULL, "contentHash" varchar(64) NOT NULL, "status" varchar(16) NOT NULL, "supersededBy" varchar(36), "embeddingModel" varchar(128), "embedding" text, "metadata" text, "lastSeenAt" datetime(3) 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 "CHK_agents_memory_entries_status" CHECK ("status" IN ('active', 'superseded', 'dropped')), CONSTRAINT "FK_28e981fb675e9b44ce02f0ec1dd" FOREIGN KEY ("agentId") REFERENCES "agents" ("id") ON DELETE CASCADE, CONSTRAINT "FK_1443a75e59adbfb796071d66393" FOREIGN KEY ("resourceId") REFERENCES "agents_resources" ("id") ON DELETE CASCADE, CONSTRAINT "FK_0edf1226b77ddc525eae4938079" FOREIGN KEY ("supersededBy") REFERENCES "agents_memory_entries" ("id")) +``` + +</details> + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| agentId | varchar(36) | | false | | [agents](agents.md) | | +| content | TEXT | | false | | | | +| contentHash | varchar(64) | | false | | | | +| createdAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | +| embedding | TEXT | | true | | | | +| embeddingModel | varchar(128) | | true | | | | +| id | varchar(36) | | false | [agents_memory_entries](agents_memory_entries.md) [agents_memory_entry_sources](agents_memory_entry_sources.md) | | | +| lastSeenAt | datetime(3) | | false | | | | +| metadata | TEXT | | true | | | | +| resourceId | varchar(255) | | false | | [agents_resources](agents_resources.md) | | +| status | varchar(16) | | false | | | | +| supersededBy | varchar(36) | | true | | [agents_memory_entries](agents_memory_entries.md) | | +| updatedAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| - | CHECK | CHECK ("status" IN ('active', 'superseded', 'dropped')) | +| - (Foreign key ID: 0) | FOREIGN KEY | FOREIGN KEY (supersededBy) REFERENCES agents_memory_entries (id) ON UPDATE NO ACTION ON DELETE NO ACTION MATCH NONE | +| - (Foreign key ID: 1) | FOREIGN KEY | FOREIGN KEY (resourceId) REFERENCES agents_resources (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 | +| id | PRIMARY KEY | PRIMARY KEY (id) | +| sqlite_autoindex_agents_memory_entries_1 | PRIMARY KEY | PRIMARY KEY (id) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_0edf1226b77ddc525eae493807 | CREATE INDEX "IDX_0edf1226b77ddc525eae493807" ON "agents_memory_entries" ("supersededBy") | +| IDX_1443a75e59adbfb796071d6639 | CREATE INDEX "IDX_1443a75e59adbfb796071d6639" ON "agents_memory_entries" ("resourceId") | +| IDX_a03e04e94bea8439dd166d4b52 | CREATE UNIQUE INDEX "IDX_a03e04e94bea8439dd166d4b52" ON "agents_memory_entries" ("agentId", "resourceId", "contentHash") | +| IDX_aff2807b31eccbafe59d0474f0 | CREATE INDEX "IDX_aff2807b31eccbafe59d0474f0" ON "agents_memory_entries" ("agentId", "resourceId", "status", "createdAt", "id") | +| sqlite_autoindex_agents_memory_entries_1 | PRIMARY KEY (id) | + +## Relations + +```mermaid +erDiagram + +"agents_memory_entries" }o--|| "agents" : "FOREIGN KEY (agentId) REFERENCES agents (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"agents_memory_entries" }o--o| "agents_memory_entries" : "FOREIGN KEY (supersededBy) REFERENCES agents_memory_entries (id) ON UPDATE NO ACTION ON DELETE NO ACTION MATCH NONE" +"agents_memory_entry_sources" }o--|| "agents_memory_entries" : "FOREIGN KEY (memoryEntryId) REFERENCES agents_memory_entries (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"agents_memory_entries" }o--|| "agents_resources" : "FOREIGN KEY (resourceId) REFERENCES agents_resources (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" + +"agents_memory_entries" { + varchar_36_ agentId FK + TEXT content + varchar_64_ contentHash + datetime_3_ createdAt + TEXT embedding + varchar_128_ embeddingModel + varchar_36_ id PK + datetime_3_ lastSeenAt + TEXT metadata + varchar_255_ resourceId FK + varchar_16_ status + varchar_36_ supersededBy FK + datetime_3_ updatedAt +} +"agents" { + varchar_36_ activeVersionId FK + datetime_3_ createdAt + varchar_512_ description + varchar_36_ id PK + TEXT integrations + varchar_128_ name + varchar_255_ projectId FK + TEXT schema + TEXT skills + TEXT tools + datetime_3_ updatedAt + varchar_36_ versionId +} +"agents_memory_entry_sources" { + varchar_36_ agentId FK + datetime_3_ createdAt + varchar_64_ evidenceHash + TEXT evidenceText + varchar_36_ id PK + varchar_36_ memoryEntryId FK + varchar_36_ observationId FK + varchar_255_ threadId FK + datetime_3_ updatedAt +} +"agents_resources" { + datetime_3_ createdAt + varchar_255_ id PK + TEXT metadata + datetime_3_ updatedAt +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/sqlite-schema/agents_memory_entry_cursors.md b/docs/generated/sqlite-schema/agents_memory_entry_cursors.md new file mode 100644 index 00000000000..688ec514214 --- /dev/null +++ b/docs/generated/sqlite-schema/agents_memory_entry_cursors.md @@ -0,0 +1,84 @@ +# agents_memory_entry_cursors + +## Description + +<details> +<summary><strong>Table Definition</strong></summary> + +```sql +CREATE TABLE "agents_memory_entry_cursors" ("agentId" varchar(36) NOT NULL, "observationScopeId" varchar(255) NOT NULL, "lastIndexedObservationId" varchar(36) NOT NULL, "lastIndexedObservationCreatedAt" datetime(3) 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_746780fd115e5e4352457a3c617" FOREIGN KEY ("agentId") REFERENCES "agents" ("id") ON DELETE CASCADE, CONSTRAINT "FK_069e791e428391a5569e7a96b20" FOREIGN KEY ("observationScopeId") REFERENCES "agents_threads" ("id") ON DELETE CASCADE, PRIMARY KEY ("agentId", "observationScopeId")) +``` + +</details> + +## 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 | | | | +| lastIndexedObservationCreatedAt | datetime(3) | | false | | | | +| lastIndexedObservationId | varchar(36) | | false | | | | +| observationScopeId | varchar(255) | | false | | [agents_threads](agents_threads.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 (observationScopeId) REFERENCES agents_threads (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| - (Foreign key ID: 1) | FOREIGN KEY | FOREIGN KEY (agentId) REFERENCES agents (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| agentId | PRIMARY KEY | PRIMARY KEY (agentId) | +| observationScopeId | PRIMARY KEY | PRIMARY KEY (observationScopeId) | +| sqlite_autoindex_agents_memory_entry_cursors_1 | PRIMARY KEY | PRIMARY KEY (agentId, observationScopeId) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_069e791e428391a5569e7a96b2 | CREATE INDEX "IDX_069e791e428391a5569e7a96b2" ON "agents_memory_entry_cursors" ("observationScopeId") | +| sqlite_autoindex_agents_memory_entry_cursors_1 | PRIMARY KEY (agentId, observationScopeId) | + +## Relations + +```mermaid +erDiagram + +"agents_memory_entry_cursors" |o--|| "agents" : "FOREIGN KEY (agentId) REFERENCES agents (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"agents_memory_entry_cursors" |o--|| "agents_threads" : "FOREIGN KEY (observationScopeId) REFERENCES agents_threads (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" + +"agents_memory_entry_cursors" { + varchar_36_ agentId PK + datetime_3_ createdAt + datetime_3_ lastIndexedObservationCreatedAt + varchar_36_ lastIndexedObservationId + varchar_255_ observationScopeId PK + datetime_3_ updatedAt +} +"agents" { + varchar_36_ activeVersionId FK + datetime_3_ createdAt + varchar_512_ description + varchar_36_ id PK + TEXT integrations + varchar_128_ name + varchar_255_ projectId FK + TEXT schema + TEXT skills + TEXT tools + datetime_3_ updatedAt + varchar_36_ versionId +} +"agents_threads" { + datetime_3_ createdAt + varchar_128_ id PK + TEXT metadata + varchar_255_ resourceId + varchar_255_ title + datetime_3_ updatedAt +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/sqlite-schema/agents_memory_entry_locks.md b/docs/generated/sqlite-schema/agents_memory_entry_locks.md new file mode 100644 index 00000000000..af3b3a1d42c --- /dev/null +++ b/docs/generated/sqlite-schema/agents_memory_entry_locks.md @@ -0,0 +1,82 @@ +# agents_memory_entry_locks + +## Description + +<details> +<summary><strong>Table Definition</strong></summary> + +```sql +CREATE TABLE "agents_memory_entry_locks" ("agentId" varchar(36) NOT NULL, "resourceId" varchar(255) NOT NULL, "holderId" varchar(64) NOT NULL, "heldUntil" datetime(3) 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_0ccf6d9ea6f44fa1c264fc2f795" FOREIGN KEY ("agentId") REFERENCES "agents" ("id") ON DELETE CASCADE, CONSTRAINT "FK_9594c0983cfee1c8ff49b05848b" FOREIGN KEY ("resourceId") REFERENCES "agents_resources" ("id") ON DELETE CASCADE, PRIMARY KEY ("agentId", "resourceId")) +``` + +</details> + +## 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 | | | | +| heldUntil | datetime(3) | | false | | | | +| holderId | varchar(64) | | false | | | | +| resourceId | varchar(255) | | false | | [agents_resources](agents_resources.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 (resourceId) REFERENCES agents_resources (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| - (Foreign key ID: 1) | FOREIGN KEY | FOREIGN KEY (agentId) REFERENCES agents (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| agentId | PRIMARY KEY | PRIMARY KEY (agentId) | +| resourceId | PRIMARY KEY | PRIMARY KEY (resourceId) | +| sqlite_autoindex_agents_memory_entry_locks_1 | PRIMARY KEY | PRIMARY KEY (agentId, resourceId) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_9594c0983cfee1c8ff49b05848 | CREATE INDEX "IDX_9594c0983cfee1c8ff49b05848" ON "agents_memory_entry_locks" ("resourceId") | +| sqlite_autoindex_agents_memory_entry_locks_1 | PRIMARY KEY (agentId, resourceId) | + +## Relations + +```mermaid +erDiagram + +"agents_memory_entry_locks" |o--|| "agents" : "FOREIGN KEY (agentId) REFERENCES agents (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"agents_memory_entry_locks" |o--|| "agents_resources" : "FOREIGN KEY (resourceId) REFERENCES agents_resources (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" + +"agents_memory_entry_locks" { + varchar_36_ agentId PK + datetime_3_ createdAt + datetime_3_ heldUntil + varchar_64_ holderId + varchar_255_ resourceId PK + datetime_3_ updatedAt +} +"agents" { + varchar_36_ activeVersionId FK + datetime_3_ createdAt + varchar_512_ description + varchar_36_ id PK + TEXT integrations + varchar_128_ name + varchar_255_ projectId FK + TEXT schema + TEXT skills + TEXT tools + datetime_3_ updatedAt + varchar_36_ versionId +} +"agents_resources" { + datetime_3_ createdAt + varchar_255_ id PK + TEXT metadata + datetime_3_ updatedAt +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/sqlite-schema/agents_memory_entry_sources.md b/docs/generated/sqlite-schema/agents_memory_entry_sources.md new file mode 100644 index 00000000000..9b76671b4e1 --- /dev/null +++ b/docs/generated/sqlite-schema/agents_memory_entry_sources.md @@ -0,0 +1,124 @@ +# agents_memory_entry_sources + +## Description + +<details> +<summary><strong>Table Definition</strong></summary> + +```sql +CREATE TABLE "agents_memory_entry_sources" ("id" varchar(36) PRIMARY KEY NOT NULL, "agentId" varchar(36) NOT NULL, "memoryEntryId" varchar(36) NOT NULL, "observationId" varchar(36) NOT NULL, "threadId" varchar(255) NOT NULL, "evidenceHash" varchar(64) NOT NULL, "evidenceText" 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_c38e8a57a36b880e39a52ada2e8" FOREIGN KEY ("agentId") REFERENCES "agents" ("id") ON DELETE CASCADE, CONSTRAINT "FK_4706f6223313959b7437a2b48df" FOREIGN KEY ("memoryEntryId") REFERENCES "agents_memory_entries" ("id") ON DELETE CASCADE, CONSTRAINT "FK_cb7c15d22fd068a0806aa57fc03" FOREIGN KEY ("observationId") REFERENCES "agents_observations" ("id") ON DELETE CASCADE, CONSTRAINT "FK_451d387a182fa8dd8002dfc3a77" FOREIGN KEY ("threadId") REFERENCES "agents_threads" ("id") ON DELETE CASCADE) +``` + +</details> + +## 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 | | | | +| evidenceHash | varchar(64) | | false | | | | +| evidenceText | TEXT | | false | | | | +| id | varchar(36) | | false | | | | +| memoryEntryId | varchar(36) | | false | | [agents_memory_entries](agents_memory_entries.md) | | +| observationId | varchar(36) | | false | | [agents_observations](agents_observations.md) | | +| threadId | varchar(255) | | false | | [agents_threads](agents_threads.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 (threadId) REFERENCES agents_threads (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| - (Foreign key ID: 1) | FOREIGN KEY | FOREIGN KEY (observationId) REFERENCES agents_observations (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| - (Foreign key ID: 2) | FOREIGN KEY | FOREIGN KEY (memoryEntryId) REFERENCES agents_memory_entries (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| - (Foreign key ID: 3) | FOREIGN KEY | FOREIGN KEY (agentId) REFERENCES agents (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| id | PRIMARY KEY | PRIMARY KEY (id) | +| sqlite_autoindex_agents_memory_entry_sources_1 | PRIMARY KEY | PRIMARY KEY (id) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_451d387a182fa8dd8002dfc3a7 | CREATE INDEX "IDX_451d387a182fa8dd8002dfc3a7" ON "agents_memory_entry_sources" ("threadId") | +| IDX_a353ac251315ef0af6ad3c9f0a | CREATE UNIQUE INDEX "IDX_a353ac251315ef0af6ad3c9f0a" ON "agents_memory_entry_sources" ("memoryEntryId", "observationId", "evidenceHash") | +| IDX_cb7c15d22fd068a0806aa57fc0 | CREATE INDEX "IDX_cb7c15d22fd068a0806aa57fc0" ON "agents_memory_entry_sources" ("observationId") | +| IDX_f9573af4ed653f13b0ba1f7b12 | CREATE INDEX "IDX_f9573af4ed653f13b0ba1f7b12" ON "agents_memory_entry_sources" ("agentId", "threadId") | +| sqlite_autoindex_agents_memory_entry_sources_1 | PRIMARY KEY (id) | + +## Relations + +```mermaid +erDiagram + +"agents_memory_entry_sources" }o--|| "agents" : "FOREIGN KEY (agentId) REFERENCES agents (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"agents_memory_entry_sources" }o--|| "agents_memory_entries" : "FOREIGN KEY (memoryEntryId) REFERENCES agents_memory_entries (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"agents_memory_entry_sources" }o--|| "agents_observations" : "FOREIGN KEY (observationId) REFERENCES agents_observations (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"agents_memory_entry_sources" }o--|| "agents_threads" : "FOREIGN KEY (threadId) REFERENCES agents_threads (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" + +"agents_memory_entry_sources" { + varchar_36_ agentId FK + datetime_3_ createdAt + varchar_64_ evidenceHash + TEXT evidenceText + varchar_36_ id PK + varchar_36_ memoryEntryId FK + varchar_36_ observationId FK + varchar_255_ threadId FK + datetime_3_ updatedAt +} +"agents" { + varchar_36_ activeVersionId FK + datetime_3_ createdAt + varchar_512_ description + varchar_36_ id PK + TEXT integrations + varchar_128_ name + varchar_255_ projectId FK + TEXT schema + TEXT skills + TEXT tools + datetime_3_ updatedAt + varchar_36_ versionId +} +"agents_memory_entries" { + varchar_36_ agentId FK + TEXT content + varchar_64_ contentHash + datetime_3_ createdAt + TEXT embedding + varchar_128_ embeddingModel + varchar_36_ id PK + datetime_3_ lastSeenAt + TEXT metadata + varchar_255_ resourceId FK + varchar_16_ status + varchar_36_ supersededBy FK + datetime_3_ updatedAt +} +"agents_observations" { + varchar_36_ agentId FK + datetime_3_ createdAt + varchar_36_ id PK + varchar_16_ marker + varchar_255_ observationScopeId FK + varchar_36_ parentId FK + varchar_16_ status + varchar_36_ supersededBy FK + TEXT text + INTEGER tokenCount + datetime_3_ updatedAt +} +"agents_threads" { + datetime_3_ createdAt + varchar_128_ id PK + TEXT metadata + varchar_255_ resourceId + varchar_255_ title + datetime_3_ updatedAt +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/sqlite-schema/agents_messages.md b/docs/generated/sqlite-schema/agents_messages.md new file mode 100644 index 00000000000..15fd9b3c45d --- /dev/null +++ b/docs/generated/sqlite-schema/agents_messages.md @@ -0,0 +1,72 @@ +# agents_messages + +## Description + +<details> +<summary><strong>Table Definition</strong></summary> + +```sql +CREATE TABLE "agents_messages" ("id" varchar(36) PRIMARY KEY NOT NULL, "threadId" varchar(255) NOT NULL, "resourceId" varchar(255) NOT NULL, "role" varchar(36) NOT NULL, "type" varchar(36), "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_0a8057a61afabd2999608ffd0d9" FOREIGN KEY ("threadId") REFERENCES "agents_threads" ("id") ON DELETE CASCADE) +``` + +</details> + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| content | TEXT | | false | | | | +| createdAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | +| id | varchar(36) | | false | | | | +| resourceId | varchar(255) | | false | | | | +| role | varchar(36) | | false | | | | +| threadId | varchar(255) | | false | | [agents_threads](agents_threads.md) | | +| type | varchar(36) | | true | | | | +| updatedAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| - (Foreign key ID: 0) | FOREIGN KEY | FOREIGN KEY (threadId) REFERENCES agents_threads (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| id | PRIMARY KEY | PRIMARY KEY (id) | +| sqlite_autoindex_agents_messages_1 | PRIMARY KEY | PRIMARY KEY (id) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_agents_messages_threadId_createdAt | CREATE INDEX "IDX_agents_messages_threadId_createdAt" ON "agents_messages" ("threadId", "createdAt") | +| IDX_fc7bf858660bfafd19181e8e35 | CREATE INDEX "IDX_fc7bf858660bfafd19181e8e35" ON "agents_messages" ("threadId", "createdAt") | +| sqlite_autoindex_agents_messages_1 | PRIMARY KEY (id) | + +## Relations + +```mermaid +erDiagram + +"agents_messages" }o--|| "agents_threads" : "FOREIGN KEY (threadId) REFERENCES agents_threads (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" + +"agents_messages" { + TEXT content + datetime_3_ createdAt + varchar_36_ id PK + varchar_255_ resourceId + varchar_36_ role + varchar_255_ threadId FK + varchar_36_ type + datetime_3_ updatedAt +} +"agents_threads" { + datetime_3_ createdAt + varchar_128_ id PK + TEXT metadata + varchar_255_ resourceId + varchar_255_ title + datetime_3_ updatedAt +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/sqlite-schema/agents_observation_cursors.md b/docs/generated/sqlite-schema/agents_observation_cursors.md new file mode 100644 index 00000000000..342f9a44edb --- /dev/null +++ b/docs/generated/sqlite-schema/agents_observation_cursors.md @@ -0,0 +1,84 @@ +# agents_observation_cursors + +## Description + +<details> +<summary><strong>Table Definition</strong></summary> + +```sql +CREATE TABLE "agents_observation_cursors" ("agentId" varchar(36) NOT NULL, "observationScopeId" varchar(255) NOT NULL, "lastObservedMessageId" varchar(36) NOT NULL, "lastObservedAt" datetime(3) 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_64e92819f4b413661ed6e2c3c3d" FOREIGN KEY ("agentId") REFERENCES "agents" ("id") ON DELETE CASCADE, CONSTRAINT "FK_87aa187d27ea67eafd164905154" FOREIGN KEY ("observationScopeId") REFERENCES "agents_threads" ("id") ON DELETE CASCADE, PRIMARY KEY ("agentId", "observationScopeId")) +``` + +</details> + +## 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 | | | | +| lastObservedAt | datetime(3) | | false | | | | +| lastObservedMessageId | varchar(36) | | false | | | | +| observationScopeId | varchar(255) | | false | | [agents_threads](agents_threads.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 (observationScopeId) REFERENCES agents_threads (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| - (Foreign key ID: 1) | FOREIGN KEY | FOREIGN KEY (agentId) REFERENCES agents (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| agentId | PRIMARY KEY | PRIMARY KEY (agentId) | +| observationScopeId | PRIMARY KEY | PRIMARY KEY (observationScopeId) | +| sqlite_autoindex_agents_observation_cursors_1 | PRIMARY KEY | PRIMARY KEY (agentId, observationScopeId) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_87aa187d27ea67eafd16490515 | CREATE INDEX "IDX_87aa187d27ea67eafd16490515" ON "agents_observation_cursors" ("observationScopeId") | +| sqlite_autoindex_agents_observation_cursors_1 | PRIMARY KEY (agentId, observationScopeId) | + +## Relations + +```mermaid +erDiagram + +"agents_observation_cursors" |o--|| "agents" : "FOREIGN KEY (agentId) REFERENCES agents (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"agents_observation_cursors" |o--|| "agents_threads" : "FOREIGN KEY (observationScopeId) REFERENCES agents_threads (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" + +"agents_observation_cursors" { + varchar_36_ agentId PK + datetime_3_ createdAt + datetime_3_ lastObservedAt + varchar_36_ lastObservedMessageId + varchar_255_ observationScopeId PK + datetime_3_ updatedAt +} +"agents" { + varchar_36_ activeVersionId FK + datetime_3_ createdAt + varchar_512_ description + varchar_36_ id PK + TEXT integrations + varchar_128_ name + varchar_255_ projectId FK + TEXT schema + TEXT skills + TEXT tools + datetime_3_ updatedAt + varchar_36_ versionId +} +"agents_threads" { + datetime_3_ createdAt + varchar_128_ id PK + TEXT metadata + varchar_255_ resourceId + varchar_255_ title + datetime_3_ updatedAt +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/sqlite-schema/agents_observation_locks.md b/docs/generated/sqlite-schema/agents_observation_locks.md new file mode 100644 index 00000000000..47feee013d2 --- /dev/null +++ b/docs/generated/sqlite-schema/agents_observation_locks.md @@ -0,0 +1,88 @@ +# agents_observation_locks + +## Description + +<details> +<summary><strong>Table Definition</strong></summary> + +```sql +CREATE TABLE "agents_observation_locks" ("agentId" varchar(36) NOT NULL, "observationScopeId" varchar(255) NOT NULL, "taskKind" varchar(20) NOT NULL, "holderId" varchar(64) NOT NULL, "heldUntil" datetime(3) 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 "CHK_agents_observation_locks_taskKind" CHECK ("taskKind" IN ('observer', 'reflector')), CONSTRAINT "FK_093e44ae20f2518e97d83a95433" FOREIGN KEY ("agentId") REFERENCES "agents" ("id") ON DELETE CASCADE, CONSTRAINT "FK_6b55089892e447c2f82e5ec60ed" FOREIGN KEY ("observationScopeId") REFERENCES "agents_threads" ("id") ON DELETE CASCADE, PRIMARY KEY ("agentId", "observationScopeId", "taskKind")) +``` + +</details> + +## 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 | | | | +| heldUntil | datetime(3) | | false | | | | +| holderId | varchar(64) | | false | | | | +| observationScopeId | varchar(255) | | false | | [agents_threads](agents_threads.md) | | +| taskKind | varchar(20) | | false | | | | +| updatedAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| - | CHECK | CHECK ("taskKind" IN ('observer', 'reflector')) | +| - (Foreign key ID: 0) | FOREIGN KEY | FOREIGN KEY (observationScopeId) REFERENCES agents_threads (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| - (Foreign key ID: 1) | FOREIGN KEY | FOREIGN KEY (agentId) REFERENCES agents (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| agentId | PRIMARY KEY | PRIMARY KEY (agentId) | +| observationScopeId | PRIMARY KEY | PRIMARY KEY (observationScopeId) | +| sqlite_autoindex_agents_observation_locks_1 | PRIMARY KEY | PRIMARY KEY (agentId, observationScopeId, taskKind) | +| taskKind | PRIMARY KEY | PRIMARY KEY (taskKind) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_6b55089892e447c2f82e5ec60e | CREATE INDEX "IDX_6b55089892e447c2f82e5ec60e" ON "agents_observation_locks" ("observationScopeId") | +| sqlite_autoindex_agents_observation_locks_1 | PRIMARY KEY (agentId, observationScopeId, taskKind) | + +## Relations + +```mermaid +erDiagram + +"agents_observation_locks" |o--|| "agents" : "FOREIGN KEY (agentId) REFERENCES agents (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"agents_observation_locks" |o--|| "agents_threads" : "FOREIGN KEY (observationScopeId) REFERENCES agents_threads (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" + +"agents_observation_locks" { + varchar_36_ agentId PK + datetime_3_ createdAt + datetime_3_ heldUntil + varchar_64_ holderId + varchar_255_ observationScopeId PK + varchar_20_ taskKind PK + datetime_3_ updatedAt +} +"agents" { + varchar_36_ activeVersionId FK + datetime_3_ createdAt + varchar_512_ description + varchar_36_ id PK + TEXT integrations + varchar_128_ name + varchar_255_ projectId FK + TEXT schema + TEXT skills + TEXT tools + datetime_3_ updatedAt + varchar_36_ versionId +} +"agents_threads" { + datetime_3_ createdAt + varchar_128_ id PK + TEXT metadata + varchar_255_ resourceId + varchar_255_ title + datetime_3_ updatedAt +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/sqlite-schema/agents_observations.md b/docs/generated/sqlite-schema/agents_observations.md new file mode 100644 index 00000000000..a40590d30f3 --- /dev/null +++ b/docs/generated/sqlite-schema/agents_observations.md @@ -0,0 +1,114 @@ +# agents_observations + +## Description + +<details> +<summary><strong>Table Definition</strong></summary> + +```sql +CREATE TABLE "agents_observations" ("id" varchar(36) PRIMARY KEY NOT NULL, "agentId" varchar(36) NOT NULL, "observationScopeId" varchar(255) NOT NULL, "marker" varchar(16) NOT NULL, "text" text NOT NULL, "parentId" varchar(36), "tokenCount" integer NOT NULL DEFAULT (0), "status" varchar(16) NOT NULL, "supersededBy" varchar(36), "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_agents_observations_marker" CHECK ("marker" IN ('critical', 'important', 'info', 'completion')), CONSTRAINT "CHK_agents_observations_status" CHECK ("status" IN ('active', 'superseded', 'dropped')), CONSTRAINT "FK_d206432be97b7ed88d187479b1b" FOREIGN KEY ("agentId") REFERENCES "agents" ("id") ON DELETE CASCADE, CONSTRAINT "FK_4cfd8a70ebb0a5b0cf047dca3cf" FOREIGN KEY ("observationScopeId") REFERENCES "agents_threads" ("id") ON DELETE CASCADE, CONSTRAINT "FK_501e2d1701a10e24fb69ab5fc5f" FOREIGN KEY ("parentId") REFERENCES "agents_observations" ("id"), CONSTRAINT "FK_127ee1078ffa952bb37b511efad" FOREIGN KEY ("supersededBy") REFERENCES "agents_observations" ("id")) +``` + +</details> + +## 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 | | | | +| id | varchar(36) | | false | [agents_memory_entry_sources](agents_memory_entry_sources.md) [agents_observations](agents_observations.md) | | | +| marker | varchar(16) | | false | | | | +| observationScopeId | varchar(255) | | false | | [agents_threads](agents_threads.md) | | +| parentId | varchar(36) | | true | | [agents_observations](agents_observations.md) | | +| status | varchar(16) | | false | | | | +| supersededBy | varchar(36) | | true | | [agents_observations](agents_observations.md) | | +| text | TEXT | | false | | | | +| tokenCount | INTEGER | 0 | false | | | | +| updatedAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| - | CHECK | CHECK ("marker" IN ('critical', 'important', 'info', 'completion')) | +| - | CHECK | CHECK ("status" IN ('active', 'superseded', 'dropped')) | +| - (Foreign key ID: 0) | FOREIGN KEY | FOREIGN KEY (supersededBy) REFERENCES agents_observations (id) ON UPDATE NO ACTION ON DELETE NO ACTION MATCH NONE | +| - (Foreign key ID: 1) | FOREIGN KEY | FOREIGN KEY (parentId) REFERENCES agents_observations (id) ON UPDATE NO ACTION ON DELETE NO ACTION MATCH NONE | +| - (Foreign key ID: 2) | FOREIGN KEY | FOREIGN KEY (observationScopeId) REFERENCES agents_threads (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| - (Foreign key ID: 3) | FOREIGN KEY | FOREIGN KEY (agentId) REFERENCES agents (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| id | PRIMARY KEY | PRIMARY KEY (id) | +| sqlite_autoindex_agents_observations_1 | PRIMARY KEY | PRIMARY KEY (id) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_07cb1e4a302629c5fa5d74d2bb | CREATE INDEX "IDX_07cb1e4a302629c5fa5d74d2bb" ON "agents_observations" ("agentId", "observationScopeId", "status") | +| IDX_127ee1078ffa952bb37b511efa | CREATE INDEX "IDX_127ee1078ffa952bb37b511efa" ON "agents_observations" ("supersededBy") | +| IDX_4cfd8a70ebb0a5b0cf047dca3c | CREATE INDEX "IDX_4cfd8a70ebb0a5b0cf047dca3c" ON "agents_observations" ("observationScopeId") | +| IDX_501e2d1701a10e24fb69ab5fc5 | CREATE INDEX "IDX_501e2d1701a10e24fb69ab5fc5" ON "agents_observations" ("parentId") | +| sqlite_autoindex_agents_observations_1 | PRIMARY KEY (id) | + +## Relations + +```mermaid +erDiagram + +"agents_observations" }o--|| "agents" : "FOREIGN KEY (agentId) REFERENCES agents (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"agents_memory_entry_sources" }o--|| "agents_observations" : "FOREIGN KEY (observationId) REFERENCES agents_observations (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"agents_observations" }o--o| "agents_observations" : "FOREIGN KEY (supersededBy) REFERENCES agents_observations (id) ON UPDATE NO ACTION ON DELETE NO ACTION MATCH NONE" +"agents_observations" }o--o| "agents_observations" : "FOREIGN KEY (parentId) REFERENCES agents_observations (id) ON UPDATE NO ACTION ON DELETE NO ACTION MATCH NONE" +"agents_observations" }o--|| "agents_threads" : "FOREIGN KEY (observationScopeId) REFERENCES agents_threads (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" + +"agents_observations" { + varchar_36_ agentId FK + datetime_3_ createdAt + varchar_36_ id PK + varchar_16_ marker + varchar_255_ observationScopeId FK + varchar_36_ parentId FK + varchar_16_ status + varchar_36_ supersededBy FK + TEXT text + INTEGER tokenCount + datetime_3_ updatedAt +} +"agents" { + varchar_36_ activeVersionId FK + datetime_3_ createdAt + varchar_512_ description + varchar_36_ id PK + TEXT integrations + varchar_128_ name + varchar_255_ projectId FK + TEXT schema + TEXT skills + TEXT tools + datetime_3_ updatedAt + varchar_36_ versionId +} +"agents_memory_entry_sources" { + varchar_36_ agentId FK + datetime_3_ createdAt + varchar_64_ evidenceHash + TEXT evidenceText + varchar_36_ id PK + varchar_36_ memoryEntryId FK + varchar_36_ observationId FK + varchar_255_ threadId FK + datetime_3_ updatedAt +} +"agents_threads" { + datetime_3_ createdAt + varchar_128_ id PK + TEXT metadata + varchar_255_ resourceId + varchar_255_ title + datetime_3_ updatedAt +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/sqlite-schema/agents_resources.md b/docs/generated/sqlite-schema/agents_resources.md new file mode 100644 index 00000000000..9bcd8be08c4 --- /dev/null +++ b/docs/generated/sqlite-schema/agents_resources.md @@ -0,0 +1,77 @@ +# agents_resources + +## Description + +<details> +<summary><strong>Table Definition</strong></summary> + +```sql +CREATE TABLE "agents_resources" ("id" varchar(255) PRIMARY KEY NOT NULL, "metadata" text, "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'))) +``` + +</details> + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| createdAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | +| id | varchar(255) | | false | [agents_memory_entries](agents_memory_entries.md) [agents_memory_entry_locks](agents_memory_entry_locks.md) | | | +| metadata | TEXT | | true | | | | +| updatedAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| id | PRIMARY KEY | PRIMARY KEY (id) | +| sqlite_autoindex_agents_resources_1 | PRIMARY KEY | PRIMARY KEY (id) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| sqlite_autoindex_agents_resources_1 | PRIMARY KEY (id) | + +## Relations + +```mermaid +erDiagram + +"agents_memory_entries" }o--|| "agents_resources" : "FOREIGN KEY (resourceId) REFERENCES agents_resources (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"agents_memory_entry_locks" |o--|| "agents_resources" : "FOREIGN KEY (resourceId) REFERENCES agents_resources (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" + +"agents_resources" { + datetime_3_ createdAt + varchar_255_ id PK + TEXT metadata + datetime_3_ updatedAt +} +"agents_memory_entries" { + varchar_36_ agentId FK + TEXT content + varchar_64_ contentHash + datetime_3_ createdAt + TEXT embedding + varchar_128_ embeddingModel + varchar_36_ id PK + datetime_3_ lastSeenAt + TEXT metadata + varchar_255_ resourceId FK + varchar_16_ status + varchar_36_ supersededBy FK + datetime_3_ updatedAt +} +"agents_memory_entry_locks" { + varchar_36_ agentId PK + datetime_3_ createdAt + datetime_3_ heldUntil + varchar_64_ holderId + varchar_255_ resourceId PK + datetime_3_ updatedAt +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/sqlite-schema/agents_threads.md b/docs/generated/sqlite-schema/agents_threads.md new file mode 100644 index 00000000000..e62190e9792 --- /dev/null +++ b/docs/generated/sqlite-schema/agents_threads.md @@ -0,0 +1,122 @@ +# agents_threads + +## Description + +<details> +<summary><strong>Table Definition</strong></summary> + +```sql +CREATE TABLE "agents_threads" ("id" varchar(128) PRIMARY KEY NOT NULL, "resourceId" varchar(255) NOT NULL, "title" varchar(255), "metadata" text, "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'))) +``` + +</details> + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| createdAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | +| id | varchar(128) | | false | [agents_memory_entry_cursors](agents_memory_entry_cursors.md) [agents_memory_entry_sources](agents_memory_entry_sources.md) [agents_messages](agents_messages.md) [agents_observation_cursors](agents_observation_cursors.md) [agents_observation_locks](agents_observation_locks.md) [agents_observations](agents_observations.md) | | | +| metadata | TEXT | | true | | | | +| resourceId | varchar(255) | | false | | | | +| title | varchar(255) | | true | | | | +| updatedAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| id | PRIMARY KEY | PRIMARY KEY (id) | +| sqlite_autoindex_agents_threads_1 | PRIMARY KEY | PRIMARY KEY (id) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_54fa1b94f34a409beafae567a4 | CREATE INDEX "IDX_54fa1b94f34a409beafae567a4" ON "agents_threads" ("resourceId") | +| sqlite_autoindex_agents_threads_1 | PRIMARY KEY (id) | + +## Relations + +```mermaid +erDiagram + +"agents_memory_entry_cursors" |o--|| "agents_threads" : "FOREIGN KEY (observationScopeId) REFERENCES agents_threads (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"agents_memory_entry_sources" }o--|| "agents_threads" : "FOREIGN KEY (threadId) REFERENCES agents_threads (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"agents_messages" }o--|| "agents_threads" : "FOREIGN KEY (threadId) REFERENCES agents_threads (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"agents_observation_cursors" |o--|| "agents_threads" : "FOREIGN KEY (observationScopeId) REFERENCES agents_threads (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"agents_observation_locks" |o--|| "agents_threads" : "FOREIGN KEY (observationScopeId) REFERENCES agents_threads (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"agents_observations" }o--|| "agents_threads" : "FOREIGN KEY (observationScopeId) REFERENCES agents_threads (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" + +"agents_threads" { + datetime_3_ createdAt + varchar_128_ id PK + TEXT metadata + varchar_255_ resourceId + varchar_255_ title + datetime_3_ updatedAt +} +"agents_memory_entry_cursors" { + varchar_36_ agentId PK + datetime_3_ createdAt + datetime_3_ lastIndexedObservationCreatedAt + varchar_36_ lastIndexedObservationId + varchar_255_ observationScopeId PK + datetime_3_ updatedAt +} +"agents_memory_entry_sources" { + varchar_36_ agentId FK + datetime_3_ createdAt + varchar_64_ evidenceHash + TEXT evidenceText + varchar_36_ id PK + varchar_36_ memoryEntryId FK + varchar_36_ observationId FK + varchar_255_ threadId FK + datetime_3_ updatedAt +} +"agents_messages" { + TEXT content + datetime_3_ createdAt + varchar_36_ id PK + varchar_255_ resourceId + varchar_36_ role + varchar_255_ threadId FK + varchar_36_ type + datetime_3_ updatedAt +} +"agents_observation_cursors" { + varchar_36_ agentId PK + datetime_3_ createdAt + datetime_3_ lastObservedAt + varchar_36_ lastObservedMessageId + varchar_255_ observationScopeId PK + datetime_3_ updatedAt +} +"agents_observation_locks" { + varchar_36_ agentId PK + datetime_3_ createdAt + datetime_3_ heldUntil + varchar_64_ holderId + varchar_255_ observationScopeId PK + varchar_20_ taskKind PK + datetime_3_ updatedAt +} +"agents_observations" { + varchar_36_ agentId FK + datetime_3_ createdAt + varchar_36_ id PK + varchar_16_ marker + varchar_255_ observationScopeId FK + varchar_36_ parentId FK + varchar_16_ status + varchar_36_ supersededBy FK + TEXT text + INTEGER tokenCount + datetime_3_ updatedAt +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/sqlite-schema/ai_builder_temporary_workflow.md b/docs/generated/sqlite-schema/ai_builder_temporary_workflow.md new file mode 100644 index 00000000000..d13c73a6149 --- /dev/null +++ b/docs/generated/sqlite-schema/ai_builder_temporary_workflow.md @@ -0,0 +1,88 @@ +# ai_builder_temporary_workflow + +## Description + +<details> +<summary><strong>Table Definition</strong></summary> + +```sql +CREATE TABLE "ai_builder_temporary_workflow" ("workflowId" varchar(36) PRIMARY KEY NOT NULL, "threadId" varchar 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_85a87a1ba0f61999fe11dc56325" FOREIGN KEY ("workflowId") REFERENCES "workflow_entity" ("id") ON DELETE CASCADE, CONSTRAINT "FK_39b07732e819fb561d74c38763f" FOREIGN KEY ("threadId") REFERENCES "instance_ai_threads" ("id") ON DELETE CASCADE) +``` + +</details> + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| createdAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | +| threadId | varchar | | false | | [instance_ai_threads](instance_ai_threads.md) | | +| updatedAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | +| workflowId | varchar(36) | | false | | [workflow_entity](workflow_entity.md) | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| - (Foreign key ID: 0) | FOREIGN KEY | FOREIGN KEY (threadId) REFERENCES instance_ai_threads (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| - (Foreign key ID: 1) | FOREIGN KEY | FOREIGN KEY (workflowId) REFERENCES workflow_entity (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| sqlite_autoindex_ai_builder_temporary_workflow_1 | PRIMARY KEY | PRIMARY KEY (workflowId) | +| workflowId | PRIMARY KEY | PRIMARY KEY (workflowId) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_39b07732e819fb561d74c38763 | CREATE INDEX "IDX_39b07732e819fb561d74c38763" ON "ai_builder_temporary_workflow" ("threadId") | +| sqlite_autoindex_ai_builder_temporary_workflow_1 | PRIMARY KEY (workflowId) | + +## Relations + +```mermaid +erDiagram + +"ai_builder_temporary_workflow" }o--|| "instance_ai_threads" : "FOREIGN KEY (threadId) REFERENCES instance_ai_threads (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"ai_builder_temporary_workflow" |o--|| "workflow_entity" : "FOREIGN KEY (workflowId) REFERENCES workflow_entity (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" + +"ai_builder_temporary_workflow" { + datetime_3_ createdAt + varchar threadId FK + datetime_3_ updatedAt + varchar_36_ workflowId PK +} +"instance_ai_threads" { + datetime_3_ createdAt + varchar id PK + TEXT metadata + varchar_36_ projectId FK + varchar_255_ resourceId + TEXT title + datetime_3_ updatedAt +} +"workflow_entity" { + boolean active + varchar_36_ activeVersionId FK + TEXT connections + datetime_3_ createdAt + TEXT description + varchar_36_ id PK + boolean isArchived + TEXT meta + varchar_128_ name + TEXT nodeGroups + TEXT nodes + varchar_36_ parentFolderId FK + TEXT pinData + TEXT settings + varchar sourceWorkflowId + TEXT staticData + INTEGER triggerCount + datetime_3_ updatedAt + INTEGER versionCounter + varchar_36_ versionId +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/sqlite-schema/annotation_tag_entity.md b/docs/generated/sqlite-schema/annotation_tag_entity.md new file mode 100644 index 00000000000..d698191c0f9 --- /dev/null +++ b/docs/generated/sqlite-schema/annotation_tag_entity.md @@ -0,0 +1,58 @@ +# annotation_tag_entity + +## Description + +<details> +<summary><strong>Table Definition</strong></summary> + +```sql +CREATE TABLE "annotation_tag_entity" ("id" varchar(16) PRIMARY KEY NOT NULL, "name" varchar(24) 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'))) +``` + +</details> + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| createdAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | +| id | varchar(16) | | false | [execution_annotation_tags](execution_annotation_tags.md) | | | +| name | varchar(24) | | false | | | | +| updatedAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| id | PRIMARY KEY | PRIMARY KEY (id) | +| sqlite_autoindex_annotation_tag_entity_1 | PRIMARY KEY | PRIMARY KEY (id) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_ae51b54c4bb430cf92f48b623f | CREATE UNIQUE INDEX "IDX_ae51b54c4bb430cf92f48b623f" ON "annotation_tag_entity" ("name") | +| sqlite_autoindex_annotation_tag_entity_1 | PRIMARY KEY (id) | + +## Relations + +```mermaid +erDiagram + +"execution_annotation_tags" |o--|| "annotation_tag_entity" : "FOREIGN KEY (tagId) REFERENCES annotation_tag_entity (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" + +"annotation_tag_entity" { + datetime_3_ createdAt + varchar_16_ id PK + varchar_24_ name + datetime_3_ updatedAt +} +"execution_annotation_tags" { + INTEGER annotationId PK + varchar_24_ tagId PK +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/sqlite-schema/auth_identity.md b/docs/generated/sqlite-schema/auth_identity.md new file mode 100644 index 00000000000..7516e809fac --- /dev/null +++ b/docs/generated/sqlite-schema/auth_identity.md @@ -0,0 +1,81 @@ +# auth_identity + +## Description + +<details> +<summary><strong>Table Definition</strong></summary> + +```sql +CREATE TABLE "auth_identity" ( + "userId" VARCHAR(36) REFERENCES "user" (id), + "providerId" VARCHAR(64) NOT NULL, + "providerType" VARCHAR(32) NOT NULL, + "createdAt" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY("providerId", "providerType") + ) +``` + +</details> + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| createdAt | timestamp | CURRENT_TIMESTAMP | false | | | | +| providerId | VARCHAR(64) | | false | | | | +| providerType | VARCHAR(32) | | false | | | | +| updatedAt | timestamp | CURRENT_TIMESTAMP | false | | | | +| userId | VARCHAR(36) | | true | | [user](user.md) | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| - (Foreign key ID: 0) | FOREIGN KEY | FOREIGN KEY (userId) REFERENCES user (id) ON UPDATE NO ACTION ON DELETE NO ACTION MATCH NONE | +| providerId | PRIMARY KEY | PRIMARY KEY (providerId) | +| providerType | PRIMARY KEY | PRIMARY KEY (providerType) | +| sqlite_autoindex_auth_identity_1 | PRIMARY KEY | PRIMARY KEY (providerId, providerType) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| sqlite_autoindex_auth_identity_1 | PRIMARY KEY (providerId, providerType) | + +## Relations + +```mermaid +erDiagram + +"auth_identity" }o--o| "user" : "FOREIGN KEY (userId) REFERENCES user (id) ON UPDATE NO ACTION ON DELETE NO ACTION MATCH NONE" + +"auth_identity" { + timestamp createdAt + VARCHAR_64_ providerId PK + VARCHAR_32_ providerType PK + timestamp updatedAt + VARCHAR_36_ userId FK +} +"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 +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/sqlite-schema/auth_provider_sync_history.md b/docs/generated/sqlite-schema/auth_provider_sync_history.md new file mode 100644 index 00000000000..0c2ca0087d7 --- /dev/null +++ b/docs/generated/sqlite-schema/auth_provider_sync_history.md @@ -0,0 +1,71 @@ +# auth_provider_sync_history + +## Description + +<details> +<summary><strong>Table Definition</strong></summary> + +```sql +CREATE TABLE "auth_provider_sync_history" ( + "id" INTEGER PRIMARY KEY AUTOINCREMENT, + "providerType" VARCHAR(32) NOT NULL, + "runMode" TEXT NOT NULL, + "status" TEXT NOT NULL, + "startedAt" DATETIME NOT NULL, + "endedAt" DATETIME NOT NULL, + "scanned" INTEGER NOT NULL, + "created" INTEGER NOT NULL, + "updated" INTEGER NOT NULL, + "disabled" INTEGER NOT NULL, + "error" TEXT + ) +``` + +</details> + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| created | INTEGER | | false | | | | +| disabled | INTEGER | | false | | | | +| endedAt | DATETIME | | false | | | | +| error | TEXT | | true | | | | +| id | INTEGER | | true | | | | +| providerType | VARCHAR(32) | | false | | | | +| runMode | TEXT | | false | | | | +| scanned | INTEGER | | false | | | | +| startedAt | DATETIME | | false | | | | +| status | TEXT | | false | | | | +| updated | INTEGER | | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| id | PRIMARY KEY | PRIMARY KEY (id) | + +## Relations + +```mermaid +erDiagram + + +"auth_provider_sync_history" { + INTEGER created + INTEGER disabled + DATETIME endedAt + TEXT error + INTEGER id + VARCHAR_32_ providerType + TEXT runMode + INTEGER scanned + DATETIME startedAt + TEXT status + INTEGER updated +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/sqlite-schema/binary_data.md b/docs/generated/sqlite-schema/binary_data.md new file mode 100644 index 00000000000..50403e36e30 --- /dev/null +++ b/docs/generated/sqlite-schema/binary_data.md @@ -0,0 +1,64 @@ +# binary_data + +## Description + +<details> +<summary><strong>Table Definition</strong></summary> + +```sql +CREATE TABLE "binary_data" ("fileId" varchar PRIMARY KEY NOT NULL, "sourceType" varchar(50) NOT NULL, "sourceId" varchar(255) NOT NULL, "data" blob NOT NULL, "mimeType" varchar(255), "fileName" varchar(255), "fileSize" integer 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 "CHK_binary_data_sourceType" CHECK ("sourceType" IN ('execution', 'chat_message_attachment', 'agent_file'))) +``` + +</details> + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| createdAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | +| data | BLOB | | false | | | | +| fileId | varchar | | false | | | | +| fileName | varchar(255) | | true | | | | +| fileSize | INTEGER | | false | | | | +| mimeType | varchar(255) | | true | | | | +| sourceId | varchar(255) | | false | | | | +| sourceType | varchar(50) | | false | | | | +| updatedAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| - | CHECK | CHECK ("sourceType" IN ('execution', 'chat_message_attachment', 'agent_file')) | +| fileId | PRIMARY KEY | PRIMARY KEY (fileId) | +| sqlite_autoindex_binary_data_1 | PRIMARY KEY | PRIMARY KEY (fileId) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_56900edc3cfd16612e2ef2c6a8 | CREATE INDEX "IDX_56900edc3cfd16612e2ef2c6a8" ON "binary_data" ("sourceType", "sourceId") | +| sqlite_autoindex_binary_data_1 | PRIMARY KEY (fileId) | + +## Relations + +```mermaid +erDiagram + + +"binary_data" { + datetime_3_ createdAt + BLOB data + varchar fileId PK + varchar_255_ fileName + INTEGER fileSize + varchar_255_ mimeType + varchar_255_ sourceId + varchar_50_ sourceType + datetime_3_ updatedAt +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/sqlite-schema/chat_hub_agent_tools.md b/docs/generated/sqlite-schema/chat_hub_agent_tools.md new file mode 100644 index 00000000000..24e285b1413 --- /dev/null +++ b/docs/generated/sqlite-schema/chat_hub_agent_tools.md @@ -0,0 +1,79 @@ +# chat_hub_agent_tools + +## Description + +<details> +<summary><strong>Table Definition</strong></summary> + +```sql +CREATE TABLE "chat_hub_agent_tools" ("agentId" varchar NOT NULL, "toolId" varchar NOT NULL, CONSTRAINT "FK_2b53d796b3dbae91b1a9553c048" FOREIGN KEY ("agentId") REFERENCES "chat_hub_agents" ("id") ON DELETE CASCADE, CONSTRAINT "FK_43e70f04c53344f82483d0570f6" FOREIGN KEY ("toolId") REFERENCES "chat_hub_tools" ("id") ON DELETE CASCADE, PRIMARY KEY ("agentId", "toolId")) +``` + +</details> + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| agentId | varchar | | false | | [chat_hub_agents](chat_hub_agents.md) | | +| toolId | varchar | | false | | [chat_hub_tools](chat_hub_tools.md) | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| - (Foreign key ID: 0) | FOREIGN KEY | FOREIGN KEY (toolId) REFERENCES chat_hub_tools (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| - (Foreign key ID: 1) | FOREIGN KEY | FOREIGN KEY (agentId) REFERENCES chat_hub_agents (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| agentId | PRIMARY KEY | PRIMARY KEY (agentId) | +| sqlite_autoindex_chat_hub_agent_tools_1 | PRIMARY KEY | PRIMARY KEY (agentId, toolId) | +| toolId | PRIMARY KEY | PRIMARY KEY (toolId) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| sqlite_autoindex_chat_hub_agent_tools_1 | PRIMARY KEY (agentId, toolId) | + +## Relations + +```mermaid +erDiagram + +"chat_hub_agent_tools" |o--|| "chat_hub_agents" : "FOREIGN KEY (agentId) REFERENCES chat_hub_agents (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"chat_hub_agent_tools" |o--|| "chat_hub_tools" : "FOREIGN KEY (toolId) REFERENCES chat_hub_tools (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" + +"chat_hub_agent_tools" { + varchar agentId PK + varchar toolId PK +} +"chat_hub_agents" { + datetime_3_ createdAt + varchar_36_ credentialId FK + varchar_512_ description + TEXT files + TEXT icon + varchar id PK + varchar_64_ model + varchar_256_ name + varchar ownerId FK + varchar_16_ provider + TEXT suggestedPrompts + TEXT systemPrompt + datetime_3_ updatedAt +} +"chat_hub_tools" { + datetime_3_ createdAt + TEXT definition + boolean enabled + varchar id PK + varchar_255_ name + varchar ownerId FK + varchar_255_ type + REAL typeVersion + datetime_3_ updatedAt +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/sqlite-schema/chat_hub_agents.md b/docs/generated/sqlite-schema/chat_hub_agents.md new file mode 100644 index 00000000000..7227a5c12e7 --- /dev/null +++ b/docs/generated/sqlite-schema/chat_hub_agents.md @@ -0,0 +1,145 @@ +# chat_hub_agents + +## Description + +<details> +<summary><strong>Table Definition</strong></summary> + +```sql +CREATE TABLE "chat_hub_agents" ("id" varchar PRIMARY KEY NOT NULL, "name" varchar(256) NOT NULL, "description" varchar(512), "systemPrompt" text NOT NULL, "ownerId" varchar NOT NULL, "credentialId" varchar(36), "provider" varchar(16) NOT NULL, "model" varchar(64) 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')), "icon" text, "files" text NOT NULL DEFAULT ('[]'), "suggestedPrompts" text NOT NULL DEFAULT ('[]'), CONSTRAINT "FK_9c61ad497dcbae499c96a6a78ba" FOREIGN KEY ("credentialId") REFERENCES "credentials_entity" ("id") ON DELETE SET NULL ON UPDATE NO ACTION, CONSTRAINT "FK_441ba2caba11e077ce3fbfa2cd8" FOREIGN KEY ("ownerId") REFERENCES "user" ("id") ON DELETE CASCADE ON UPDATE NO ACTION) +``` + +</details> + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| createdAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | +| credentialId | varchar(36) | | true | | [credentials_entity](credentials_entity.md) | | +| description | varchar(512) | | true | | | | +| files | TEXT | '[]' | false | | | | +| icon | TEXT | | true | | | | +| id | varchar | | false | [chat_hub_agent_tools](chat_hub_agent_tools.md) [chat_hub_messages](chat_hub_messages.md) [chat_hub_sessions](chat_hub_sessions.md) | | | +| model | varchar(64) | | false | | | | +| name | varchar(256) | | false | | | | +| ownerId | varchar | | false | | [user](user.md) | | +| provider | varchar(16) | | false | | | | +| suggestedPrompts | TEXT | '[]' | false | | | | +| systemPrompt | TEXT | | false | | | | +| updatedAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| - (Foreign key ID: 0) | FOREIGN KEY | FOREIGN KEY (ownerId) REFERENCES user (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| - (Foreign key ID: 1) | FOREIGN KEY | FOREIGN KEY (credentialId) REFERENCES credentials_entity (id) ON UPDATE NO ACTION ON DELETE SET NULL MATCH NONE | +| id | PRIMARY KEY | PRIMARY KEY (id) | +| sqlite_autoindex_chat_hub_agents_1 | PRIMARY KEY | PRIMARY KEY (id) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| sqlite_autoindex_chat_hub_agents_1 | PRIMARY KEY (id) | + +## Relations + +```mermaid +erDiagram + +"chat_hub_agents" }o--o| "credentials_entity" : "FOREIGN KEY (credentialId) REFERENCES credentials_entity (id) ON UPDATE NO ACTION ON DELETE SET NULL MATCH NONE" +"chat_hub_agent_tools" |o--|| "chat_hub_agents" : "FOREIGN KEY (agentId) REFERENCES chat_hub_agents (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"chat_hub_messages" }o--o| "chat_hub_agents" : "FOREIGN KEY (agentId) REFERENCES chat_hub_agents (id) ON UPDATE NO ACTION ON DELETE SET NULL MATCH NONE" +"chat_hub_sessions" }o--o| "chat_hub_agents" : "FOREIGN KEY (agentId) REFERENCES chat_hub_agents (id) ON UPDATE NO ACTION ON DELETE SET NULL MATCH NONE" +"chat_hub_agents" }o--|| "user" : "FOREIGN KEY (ownerId) REFERENCES user (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" + +"chat_hub_agents" { + datetime_3_ createdAt + varchar_36_ credentialId FK + varchar_512_ description + TEXT files + TEXT icon + varchar id PK + varchar_64_ model + varchar_256_ name + varchar ownerId FK + varchar_16_ provider + TEXT suggestedPrompts + TEXT systemPrompt + datetime_3_ updatedAt +} +"credentials_entity" { + datetime_3_ createdAt + TEXT data + varchar_36_ id PK + boolean isGlobal + boolean isManaged + boolean isResolvable + varchar_128_ name + boolean resolvableAllowFallback + varchar_16_ resolverId FK + varchar_32_ type + datetime_3_ updatedAt +} +"chat_hub_agent_tools" { + varchar agentId PK + varchar toolId PK +} +"chat_hub_messages" { + varchar_36_ agentId FK + TEXT attachments + TEXT content + datetime_3_ createdAt + INTEGER executionId FK + varchar id PK + VARCHAR_256_ model + varchar_128_ name + varchar previousMessageId FK + varchar_16_ provider + varchar retryOfMessageId FK + varchar revisionOfMessageId FK + varchar sessionId FK + varchar_16_ status + varchar_16_ type + datetime_3_ updatedAt + varchar_36_ workflowId FK +} +"chat_hub_sessions" { + varchar_36_ agentId FK + varchar_128_ agentName + datetime_3_ createdAt + varchar_36_ credentialId FK + varchar id PK + datetime_3_ lastMessageAt + varchar_64_ model + varchar ownerId FK + varchar_16_ provider + varchar_256_ title + varchar_16_ type + datetime_3_ updatedAt + varchar_36_ workflowId FK +} +"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 +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/sqlite-schema/chat_hub_messages.md b/docs/generated/sqlite-schema/chat_hub_messages.md new file mode 100644 index 00000000000..9afa5026871 --- /dev/null +++ b/docs/generated/sqlite-schema/chat_hub_messages.md @@ -0,0 +1,165 @@ +# chat_hub_messages + +## Description + +<details> +<summary><strong>Table Definition</strong></summary> + +```sql +CREATE TABLE "chat_hub_messages" ("id" varchar PRIMARY KEY NOT NULL, "sessionId" varchar NOT NULL, "previousMessageId" varchar, "revisionOfMessageId" varchar, "retryOfMessageId" varchar, "type" varchar(16) NOT NULL, "name" varchar(128) NOT NULL, "content" text NOT NULL, "provider" varchar(16), "workflowId" varchar(36), "executionId" integer, "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')), "agentId" varchar(36), "status" varchar(16) NOT NULL DEFAULT ('success'), "attachments" text, "model" VARCHAR(256), CONSTRAINT "FK_e22538eb50a71a17954cd7e076c" FOREIGN KEY ("sessionId") REFERENCES "chat_hub_sessions" ("id") ON DELETE CASCADE ON UPDATE NO ACTION, CONSTRAINT "FK_e5d1fa722c5a8d38ac204746662" FOREIGN KEY ("previousMessageId") REFERENCES "chat_hub_messages" ("id") ON DELETE CASCADE ON UPDATE NO ACTION, CONSTRAINT "FK_acf8926098f063cdbbad8497fd1" FOREIGN KEY ("workflowId") REFERENCES "workflow_entity" ("id") ON DELETE SET NULL ON UPDATE NO ACTION, CONSTRAINT "FK_25c9736e7f769f3a005eef4b372" FOREIGN KEY ("retryOfMessageId") REFERENCES "chat_hub_messages" ("id") ON DELETE CASCADE ON UPDATE NO ACTION, CONSTRAINT "FK_1f4998c8a7dec9e00a9ab15550e" FOREIGN KEY ("revisionOfMessageId") REFERENCES "chat_hub_messages" ("id") ON DELETE CASCADE ON UPDATE NO ACTION, CONSTRAINT "FK_6afb260449dd7a9b85355d4e0c9" FOREIGN KEY ("executionId") REFERENCES "execution_entity" ("id") ON DELETE SET NULL ON UPDATE NO ACTION, CONSTRAINT "FK_chat_hub_messages_agentId" FOREIGN KEY ("agentId") REFERENCES "chat_hub_agents" ("id") ON DELETE SET NULL) +``` + +</details> + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| agentId | varchar(36) | | true | | [chat_hub_agents](chat_hub_agents.md) | | +| attachments | TEXT | | true | | | | +| content | TEXT | | false | | | | +| createdAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | +| executionId | INTEGER | | true | | [execution_entity](execution_entity.md) | | +| id | varchar | | false | [chat_hub_messages](chat_hub_messages.md) | | | +| model | VARCHAR(256) | | true | | | | +| name | varchar(128) | | false | | | | +| previousMessageId | varchar | | true | | [chat_hub_messages](chat_hub_messages.md) | | +| provider | varchar(16) | | true | | | | +| retryOfMessageId | varchar | | true | | [chat_hub_messages](chat_hub_messages.md) | | +| revisionOfMessageId | varchar | | true | | [chat_hub_messages](chat_hub_messages.md) | | +| sessionId | varchar | | false | | [chat_hub_sessions](chat_hub_sessions.md) | | +| status | varchar(16) | 'success' | false | | | | +| type | varchar(16) | | false | | | | +| updatedAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | +| workflowId | varchar(36) | | true | | [workflow_entity](workflow_entity.md) | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| - (Foreign key ID: 0) | FOREIGN KEY | FOREIGN KEY (agentId) REFERENCES chat_hub_agents (id) ON UPDATE NO ACTION ON DELETE SET NULL MATCH NONE | +| - (Foreign key ID: 1) | FOREIGN KEY | FOREIGN KEY (executionId) REFERENCES execution_entity (id) ON UPDATE NO ACTION ON DELETE SET NULL MATCH NONE | +| - (Foreign key ID: 2) | FOREIGN KEY | FOREIGN KEY (revisionOfMessageId) REFERENCES chat_hub_messages (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| - (Foreign key ID: 3) | FOREIGN KEY | FOREIGN KEY (retryOfMessageId) REFERENCES chat_hub_messages (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| - (Foreign key ID: 4) | FOREIGN KEY | FOREIGN KEY (workflowId) REFERENCES workflow_entity (id) ON UPDATE NO ACTION ON DELETE SET NULL MATCH NONE | +| - (Foreign key ID: 5) | FOREIGN KEY | FOREIGN KEY (previousMessageId) REFERENCES chat_hub_messages (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| - (Foreign key ID: 6) | FOREIGN KEY | FOREIGN KEY (sessionId) REFERENCES chat_hub_sessions (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| id | PRIMARY KEY | PRIMARY KEY (id) | +| sqlite_autoindex_chat_hub_messages_1 | PRIMARY KEY | PRIMARY KEY (id) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_chat_hub_messages_sessionId | CREATE INDEX "IDX_chat_hub_messages_sessionId"<br /> ON "chat_hub_messages"("sessionId") | +| sqlite_autoindex_chat_hub_messages_1 | PRIMARY KEY (id) | + +## Relations + +```mermaid +erDiagram + +"chat_hub_messages" }o--o| "chat_hub_agents" : "FOREIGN KEY (agentId) REFERENCES chat_hub_agents (id) ON UPDATE NO ACTION ON DELETE SET NULL MATCH NONE" +"chat_hub_messages" }o--o| "execution_entity" : "FOREIGN KEY (executionId) REFERENCES execution_entity (id) ON UPDATE NO ACTION ON DELETE SET NULL MATCH NONE" +"chat_hub_messages" }o--o| "chat_hub_messages" : "FOREIGN KEY (revisionOfMessageId) REFERENCES chat_hub_messages (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"chat_hub_messages" }o--o| "chat_hub_messages" : "FOREIGN KEY (retryOfMessageId) REFERENCES chat_hub_messages (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"chat_hub_messages" }o--o| "chat_hub_messages" : "FOREIGN KEY (previousMessageId) REFERENCES chat_hub_messages (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"chat_hub_messages" }o--|| "chat_hub_sessions" : "FOREIGN KEY (sessionId) REFERENCES chat_hub_sessions (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"chat_hub_messages" }o--o| "workflow_entity" : "FOREIGN KEY (workflowId) REFERENCES workflow_entity (id) ON UPDATE NO ACTION ON DELETE SET NULL MATCH NONE" + +"chat_hub_messages" { + varchar_36_ agentId FK + TEXT attachments + TEXT content + datetime_3_ createdAt + INTEGER executionId FK + varchar id PK + VARCHAR_256_ model + varchar_128_ name + varchar previousMessageId FK + varchar_16_ provider + varchar retryOfMessageId FK + varchar revisionOfMessageId FK + varchar sessionId FK + varchar_16_ status + varchar_16_ type + datetime_3_ updatedAt + varchar_36_ workflowId FK +} +"chat_hub_agents" { + datetime_3_ createdAt + varchar_36_ credentialId FK + varchar_512_ description + TEXT files + TEXT icon + varchar id PK + varchar_64_ model + varchar_256_ name + varchar ownerId FK + varchar_16_ provider + TEXT suggestedPrompts + TEXT systemPrompt + datetime_3_ updatedAt +} +"execution_entity" { + BIGINT binaryDataSizeBytes + datetime_3_ createdAt + varchar_255_ deduplicationKey + datetime_3_ deletedAt + boolean finished + INTEGER id + BIGINT jsonSizeBytes + varchar mode + varchar retryOf + varchar retrySuccessId + datetime startedAt + varchar status + datetime stoppedAt + varchar_2_ storedAt + TEXT tracingContext + datetime waitTill + varchar_36_ workflowId FK + VARCHAR_36_ workflowVersionId +} +"chat_hub_sessions" { + varchar_36_ agentId FK + varchar_128_ agentName + datetime_3_ createdAt + varchar_36_ credentialId FK + varchar id PK + datetime_3_ lastMessageAt + varchar_64_ model + varchar ownerId FK + varchar_16_ provider + varchar_256_ title + varchar_16_ type + datetime_3_ updatedAt + varchar_36_ workflowId FK +} +"workflow_entity" { + boolean active + varchar_36_ activeVersionId FK + TEXT connections + datetime_3_ createdAt + TEXT description + varchar_36_ id PK + boolean isArchived + TEXT meta + varchar_128_ name + TEXT nodeGroups + TEXT nodes + varchar_36_ parentFolderId FK + TEXT pinData + TEXT settings + varchar sourceWorkflowId + TEXT staticData + INTEGER triggerCount + datetime_3_ updatedAt + INTEGER versionCounter + varchar_36_ versionId +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/sqlite-schema/chat_hub_session_tools.md b/docs/generated/sqlite-schema/chat_hub_session_tools.md new file mode 100644 index 00000000000..d75134e39ef --- /dev/null +++ b/docs/generated/sqlite-schema/chat_hub_session_tools.md @@ -0,0 +1,79 @@ +# chat_hub_session_tools + +## Description + +<details> +<summary><strong>Table Definition</strong></summary> + +```sql +CREATE TABLE "chat_hub_session_tools" ("sessionId" varchar NOT NULL, "toolId" varchar NOT NULL, CONSTRAINT "FK_e649bf1295f4ed8d4299ed290f9" FOREIGN KEY ("sessionId") REFERENCES "chat_hub_sessions" ("id") ON DELETE CASCADE, CONSTRAINT "FK_6596a328affd8d4967ffb303eee" FOREIGN KEY ("toolId") REFERENCES "chat_hub_tools" ("id") ON DELETE CASCADE, PRIMARY KEY ("sessionId", "toolId")) +``` + +</details> + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| sessionId | varchar | | false | | [chat_hub_sessions](chat_hub_sessions.md) | | +| toolId | varchar | | false | | [chat_hub_tools](chat_hub_tools.md) | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| - (Foreign key ID: 0) | FOREIGN KEY | FOREIGN KEY (toolId) REFERENCES chat_hub_tools (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| - (Foreign key ID: 1) | FOREIGN KEY | FOREIGN KEY (sessionId) REFERENCES chat_hub_sessions (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| sessionId | PRIMARY KEY | PRIMARY KEY (sessionId) | +| sqlite_autoindex_chat_hub_session_tools_1 | PRIMARY KEY | PRIMARY KEY (sessionId, toolId) | +| toolId | PRIMARY KEY | PRIMARY KEY (toolId) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| sqlite_autoindex_chat_hub_session_tools_1 | PRIMARY KEY (sessionId, toolId) | + +## Relations + +```mermaid +erDiagram + +"chat_hub_session_tools" |o--|| "chat_hub_sessions" : "FOREIGN KEY (sessionId) REFERENCES chat_hub_sessions (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"chat_hub_session_tools" |o--|| "chat_hub_tools" : "FOREIGN KEY (toolId) REFERENCES chat_hub_tools (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" + +"chat_hub_session_tools" { + varchar sessionId PK + varchar toolId PK +} +"chat_hub_sessions" { + varchar_36_ agentId FK + varchar_128_ agentName + datetime_3_ createdAt + varchar_36_ credentialId FK + varchar id PK + datetime_3_ lastMessageAt + varchar_64_ model + varchar ownerId FK + varchar_16_ provider + varchar_256_ title + varchar_16_ type + datetime_3_ updatedAt + varchar_36_ workflowId FK +} +"chat_hub_tools" { + datetime_3_ createdAt + TEXT definition + boolean enabled + varchar id PK + varchar_255_ name + varchar ownerId FK + varchar_255_ type + REAL typeVersion + datetime_3_ updatedAt +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/sqlite-schema/chat_hub_sessions.md b/docs/generated/sqlite-schema/chat_hub_sessions.md new file mode 100644 index 00000000000..bed4574bb2b --- /dev/null +++ b/docs/generated/sqlite-schema/chat_hub_sessions.md @@ -0,0 +1,171 @@ +# chat_hub_sessions + +## Description + +<details> +<summary><strong>Table Definition</strong></summary> + +```sql +CREATE TABLE "chat_hub_sessions" ("id" varchar PRIMARY KEY NOT NULL, "title" varchar(256) NOT NULL, "ownerId" varchar NOT NULL, "lastMessageAt" datetime(3) NOT NULL, "credentialId" varchar(36), "provider" varchar(16), "model" varchar(64), "workflowId" varchar(36), "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')), "agentId" varchar(36), "agentName" varchar(128), "type" varchar(16) NOT NULL DEFAULT ('production'), CONSTRAINT "CHK_chat_hub_sessions_type" CHECK ("type" IN ('production', 'manual')), CONSTRAINT "FK_chat_hub_sessions_agentId" FOREIGN KEY ("agentId") REFERENCES "chat_hub_agents" ("id") ON DELETE SET NULL ON UPDATE NO ACTION, CONSTRAINT "FK_9f9293d9f552496c40e0d1a8f80" FOREIGN KEY ("workflowId") REFERENCES "workflow_entity" ("id") ON DELETE SET NULL ON UPDATE NO ACTION, CONSTRAINT "FK_7bc13b4c7e6afbfaf9be326c189" FOREIGN KEY ("credentialId") REFERENCES "credentials_entity" ("id") ON DELETE SET NULL ON UPDATE NO ACTION, CONSTRAINT "FK_e9ecf8ede7d989fcd18790fe36a" FOREIGN KEY ("ownerId") REFERENCES "user" ("id") ON DELETE CASCADE ON UPDATE NO ACTION) +``` + +</details> + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| agentId | varchar(36) | | true | | [chat_hub_agents](chat_hub_agents.md) | | +| agentName | varchar(128) | | true | | | | +| createdAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | +| credentialId | varchar(36) | | true | | [credentials_entity](credentials_entity.md) | | +| id | varchar | | false | [chat_hub_messages](chat_hub_messages.md) [chat_hub_session_tools](chat_hub_session_tools.md) | | | +| lastMessageAt | datetime(3) | | false | | | | +| model | varchar(64) | | true | | | | +| ownerId | varchar | | false | | [user](user.md) | | +| provider | varchar(16) | | true | | | | +| title | varchar(256) | | false | | | | +| type | varchar(16) | 'production' | false | | | | +| updatedAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | +| workflowId | varchar(36) | | true | | [workflow_entity](workflow_entity.md) | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| - | CHECK | CHECK ("type" IN ('production', 'manual')) | +| - (Foreign key ID: 0) | FOREIGN KEY | FOREIGN KEY (ownerId) REFERENCES user (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| - (Foreign key ID: 1) | FOREIGN KEY | FOREIGN KEY (credentialId) REFERENCES credentials_entity (id) ON UPDATE NO ACTION ON DELETE SET NULL MATCH NONE | +| - (Foreign key ID: 2) | FOREIGN KEY | FOREIGN KEY (workflowId) REFERENCES workflow_entity (id) ON UPDATE NO ACTION ON DELETE SET NULL MATCH NONE | +| - (Foreign key ID: 3) | FOREIGN KEY | FOREIGN KEY (agentId) REFERENCES chat_hub_agents (id) ON UPDATE NO ACTION ON DELETE SET NULL MATCH NONE | +| id | PRIMARY KEY | PRIMARY KEY (id) | +| sqlite_autoindex_chat_hub_sessions_1 | PRIMARY KEY | PRIMARY KEY (id) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| sqlite_autoindex_chat_hub_sessions_1 | PRIMARY KEY (id) | + +## Relations + +```mermaid +erDiagram + +"chat_hub_sessions" }o--o| "chat_hub_agents" : "FOREIGN KEY (agentId) REFERENCES chat_hub_agents (id) ON UPDATE NO ACTION ON DELETE SET NULL MATCH NONE" +"chat_hub_sessions" }o--o| "credentials_entity" : "FOREIGN KEY (credentialId) REFERENCES credentials_entity (id) ON UPDATE NO ACTION ON DELETE SET NULL MATCH NONE" +"chat_hub_messages" }o--|| "chat_hub_sessions" : "FOREIGN KEY (sessionId) REFERENCES chat_hub_sessions (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"chat_hub_session_tools" |o--|| "chat_hub_sessions" : "FOREIGN KEY (sessionId) REFERENCES chat_hub_sessions (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"chat_hub_sessions" }o--|| "user" : "FOREIGN KEY (ownerId) REFERENCES user (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"chat_hub_sessions" }o--o| "workflow_entity" : "FOREIGN KEY (workflowId) REFERENCES workflow_entity (id) ON UPDATE NO ACTION ON DELETE SET NULL MATCH NONE" + +"chat_hub_sessions" { + varchar_36_ agentId FK + varchar_128_ agentName + datetime_3_ createdAt + varchar_36_ credentialId FK + varchar id PK + datetime_3_ lastMessageAt + varchar_64_ model + varchar ownerId FK + varchar_16_ provider + varchar_256_ title + varchar_16_ type + datetime_3_ updatedAt + varchar_36_ workflowId FK +} +"chat_hub_agents" { + datetime_3_ createdAt + varchar_36_ credentialId FK + varchar_512_ description + TEXT files + TEXT icon + varchar id PK + varchar_64_ model + varchar_256_ name + varchar ownerId FK + varchar_16_ provider + TEXT suggestedPrompts + TEXT systemPrompt + datetime_3_ updatedAt +} +"credentials_entity" { + datetime_3_ createdAt + TEXT data + varchar_36_ id PK + boolean isGlobal + boolean isManaged + boolean isResolvable + varchar_128_ name + boolean resolvableAllowFallback + varchar_16_ resolverId FK + varchar_32_ type + datetime_3_ updatedAt +} +"chat_hub_messages" { + varchar_36_ agentId FK + TEXT attachments + TEXT content + datetime_3_ createdAt + INTEGER executionId FK + varchar id PK + VARCHAR_256_ model + varchar_128_ name + varchar previousMessageId FK + varchar_16_ provider + varchar retryOfMessageId FK + varchar revisionOfMessageId FK + varchar sessionId FK + varchar_16_ status + varchar_16_ type + datetime_3_ updatedAt + varchar_36_ workflowId FK +} +"chat_hub_session_tools" { + varchar sessionId PK + varchar toolId PK +} +"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 +} +"workflow_entity" { + boolean active + varchar_36_ activeVersionId FK + TEXT connections + datetime_3_ createdAt + TEXT description + varchar_36_ id PK + boolean isArchived + TEXT meta + varchar_128_ name + TEXT nodeGroups + TEXT nodes + varchar_36_ parentFolderId FK + TEXT pinData + TEXT settings + varchar sourceWorkflowId + TEXT staticData + INTEGER triggerCount + datetime_3_ updatedAt + INTEGER versionCounter + varchar_36_ versionId +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/sqlite-schema/chat_hub_tools.md b/docs/generated/sqlite-schema/chat_hub_tools.md new file mode 100644 index 00000000000..1044c1fc23a --- /dev/null +++ b/docs/generated/sqlite-schema/chat_hub_tools.md @@ -0,0 +1,92 @@ +# chat_hub_tools + +## Description + +<details> +<summary><strong>Table Definition</strong></summary> + +```sql +CREATE TABLE "chat_hub_tools" ("id" varchar PRIMARY KEY NOT NULL, "name" varchar(255) NOT NULL, "type" varchar(255) NOT NULL, "typeVersion" real NOT NULL, "ownerId" varchar NOT NULL, "definition" text NOT NULL, "enabled" boolean NOT NULL DEFAULT (true), "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_b8030b47af9213f1fd15450fb7f" FOREIGN KEY ("ownerId") REFERENCES "user" ("id") ON DELETE CASCADE) +``` + +</details> + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| createdAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | +| definition | TEXT | | false | | | | +| enabled | boolean | true | false | | | | +| id | varchar | | false | [chat_hub_agent_tools](chat_hub_agent_tools.md) [chat_hub_session_tools](chat_hub_session_tools.md) | | | +| name | varchar(255) | | false | | | | +| ownerId | varchar | | false | | [user](user.md) | | +| type | varchar(255) | | false | | | | +| typeVersion | REAL | | false | | | | +| updatedAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| - (Foreign key ID: 0) | FOREIGN KEY | FOREIGN KEY (ownerId) REFERENCES user (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| id | PRIMARY KEY | PRIMARY KEY (id) | +| sqlite_autoindex_chat_hub_tools_1 | PRIMARY KEY | PRIMARY KEY (id) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_4c72ebdb265d1775bf61147af0 | CREATE UNIQUE INDEX "IDX_4c72ebdb265d1775bf61147af0" ON "chat_hub_tools" ("ownerId", "name") | +| sqlite_autoindex_chat_hub_tools_1 | PRIMARY KEY (id) | + +## Relations + +```mermaid +erDiagram + +"chat_hub_agent_tools" |o--|| "chat_hub_tools" : "FOREIGN KEY (toolId) REFERENCES chat_hub_tools (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"chat_hub_session_tools" |o--|| "chat_hub_tools" : "FOREIGN KEY (toolId) REFERENCES chat_hub_tools (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"chat_hub_tools" }o--|| "user" : "FOREIGN KEY (ownerId) REFERENCES user (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" + +"chat_hub_tools" { + datetime_3_ createdAt + TEXT definition + boolean enabled + varchar id PK + varchar_255_ name + varchar ownerId FK + varchar_255_ type + REAL typeVersion + datetime_3_ updatedAt +} +"chat_hub_agent_tools" { + varchar agentId PK + varchar toolId PK +} +"chat_hub_session_tools" { + varchar sessionId PK + varchar toolId PK +} +"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 +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/sqlite-schema/credential_dependency.md b/docs/generated/sqlite-schema/credential_dependency.md new file mode 100644 index 00000000000..02ba378805c --- /dev/null +++ b/docs/generated/sqlite-schema/credential_dependency.md @@ -0,0 +1,70 @@ +# credential_dependency + +## Description + +<details> +<summary><strong>Table Definition</strong></summary> + +```sql +CREATE TABLE "credential_dependency" ("id" integer PRIMARY KEY NOT NULL, "credentialId" varchar(36) NOT NULL, "dependencyType" varchar(64) NOT NULL, "dependencyId" varchar(255) NOT NULL, "createdAt" datetime(3) NOT NULL DEFAULT (STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW')), CONSTRAINT "FK_5ec8e8c8d3539f3696cf73b43bf" FOREIGN KEY ("credentialId") REFERENCES "credentials_entity" ("id") ON DELETE CASCADE) +``` + +</details> + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| createdAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | +| credentialId | varchar(36) | | false | | [credentials_entity](credentials_entity.md) | | +| dependencyId | varchar(255) | | false | | | | +| dependencyType | varchar(64) | | false | | | | +| id | INTEGER | | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| - (Foreign key ID: 0) | FOREIGN KEY | FOREIGN KEY (credentialId) REFERENCES credentials_entity (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| id | PRIMARY KEY | PRIMARY KEY (id) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_5ec8e8c8d3539f3696cf73b43b | CREATE INDEX "IDX_5ec8e8c8d3539f3696cf73b43b" ON "credential_dependency" ("credentialId") | +| IDX_91ee85fa9619dd6776725e117b | CREATE INDEX "IDX_91ee85fa9619dd6776725e117b" ON "credential_dependency" ("dependencyType", "dependencyId") | +| IDX_credential_dependency_credentialId_dependencyType_dependencyId | CREATE UNIQUE INDEX "IDX_credential_dependency_credentialId_dependencyType_dependencyId" ON "credential_dependency" ("credentialId", "dependencyType", "dependencyId") | + +## Relations + +```mermaid +erDiagram + +"credential_dependency" }o--|| "credentials_entity" : "FOREIGN KEY (credentialId) REFERENCES credentials_entity (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" + +"credential_dependency" { + datetime_3_ createdAt + varchar_36_ credentialId FK + varchar_255_ dependencyId + varchar_64_ dependencyType + INTEGER id +} +"credentials_entity" { + datetime_3_ createdAt + TEXT data + varchar_36_ id PK + boolean isGlobal + boolean isManaged + boolean isResolvable + varchar_128_ name + boolean resolvableAllowFallback + varchar_16_ resolverId FK + varchar_32_ type + datetime_3_ updatedAt +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/sqlite-schema/credentials_entity.md b/docs/generated/sqlite-schema/credentials_entity.md new file mode 100644 index 00000000000..67f4accc786 --- /dev/null +++ b/docs/generated/sqlite-schema/credentials_entity.md @@ -0,0 +1,153 @@ +# credentials_entity + +## Description + +<details> +<summary><strong>Table Definition</strong></summary> + +```sql +CREATE TABLE "credentials_entity" ("id" varchar(36) PRIMARY KEY NOT NULL, "name" varchar(128) NOT NULL, "data" text NOT NULL, "type" varchar(32) 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')), "isManaged" boolean NOT NULL DEFAULT (0), "isGlobal" boolean NOT NULL DEFAULT (0), "isResolvable" boolean NOT NULL DEFAULT (false), "resolvableAllowFallback" boolean NOT NULL DEFAULT (false), "resolverId" varchar(16), CONSTRAINT "credentials_entity_resolverId_foreign" FOREIGN KEY ("resolverId") REFERENCES "dynamic_credential_resolver" ("id") ON DELETE SET NULL) +``` + +</details> + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| createdAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | +| data | TEXT | | false | | | | +| id | varchar(36) | | false | [chat_hub_agents](chat_hub_agents.md) [chat_hub_sessions](chat_hub_sessions.md) [credential_dependency](credential_dependency.md) [dynamic_credential_entry](dynamic_credential_entry.md) [dynamic_credential_user_entry](dynamic_credential_user_entry.md) [instance_ai_mcp_registry_connections](instance_ai_mcp_registry_connections.md) [shared_credentials](shared_credentials.md) | | | +| isGlobal | boolean | 0 | false | | | | +| isManaged | boolean | 0 | false | | | | +| isResolvable | boolean | false | false | | | | +| name | varchar(128) | | false | | | | +| resolvableAllowFallback | boolean | false | false | | | | +| resolverId | varchar(16) | | true | | [dynamic_credential_resolver](dynamic_credential_resolver.md) | | +| type | varchar(32) | | false | | | | +| updatedAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| - (Foreign key ID: 0) | FOREIGN KEY | FOREIGN KEY (resolverId) REFERENCES dynamic_credential_resolver (id) ON UPDATE NO ACTION ON DELETE SET NULL MATCH NONE | +| id | PRIMARY KEY | PRIMARY KEY (id) | +| sqlite_autoindex_credentials_entity_1 | PRIMARY KEY | PRIMARY KEY (id) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| idx_credentials_entity_type | CREATE INDEX "idx_credentials_entity_type" ON "credentials_entity" ("type") | +| sqlite_autoindex_credentials_entity_1 | PRIMARY KEY (id) | + +## Relations + +```mermaid +erDiagram + +"chat_hub_agents" }o--o| "credentials_entity" : "FOREIGN KEY (credentialId) REFERENCES credentials_entity (id) ON UPDATE NO ACTION ON DELETE SET NULL MATCH NONE" +"chat_hub_sessions" }o--o| "credentials_entity" : "FOREIGN KEY (credentialId) REFERENCES credentials_entity (id) ON UPDATE NO ACTION ON DELETE SET NULL MATCH NONE" +"credential_dependency" }o--|| "credentials_entity" : "FOREIGN KEY (credentialId) REFERENCES credentials_entity (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"dynamic_credential_entry" |o--|| "credentials_entity" : "FOREIGN KEY (credential_id) REFERENCES credentials_entity (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"dynamic_credential_user_entry" |o--|| "credentials_entity" : "FOREIGN KEY (credentialId) REFERENCES credentials_entity (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"instance_ai_mcp_registry_connections" }o--|| "credentials_entity" : "FOREIGN KEY (credentialId) REFERENCES credentials_entity (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"shared_credentials" |o--|| "credentials_entity" : "FOREIGN KEY (credentialsId) REFERENCES credentials_entity (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"credentials_entity" }o--o| "dynamic_credential_resolver" : "FOREIGN KEY (resolverId) REFERENCES dynamic_credential_resolver (id) ON UPDATE NO ACTION ON DELETE SET NULL MATCH NONE" + +"credentials_entity" { + datetime_3_ createdAt + TEXT data + varchar_36_ id PK + boolean isGlobal + boolean isManaged + boolean isResolvable + varchar_128_ name + boolean resolvableAllowFallback + varchar_16_ resolverId FK + varchar_32_ type + datetime_3_ updatedAt +} +"chat_hub_agents" { + datetime_3_ createdAt + varchar_36_ credentialId FK + varchar_512_ description + TEXT files + TEXT icon + varchar id PK + varchar_64_ model + varchar_256_ name + varchar ownerId FK + varchar_16_ provider + TEXT suggestedPrompts + TEXT systemPrompt + datetime_3_ updatedAt +} +"chat_hub_sessions" { + varchar_36_ agentId FK + varchar_128_ agentName + datetime_3_ createdAt + varchar_36_ credentialId FK + varchar id PK + datetime_3_ lastMessageAt + varchar_64_ model + varchar ownerId FK + varchar_16_ provider + varchar_256_ title + varchar_16_ type + datetime_3_ updatedAt + varchar_36_ workflowId FK +} +"credential_dependency" { + datetime_3_ createdAt + varchar_36_ credentialId FK + varchar_255_ dependencyId + varchar_64_ dependencyType + INTEGER id +} +"dynamic_credential_entry" { + datetime_3_ createdAt + varchar_16_ credential_id PK + TEXT data + varchar_16_ resolver_id PK + varchar_2048_ subject_id PK + datetime_3_ updatedAt +} +"dynamic_credential_user_entry" { + datetime_3_ createdAt + varchar_16_ credentialId PK + TEXT data + varchar_16_ resolverId PK + datetime_3_ updatedAt + varchar userId PK +} +"instance_ai_mcp_registry_connections" { + datetime_3_ createdAt + varchar_36_ credentialId FK + varchar id PK + varchar_255_ serverSlug FK + TEXT toolFilter + datetime_3_ updatedAt + varchar userId FK +} +"shared_credentials" { + datetime_3_ createdAt + varchar_36_ credentialsId PK + varchar_36_ projectId PK + TEXT role + datetime_3_ updatedAt +} +"dynamic_credential_resolver" { + TEXT config + datetime_3_ createdAt + varchar_16_ id PK + varchar_128_ name + varchar_128_ type + datetime_3_ updatedAt +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/sqlite-schema/data_table.md b/docs/generated/sqlite-schema/data_table.md new file mode 100644 index 00000000000..c975b131969 --- /dev/null +++ b/docs/generated/sqlite-schema/data_table.md @@ -0,0 +1,79 @@ +# data_table + +## Description + +<details> +<summary><strong>Table Definition</strong></summary> + +```sql +CREATE TABLE "data_table" ("id" varchar(36) PRIMARY KEY NOT NULL, "name" varchar(128) NOT NULL, "projectId" varchar(36) 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 "UQ_b23096ef747281ac944d28e8b0d" UNIQUE ("projectId", "name"), CONSTRAINT "FK_c2a794257dee48af7c9abf681de" FOREIGN KEY ("projectId") REFERENCES "project" ("id") ON DELETE CASCADE) +``` + +</details> + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| createdAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | +| id | varchar(36) | | false | [data_table_column](data_table_column.md) | | | +| name | varchar(128) | | false | | | | +| projectId | varchar(36) | | false | | [project](project.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 (projectId) REFERENCES project (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| id | PRIMARY KEY | PRIMARY KEY (id) | +| sqlite_autoindex_data_table_1 | PRIMARY KEY | PRIMARY KEY (id) | +| sqlite_autoindex_data_table_2 | UNIQUE | UNIQUE (projectId, name) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| sqlite_autoindex_data_table_1 | PRIMARY KEY (id) | +| sqlite_autoindex_data_table_2 | UNIQUE (projectId, name) | + +## Relations + +```mermaid +erDiagram + +"data_table_column" }o--|| "data_table" : "FOREIGN KEY (dataTableId) REFERENCES data_table (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"data_table" }o--|| "project" : "FOREIGN KEY (projectId) REFERENCES project (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" + +"data_table" { + datetime_3_ createdAt + varchar_36_ id PK + varchar_128_ name + varchar_36_ projectId FK + datetime_3_ updatedAt +} +"data_table_column" { + datetime_3_ createdAt + varchar_36_ dataTableId FK + varchar_36_ id PK + INTEGER index + varchar_128_ name + varchar_32_ type + datetime_3_ updatedAt +} +"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/data_table_column.md b/docs/generated/sqlite-schema/data_table_column.md new file mode 100644 index 00000000000..e0eea96c6e2 --- /dev/null +++ b/docs/generated/sqlite-schema/data_table_column.md @@ -0,0 +1,69 @@ +# data_table_column + +## Description + +<details> +<summary><strong>Table Definition</strong></summary> + +```sql +CREATE TABLE "data_table_column" ("id" varchar(36) PRIMARY KEY NOT NULL, "name" varchar(128) NOT NULL, "type" varchar(32) NOT NULL, "index" integer NOT NULL, "dataTableId" varchar(36) 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 "UQ_8082ec4890f892f0bc77473a123" UNIQUE ("dataTableId", "name"), CONSTRAINT "FK_930b6e8faaf88294cef23484160" FOREIGN KEY ("dataTableId") REFERENCES "data_table" ("id") ON DELETE CASCADE) +``` + +</details> + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| createdAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | +| dataTableId | varchar(36) | | false | | [data_table](data_table.md) | | +| id | varchar(36) | | false | | | | +| index | INTEGER | | false | | | | +| name | varchar(128) | | false | | | | +| type | varchar(32) | | false | | | | +| updatedAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| - (Foreign key ID: 0) | FOREIGN KEY | FOREIGN KEY (dataTableId) REFERENCES data_table (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| id | PRIMARY KEY | PRIMARY KEY (id) | +| sqlite_autoindex_data_table_column_1 | PRIMARY KEY | PRIMARY KEY (id) | +| sqlite_autoindex_data_table_column_2 | UNIQUE | UNIQUE (dataTableId, name) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| sqlite_autoindex_data_table_column_1 | PRIMARY KEY (id) | +| sqlite_autoindex_data_table_column_2 | UNIQUE (dataTableId, name) | + +## Relations + +```mermaid +erDiagram + +"data_table_column" }o--|| "data_table" : "FOREIGN KEY (dataTableId) REFERENCES data_table (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" + +"data_table_column" { + datetime_3_ createdAt + varchar_36_ dataTableId FK + varchar_36_ id PK + INTEGER index + varchar_128_ name + varchar_32_ type + datetime_3_ updatedAt +} +"data_table" { + datetime_3_ createdAt + varchar_36_ id PK + varchar_128_ name + varchar_36_ projectId FK + datetime_3_ updatedAt +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/sqlite-schema/deployment_key.md b/docs/generated/sqlite-schema/deployment_key.md new file mode 100644 index 00000000000..88561b33636 --- /dev/null +++ b/docs/generated/sqlite-schema/deployment_key.md @@ -0,0 +1,64 @@ +# deployment_key + +## Description + +<details> +<summary><strong>Table Definition</strong></summary> + +```sql +CREATE TABLE "deployment_key" ("id" varchar(36) PRIMARY KEY NOT NULL, "type" varchar(64) NOT NULL, "value" text NOT NULL, "algorithm" varchar(20), "status" varchar(20) 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'))) +``` + +</details> + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| algorithm | varchar(20) | | true | | | | +| createdAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | +| id | varchar(36) | | false | | | | +| status | varchar(20) | | false | | | | +| type | varchar(64) | | false | | | | +| updatedAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | +| value | TEXT | | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| id | PRIMARY KEY | PRIMARY KEY (id) | +| sqlite_autoindex_deployment_key_1 | PRIMARY KEY | PRIMARY KEY (id) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_deployment_key_data_encryption_active | CREATE UNIQUE INDEX "IDX_deployment_key_data_encryption_active" ON "deployment_key" ("type") WHERE status = 'active' AND type = 'data_encryption' | +| IDX_deployment_key_instance_id_active | CREATE UNIQUE INDEX "IDX_deployment_key_instance_id_active" ON "deployment_key" ("type") WHERE status = 'active' AND type = 'instance.id' | +| IDX_deployment_key_jwe_private_key_active | CREATE UNIQUE INDEX "IDX_deployment_key_jwe_private_key_active" ON "deployment_key" ("type", "algorithm") WHERE status = 'active' AND type = 'jwe.private-key' | +| IDX_deployment_key_signing_binary_data_active | CREATE UNIQUE INDEX "IDX_deployment_key_signing_binary_data_active" ON "deployment_key" ("type") WHERE status = 'active' AND type = 'signing.binary_data' | +| IDX_deployment_key_signing_hmac_active | CREATE UNIQUE INDEX "IDX_deployment_key_signing_hmac_active" ON "deployment_key" ("type") WHERE status = 'active' AND type = 'signing.hmac' | +| IDX_deployment_key_signing_jwt_active | CREATE UNIQUE INDEX "IDX_deployment_key_signing_jwt_active" ON "deployment_key" ("type") WHERE status = 'active' AND type = 'signing.jwt' | +| sqlite_autoindex_deployment_key_1 | PRIMARY KEY (id) | + +## Relations + +```mermaid +erDiagram + + +"deployment_key" { + varchar_20_ algorithm + datetime_3_ createdAt + varchar_36_ id PK + varchar_20_ status + varchar_64_ type + datetime_3_ updatedAt + TEXT value +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/sqlite-schema/dynamic_credential_entry.md b/docs/generated/sqlite-schema/dynamic_credential_entry.md new file mode 100644 index 00000000000..4bbb9959d1e --- /dev/null +++ b/docs/generated/sqlite-schema/dynamic_credential_entry.md @@ -0,0 +1,85 @@ +# dynamic_credential_entry + +## Description + +<details> +<summary><strong>Table Definition</strong></summary> + +```sql +CREATE TABLE "dynamic_credential_entry" ("credential_id" varchar(16) NOT NULL, "subject_id" varchar(2048) NOT NULL, "resolver_id" varchar(16) NOT NULL, "data" 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_a6d1dd080958304a47a02952aab" FOREIGN KEY ("credential_id") REFERENCES "credentials_entity" ("id") ON DELETE CASCADE, CONSTRAINT "FK_d61a12235d268a49af6a3c09c13" FOREIGN KEY ("resolver_id") REFERENCES "dynamic_credential_resolver" ("id") ON DELETE CASCADE, PRIMARY KEY ("credential_id", "subject_id", "resolver_id")) +``` + +</details> + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| createdAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | +| credential_id | varchar(16) | | false | | [credentials_entity](credentials_entity.md) | | +| data | TEXT | | false | | | | +| resolver_id | varchar(16) | | false | | [dynamic_credential_resolver](dynamic_credential_resolver.md) | | +| subject_id | varchar(2048) | | false | | | | +| updatedAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| - (Foreign key ID: 0) | FOREIGN KEY | FOREIGN KEY (resolver_id) REFERENCES dynamic_credential_resolver (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| - (Foreign key ID: 1) | FOREIGN KEY | FOREIGN KEY (credential_id) REFERENCES credentials_entity (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| credential_id | PRIMARY KEY | PRIMARY KEY (credential_id) | +| resolver_id | PRIMARY KEY | PRIMARY KEY (resolver_id) | +| sqlite_autoindex_dynamic_credential_entry_1 | PRIMARY KEY | PRIMARY KEY (credential_id, subject_id, resolver_id) | +| subject_id | PRIMARY KEY | PRIMARY KEY (subject_id) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_62476b94b56d9dc7ed9ed75d3d | CREATE INDEX "IDX_62476b94b56d9dc7ed9ed75d3d" ON "dynamic_credential_entry" ("subject_id") | +| IDX_d61a12235d268a49af6a3c09c1 | CREATE INDEX "IDX_d61a12235d268a49af6a3c09c1" ON "dynamic_credential_entry" ("resolver_id") | +| sqlite_autoindex_dynamic_credential_entry_1 | PRIMARY KEY (credential_id, subject_id, resolver_id) | + +## Relations + +```mermaid +erDiagram + +"dynamic_credential_entry" |o--|| "credentials_entity" : "FOREIGN KEY (credential_id) REFERENCES credentials_entity (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"dynamic_credential_entry" |o--|| "dynamic_credential_resolver" : "FOREIGN KEY (resolver_id) REFERENCES dynamic_credential_resolver (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" + +"dynamic_credential_entry" { + datetime_3_ createdAt + varchar_16_ credential_id PK + TEXT data + varchar_16_ resolver_id PK + varchar_2048_ subject_id PK + datetime_3_ updatedAt +} +"credentials_entity" { + datetime_3_ createdAt + TEXT data + varchar_36_ id PK + boolean isGlobal + boolean isManaged + boolean isResolvable + varchar_128_ name + boolean resolvableAllowFallback + varchar_16_ resolverId FK + varchar_32_ type + datetime_3_ updatedAt +} +"dynamic_credential_resolver" { + TEXT config + datetime_3_ createdAt + varchar_16_ id PK + varchar_128_ name + varchar_128_ type + datetime_3_ updatedAt +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/sqlite-schema/dynamic_credential_resolver.md b/docs/generated/sqlite-schema/dynamic_credential_resolver.md new file mode 100644 index 00000000000..9f2381f79fb --- /dev/null +++ b/docs/generated/sqlite-schema/dynamic_credential_resolver.md @@ -0,0 +1,89 @@ +# dynamic_credential_resolver + +## Description + +<details> +<summary><strong>Table Definition</strong></summary> + +```sql +CREATE TABLE "dynamic_credential_resolver" ("id" varchar(16) PRIMARY KEY NOT NULL, "name" varchar(128) NOT NULL, "type" varchar(128) NOT NULL, "config" 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'))) +``` + +</details> + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| config | TEXT | | false | | | | +| createdAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | +| id | varchar(16) | | false | [credentials_entity](credentials_entity.md) [dynamic_credential_entry](dynamic_credential_entry.md) [dynamic_credential_user_entry](dynamic_credential_user_entry.md) | | | +| name | varchar(128) | | false | | | | +| type | varchar(128) | | false | | | | +| updatedAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| id | PRIMARY KEY | PRIMARY KEY (id) | +| sqlite_autoindex_dynamic_credential_resolver_1 | PRIMARY KEY | PRIMARY KEY (id) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_9c9ee9df586e60bb723234e499 | CREATE INDEX "IDX_9c9ee9df586e60bb723234e499" ON "dynamic_credential_resolver" ("type") | +| sqlite_autoindex_dynamic_credential_resolver_1 | PRIMARY KEY (id) | + +## Relations + +```mermaid +erDiagram + +"credentials_entity" }o--o| "dynamic_credential_resolver" : "FOREIGN KEY (resolverId) REFERENCES dynamic_credential_resolver (id) ON UPDATE NO ACTION ON DELETE SET NULL MATCH NONE" +"dynamic_credential_entry" |o--|| "dynamic_credential_resolver" : "FOREIGN KEY (resolver_id) REFERENCES dynamic_credential_resolver (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"dynamic_credential_user_entry" |o--|| "dynamic_credential_resolver" : "FOREIGN KEY (resolverId) REFERENCES dynamic_credential_resolver (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" + +"dynamic_credential_resolver" { + TEXT config + datetime_3_ createdAt + varchar_16_ id PK + varchar_128_ name + varchar_128_ type + datetime_3_ updatedAt +} +"credentials_entity" { + datetime_3_ createdAt + TEXT data + varchar_36_ id PK + boolean isGlobal + boolean isManaged + boolean isResolvable + varchar_128_ name + boolean resolvableAllowFallback + varchar_16_ resolverId FK + varchar_32_ type + datetime_3_ updatedAt +} +"dynamic_credential_entry" { + datetime_3_ createdAt + varchar_16_ credential_id PK + TEXT data + varchar_16_ resolver_id PK + varchar_2048_ subject_id PK + datetime_3_ updatedAt +} +"dynamic_credential_user_entry" { + datetime_3_ createdAt + varchar_16_ credentialId PK + TEXT data + varchar_16_ resolverId PK + datetime_3_ updatedAt + varchar userId PK +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/sqlite-schema/dynamic_credential_user_entry.md b/docs/generated/sqlite-schema/dynamic_credential_user_entry.md new file mode 100644 index 00000000000..e64a6b26f81 --- /dev/null +++ b/docs/generated/sqlite-schema/dynamic_credential_user_entry.md @@ -0,0 +1,104 @@ +# dynamic_credential_user_entry + +## Description + +<details> +<summary><strong>Table Definition</strong></summary> + +```sql +CREATE TABLE "dynamic_credential_user_entry" ("credentialId" varchar(16) NOT NULL, "userId" varchar NOT NULL, "resolverId" varchar(16) NOT NULL, "data" 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_945ba70b342a066d1306b12ccd2" FOREIGN KEY ("credentialId") REFERENCES "credentials_entity" ("id") ON DELETE CASCADE, CONSTRAINT "FK_6edec973a6450990977bb854c38" FOREIGN KEY ("resolverId") REFERENCES "dynamic_credential_resolver" ("id") ON DELETE CASCADE, CONSTRAINT "FK_a36dc616fabc3f736bb82410a22" FOREIGN KEY ("userId") REFERENCES "user" ("id") ON DELETE CASCADE, PRIMARY KEY ("credentialId", "userId", "resolverId")) +``` + +</details> + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| createdAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | +| credentialId | varchar(16) | | false | | [credentials_entity](credentials_entity.md) | | +| data | TEXT | | false | | | | +| resolverId | varchar(16) | | false | | [dynamic_credential_resolver](dynamic_credential_resolver.md) | | +| updatedAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | +| userId | varchar | | false | | [user](user.md) | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| - (Foreign key ID: 0) | FOREIGN KEY | FOREIGN KEY (userId) REFERENCES user (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| - (Foreign key ID: 1) | FOREIGN KEY | FOREIGN KEY (resolverId) REFERENCES dynamic_credential_resolver (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| - (Foreign key ID: 2) | FOREIGN KEY | FOREIGN KEY (credentialId) REFERENCES credentials_entity (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| credentialId | PRIMARY KEY | PRIMARY KEY (credentialId) | +| resolverId | PRIMARY KEY | PRIMARY KEY (resolverId) | +| sqlite_autoindex_dynamic_credential_user_entry_1 | PRIMARY KEY | PRIMARY KEY (credentialId, userId, resolverId) | +| userId | PRIMARY KEY | PRIMARY KEY (userId) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_6edec973a6450990977bb854c3 | CREATE INDEX "IDX_6edec973a6450990977bb854c3" ON "dynamic_credential_user_entry" ("resolverId") | +| IDX_a36dc616fabc3f736bb82410a2 | CREATE INDEX "IDX_a36dc616fabc3f736bb82410a2" ON "dynamic_credential_user_entry" ("userId") | +| sqlite_autoindex_dynamic_credential_user_entry_1 | PRIMARY KEY (credentialId, userId, resolverId) | + +## Relations + +```mermaid +erDiagram + +"dynamic_credential_user_entry" |o--|| "credentials_entity" : "FOREIGN KEY (credentialId) REFERENCES credentials_entity (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"dynamic_credential_user_entry" |o--|| "dynamic_credential_resolver" : "FOREIGN KEY (resolverId) REFERENCES dynamic_credential_resolver (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"dynamic_credential_user_entry" |o--|| "user" : "FOREIGN KEY (userId) REFERENCES user (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" + +"dynamic_credential_user_entry" { + datetime_3_ createdAt + varchar_16_ credentialId PK + TEXT data + varchar_16_ resolverId PK + datetime_3_ updatedAt + varchar userId PK +} +"credentials_entity" { + datetime_3_ createdAt + TEXT data + varchar_36_ id PK + boolean isGlobal + boolean isManaged + boolean isResolvable + varchar_128_ name + boolean resolvableAllowFallback + varchar_16_ resolverId FK + varchar_32_ type + datetime_3_ updatedAt +} +"dynamic_credential_resolver" { + TEXT config + datetime_3_ createdAt + varchar_16_ id PK + varchar_128_ name + varchar_128_ type + datetime_3_ updatedAt +} +"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 +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/sqlite-schema/evaluation_collection.md b/docs/generated/sqlite-schema/evaluation_collection.md new file mode 100644 index 00000000000..cf55460da33 --- /dev/null +++ b/docs/generated/sqlite-schema/evaluation_collection.md @@ -0,0 +1,142 @@ +# evaluation_collection + +## Description + +<details> +<summary><strong>Table Definition</strong></summary> + +```sql +CREATE TABLE "evaluation_collection" ("id" varchar(36) PRIMARY KEY NOT NULL, "name" varchar(128) NOT NULL, "description" text, "workflowId" varchar(36) NOT NULL, "evaluationConfigId" varchar(36) NOT NULL, "createdById" varchar, "insightsCache" text, "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_a48ce930c3bc7604894b8f0eaad" FOREIGN KEY ("workflowId") REFERENCES "workflow_entity" ("id") ON DELETE CASCADE, CONSTRAINT "FK_d634a0c93fd7de68a87eab951b2" FOREIGN KEY ("evaluationConfigId") REFERENCES "evaluation_config" ("id") ON DELETE CASCADE, CONSTRAINT "FK_f4561f38b5a22a4f090d5cd3eae" FOREIGN KEY ("createdById") REFERENCES "user" ("id") ON DELETE SET NULL) +``` + +</details> + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| createdAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | +| createdById | varchar | | true | | [user](user.md) | | +| description | TEXT | | true | | | | +| evaluationConfigId | varchar(36) | | false | | [evaluation_config](evaluation_config.md) | | +| id | varchar(36) | | false | [test_run](test_run.md) | | | +| insightsCache | TEXT | | true | | | | +| name | varchar(128) | | false | | | | +| updatedAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | +| workflowId | varchar(36) | | false | | [workflow_entity](workflow_entity.md) | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| - (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 (evaluationConfigId) REFERENCES evaluation_config (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| - (Foreign key ID: 2) | FOREIGN KEY | FOREIGN KEY (workflowId) REFERENCES workflow_entity (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| id | PRIMARY KEY | PRIMARY KEY (id) | +| sqlite_autoindex_evaluation_collection_1 | PRIMARY KEY | PRIMARY KEY (id) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_a48ce930c3bc7604894b8f0eaa | CREATE INDEX "IDX_a48ce930c3bc7604894b8f0eaa" ON "evaluation_collection" ("workflowId") | +| IDX_d634a0c93fd7de68a87eab951b | CREATE INDEX "IDX_d634a0c93fd7de68a87eab951b" ON "evaluation_collection" ("evaluationConfigId") | +| sqlite_autoindex_evaluation_collection_1 | PRIMARY KEY (id) | + +## Relations + +```mermaid +erDiagram + +"evaluation_collection" }o--o| "user" : "FOREIGN KEY (createdById) REFERENCES user (id) ON UPDATE NO ACTION ON DELETE SET NULL MATCH NONE" +"evaluation_collection" }o--|| "evaluation_config" : "FOREIGN KEY (evaluationConfigId) REFERENCES evaluation_config (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"test_run" }o--o| "evaluation_collection" : "FOREIGN KEY (collectionId) REFERENCES evaluation_collection (id) ON UPDATE NO ACTION ON DELETE SET NULL MATCH NONE" +"evaluation_collection" }o--|| "workflow_entity" : "FOREIGN KEY (workflowId) REFERENCES workflow_entity (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" + +"evaluation_collection" { + datetime_3_ createdAt + varchar createdById FK + TEXT description + varchar_36_ evaluationConfigId FK + varchar_36_ id PK + TEXT insightsCache + varchar_128_ name + datetime_3_ updatedAt + varchar_36_ workflowId FK +} +"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 +} +"evaluation_config" { + datetime_3_ createdAt + TEXT datasetRef + varchar_32_ datasetSource + varchar_255_ endNodeName + varchar_36_ id PK + varchar_64_ invalidReason + TEXT metrics + varchar_128_ name + varchar_255_ startNodeName + varchar_16_ status + datetime_3_ updatedAt + varchar_36_ workflowId FK +} +"test_run" { + boolean cancelRequested + varchar_36_ collectionId FK + datetime_3_ completedAt + datetime_3_ createdAt + varchar errorCode + TEXT errorDetails + varchar_36_ evaluationConfigId FK + TEXT evaluationConfigSnapshot + varchar_36_ id PK + TEXT metrics + datetime_3_ runAt + varchar_255_ runningInstanceId + varchar status + datetime_3_ updatedAt + varchar_36_ workflowId FK + varchar_36_ workflowVersionId +} +"workflow_entity" { + boolean active + varchar_36_ activeVersionId FK + TEXT connections + datetime_3_ createdAt + TEXT description + varchar_36_ id PK + boolean isArchived + TEXT meta + varchar_128_ name + TEXT nodeGroups + TEXT nodes + varchar_36_ parentFolderId FK + TEXT pinData + TEXT settings + varchar sourceWorkflowId + TEXT staticData + INTEGER triggerCount + datetime_3_ updatedAt + INTEGER versionCounter + varchar_36_ versionId +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/sqlite-schema/evaluation_config.md b/docs/generated/sqlite-schema/evaluation_config.md new file mode 100644 index 00000000000..b779e1a12b5 --- /dev/null +++ b/docs/generated/sqlite-schema/evaluation_config.md @@ -0,0 +1,126 @@ +# evaluation_config + +## Description + +<details> +<summary><strong>Table Definition</strong></summary> + +```sql +CREATE TABLE "evaluation_config" ("id" varchar(36) PRIMARY KEY NOT NULL, "workflowId" varchar(36) NOT NULL, "name" varchar(128) NOT NULL, "status" varchar(16) NOT NULL DEFAULT ('valid'), "invalidReason" varchar(64), "datasetSource" varchar(32) NOT NULL, "datasetRef" text NOT NULL, "startNodeName" varchar(255) NOT NULL, "endNodeName" varchar(255) NOT NULL, "metrics" 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 "UQ_3c3c99a712e971835c52292e44c" UNIQUE ("workflowId", "name"), CONSTRAINT "FK_fd7542bb123074760285dc1bbf3" FOREIGN KEY ("workflowId") REFERENCES "workflow_entity" ("id") ON DELETE CASCADE) +``` + +</details> + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| createdAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | +| datasetRef | TEXT | | false | | | | +| datasetSource | varchar(32) | | false | | | | +| endNodeName | varchar(255) | | false | | | | +| id | varchar(36) | | false | [evaluation_collection](evaluation_collection.md) [test_run](test_run.md) | | | +| invalidReason | varchar(64) | | true | | | | +| metrics | TEXT | | false | | | | +| name | varchar(128) | | false | | | | +| startNodeName | varchar(255) | | false | | | | +| status | varchar(16) | 'valid' | false | | | | +| updatedAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | +| workflowId | varchar(36) | | false | | [workflow_entity](workflow_entity.md) | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| - (Foreign key ID: 0) | FOREIGN KEY | FOREIGN KEY (workflowId) REFERENCES workflow_entity (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| id | PRIMARY KEY | PRIMARY KEY (id) | +| sqlite_autoindex_evaluation_config_1 | PRIMARY KEY | PRIMARY KEY (id) | +| sqlite_autoindex_evaluation_config_2 | UNIQUE | UNIQUE (workflowId, name) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_fd7542bb123074760285dc1bbf | CREATE INDEX "IDX_fd7542bb123074760285dc1bbf" ON "evaluation_config" ("workflowId") | +| sqlite_autoindex_evaluation_config_1 | PRIMARY KEY (id) | +| sqlite_autoindex_evaluation_config_2 | UNIQUE (workflowId, name) | + +## Relations + +```mermaid +erDiagram + +"evaluation_collection" }o--|| "evaluation_config" : "FOREIGN KEY (evaluationConfigId) REFERENCES evaluation_config (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"test_run" }o--o| "evaluation_config" : "FOREIGN KEY (evaluationConfigId) REFERENCES evaluation_config (id) ON UPDATE NO ACTION ON DELETE SET NULL MATCH NONE" +"evaluation_config" }o--|| "workflow_entity" : "FOREIGN KEY (workflowId) REFERENCES workflow_entity (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" + +"evaluation_config" { + datetime_3_ createdAt + TEXT datasetRef + varchar_32_ datasetSource + varchar_255_ endNodeName + varchar_36_ id PK + varchar_64_ invalidReason + TEXT metrics + varchar_128_ name + varchar_255_ startNodeName + varchar_16_ status + datetime_3_ updatedAt + varchar_36_ workflowId FK +} +"evaluation_collection" { + datetime_3_ createdAt + varchar createdById FK + TEXT description + varchar_36_ evaluationConfigId FK + varchar_36_ id PK + TEXT insightsCache + varchar_128_ name + datetime_3_ updatedAt + varchar_36_ workflowId FK +} +"test_run" { + boolean cancelRequested + varchar_36_ collectionId FK + datetime_3_ completedAt + datetime_3_ createdAt + varchar errorCode + TEXT errorDetails + varchar_36_ evaluationConfigId FK + TEXT evaluationConfigSnapshot + varchar_36_ id PK + TEXT metrics + datetime_3_ runAt + varchar_255_ runningInstanceId + varchar status + datetime_3_ updatedAt + varchar_36_ workflowId FK + varchar_36_ workflowVersionId +} +"workflow_entity" { + boolean active + varchar_36_ activeVersionId FK + TEXT connections + datetime_3_ createdAt + TEXT description + varchar_36_ id PK + boolean isArchived + TEXT meta + varchar_128_ name + TEXT nodeGroups + TEXT nodes + varchar_36_ parentFolderId FK + TEXT pinData + TEXT settings + varchar sourceWorkflowId + TEXT staticData + INTEGER triggerCount + datetime_3_ updatedAt + INTEGER versionCounter + varchar_36_ versionId +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/sqlite-schema/event_destinations.md b/docs/generated/sqlite-schema/event_destinations.md new file mode 100644 index 00000000000..9a9301474e3 --- /dev/null +++ b/docs/generated/sqlite-schema/event_destinations.md @@ -0,0 +1,52 @@ +# event_destinations + +## Description + +<details> +<summary><strong>Table Definition</strong></summary> + +```sql +CREATE TABLE "event_destinations" ("id" varchar(36) PRIMARY KEY NOT NULL,"destination" 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'')') +``` + +</details> + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| createdAt | datetime(3) | 'STRFTIME(''%Y-%m-%d %H:%M:%f'', ''NOW'')' | false | | | | +| destination | TEXT | | false | | | | +| id | varchar(36) | | false | | | | +| updatedAt | datetime(3) | 'STRFTIME(''%Y-%m-%d %H:%M:%f'', ''NOW'')' | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| id | PRIMARY KEY | PRIMARY KEY (id) | +| sqlite_autoindex_event_destinations_1 | PRIMARY KEY | PRIMARY KEY (id) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| sqlite_autoindex_event_destinations_1 | PRIMARY KEY (id) | + +## Relations + +```mermaid +erDiagram + + +"event_destinations" { + datetime_3_ createdAt + TEXT destination + varchar_36_ id PK + datetime_3_ updatedAt +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/sqlite-schema/execution_annotation_tags.md b/docs/generated/sqlite-schema/execution_annotation_tags.md new file mode 100644 index 00000000000..2be4c2ce5e7 --- /dev/null +++ b/docs/generated/sqlite-schema/execution_annotation_tags.md @@ -0,0 +1,69 @@ +# execution_annotation_tags + +## Description + +<details> +<summary><strong>Table Definition</strong></summary> + +```sql +CREATE TABLE "execution_annotation_tags" ("annotationId" integer NOT NULL, "tagId" varchar(24) NOT NULL, CONSTRAINT "FK_c1519757391996eb06064f0e7c8" FOREIGN KEY ("annotationId") REFERENCES "execution_annotations" ("id") ON DELETE CASCADE, CONSTRAINT "FK_a3697779b366e131b2bbdae2976" FOREIGN KEY ("tagId") REFERENCES "annotation_tag_entity" ("id") ON DELETE CASCADE, PRIMARY KEY ("annotationId", "tagId")) +``` + +</details> + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| annotationId | INTEGER | | false | | [execution_annotations](execution_annotations.md) | | +| tagId | varchar(24) | | false | | [annotation_tag_entity](annotation_tag_entity.md) | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| - (Foreign key ID: 0) | FOREIGN KEY | FOREIGN KEY (tagId) REFERENCES annotation_tag_entity (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| - (Foreign key ID: 1) | FOREIGN KEY | FOREIGN KEY (annotationId) REFERENCES execution_annotations (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| annotationId | PRIMARY KEY | PRIMARY KEY (annotationId) | +| sqlite_autoindex_execution_annotation_tags_1 | PRIMARY KEY | PRIMARY KEY (annotationId, tagId) | +| tagId | PRIMARY KEY | PRIMARY KEY (tagId) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_a3697779b366e131b2bbdae297 | CREATE INDEX "IDX_a3697779b366e131b2bbdae297" ON "execution_annotation_tags" ("tagId") | +| IDX_c1519757391996eb06064f0e7c | CREATE INDEX "IDX_c1519757391996eb06064f0e7c" ON "execution_annotation_tags" ("annotationId") | +| sqlite_autoindex_execution_annotation_tags_1 | PRIMARY KEY (annotationId, tagId) | + +## Relations + +```mermaid +erDiagram + +"execution_annotation_tags" |o--|| "execution_annotations" : "FOREIGN KEY (annotationId) REFERENCES execution_annotations (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"execution_annotation_tags" |o--|| "annotation_tag_entity" : "FOREIGN KEY (tagId) REFERENCES annotation_tag_entity (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" + +"execution_annotation_tags" { + INTEGER annotationId PK + varchar_24_ tagId PK +} +"execution_annotations" { + datetime_3_ createdAt + INTEGER executionId FK + INTEGER id + TEXT note + datetime_3_ updatedAt + varchar_6_ vote +} +"annotation_tag_entity" { + datetime_3_ createdAt + varchar_16_ id PK + varchar_24_ name + datetime_3_ updatedAt +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/sqlite-schema/execution_annotations.md b/docs/generated/sqlite-schema/execution_annotations.md new file mode 100644 index 00000000000..eb96181e32d --- /dev/null +++ b/docs/generated/sqlite-schema/execution_annotations.md @@ -0,0 +1,82 @@ +# execution_annotations + +## Description + +<details> +<summary><strong>Table Definition</strong></summary> + +```sql +CREATE TABLE "execution_annotations" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "executionId" integer NOT NULL, "vote" varchar(6), "note" text, "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_97f863fa83c4786f19565084960" FOREIGN KEY ("executionId") REFERENCES "execution_entity" ("id") ON DELETE CASCADE) +``` + +</details> + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| createdAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | +| executionId | INTEGER | | false | | [execution_entity](execution_entity.md) | | +| id | INTEGER | | false | [execution_annotation_tags](execution_annotation_tags.md) | | | +| note | TEXT | | true | | | | +| updatedAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | +| vote | varchar(6) | | true | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| - (Foreign key ID: 0) | FOREIGN KEY | FOREIGN KEY (executionId) REFERENCES execution_entity (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| id | PRIMARY KEY | PRIMARY KEY (id) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_97f863fa83c4786f1956508496 | CREATE UNIQUE INDEX "IDX_97f863fa83c4786f1956508496" ON "execution_annotations" ("executionId") | + +## Relations + +```mermaid +erDiagram + +"execution_annotations" }o--|| "execution_entity" : "FOREIGN KEY (executionId) REFERENCES execution_entity (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"execution_annotation_tags" |o--|| "execution_annotations" : "FOREIGN KEY (annotationId) REFERENCES execution_annotations (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" + +"execution_annotations" { + datetime_3_ createdAt + INTEGER executionId FK + INTEGER id + TEXT note + datetime_3_ updatedAt + varchar_6_ vote +} +"execution_entity" { + BIGINT binaryDataSizeBytes + datetime_3_ createdAt + varchar_255_ deduplicationKey + datetime_3_ deletedAt + boolean finished + INTEGER id + BIGINT jsonSizeBytes + varchar mode + varchar retryOf + varchar retrySuccessId + datetime startedAt + varchar status + datetime stoppedAt + varchar_2_ storedAt + TEXT tracingContext + datetime waitTill + varchar_36_ workflowId FK + VARCHAR_36_ workflowVersionId +} +"execution_annotation_tags" { + INTEGER annotationId PK + varchar_24_ tagId PK +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/sqlite-schema/execution_data.md b/docs/generated/sqlite-schema/execution_data.md new file mode 100644 index 00000000000..6e29cde6a05 --- /dev/null +++ b/docs/generated/sqlite-schema/execution_data.md @@ -0,0 +1,79 @@ +# execution_data + +## Description + +<details> +<summary><strong>Table Definition</strong></summary> + +```sql +CREATE TABLE "execution_data" ( + "executionId" int PRIMARY KEY NOT NULL, + "workflowData" text NOT NULL, + "data" text NOT NULL, "workflowVersionId" VARCHAR(36), + FOREIGN KEY("executionId") REFERENCES "execution_entity" ("id") ON DELETE CASCADE + ) +``` + +</details> + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| data | TEXT | | false | | | | +| executionId | INT | | false | | [execution_entity](execution_entity.md) | | +| workflowData | TEXT | | false | | | | +| workflowVersionId | VARCHAR(36) | | true | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| - (Foreign key ID: 0) | FOREIGN KEY | FOREIGN KEY (executionId) REFERENCES execution_entity (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| executionId | PRIMARY KEY | PRIMARY KEY (executionId) | +| sqlite_autoindex_execution_data_1 | PRIMARY KEY | PRIMARY KEY (executionId) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| sqlite_autoindex_execution_data_1 | PRIMARY KEY (executionId) | + +## Relations + +```mermaid +erDiagram + +"execution_data" |o--|| "execution_entity" : "FOREIGN KEY (executionId) REFERENCES execution_entity (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" + +"execution_data" { + TEXT data + INT executionId PK + TEXT workflowData + VARCHAR_36_ workflowVersionId +} +"execution_entity" { + BIGINT binaryDataSizeBytes + datetime_3_ createdAt + varchar_255_ deduplicationKey + datetime_3_ deletedAt + boolean finished + INTEGER id + BIGINT jsonSizeBytes + varchar mode + varchar retryOf + varchar retrySuccessId + datetime startedAt + varchar status + datetime stoppedAt + varchar_2_ storedAt + TEXT tracingContext + datetime waitTill + varchar_36_ workflowId FK + VARCHAR_36_ workflowVersionId +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/sqlite-schema/execution_entity.md b/docs/generated/sqlite-schema/execution_entity.md new file mode 100644 index 00000000000..f1a2abf0d0a --- /dev/null +++ b/docs/generated/sqlite-schema/execution_entity.md @@ -0,0 +1,169 @@ +# execution_entity + +## Description + +<details> +<summary><strong>Table Definition</strong></summary> + +```sql +CREATE TABLE "execution_entity" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "workflowId" varchar(36) NOT NULL, "finished" boolean NOT NULL, "mode" varchar NOT NULL, "retryOf" varchar, "retrySuccessId" varchar, "startedAt" datetime, "stoppedAt" datetime, "waitTill" datetime, "status" varchar NOT NULL, "deletedAt" datetime(3), "createdAt" datetime(3) NOT NULL DEFAULT (STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW')), "storedAt" varchar(2) NOT NULL DEFAULT ('db'), "tracingContext" text, "deduplicationKey" varchar(255), "jsonSizeBytes" BIGINT NOT NULL DEFAULT 0, "workflowVersionId" VARCHAR(36) DEFAULT NULL, "binaryDataSizeBytes" BIGINT NOT NULL DEFAULT 0, CONSTRAINT "FK_c4d999a5e90784e8caccf5589de" FOREIGN KEY ("workflowId") REFERENCES "workflow_entity" ("id") ON DELETE CASCADE ON UPDATE NO ACTION) +``` + +</details> + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| binaryDataSizeBytes | BIGINT | 0 | false | | | | +| createdAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | +| deduplicationKey | varchar(255) | | true | | | | +| deletedAt | datetime(3) | | true | | | | +| finished | boolean | | false | | | | +| id | INTEGER | | false | [chat_hub_messages](chat_hub_messages.md) [execution_annotations](execution_annotations.md) [execution_data](execution_data.md) [execution_metadata](execution_metadata.md) [test_case_execution](test_case_execution.md) | | | +| jsonSizeBytes | BIGINT | 0 | false | | | | +| mode | varchar | | false | | | | +| retryOf | varchar | | true | | | | +| retrySuccessId | varchar | | true | | | | +| startedAt | datetime | | true | | | | +| status | varchar | | false | | | | +| stoppedAt | datetime | | true | | | | +| storedAt | varchar(2) | 'db' | false | | | | +| tracingContext | TEXT | | true | | | | +| waitTill | datetime | | true | | | | +| workflowId | varchar(36) | | false | | [workflow_entity](workflow_entity.md) | | +| workflowVersionId | VARCHAR(36) | NULL | true | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| - (Foreign key ID: 0) | FOREIGN KEY | FOREIGN KEY (workflowId) REFERENCES workflow_entity (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| id | PRIMARY KEY | PRIMARY KEY (id) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_execution_entity_deduplicationKey | CREATE UNIQUE INDEX "IDX_execution_entity_deduplicationKey" ON "execution_entity" ("deduplicationKey") WHERE "deduplicationKey" IS NOT NULL | +| IDX_execution_entity_deletedAt | CREATE INDEX "IDX_execution_entity_deletedAt" ON "execution_entity" ("deletedAt") | +| IDX_execution_entity_stoppedAt | CREATE INDEX "IDX_execution_entity_stoppedAt" ON "execution_entity" ("stoppedAt") | + +## Relations + +```mermaid +erDiagram + +"chat_hub_messages" }o--o| "execution_entity" : "FOREIGN KEY (executionId) REFERENCES execution_entity (id) ON UPDATE NO ACTION ON DELETE SET NULL MATCH NONE" +"execution_annotations" }o--|| "execution_entity" : "FOREIGN KEY (executionId) REFERENCES execution_entity (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"execution_data" |o--|| "execution_entity" : "FOREIGN KEY (executionId) REFERENCES execution_entity (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"execution_metadata" }o--|| "execution_entity" : "FOREIGN KEY (executionId) REFERENCES execution_entity (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" +"test_case_execution" }o--o| "execution_entity" : "FOREIGN KEY (evaluationExecutionId) REFERENCES execution_entity (id) ON UPDATE NO ACTION ON DELETE SET NULL MATCH NONE" +"execution_entity" }o--|| "workflow_entity" : "FOREIGN KEY (workflowId) REFERENCES workflow_entity (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" + +"execution_entity" { + BIGINT binaryDataSizeBytes + datetime_3_ createdAt + varchar_255_ deduplicationKey + datetime_3_ deletedAt + boolean finished + INTEGER id + BIGINT jsonSizeBytes + varchar mode + varchar retryOf + varchar retrySuccessId + datetime startedAt + varchar status + datetime stoppedAt + varchar_2_ storedAt + TEXT tracingContext + datetime waitTill + varchar_36_ workflowId FK + VARCHAR_36_ workflowVersionId +} +"chat_hub_messages" { + varchar_36_ agentId FK + TEXT attachments + TEXT content + datetime_3_ createdAt + INTEGER executionId FK + varchar id PK + VARCHAR_256_ model + varchar_128_ name + varchar previousMessageId FK + varchar_16_ provider + varchar retryOfMessageId FK + varchar revisionOfMessageId FK + varchar sessionId FK + varchar_16_ status + varchar_16_ type + datetime_3_ updatedAt + varchar_36_ workflowId FK +} +"execution_annotations" { + datetime_3_ createdAt + INTEGER executionId FK + INTEGER id + TEXT note + datetime_3_ updatedAt + varchar_6_ vote +} +"execution_data" { + TEXT data + INT executionId PK + TEXT workflowData + VARCHAR_36_ workflowVersionId +} +"execution_metadata" { + INTEGER executionId FK + INTEGER id + varchar_255_ key + TEXT value +} +"test_case_execution" { + datetime_3_ completedAt + datetime_3_ createdAt + varchar errorCode + TEXT errorDetails + INTEGER evaluationExecutionId FK + INTEGER executionId FK + varchar_36_ id PK + TEXT inputs + TEXT metrics + TEXT outputs + INTEGER pastExecutionId FK + datetime_3_ runAt + INTEGER runIndex + varchar status + varchar_36_ testRunId FK + datetime_3_ updatedAt +} +"workflow_entity" { + boolean active + varchar_36_ activeVersionId FK + TEXT connections + datetime_3_ createdAt + TEXT description + varchar_36_ id PK + boolean isArchived + TEXT meta + varchar_128_ name + TEXT nodeGroups + TEXT nodes + varchar_36_ parentFolderId FK + TEXT pinData + TEXT settings + varchar sourceWorkflowId + TEXT staticData + INTEGER triggerCount + datetime_3_ updatedAt + INTEGER versionCounter + varchar_36_ versionId +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/sqlite-schema/execution_metadata.md b/docs/generated/sqlite-schema/execution_metadata.md new file mode 100644 index 00000000000..39838cb6122 --- /dev/null +++ b/docs/generated/sqlite-schema/execution_metadata.md @@ -0,0 +1,73 @@ +# execution_metadata + +## Description + +<details> +<summary><strong>Table Definition</strong></summary> + +```sql +CREATE TABLE "execution_metadata" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "executionId" integer NOT NULL, "key" varchar(255) NOT NULL, "value" text NOT NULL, CONSTRAINT "FK_31d0b4c93fb85ced26f6005cda3" FOREIGN KEY ("executionId") REFERENCES "execution_entity" ("id") ON DELETE CASCADE) +``` + +</details> + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| executionId | INTEGER | | false | | [execution_entity](execution_entity.md) | | +| id | INTEGER | | false | | | | +| key | varchar(255) | | false | | | | +| value | TEXT | | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| - (Foreign key ID: 0) | FOREIGN KEY | FOREIGN KEY (executionId) REFERENCES execution_entity (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| id | PRIMARY KEY | PRIMARY KEY (id) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_cec8eea3bf49551482ccb4933e | CREATE UNIQUE INDEX "IDX_cec8eea3bf49551482ccb4933e" ON "execution_metadata" ("executionId", "key") | + +## Relations + +```mermaid +erDiagram + +"execution_metadata" }o--|| "execution_entity" : "FOREIGN KEY (executionId) REFERENCES execution_entity (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" + +"execution_metadata" { + INTEGER executionId FK + INTEGER id + varchar_255_ key + TEXT value +} +"execution_entity" { + BIGINT binaryDataSizeBytes + datetime_3_ createdAt + varchar_255_ deduplicationKey + datetime_3_ deletedAt + boolean finished + INTEGER id + BIGINT jsonSizeBytes + varchar mode + varchar retryOf + varchar retrySuccessId + datetime startedAt + varchar status + datetime stoppedAt + varchar_2_ storedAt + TEXT tracingContext + datetime waitTill + varchar_36_ workflowId FK + VARCHAR_36_ workflowVersionId +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/sqlite-schema/folder.md b/docs/generated/sqlite-schema/folder.md new file mode 100644 index 00000000000..d64e0cdb662 --- /dev/null +++ b/docs/generated/sqlite-schema/folder.md @@ -0,0 +1,100 @@ +# folder + +## Description + +<details> +<summary><strong>Table Definition</strong></summary> + +```sql +CREATE TABLE "folder" ("id" varchar(36) PRIMARY KEY NOT NULL, "name" varchar(128) NOT NULL, "parentFolderId" varchar(36), "projectId" varchar(36) 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_a8260b0b36939c6247f385b8221" FOREIGN KEY ("projectId") REFERENCES "project" ("id") ON DELETE CASCADE, CONSTRAINT "FK_804ea52f6729e3940498bd54d78" FOREIGN KEY ("parentFolderId") REFERENCES "folder" ("id") ON DELETE CASCADE) +``` + +</details> + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| createdAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | +| id | varchar(36) | | false | [folder](folder.md) [folder_tag](folder_tag.md) [workflow_entity](workflow_entity.md) | | | +| name | varchar(128) | | false | | | | +| parentFolderId | varchar(36) | | true | | [folder](folder.md) | | +| projectId | varchar(36) | | false | | [project](project.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 (parentFolderId) REFERENCES folder (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| - (Foreign key ID: 1) | 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_folder_1 | PRIMARY KEY | PRIMARY KEY (id) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_14f68deffaf858465715995508 | CREATE UNIQUE INDEX "IDX_14f68deffaf858465715995508" ON "folder" ("projectId", "id") | +| sqlite_autoindex_folder_1 | PRIMARY KEY (id) | + +## Relations + +```mermaid +erDiagram + +"folder" }o--o| "folder" : "FOREIGN KEY (parentFolderId) REFERENCES folder (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"folder_tag" |o--|| "folder" : "FOREIGN KEY (folderId) REFERENCES folder (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"workflow_entity" }o--o| "folder" : "FOREIGN KEY (parentFolderId) REFERENCES folder (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"folder" }o--|| "project" : "FOREIGN KEY (projectId) REFERENCES project (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" + +"folder" { + datetime_3_ createdAt + varchar_36_ id PK + varchar_128_ name + varchar_36_ parentFolderId FK + varchar_36_ projectId FK + datetime_3_ updatedAt +} +"folder_tag" { + varchar_36_ folderId PK + varchar_36_ tagId PK +} +"workflow_entity" { + boolean active + varchar_36_ activeVersionId FK + TEXT connections + datetime_3_ createdAt + TEXT description + varchar_36_ id PK + boolean isArchived + TEXT meta + varchar_128_ name + TEXT nodeGroups + TEXT nodes + varchar_36_ parentFolderId FK + TEXT pinData + TEXT settings + varchar sourceWorkflowId + TEXT staticData + INTEGER triggerCount + datetime_3_ updatedAt + INTEGER versionCounter + varchar_36_ versionId +} +"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/folder_tag.md b/docs/generated/sqlite-schema/folder_tag.md new file mode 100644 index 00000000000..934d8868497 --- /dev/null +++ b/docs/generated/sqlite-schema/folder_tag.md @@ -0,0 +1,67 @@ +# folder_tag + +## Description + +<details> +<summary><strong>Table Definition</strong></summary> + +```sql +CREATE TABLE "folder_tag" ("folderId" varchar(36) NOT NULL, "tagId" varchar(36) NOT NULL, CONSTRAINT "FK_94a60854e06f2897b2e0d39edba" FOREIGN KEY ("folderId") REFERENCES "folder" ("id") ON DELETE CASCADE, CONSTRAINT "FK_dc88164176283de80af47621746" FOREIGN KEY ("tagId") REFERENCES "tag_entity" ("id") ON DELETE CASCADE, PRIMARY KEY ("folderId", "tagId")) +``` + +</details> + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| folderId | varchar(36) | | false | | [folder](folder.md) | | +| tagId | varchar(36) | | false | | [tag_entity](tag_entity.md) | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| - (Foreign key ID: 0) | FOREIGN KEY | FOREIGN KEY (tagId) REFERENCES tag_entity (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| - (Foreign key ID: 1) | FOREIGN KEY | FOREIGN KEY (folderId) REFERENCES folder (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| folderId | PRIMARY KEY | PRIMARY KEY (folderId) | +| sqlite_autoindex_folder_tag_1 | PRIMARY KEY | PRIMARY KEY (folderId, tagId) | +| tagId | PRIMARY KEY | PRIMARY KEY (tagId) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| sqlite_autoindex_folder_tag_1 | PRIMARY KEY (folderId, tagId) | + +## Relations + +```mermaid +erDiagram + +"folder_tag" |o--|| "folder" : "FOREIGN KEY (folderId) REFERENCES folder (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"folder_tag" |o--|| "tag_entity" : "FOREIGN KEY (tagId) REFERENCES tag_entity (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" + +"folder_tag" { + varchar_36_ folderId PK + varchar_36_ tagId PK +} +"folder" { + datetime_3_ createdAt + varchar_36_ id PK + varchar_128_ name + varchar_36_ parentFolderId FK + varchar_36_ projectId FK + datetime_3_ updatedAt +} +"tag_entity" { + datetime_3_ createdAt + varchar_36_ id PK + varchar_24_ name + datetime_3_ updatedAt +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/sqlite-schema/insights_by_period.md b/docs/generated/sqlite-schema/insights_by_period.md new file mode 100644 index 00000000000..784b5702f1c --- /dev/null +++ b/docs/generated/sqlite-schema/insights_by_period.md @@ -0,0 +1,64 @@ +# insights_by_period + +## Description + +<details> +<summary><strong>Table Definition</strong></summary> + +```sql +CREATE TABLE "insights_by_period" ("id" integer PRIMARY KEY NOT NULL, "metaId" integer NOT NULL, "type" integer NOT NULL, "value" bigint NOT NULL, "periodUnit" integer NOT NULL, "periodStart" datetime(0) DEFAULT (CURRENT_TIMESTAMP), CONSTRAINT "FK_e8881f2214df046dc2740260fe8" FOREIGN KEY ("metaId") REFERENCES "insights_metadata" ("metaId") ON DELETE CASCADE) +``` + +</details> + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| id | INTEGER | | false | | | | +| metaId | INTEGER | | false | | [insights_metadata](insights_metadata.md) | | +| periodStart | datetime(0) | CURRENT_TIMESTAMP | true | | | | +| periodUnit | INTEGER | | false | | | | +| type | INTEGER | | false | | | | +| value | bigint | | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| - (Foreign key ID: 0) | FOREIGN KEY | FOREIGN KEY (metaId) REFERENCES insights_metadata (metaId) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| id | PRIMARY KEY | PRIMARY KEY (id) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_a4da41795da1422f680c723e80 | CREATE UNIQUE INDEX "IDX_a4da41795da1422f680c723e80" ON "insights_by_period" ("periodStart", "type", "periodUnit", "metaId") | + +## Relations + +```mermaid +erDiagram + +"insights_by_period" }o--|| "insights_metadata" : "FOREIGN KEY (metaId) REFERENCES insights_metadata (metaId) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" + +"insights_by_period" { + INTEGER id + INTEGER metaId FK + datetime_0_ periodStart + INTEGER periodUnit + INTEGER type + bigint value +} +"insights_metadata" { + INTEGER metaId + varchar_36_ projectId FK + varchar_255_ projectName + varchar_16_ workflowId FK + varchar_128_ workflowName +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/sqlite-schema/insights_metadata.md b/docs/generated/sqlite-schema/insights_metadata.md new file mode 100644 index 00000000000..a553aa580ef --- /dev/null +++ b/docs/generated/sqlite-schema/insights_metadata.md @@ -0,0 +1,107 @@ +# insights_metadata + +## Description + +<details> +<summary><strong>Table Definition</strong></summary> + +```sql +CREATE TABLE "insights_metadata" ("metaId" integer PRIMARY KEY NOT NULL, "workflowId" varchar(16), "projectId" varchar(36), "workflowName" varchar(128) NOT NULL, "projectName" varchar(255) NOT NULL, CONSTRAINT "FK_1d8ab99d5861c9388d2dc1cf733" FOREIGN KEY ("workflowId") REFERENCES "workflow_entity" ("id") ON DELETE SET NULL, CONSTRAINT "FK_2375a1eda085adb16b24615b69c" FOREIGN KEY ("projectId") REFERENCES "project" ("id") ON DELETE SET NULL) +``` + +</details> + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| metaId | INTEGER | | false | [insights_by_period](insights_by_period.md) [insights_raw](insights_raw.md) | | | +| projectId | varchar(36) | | true | | [project](project.md) | | +| projectName | varchar(255) | | false | | | | +| workflowId | varchar(16) | | true | | [workflow_entity](workflow_entity.md) | | +| workflowName | varchar(128) | | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| - (Foreign key ID: 0) | FOREIGN KEY | FOREIGN KEY (projectId) REFERENCES project (id) ON UPDATE NO ACTION ON DELETE SET NULL MATCH NONE | +| - (Foreign key ID: 1) | FOREIGN KEY | FOREIGN KEY (workflowId) REFERENCES workflow_entity (id) ON UPDATE NO ACTION ON DELETE SET NULL MATCH NONE | +| metaId | PRIMARY KEY | PRIMARY KEY (metaId) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_1d8ab99d5861c9388d2dc1cf73 | CREATE UNIQUE INDEX "IDX_1d8ab99d5861c9388d2dc1cf73" ON "insights_metadata" ("workflowId") | + +## Relations + +```mermaid +erDiagram + +"insights_by_period" }o--|| "insights_metadata" : "FOREIGN KEY (metaId) REFERENCES insights_metadata (metaId) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"insights_raw" }o--|| "insights_metadata" : "FOREIGN KEY (metaId) REFERENCES insights_metadata (metaId) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"insights_metadata" }o--o| "project" : "FOREIGN KEY (projectId) REFERENCES project (id) ON UPDATE NO ACTION ON DELETE SET NULL MATCH NONE" +"insights_metadata" }o--o| "workflow_entity" : "FOREIGN KEY (workflowId) REFERENCES workflow_entity (id) ON UPDATE NO ACTION ON DELETE SET NULL MATCH NONE" + +"insights_metadata" { + INTEGER metaId + varchar_36_ projectId FK + varchar_255_ projectName + varchar_16_ workflowId FK + varchar_128_ workflowName +} +"insights_by_period" { + INTEGER id + INTEGER metaId FK + datetime_0_ periodStart + INTEGER periodUnit + INTEGER type + bigint value +} +"insights_raw" { + INTEGER id + INTEGER metaId FK + datetime_0_ timestamp + INTEGER type + bigint value +} +"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 +} +"workflow_entity" { + boolean active + varchar_36_ activeVersionId FK + TEXT connections + datetime_3_ createdAt + TEXT description + varchar_36_ id PK + boolean isArchived + TEXT meta + varchar_128_ name + TEXT nodeGroups + TEXT nodes + varchar_36_ parentFolderId FK + TEXT pinData + TEXT settings + varchar sourceWorkflowId + TEXT staticData + INTEGER triggerCount + datetime_3_ updatedAt + INTEGER versionCounter + varchar_36_ versionId +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/sqlite-schema/insights_raw.md b/docs/generated/sqlite-schema/insights_raw.md new file mode 100644 index 00000000000..6f84c384301 --- /dev/null +++ b/docs/generated/sqlite-schema/insights_raw.md @@ -0,0 +1,62 @@ +# insights_raw + +## Description + +<details> +<summary><strong>Table Definition</strong></summary> + +```sql +CREATE TABLE "insights_raw" ("id" integer PRIMARY KEY NOT NULL, "metaId" integer NOT NULL, "type" integer NOT NULL, "value" bigint NOT NULL, "timestamp" datetime(0) NOT NULL DEFAULT (CURRENT_TIMESTAMP), CONSTRAINT "FK_d66d942bc9907488832eb0eed81" FOREIGN KEY ("metaId") REFERENCES "insights_metadata" ("metaId") ON DELETE CASCADE) +``` + +</details> + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| id | INTEGER | | false | | | | +| metaId | INTEGER | | false | | [insights_metadata](insights_metadata.md) | | +| timestamp | datetime(0) | CURRENT_TIMESTAMP | false | | | | +| type | INTEGER | | false | | | | +| value | bigint | | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| - (Foreign key ID: 0) | FOREIGN KEY | FOREIGN KEY (metaId) REFERENCES insights_metadata (metaId) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| id | PRIMARY KEY | PRIMARY KEY (id) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_insights_raw_timestamp_id | CREATE INDEX "IDX_insights_raw_timestamp_id" ON "insights_raw" ("timestamp", "id") | + +## Relations + +```mermaid +erDiagram + +"insights_raw" }o--|| "insights_metadata" : "FOREIGN KEY (metaId) REFERENCES insights_metadata (metaId) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" + +"insights_raw" { + INTEGER id + INTEGER metaId FK + datetime_0_ timestamp + INTEGER type + bigint value +} +"insights_metadata" { + INTEGER metaId + varchar_36_ projectId FK + varchar_255_ projectName + varchar_16_ workflowId FK + varchar_128_ workflowName +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/sqlite-schema/installed_nodes.md b/docs/generated/sqlite-schema/installed_nodes.md new file mode 100644 index 00000000000..560caa42eca --- /dev/null +++ b/docs/generated/sqlite-schema/installed_nodes.md @@ -0,0 +1,62 @@ +# installed_nodes + +## Description + +<details> +<summary><strong>Table Definition</strong></summary> + +```sql +CREATE TABLE "installed_nodes" ("name" char(200) NOT NULL,"type" char(200) NOT NULL,"latestVersion" INTEGER DEFAULT 1,"package" char(214) NOT NULL,PRIMARY KEY("name"),FOREIGN KEY("package") REFERENCES "installed_packages"("packageName") ON DELETE CASCADE ON UPDATE CASCADE) +``` + +</details> + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| latestVersion | INTEGER | 1 | true | | | | +| name | char(200) | | false | | | | +| package | char(214) | | false | | [installed_packages](installed_packages.md) | | +| type | char(200) | | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| - (Foreign key ID: 0) | FOREIGN KEY | FOREIGN KEY (package) REFERENCES installed_packages (packageName) ON UPDATE CASCADE ON DELETE CASCADE MATCH NONE | +| name | PRIMARY KEY | PRIMARY KEY (name) | +| sqlite_autoindex_installed_nodes_1 | PRIMARY KEY | PRIMARY KEY (name) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| sqlite_autoindex_installed_nodes_1 | PRIMARY KEY (name) | + +## Relations + +```mermaid +erDiagram + +"installed_nodes" }o--|| "installed_packages" : "FOREIGN KEY (package) REFERENCES installed_packages (packageName) ON UPDATE CASCADE ON DELETE CASCADE MATCH NONE" + +"installed_nodes" { + INTEGER latestVersion + char_200_ name PK + char_214_ package FK + char_200_ type +} +"installed_packages" { + char_70_ authorEmail + char_70_ authorName + datetime_3_ createdAt + char_50_ installedVersion + char_214_ packageName PK + datetime_3_ updatedAt +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/sqlite-schema/installed_packages.md b/docs/generated/sqlite-schema/installed_packages.md new file mode 100644 index 00000000000..75b58f5269d --- /dev/null +++ b/docs/generated/sqlite-schema/installed_packages.md @@ -0,0 +1,63 @@ +# installed_packages + +## Description + +<details> +<summary><strong>Table Definition</strong></summary> + +```sql +CREATE TABLE "installed_packages" ("packageName" char(214) NOT NULL,"installedVersion" char(50) NOT NULL,"authorName" char(70) NULL,"authorEmail" char(70) 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'')',PRIMARY KEY("packageName")) +``` + +</details> + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| authorEmail | char(70) | | true | | | | +| authorName | char(70) | | true | | | | +| createdAt | datetime(3) | 'STRFTIME(''%Y-%m-%d %H:%M:%f'', ''NOW'')' | false | | | | +| installedVersion | char(50) | | false | | | | +| packageName | char(214) | | false | [installed_nodes](installed_nodes.md) | | | +| updatedAt | datetime(3) | 'STRFTIME(''%Y-%m-%d %H:%M:%f'', ''NOW'')' | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| packageName | PRIMARY KEY | PRIMARY KEY (packageName) | +| sqlite_autoindex_installed_packages_1 | PRIMARY KEY | PRIMARY KEY (packageName) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| sqlite_autoindex_installed_packages_1 | PRIMARY KEY (packageName) | + +## Relations + +```mermaid +erDiagram + +"installed_nodes" }o--|| "installed_packages" : "FOREIGN KEY (package) REFERENCES installed_packages (packageName) ON UPDATE CASCADE ON DELETE CASCADE MATCH NONE" + +"installed_packages" { + char_70_ authorEmail + char_70_ authorName + datetime_3_ createdAt + char_50_ installedVersion + char_214_ packageName PK + datetime_3_ updatedAt +} +"installed_nodes" { + INTEGER latestVersion + char_200_ name PK + char_214_ package FK + char_200_ type +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/sqlite-schema/instance_ai_checkpoints.md b/docs/generated/sqlite-schema/instance_ai_checkpoints.md new file mode 100644 index 00000000000..bb4bf5b4d74 --- /dev/null +++ b/docs/generated/sqlite-schema/instance_ai_checkpoints.md @@ -0,0 +1,90 @@ +# instance_ai_checkpoints + +## Description + +<details> +<summary><strong>Table Definition</strong></summary> + +```sql +CREATE TABLE "instance_ai_checkpoints" ("key" varchar(255) PRIMARY KEY NOT NULL, "runId" varchar(255), "threadId" varchar NOT NULL, "resourceId" varchar(255), "state" text, "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')), "expiredAt" datetime(3), CONSTRAINT "instance_ai_checkpoints_state_tombstone_check" CHECK (("expiredAt" IS NOT NULL AND "state" IS NULL) OR "expiredAt" IS NULL), CONSTRAINT "FK_2b23f3f24a70bebb990203b011e" FOREIGN KEY ("threadId") REFERENCES "instance_ai_threads" ("id") ON DELETE CASCADE ON UPDATE NO ACTION) +``` + +</details> + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| createdAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | +| expiredAt | datetime(3) | | true | | | | +| key | varchar(255) | | false | [instance_ai_pending_confirmations](instance_ai_pending_confirmations.md) | | | +| resourceId | varchar(255) | | true | | | | +| runId | varchar(255) | | true | | | | +| state | TEXT | | true | | | | +| threadId | varchar | | false | | [instance_ai_threads](instance_ai_threads.md) | | +| updatedAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| - | CHECK | CHECK (("expiredAt" IS NOT NULL AND "state" IS NULL) OR "expiredAt" IS NULL) | +| - (Foreign key ID: 0) | FOREIGN KEY | FOREIGN KEY (threadId) REFERENCES instance_ai_threads (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| key | PRIMARY KEY | PRIMARY KEY (key) | +| sqlite_autoindex_instance_ai_checkpoints_1 | PRIMARY KEY | PRIMARY KEY (key) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_2b23f3f24a70bebb990203b011 | CREATE INDEX "IDX_2b23f3f24a70bebb990203b011" ON "instance_ai_checkpoints" ("threadId") | +| IDX_768189b506cc26c4fe878b87cb | CREATE INDEX "IDX_768189b506cc26c4fe878b87cb" ON "instance_ai_checkpoints" ("runId") | +| IDX_be9d0eca0b19fb93d4eb74b327 | CREATE INDEX "IDX_be9d0eca0b19fb93d4eb74b327" ON "instance_ai_checkpoints" ("resourceId") | +| sqlite_autoindex_instance_ai_checkpoints_1 | PRIMARY KEY (key) | + +## Relations + +```mermaid +erDiagram + +"instance_ai_pending_confirmations" }o--o| "instance_ai_checkpoints" : "FOREIGN KEY (checkpointKey) REFERENCES instance_ai_checkpoints (key) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"instance_ai_checkpoints" }o--|| "instance_ai_threads" : "FOREIGN KEY (threadId) REFERENCES instance_ai_threads (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" + +"instance_ai_checkpoints" { + datetime_3_ createdAt + datetime_3_ expiredAt + varchar_255_ key PK + varchar_255_ resourceId + varchar_255_ runId + TEXT state + varchar threadId FK + datetime_3_ updatedAt +} +"instance_ai_pending_confirmations" { + varchar_255_ checkpointKey FK + varchar_36_ checkpointTaskId + datetime_3_ createdAt + datetime_3_ expiresAt + varchar_16_ kind + varchar_36_ messageGroupId + varchar_36_ requestId PK + varchar_36_ runId + varchar threadId FK + varchar_64_ toolCallId + datetime_3_ updatedAt + varchar userId FK +} +"instance_ai_threads" { + datetime_3_ createdAt + varchar id PK + TEXT metadata + varchar_36_ projectId FK + varchar_255_ resourceId + TEXT title + datetime_3_ updatedAt +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/sqlite-schema/instance_ai_iteration_logs.md b/docs/generated/sqlite-schema/instance_ai_iteration_logs.md new file mode 100644 index 00000000000..3200a4a4ed8 --- /dev/null +++ b/docs/generated/sqlite-schema/instance_ai_iteration_logs.md @@ -0,0 +1,68 @@ +# instance_ai_iteration_logs + +## Description + +<details> +<summary><strong>Table Definition</strong></summary> + +```sql +CREATE TABLE "instance_ai_iteration_logs" ("id" varchar(36) PRIMARY KEY NOT NULL, "threadId" varchar NOT NULL, "taskKey" varchar NOT NULL, "entry" 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_8bfcc6c51fd3d69b1eae8aebd49" FOREIGN KEY ("threadId") REFERENCES "instance_ai_threads" ("id") ON DELETE CASCADE) +``` + +</details> + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| createdAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | +| entry | TEXT | | false | | | | +| id | varchar(36) | | false | | | | +| taskKey | varchar | | false | | | | +| threadId | varchar | | false | | [instance_ai_threads](instance_ai_threads.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 (threadId) REFERENCES instance_ai_threads (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| id | PRIMARY KEY | PRIMARY KEY (id) | +| sqlite_autoindex_instance_ai_iteration_logs_1 | PRIMARY KEY | PRIMARY KEY (id) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_02751202c9a2ad75f2d8e14f5e | CREATE INDEX "IDX_02751202c9a2ad75f2d8e14f5e" ON "instance_ai_iteration_logs" ("threadId", "taskKey", "createdAt") | +| sqlite_autoindex_instance_ai_iteration_logs_1 | PRIMARY KEY (id) | + +## Relations + +```mermaid +erDiagram + +"instance_ai_iteration_logs" }o--|| "instance_ai_threads" : "FOREIGN KEY (threadId) REFERENCES instance_ai_threads (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" + +"instance_ai_iteration_logs" { + datetime_3_ createdAt + TEXT entry + varchar_36_ id PK + varchar taskKey + varchar threadId FK + datetime_3_ updatedAt +} +"instance_ai_threads" { + datetime_3_ createdAt + varchar id PK + TEXT metadata + varchar_36_ projectId FK + varchar_255_ resourceId + TEXT title + datetime_3_ updatedAt +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/sqlite-schema/instance_ai_mcp_registry_connections.md b/docs/generated/sqlite-schema/instance_ai_mcp_registry_connections.md new file mode 100644 index 00000000000..35b836acce0 --- /dev/null +++ b/docs/generated/sqlite-schema/instance_ai_mcp_registry_connections.md @@ -0,0 +1,104 @@ +# instance_ai_mcp_registry_connections + +## Description + +<details> +<summary><strong>Table Definition</strong></summary> + +```sql +CREATE TABLE "instance_ai_mcp_registry_connections" ("id" varchar PRIMARY KEY NOT NULL, "credentialId" varchar(36) NOT NULL, "serverSlug" varchar(255) NOT NULL, "toolFilter" text, "userId" varchar 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_1e826120e7e53ebc4681f026de8" FOREIGN KEY ("credentialId") REFERENCES "credentials_entity" ("id") ON DELETE CASCADE, CONSTRAINT "FK_1d25707354d2012da256eb2ec0a" FOREIGN KEY ("serverSlug") REFERENCES "mcp_registry_server" ("slug") ON DELETE CASCADE, CONSTRAINT "FK_8b42c08a531d76410980c639a5b" FOREIGN KEY ("userId") REFERENCES "user" ("id") ON DELETE CASCADE) +``` + +</details> + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| createdAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | +| credentialId | varchar(36) | | false | | [credentials_entity](credentials_entity.md) | | +| id | varchar | | false | | | | +| serverSlug | varchar(255) | | false | | [mcp_registry_server](mcp_registry_server.md) | | +| toolFilter | TEXT | | true | | | | +| updatedAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | +| userId | varchar | | false | | [user](user.md) | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| - (Foreign key ID: 0) | FOREIGN KEY | FOREIGN KEY (userId) REFERENCES user (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| - (Foreign key ID: 1) | FOREIGN KEY | FOREIGN KEY (serverSlug) REFERENCES mcp_registry_server (slug) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| - (Foreign key ID: 2) | FOREIGN KEY | FOREIGN KEY (credentialId) REFERENCES credentials_entity (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| id | PRIMARY KEY | PRIMARY KEY (id) | +| sqlite_autoindex_instance_ai_mcp_registry_connections_1 | PRIMARY KEY | PRIMARY KEY (id) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_16db3adb7b19df1ee55ff06b27 | CREATE UNIQUE INDEX "IDX_16db3adb7b19df1ee55ff06b27" ON "instance_ai_mcp_registry_connections" ("userId", "serverSlug", "credentialId") | +| sqlite_autoindex_instance_ai_mcp_registry_connections_1 | PRIMARY KEY (id) | + +## Relations + +```mermaid +erDiagram + +"instance_ai_mcp_registry_connections" }o--|| "credentials_entity" : "FOREIGN KEY (credentialId) REFERENCES credentials_entity (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"instance_ai_mcp_registry_connections" }o--|| "mcp_registry_server" : "FOREIGN KEY (serverSlug) REFERENCES mcp_registry_server (slug) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"instance_ai_mcp_registry_connections" }o--|| "user" : "FOREIGN KEY (userId) REFERENCES user (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" + +"instance_ai_mcp_registry_connections" { + datetime_3_ createdAt + varchar_36_ credentialId FK + varchar id PK + varchar_255_ serverSlug FK + TEXT toolFilter + datetime_3_ updatedAt + varchar userId FK +} +"credentials_entity" { + datetime_3_ createdAt + TEXT data + varchar_36_ id PK + boolean isGlobal + boolean isManaged + boolean isResolvable + varchar_128_ name + boolean resolvableAllowFallback + varchar_16_ resolverId FK + varchar_32_ type + datetime_3_ updatedAt +} +"mcp_registry_server" { + datetime_3_ createdAt + TEXT data + datetime_3_ registryUpdatedAt + varchar_255_ slug PK + varchar_50_ status + datetime_3_ updatedAt + varchar_50_ 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 +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/sqlite-schema/instance_ai_messages.md b/docs/generated/sqlite-schema/instance_ai_messages.md new file mode 100644 index 00000000000..da85559999f --- /dev/null +++ b/docs/generated/sqlite-schema/instance_ai_messages.md @@ -0,0 +1,73 @@ +# instance_ai_messages + +## Description + +<details> +<summary><strong>Table Definition</strong></summary> + +```sql +CREATE TABLE "instance_ai_messages" ("id" varchar(36) PRIMARY KEY NOT NULL, "threadId" varchar NOT NULL, "content" text NOT NULL, "role" varchar(16) NOT NULL, "type" varchar(32), "resourceId" varchar(255), "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_1eeb64cb9d66a927988de759e6e" FOREIGN KEY ("threadId") REFERENCES "instance_ai_threads" ("id") ON DELETE CASCADE) +``` + +</details> + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| content | TEXT | | false | | | | +| createdAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | +| id | varchar(36) | | false | | | | +| resourceId | varchar(255) | | true | | | | +| role | varchar(16) | | false | | | | +| threadId | varchar | | false | | [instance_ai_threads](instance_ai_threads.md) | | +| type | varchar(32) | | true | | | | +| updatedAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| - (Foreign key ID: 0) | FOREIGN KEY | FOREIGN KEY (threadId) REFERENCES instance_ai_threads (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| id | PRIMARY KEY | PRIMARY KEY (id) | +| sqlite_autoindex_instance_ai_messages_1 | PRIMARY KEY | PRIMARY KEY (id) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_1eeb64cb9d66a927988de759e6 | CREATE INDEX "IDX_1eeb64cb9d66a927988de759e6" ON "instance_ai_messages" ("threadId") | +| IDX_76e212c6867fbaa06bf0decd6f | CREATE INDEX "IDX_76e212c6867fbaa06bf0decd6f" ON "instance_ai_messages" ("resourceId") | +| sqlite_autoindex_instance_ai_messages_1 | PRIMARY KEY (id) | + +## Relations + +```mermaid +erDiagram + +"instance_ai_messages" }o--|| "instance_ai_threads" : "FOREIGN KEY (threadId) REFERENCES instance_ai_threads (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" + +"instance_ai_messages" { + TEXT content + datetime_3_ createdAt + varchar_36_ id PK + varchar_255_ resourceId + varchar_16_ role + varchar threadId FK + varchar_32_ type + datetime_3_ updatedAt +} +"instance_ai_threads" { + datetime_3_ createdAt + varchar id PK + TEXT metadata + varchar_36_ projectId FK + varchar_255_ resourceId + TEXT title + datetime_3_ updatedAt +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/sqlite-schema/instance_ai_observation_cursors.md b/docs/generated/sqlite-schema/instance_ai_observation_cursors.md new file mode 100644 index 00000000000..ec509059190 --- /dev/null +++ b/docs/generated/sqlite-schema/instance_ai_observation_cursors.md @@ -0,0 +1,65 @@ +# instance_ai_observation_cursors + +## Description + +<details> +<summary><strong>Table Definition</strong></summary> + +```sql +CREATE TABLE "instance_ai_observation_cursors" ("observationScopeId" varchar PRIMARY KEY NOT NULL, "lastObservedMessageId" varchar(36) NOT NULL, "lastObservedAt" datetime(3) 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_5b6319b2e9a37c1064a72428f9a" FOREIGN KEY ("observationScopeId") REFERENCES "instance_ai_threads" ("id") ON DELETE CASCADE) +``` + +</details> + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| createdAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | +| lastObservedAt | datetime(3) | | false | | | | +| lastObservedMessageId | varchar(36) | | false | | | | +| observationScopeId | varchar | | false | | [instance_ai_threads](instance_ai_threads.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 (observationScopeId) REFERENCES instance_ai_threads (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| observationScopeId | PRIMARY KEY | PRIMARY KEY (observationScopeId) | +| sqlite_autoindex_instance_ai_observation_cursors_1 | PRIMARY KEY | PRIMARY KEY (observationScopeId) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| sqlite_autoindex_instance_ai_observation_cursors_1 | PRIMARY KEY (observationScopeId) | + +## Relations + +```mermaid +erDiagram + +"instance_ai_observation_cursors" |o--|| "instance_ai_threads" : "FOREIGN KEY (observationScopeId) REFERENCES instance_ai_threads (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" + +"instance_ai_observation_cursors" { + datetime_3_ createdAt + datetime_3_ lastObservedAt + varchar_36_ lastObservedMessageId + varchar observationScopeId PK + datetime_3_ updatedAt +} +"instance_ai_threads" { + datetime_3_ createdAt + varchar id PK + TEXT metadata + varchar_36_ projectId FK + varchar_255_ resourceId + TEXT title + datetime_3_ updatedAt +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/sqlite-schema/instance_ai_observation_locks.md b/docs/generated/sqlite-schema/instance_ai_observation_locks.md new file mode 100644 index 00000000000..198ae078192 --- /dev/null +++ b/docs/generated/sqlite-schema/instance_ai_observation_locks.md @@ -0,0 +1,69 @@ +# instance_ai_observation_locks + +## Description + +<details> +<summary><strong>Table Definition</strong></summary> + +```sql +CREATE TABLE "instance_ai_observation_locks" ("observationScopeId" varchar NOT NULL, "taskKind" varchar(20) NOT NULL, "holderId" varchar(64) NOT NULL, "heldUntil" datetime(3) 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 "CHK_instance_ai_observation_locks_taskKind" CHECK ("taskKind" IN ('observer', 'reflector')), CONSTRAINT "FK_103e2e5f454860b28ea05a82c74" FOREIGN KEY ("observationScopeId") REFERENCES "instance_ai_threads" ("id") ON DELETE CASCADE, PRIMARY KEY ("observationScopeId", "taskKind")) +``` + +</details> + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| createdAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | +| heldUntil | datetime(3) | | false | | | | +| holderId | varchar(64) | | false | | | | +| observationScopeId | varchar | | false | | [instance_ai_threads](instance_ai_threads.md) | | +| taskKind | varchar(20) | | false | | | | +| updatedAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| - | CHECK | CHECK ("taskKind" IN ('observer', 'reflector')) | +| - (Foreign key ID: 0) | FOREIGN KEY | FOREIGN KEY (observationScopeId) REFERENCES instance_ai_threads (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| observationScopeId | PRIMARY KEY | PRIMARY KEY (observationScopeId) | +| sqlite_autoindex_instance_ai_observation_locks_1 | PRIMARY KEY | PRIMARY KEY (observationScopeId, taskKind) | +| taskKind | PRIMARY KEY | PRIMARY KEY (taskKind) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| sqlite_autoindex_instance_ai_observation_locks_1 | PRIMARY KEY (observationScopeId, taskKind) | + +## Relations + +```mermaid +erDiagram + +"instance_ai_observation_locks" |o--|| "instance_ai_threads" : "FOREIGN KEY (observationScopeId) REFERENCES instance_ai_threads (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" + +"instance_ai_observation_locks" { + datetime_3_ createdAt + datetime_3_ heldUntil + varchar_64_ holderId + varchar observationScopeId PK + varchar_20_ taskKind PK + datetime_3_ updatedAt +} +"instance_ai_threads" { + datetime_3_ createdAt + varchar id PK + TEXT metadata + varchar_36_ projectId FK + varchar_255_ resourceId + TEXT title + datetime_3_ updatedAt +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/sqlite-schema/instance_ai_observational_memory.md b/docs/generated/sqlite-schema/instance_ai_observational_memory.md new file mode 100644 index 00000000000..f4d64b5370e --- /dev/null +++ b/docs/generated/sqlite-schema/instance_ai_observational_memory.md @@ -0,0 +1,121 @@ +# instance_ai_observational_memory + +## Description + +<details> +<summary><strong>Table Definition</strong></summary> + +```sql +CREATE TABLE "instance_ai_observational_memory" ("id" varchar(36) PRIMARY KEY NOT NULL, "lookupKey" varchar(255) NOT NULL, "scope" varchar(16) NOT NULL, "threadId" varchar, "resourceId" varchar(255) NOT NULL, "activeObservations" text NOT NULL DEFAULT (''), "originType" varchar(32) NOT NULL, "config" text NOT NULL, "generationCount" integer NOT NULL DEFAULT (0), "lastObservedAt" datetime(3), "pendingMessageTokens" integer NOT NULL DEFAULT (0), "totalTokensObserved" integer NOT NULL DEFAULT (0), "observationTokenCount" integer NOT NULL DEFAULT (0), "isObserving" boolean NOT NULL DEFAULT (false), "isReflecting" boolean NOT NULL DEFAULT (false), "observedMessageIds" text, "observedTimezone" varchar, "bufferedObservations" text, "bufferedObservationTokens" integer, "bufferedMessageIds" text, "bufferedReflection" text, "bufferedReflectionTokens" integer, "bufferedReflectionInputTokens" integer, "reflectedObservationLineCount" integer, "bufferedObservationChunks" text, "isBufferingObservation" boolean NOT NULL DEFAULT (false), "isBufferingReflection" boolean NOT NULL DEFAULT (false), "lastBufferedAtTokens" integer NOT NULL DEFAULT (0), "lastBufferedAtTime" datetime(3), "metadata" text, "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_34018c303885cd37093458e6409" FOREIGN KEY ("threadId") REFERENCES "instance_ai_threads" ("id") ON DELETE SET NULL) +``` + +</details> + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| activeObservations | TEXT | '' | false | | | | +| bufferedMessageIds | TEXT | | true | | | | +| bufferedObservationChunks | TEXT | | true | | | | +| bufferedObservationTokens | INTEGER | | true | | | | +| bufferedObservations | TEXT | | true | | | | +| bufferedReflection | TEXT | | true | | | | +| bufferedReflectionInputTokens | INTEGER | | true | | | | +| bufferedReflectionTokens | INTEGER | | true | | | | +| config | TEXT | | false | | | | +| createdAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | +| generationCount | INTEGER | 0 | false | | | | +| id | varchar(36) | | false | | | | +| isBufferingObservation | boolean | false | false | | | | +| isBufferingReflection | boolean | false | false | | | | +| isObserving | boolean | false | false | | | | +| isReflecting | boolean | false | false | | | | +| lastBufferedAtTime | datetime(3) | | true | | | | +| lastBufferedAtTokens | INTEGER | 0 | false | | | | +| lastObservedAt | datetime(3) | | true | | | | +| lookupKey | varchar(255) | | false | | | | +| metadata | TEXT | | true | | | | +| observationTokenCount | INTEGER | 0 | false | | | | +| observedMessageIds | TEXT | | true | | | | +| observedTimezone | varchar | | true | | | | +| originType | varchar(32) | | false | | | | +| pendingMessageTokens | INTEGER | 0 | false | | | | +| reflectedObservationLineCount | INTEGER | | true | | | | +| resourceId | varchar(255) | | false | | | | +| scope | varchar(16) | | false | | | | +| threadId | varchar | | true | | [instance_ai_threads](instance_ai_threads.md) | | +| totalTokensObserved | INTEGER | 0 | false | | | | +| updatedAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| - (Foreign key ID: 0) | FOREIGN KEY | FOREIGN KEY (threadId) REFERENCES instance_ai_threads (id) ON UPDATE NO ACTION ON DELETE SET NULL MATCH NONE | +| id | PRIMARY KEY | PRIMARY KEY (id) | +| sqlite_autoindex_instance_ai_observational_memory_1 | PRIMARY KEY | PRIMARY KEY (id) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_92f13cb6bc694227e069447f7b | CREATE INDEX "IDX_92f13cb6bc694227e069447f7b" ON "instance_ai_observational_memory" ("lookupKey") | +| IDX_a680ac96aae02dc887bbaac512 | CREATE UNIQUE INDEX "IDX_a680ac96aae02dc887bbaac512" ON "instance_ai_observational_memory" ("scope", "threadId", "resourceId") | +| sqlite_autoindex_instance_ai_observational_memory_1 | PRIMARY KEY (id) | + +## Relations + +```mermaid +erDiagram + +"instance_ai_observational_memory" }o--o| "instance_ai_threads" : "FOREIGN KEY (threadId) REFERENCES instance_ai_threads (id) ON UPDATE NO ACTION ON DELETE SET NULL MATCH NONE" + +"instance_ai_observational_memory" { + TEXT activeObservations + TEXT bufferedMessageIds + TEXT bufferedObservationChunks + INTEGER bufferedObservationTokens + TEXT bufferedObservations + TEXT bufferedReflection + INTEGER bufferedReflectionInputTokens + INTEGER bufferedReflectionTokens + TEXT config + datetime_3_ createdAt + INTEGER generationCount + varchar_36_ id PK + boolean isBufferingObservation + boolean isBufferingReflection + boolean isObserving + boolean isReflecting + datetime_3_ lastBufferedAtTime + INTEGER lastBufferedAtTokens + datetime_3_ lastObservedAt + varchar_255_ lookupKey + TEXT metadata + INTEGER observationTokenCount + TEXT observedMessageIds + varchar observedTimezone + varchar_32_ originType + INTEGER pendingMessageTokens + INTEGER reflectedObservationLineCount + varchar_255_ resourceId + varchar_16_ scope + varchar threadId FK + INTEGER totalTokensObserved + datetime_3_ updatedAt +} +"instance_ai_threads" { + datetime_3_ createdAt + varchar id PK + TEXT metadata + varchar_36_ projectId FK + varchar_255_ resourceId + TEXT title + datetime_3_ updatedAt +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/sqlite-schema/instance_ai_observations.md b/docs/generated/sqlite-schema/instance_ai_observations.md new file mode 100644 index 00000000000..ab4a4c77b68 --- /dev/null +++ b/docs/generated/sqlite-schema/instance_ai_observations.md @@ -0,0 +1,84 @@ +# instance_ai_observations + +## Description + +<details> +<summary><strong>Table Definition</strong></summary> + +```sql +CREATE TABLE "instance_ai_observations" ("id" varchar(36) PRIMARY KEY NOT NULL, "observationScopeId" varchar NOT NULL, "marker" varchar(16) NOT NULL, "text" text NOT NULL, "parentId" varchar(36), "tokenCount" integer NOT NULL DEFAULT (0), "status" varchar(16) NOT NULL, "supersededBy" varchar(36), "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_instance_ai_observations_marker" CHECK ("marker" IN ('critical', 'important', 'info', 'completion')), CONSTRAINT "CHK_instance_ai_observations_status" CHECK ("status" IN ('active', 'superseded', 'dropped')), CONSTRAINT "FK_d54fc84a6c8ac91b5e0db0378a4" FOREIGN KEY ("observationScopeId") REFERENCES "instance_ai_threads" ("id") ON DELETE CASCADE, CONSTRAINT "FK_daef2195a4a846eb70eed15e039" FOREIGN KEY ("parentId") REFERENCES "instance_ai_observations" ("id"), CONSTRAINT "FK_a80e0ee839a2f10ba4b86e19998" FOREIGN KEY ("supersededBy") REFERENCES "instance_ai_observations" ("id")) +``` + +</details> + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| createdAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | +| id | varchar(36) | | false | [instance_ai_observations](instance_ai_observations.md) | | | +| marker | varchar(16) | | false | | | | +| observationScopeId | varchar | | false | | [instance_ai_threads](instance_ai_threads.md) | | +| parentId | varchar(36) | | true | | [instance_ai_observations](instance_ai_observations.md) | | +| status | varchar(16) | | false | | | | +| supersededBy | varchar(36) | | true | | [instance_ai_observations](instance_ai_observations.md) | | +| text | TEXT | | false | | | | +| tokenCount | INTEGER | 0 | false | | | | +| updatedAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| - | CHECK | CHECK ("marker" IN ('critical', 'important', 'info', 'completion')) | +| - | CHECK | CHECK ("status" IN ('active', 'superseded', 'dropped')) | +| - (Foreign key ID: 0) | FOREIGN KEY | FOREIGN KEY (supersededBy) REFERENCES instance_ai_observations (id) ON UPDATE NO ACTION ON DELETE NO ACTION MATCH NONE | +| - (Foreign key ID: 1) | FOREIGN KEY | FOREIGN KEY (parentId) REFERENCES instance_ai_observations (id) ON UPDATE NO ACTION ON DELETE NO ACTION MATCH NONE | +| - (Foreign key ID: 2) | FOREIGN KEY | FOREIGN KEY (observationScopeId) REFERENCES instance_ai_threads (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| id | PRIMARY KEY | PRIMARY KEY (id) | +| sqlite_autoindex_instance_ai_observations_1 | PRIMARY KEY | PRIMARY KEY (id) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_0d5db648188d338df7fb2a8064 | CREATE INDEX "IDX_0d5db648188d338df7fb2a8064" ON "instance_ai_observations" ("observationScopeId", "status", "createdAt", "id") | +| IDX_a80e0ee839a2f10ba4b86e1999 | CREATE INDEX "IDX_a80e0ee839a2f10ba4b86e1999" ON "instance_ai_observations" ("supersededBy") | +| IDX_daef2195a4a846eb70eed15e03 | CREATE INDEX "IDX_daef2195a4a846eb70eed15e03" ON "instance_ai_observations" ("parentId") | +| sqlite_autoindex_instance_ai_observations_1 | PRIMARY KEY (id) | + +## Relations + +```mermaid +erDiagram + +"instance_ai_observations" }o--o| "instance_ai_observations" : "FOREIGN KEY (supersededBy) REFERENCES instance_ai_observations (id) ON UPDATE NO ACTION ON DELETE NO ACTION MATCH NONE" +"instance_ai_observations" }o--o| "instance_ai_observations" : "FOREIGN KEY (parentId) REFERENCES instance_ai_observations (id) ON UPDATE NO ACTION ON DELETE NO ACTION MATCH NONE" +"instance_ai_observations" }o--|| "instance_ai_threads" : "FOREIGN KEY (observationScopeId) REFERENCES instance_ai_threads (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" + +"instance_ai_observations" { + datetime_3_ createdAt + varchar_36_ id PK + varchar_16_ marker + varchar observationScopeId FK + varchar_36_ parentId FK + varchar_16_ status + varchar_36_ supersededBy FK + TEXT text + INTEGER tokenCount + datetime_3_ updatedAt +} +"instance_ai_threads" { + datetime_3_ createdAt + varchar id PK + TEXT metadata + varchar_36_ projectId FK + varchar_255_ resourceId + TEXT title + datetime_3_ updatedAt +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/sqlite-schema/instance_ai_pending_confirmations.md b/docs/generated/sqlite-schema/instance_ai_pending_confirmations.md new file mode 100644 index 00000000000..af0c868e2a2 --- /dev/null +++ b/docs/generated/sqlite-schema/instance_ai_pending_confirmations.md @@ -0,0 +1,115 @@ +# instance_ai_pending_confirmations + +## Description + +<details> +<summary><strong>Table Definition</strong></summary> + +```sql +CREATE TABLE "instance_ai_pending_confirmations" ("requestId" varchar(36) PRIMARY KEY NOT NULL, "threadId" varchar NOT NULL, "userId" varchar NOT NULL, "kind" varchar(16) NOT NULL, "runId" varchar(36) NOT NULL, "toolCallId" varchar(64), "messageGroupId" varchar(36), "checkpointKey" varchar(255), "checkpointTaskId" varchar(36), "expiresAt" datetime(3), "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_instance_ai_pending_confirmations_kind" CHECK ("kind" IN ('suspended', 'inline')), CONSTRAINT "FK_ba67ee8dc311830a2eea89b6e96" FOREIGN KEY ("threadId") REFERENCES "instance_ai_threads" ("id") ON DELETE CASCADE, CONSTRAINT "FK_df5fd25c8bbfd2b042602600d8e" FOREIGN KEY ("userId") REFERENCES "user" ("id") ON DELETE CASCADE, CONSTRAINT "FK_0babdf6e3b897a86fe4678355eb" FOREIGN KEY ("checkpointKey") REFERENCES "instance_ai_checkpoints" ("key") ON DELETE CASCADE) +``` + +</details> + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| checkpointKey | varchar(255) | | true | | [instance_ai_checkpoints](instance_ai_checkpoints.md) | | +| checkpointTaskId | varchar(36) | | true | | | | +| createdAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | +| expiresAt | datetime(3) | | true | | | | +| kind | varchar(16) | | false | | | | +| messageGroupId | varchar(36) | | true | | | | +| requestId | varchar(36) | | false | | | | +| runId | varchar(36) | | false | | | | +| threadId | varchar | | false | | [instance_ai_threads](instance_ai_threads.md) | | +| toolCallId | varchar(64) | | true | | | | +| updatedAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | +| userId | varchar | | false | | [user](user.md) | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| - | CHECK | CHECK ("kind" IN ('suspended', 'inline')) | +| - (Foreign key ID: 0) | FOREIGN KEY | FOREIGN KEY (checkpointKey) REFERENCES instance_ai_checkpoints (key) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| - (Foreign key ID: 1) | FOREIGN KEY | FOREIGN KEY (userId) REFERENCES user (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| - (Foreign key ID: 2) | FOREIGN KEY | FOREIGN KEY (threadId) REFERENCES instance_ai_threads (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| requestId | PRIMARY KEY | PRIMARY KEY (requestId) | +| sqlite_autoindex_instance_ai_pending_confirmations_1 | PRIMARY KEY | PRIMARY KEY (requestId) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_0babdf6e3b897a86fe4678355e | CREATE INDEX "IDX_0babdf6e3b897a86fe4678355e" ON "instance_ai_pending_confirmations" ("checkpointKey") | +| IDX_ba67ee8dc311830a2eea89b6e9 | CREATE INDEX "IDX_ba67ee8dc311830a2eea89b6e9" ON "instance_ai_pending_confirmations" ("threadId") | +| IDX_d7a4aba7440449865e2b924377 | CREATE INDEX "IDX_d7a4aba7440449865e2b924377" ON "instance_ai_pending_confirmations" ("expiresAt") | +| IDX_df5fd25c8bbfd2b042602600d8 | CREATE INDEX "IDX_df5fd25c8bbfd2b042602600d8" ON "instance_ai_pending_confirmations" ("userId") | +| sqlite_autoindex_instance_ai_pending_confirmations_1 | PRIMARY KEY (requestId) | + +## Relations + +```mermaid +erDiagram + +"instance_ai_pending_confirmations" }o--o| "instance_ai_checkpoints" : "FOREIGN KEY (checkpointKey) REFERENCES instance_ai_checkpoints (key) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"instance_ai_pending_confirmations" }o--|| "instance_ai_threads" : "FOREIGN KEY (threadId) REFERENCES instance_ai_threads (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"instance_ai_pending_confirmations" }o--|| "user" : "FOREIGN KEY (userId) REFERENCES user (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" + +"instance_ai_pending_confirmations" { + varchar_255_ checkpointKey FK + varchar_36_ checkpointTaskId + datetime_3_ createdAt + datetime_3_ expiresAt + varchar_16_ kind + varchar_36_ messageGroupId + varchar_36_ requestId PK + varchar_36_ runId + varchar threadId FK + varchar_64_ toolCallId + datetime_3_ updatedAt + varchar userId FK +} +"instance_ai_checkpoints" { + datetime_3_ createdAt + datetime_3_ expiredAt + varchar_255_ key PK + varchar_255_ resourceId + varchar_255_ runId + TEXT state + varchar threadId FK + datetime_3_ updatedAt +} +"instance_ai_threads" { + datetime_3_ createdAt + varchar id PK + TEXT metadata + varchar_36_ projectId FK + varchar_255_ resourceId + TEXT title + datetime_3_ updatedAt +} +"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 +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/sqlite-schema/instance_ai_resources.md b/docs/generated/sqlite-schema/instance_ai_resources.md new file mode 100644 index 00000000000..661f893e8ec --- /dev/null +++ b/docs/generated/sqlite-schema/instance_ai_resources.md @@ -0,0 +1,54 @@ +# instance_ai_resources + +## Description + +<details> +<summary><strong>Table Definition</strong></summary> + +```sql +CREATE TABLE "instance_ai_resources" ("id" varchar(255) PRIMARY KEY NOT NULL, "workingMemory" text, "metadata" text, "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'))) +``` + +</details> + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| createdAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | +| id | varchar(255) | | false | | | | +| metadata | TEXT | | true | | | | +| updatedAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | +| workingMemory | TEXT | | true | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| id | PRIMARY KEY | PRIMARY KEY (id) | +| sqlite_autoindex_instance_ai_resources_1 | PRIMARY KEY | PRIMARY KEY (id) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| sqlite_autoindex_instance_ai_resources_1 | PRIMARY KEY (id) | + +## Relations + +```mermaid +erDiagram + + +"instance_ai_resources" { + datetime_3_ createdAt + varchar_255_ id PK + TEXT metadata + datetime_3_ updatedAt + TEXT workingMemory +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/sqlite-schema/instance_ai_run_snapshots.md b/docs/generated/sqlite-schema/instance_ai_run_snapshots.md new file mode 100644 index 00000000000..b0296d14fa2 --- /dev/null +++ b/docs/generated/sqlite-schema/instance_ai_run_snapshots.md @@ -0,0 +1,80 @@ +# instance_ai_run_snapshots + +## Description + +<details> +<summary><strong>Table Definition</strong></summary> + +```sql +CREATE TABLE "instance_ai_run_snapshots" ("threadId" varchar NOT NULL, "runId" varchar(36) NOT NULL, "messageGroupId" varchar(36), "runIds" text, "tree" 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')), "langsmithRunId" varchar(36), "langsmithTraceId" varchar(36), "traceId" varchar(64), "spanId" varchar(64), CONSTRAINT "FK_2f63fa21d09d7918f347ddbdf70" FOREIGN KEY ("threadId") REFERENCES "instance_ai_threads" ("id") ON DELETE CASCADE ON UPDATE NO ACTION, PRIMARY KEY ("threadId", "runId")) +``` + +</details> + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| createdAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | +| langsmithRunId | varchar(36) | | true | | | | +| langsmithTraceId | varchar(36) | | true | | | | +| messageGroupId | varchar(36) | | true | | | | +| runId | varchar(36) | | false | | | | +| runIds | TEXT | | true | | | | +| spanId | varchar(64) | | true | | | | +| threadId | varchar | | false | | [instance_ai_threads](instance_ai_threads.md) | | +| traceId | varchar(64) | | true | | | | +| tree | TEXT | | false | | | | +| updatedAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| - (Foreign key ID: 0) | FOREIGN KEY | FOREIGN KEY (threadId) REFERENCES instance_ai_threads (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| runId | PRIMARY KEY | PRIMARY KEY (runId) | +| sqlite_autoindex_instance_ai_run_snapshots_1 | PRIMARY KEY | PRIMARY KEY (threadId, runId) | +| threadId | PRIMARY KEY | PRIMARY KEY (threadId) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_d3a2bc880e7a8626802e5474ad | CREATE INDEX "IDX_d3a2bc880e7a8626802e5474ad" ON "instance_ai_run_snapshots" ("threadId", "createdAt") | +| IDX_d926c16c2ad9728cb9a81790c0 | CREATE INDEX "IDX_d926c16c2ad9728cb9a81790c0" ON "instance_ai_run_snapshots" ("threadId", "messageGroupId") | +| sqlite_autoindex_instance_ai_run_snapshots_1 | PRIMARY KEY (threadId, runId) | + +## Relations + +```mermaid +erDiagram + +"instance_ai_run_snapshots" |o--|| "instance_ai_threads" : "FOREIGN KEY (threadId) REFERENCES instance_ai_threads (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" + +"instance_ai_run_snapshots" { + datetime_3_ createdAt + varchar_36_ langsmithRunId + varchar_36_ langsmithTraceId + varchar_36_ messageGroupId + varchar_36_ runId PK + TEXT runIds + varchar_64_ spanId + varchar threadId PK + varchar_64_ traceId + TEXT tree + datetime_3_ updatedAt +} +"instance_ai_threads" { + datetime_3_ createdAt + varchar id PK + TEXT metadata + varchar_36_ projectId FK + varchar_255_ resourceId + TEXT title + datetime_3_ updatedAt +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/sqlite-schema/instance_ai_threads.md b/docs/generated/sqlite-schema/instance_ai_threads.md new file mode 100644 index 00000000000..e6b321e4a5f --- /dev/null +++ b/docs/generated/sqlite-schema/instance_ai_threads.md @@ -0,0 +1,205 @@ +# instance_ai_threads + +## Description + +<details> +<summary><strong>Table Definition</strong></summary> + +```sql +CREATE TABLE "instance_ai_threads" ("id" varchar PRIMARY KEY NOT NULL, "resourceId" varchar(255) NOT NULL, "projectId" varchar(36) NOT NULL, "title" text NOT NULL DEFAULT (''), "metadata" text, "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_instance_ai_threads_projectId" FOREIGN KEY ("projectId") REFERENCES "project" ("id") ON DELETE CASCADE) +``` + +</details> + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| createdAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | +| id | varchar | | false | [ai_builder_temporary_workflow](ai_builder_temporary_workflow.md) [instance_ai_checkpoints](instance_ai_checkpoints.md) [instance_ai_iteration_logs](instance_ai_iteration_logs.md) [instance_ai_messages](instance_ai_messages.md) [instance_ai_observation_cursors](instance_ai_observation_cursors.md) [instance_ai_observation_locks](instance_ai_observation_locks.md) [instance_ai_observational_memory](instance_ai_observational_memory.md) [instance_ai_observations](instance_ai_observations.md) [instance_ai_pending_confirmations](instance_ai_pending_confirmations.md) [instance_ai_run_snapshots](instance_ai_run_snapshots.md) | | | +| metadata | TEXT | | true | | | | +| projectId | varchar(36) | | false | | [project](project.md) | | +| resourceId | varchar(255) | | false | | | | +| title | TEXT | '' | false | | | | +| updatedAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| - (Foreign key ID: 0) | 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_instance_ai_threads_1 | PRIMARY KEY | PRIMARY KEY (id) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_instance_ai_threads_projectId | CREATE INDEX "IDX_instance_ai_threads_projectId" ON "instance_ai_threads" ("projectId") | +| IDX_instance_ai_threads_resourceId | CREATE INDEX "IDX_instance_ai_threads_resourceId" ON "instance_ai_threads" ("resourceId") | +| sqlite_autoindex_instance_ai_threads_1 | PRIMARY KEY (id) | + +## Relations + +```mermaid +erDiagram + +"ai_builder_temporary_workflow" }o--|| "instance_ai_threads" : "FOREIGN KEY (threadId) REFERENCES instance_ai_threads (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"instance_ai_checkpoints" }o--|| "instance_ai_threads" : "FOREIGN KEY (threadId) REFERENCES instance_ai_threads (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"instance_ai_iteration_logs" }o--|| "instance_ai_threads" : "FOREIGN KEY (threadId) REFERENCES instance_ai_threads (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"instance_ai_messages" }o--|| "instance_ai_threads" : "FOREIGN KEY (threadId) REFERENCES instance_ai_threads (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"instance_ai_observation_cursors" |o--|| "instance_ai_threads" : "FOREIGN KEY (observationScopeId) REFERENCES instance_ai_threads (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"instance_ai_observation_locks" |o--|| "instance_ai_threads" : "FOREIGN KEY (observationScopeId) REFERENCES instance_ai_threads (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"instance_ai_observational_memory" }o--o| "instance_ai_threads" : "FOREIGN KEY (threadId) REFERENCES instance_ai_threads (id) ON UPDATE NO ACTION ON DELETE SET NULL MATCH NONE" +"instance_ai_observations" }o--|| "instance_ai_threads" : "FOREIGN KEY (observationScopeId) REFERENCES instance_ai_threads (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"instance_ai_pending_confirmations" }o--|| "instance_ai_threads" : "FOREIGN KEY (threadId) REFERENCES instance_ai_threads (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"instance_ai_run_snapshots" |o--|| "instance_ai_threads" : "FOREIGN KEY (threadId) REFERENCES instance_ai_threads (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"instance_ai_threads" }o--|| "project" : "FOREIGN KEY (projectId) REFERENCES project (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" + +"instance_ai_threads" { + datetime_3_ createdAt + varchar id PK + TEXT metadata + varchar_36_ projectId FK + varchar_255_ resourceId + TEXT title + datetime_3_ updatedAt +} +"ai_builder_temporary_workflow" { + datetime_3_ createdAt + varchar threadId FK + datetime_3_ updatedAt + varchar_36_ workflowId PK +} +"instance_ai_checkpoints" { + datetime_3_ createdAt + datetime_3_ expiredAt + varchar_255_ key PK + varchar_255_ resourceId + varchar_255_ runId + TEXT state + varchar threadId FK + datetime_3_ updatedAt +} +"instance_ai_iteration_logs" { + datetime_3_ createdAt + TEXT entry + varchar_36_ id PK + varchar taskKey + varchar threadId FK + datetime_3_ updatedAt +} +"instance_ai_messages" { + TEXT content + datetime_3_ createdAt + varchar_36_ id PK + varchar_255_ resourceId + varchar_16_ role + varchar threadId FK + varchar_32_ type + datetime_3_ updatedAt +} +"instance_ai_observation_cursors" { + datetime_3_ createdAt + datetime_3_ lastObservedAt + varchar_36_ lastObservedMessageId + varchar observationScopeId PK + datetime_3_ updatedAt +} +"instance_ai_observation_locks" { + datetime_3_ createdAt + datetime_3_ heldUntil + varchar_64_ holderId + varchar observationScopeId PK + varchar_20_ taskKind PK + datetime_3_ updatedAt +} +"instance_ai_observational_memory" { + TEXT activeObservations + TEXT bufferedMessageIds + TEXT bufferedObservationChunks + INTEGER bufferedObservationTokens + TEXT bufferedObservations + TEXT bufferedReflection + INTEGER bufferedReflectionInputTokens + INTEGER bufferedReflectionTokens + TEXT config + datetime_3_ createdAt + INTEGER generationCount + varchar_36_ id PK + boolean isBufferingObservation + boolean isBufferingReflection + boolean isObserving + boolean isReflecting + datetime_3_ lastBufferedAtTime + INTEGER lastBufferedAtTokens + datetime_3_ lastObservedAt + varchar_255_ lookupKey + TEXT metadata + INTEGER observationTokenCount + TEXT observedMessageIds + varchar observedTimezone + varchar_32_ originType + INTEGER pendingMessageTokens + INTEGER reflectedObservationLineCount + varchar_255_ resourceId + varchar_16_ scope + varchar threadId FK + INTEGER totalTokensObserved + datetime_3_ updatedAt +} +"instance_ai_observations" { + datetime_3_ createdAt + varchar_36_ id PK + varchar_16_ marker + varchar observationScopeId FK + varchar_36_ parentId FK + varchar_16_ status + varchar_36_ supersededBy FK + TEXT text + INTEGER tokenCount + datetime_3_ updatedAt +} +"instance_ai_pending_confirmations" { + varchar_255_ checkpointKey FK + varchar_36_ checkpointTaskId + datetime_3_ createdAt + datetime_3_ expiresAt + varchar_16_ kind + varchar_36_ messageGroupId + varchar_36_ requestId PK + varchar_36_ runId + varchar threadId FK + varchar_64_ toolCallId + datetime_3_ updatedAt + varchar userId FK +} +"instance_ai_run_snapshots" { + datetime_3_ createdAt + varchar_36_ langsmithRunId + varchar_36_ langsmithTraceId + varchar_36_ messageGroupId + varchar_36_ runId PK + TEXT runIds + varchar_64_ spanId + varchar threadId PK + varchar_64_ traceId + TEXT tree + datetime_3_ updatedAt +} +"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/instance_ai_workflow_snapshots.md b/docs/generated/sqlite-schema/instance_ai_workflow_snapshots.md new file mode 100644 index 00000000000..0252e891312 --- /dev/null +++ b/docs/generated/sqlite-schema/instance_ai_workflow_snapshots.md @@ -0,0 +1,60 @@ +# instance_ai_workflow_snapshots + +## Description + +<details> +<summary><strong>Table Definition</strong></summary> + +```sql +CREATE TABLE "instance_ai_workflow_snapshots" ("runId" varchar(36) NOT NULL, "workflowName" varchar(255) NOT NULL, "resourceId" varchar(255), "status" varchar, "snapshot" 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')), PRIMARY KEY ("runId", "workflowName")) +``` + +</details> + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| createdAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | +| resourceId | varchar(255) | | true | | | | +| runId | varchar(36) | | false | | | | +| snapshot | TEXT | | false | | | | +| status | varchar | | true | | | | +| updatedAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | +| workflowName | varchar(255) | | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| runId | PRIMARY KEY | PRIMARY KEY (runId) | +| sqlite_autoindex_instance_ai_workflow_snapshots_1 | PRIMARY KEY | PRIMARY KEY (runId, workflowName) | +| workflowName | PRIMARY KEY | PRIMARY KEY (workflowName) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_a371ee6b8e0ebb5635f8baa46d | CREATE INDEX "IDX_a371ee6b8e0ebb5635f8baa46d" ON "instance_ai_workflow_snapshots" ("workflowName", "status") | +| sqlite_autoindex_instance_ai_workflow_snapshots_1 | PRIMARY KEY (runId, workflowName) | + +## Relations + +```mermaid +erDiagram + + +"instance_ai_workflow_snapshots" { + datetime_3_ createdAt + varchar_255_ resourceId + varchar_36_ runId PK + TEXT snapshot + varchar status + datetime_3_ updatedAt + varchar_255_ workflowName PK +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/sqlite-schema/instance_version_history.md b/docs/generated/sqlite-schema/instance_version_history.md new file mode 100644 index 00000000000..8245d42b0ea --- /dev/null +++ b/docs/generated/sqlite-schema/instance_version_history.md @@ -0,0 +1,47 @@ +# instance_version_history + +## Description + +<details> +<summary><strong>Table Definition</strong></summary> + +```sql +CREATE TABLE "instance_version_history" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "major" integer NOT NULL, "minor" integer NOT NULL, "patch" integer NOT NULL, "createdAt" datetime(3) NOT NULL DEFAULT (STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW'))) +``` + +</details> + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| createdAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | +| id | INTEGER | | false | | | | +| major | INTEGER | | false | | | | +| minor | INTEGER | | false | | | | +| patch | INTEGER | | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| id | PRIMARY KEY | PRIMARY KEY (id) | + +## Relations + +```mermaid +erDiagram + + +"instance_version_history" { + datetime_3_ createdAt + INTEGER id + INTEGER major + INTEGER minor + INTEGER patch +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/sqlite-schema/invalid_auth_token.md b/docs/generated/sqlite-schema/invalid_auth_token.md new file mode 100644 index 00000000000..27647341e24 --- /dev/null +++ b/docs/generated/sqlite-schema/invalid_auth_token.md @@ -0,0 +1,48 @@ +# invalid_auth_token + +## Description + +<details> +<summary><strong>Table Definition</strong></summary> + +```sql +CREATE TABLE "invalid_auth_token" ("token" varchar(512) PRIMARY KEY NOT NULL, "expiresAt" datetime(3) NOT NULL) +``` + +</details> + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| expiresAt | datetime(3) | | false | | | | +| token | varchar(512) | | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| sqlite_autoindex_invalid_auth_token_1 | PRIMARY KEY | PRIMARY KEY (token) | +| token | PRIMARY KEY | PRIMARY KEY (token) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| sqlite_autoindex_invalid_auth_token_1 | PRIMARY KEY (token) | + +## Relations + +```mermaid +erDiagram + + +"invalid_auth_token" { + datetime_3_ expiresAt + varchar_512_ token PK +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/sqlite-schema/mcp_registry_server.md b/docs/generated/sqlite-schema/mcp_registry_server.md new file mode 100644 index 00000000000..5083e42d24b --- /dev/null +++ b/docs/generated/sqlite-schema/mcp_registry_server.md @@ -0,0 +1,69 @@ +# mcp_registry_server + +## Description + +<details> +<summary><strong>Table Definition</strong></summary> + +```sql +CREATE TABLE "mcp_registry_server" ("slug" varchar(255) PRIMARY KEY NOT NULL, "status" varchar(50) NOT NULL, "version" varchar(50) NOT NULL, "registryUpdatedAt" datetime(3) NOT NULL, "data" text NOT NULL DEFAULT ('{}'), "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_tmp_mcp_registry_server_status" CHECK ("status" IN ('active', 'deprecated'))) +``` + +</details> + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| createdAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | +| data | TEXT | '{}' | false | | | | +| registryUpdatedAt | datetime(3) | | false | | | | +| slug | varchar(255) | | false | [instance_ai_mcp_registry_connections](instance_ai_mcp_registry_connections.md) | | | +| status | varchar(50) | | false | | | | +| updatedAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | +| version | varchar(50) | | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| - | CHECK | CHECK ("status" IN ('active', 'deprecated')) | +| slug | PRIMARY KEY | PRIMARY KEY (slug) | +| sqlite_autoindex_mcp_registry_server_1 | PRIMARY KEY | PRIMARY KEY (slug) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| sqlite_autoindex_mcp_registry_server_1 | PRIMARY KEY (slug) | + +## Relations + +```mermaid +erDiagram + +"instance_ai_mcp_registry_connections" }o--|| "mcp_registry_server" : "FOREIGN KEY (serverSlug) REFERENCES mcp_registry_server (slug) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" + +"mcp_registry_server" { + datetime_3_ createdAt + TEXT data + datetime_3_ registryUpdatedAt + varchar_255_ slug PK + varchar_50_ status + datetime_3_ updatedAt + varchar_50_ version +} +"instance_ai_mcp_registry_connections" { + datetime_3_ createdAt + varchar_36_ credentialId FK + varchar id PK + varchar_255_ serverSlug FK + TEXT toolFilter + datetime_3_ updatedAt + varchar userId FK +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/sqlite-schema/oauth_access_tokens.md b/docs/generated/sqlite-schema/oauth_access_tokens.md new file mode 100644 index 00000000000..b8e4d97757b --- /dev/null +++ b/docs/generated/sqlite-schema/oauth_access_tokens.md @@ -0,0 +1,82 @@ +# oauth_access_tokens + +## Description + +<details> +<summary><strong>Table Definition</strong></summary> + +```sql +CREATE TABLE "oauth_access_tokens" ("token" varchar PRIMARY KEY NOT NULL, "clientId" varchar NOT NULL, "userId" varchar NOT NULL, CONSTRAINT "FK_78b26968132b7e5e45b75876481" FOREIGN KEY ("clientId") REFERENCES "oauth_clients" ("id") ON DELETE CASCADE, CONSTRAINT "FK_7234a36d8e49a1fa85095328845" FOREIGN KEY ("userId") REFERENCES "user" ("id") ON DELETE CASCADE) +``` + +</details> + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| clientId | varchar | | false | | [oauth_clients](oauth_clients.md) | | +| token | varchar | | false | | | | +| userId | varchar | | false | | [user](user.md) | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| - (Foreign key ID: 0) | FOREIGN KEY | FOREIGN KEY (userId) REFERENCES user (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| - (Foreign key ID: 1) | FOREIGN KEY | FOREIGN KEY (clientId) REFERENCES oauth_clients (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| sqlite_autoindex_oauth_access_tokens_1 | PRIMARY KEY | PRIMARY KEY (token) | +| token | PRIMARY KEY | PRIMARY KEY (token) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| sqlite_autoindex_oauth_access_tokens_1 | PRIMARY KEY (token) | + +## Relations + +```mermaid +erDiagram + +"oauth_access_tokens" }o--|| "oauth_clients" : "FOREIGN KEY (clientId) REFERENCES oauth_clients (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"oauth_access_tokens" }o--|| "user" : "FOREIGN KEY (userId) REFERENCES user (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" + +"oauth_access_tokens" { + varchar clientId FK + varchar token PK + varchar userId FK +} +"oauth_clients" { + varchar_255_ clientSecret + bigint clientSecretExpiresAt + datetime_3_ createdAt + TEXT grantTypes + varchar id PK + varchar_255_ name + TEXT redirectUris + varchar_255_ tokenEndpointAuthMethod + datetime_3_ updatedAt +} +"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 +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/sqlite-schema/oauth_authorization_codes.md b/docs/generated/sqlite-schema/oauth_authorization_codes.md new file mode 100644 index 00000000000..446e13cb6ae --- /dev/null +++ b/docs/generated/sqlite-schema/oauth_authorization_codes.md @@ -0,0 +1,102 @@ +# oauth_authorization_codes + +## Description + +<details> +<summary><strong>Table Definition</strong></summary> + +```sql +CREATE TABLE "oauth_authorization_codes" ("code" varchar(255) PRIMARY KEY NOT NULL, "clientId" varchar NOT NULL, "userId" varchar NOT NULL, "redirectUri" varchar NOT NULL, "codeChallenge" varchar NOT NULL, "codeChallengeMethod" varchar(255) NOT NULL, "expiresAt" bigint NOT NULL, "state" varchar, "used" boolean NOT NULL DEFAULT (false), "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')), "resource" varchar, "scope" text NOT NULL DEFAULT ('["tool:listWorkflows","tool:getWorkflowDetails"]'), CONSTRAINT "FK_e829ca1240b877f73fd5fab14a2" FOREIGN KEY ("userId") REFERENCES "user" ("id") ON DELETE CASCADE ON UPDATE NO ACTION, CONSTRAINT "FK_81de58036895ccabf2214c6d99e" FOREIGN KEY ("clientId") REFERENCES "oauth_clients" ("id") ON DELETE CASCADE ON UPDATE NO ACTION) +``` + +</details> + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| clientId | varchar | | false | | [oauth_clients](oauth_clients.md) | | +| code | varchar(255) | | false | | | | +| codeChallenge | varchar | | false | | | | +| codeChallengeMethod | varchar(255) | | false | | | | +| createdAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | +| expiresAt | bigint | | false | | | | +| redirectUri | varchar | | false | | | | +| resource | varchar | | true | | | | +| scope | TEXT | '["tool:listWorkflows","tool:getWorkflowDetails"]' | false | | | | +| state | varchar | | true | | | | +| updatedAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | +| used | boolean | false | false | | | | +| userId | varchar | | false | | [user](user.md) | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| - (Foreign key ID: 0) | FOREIGN KEY | FOREIGN KEY (clientId) REFERENCES oauth_clients (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| - (Foreign key ID: 1) | FOREIGN KEY | FOREIGN KEY (userId) REFERENCES user (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| code | PRIMARY KEY | PRIMARY KEY (code) | +| sqlite_autoindex_oauth_authorization_codes_1 | PRIMARY KEY | PRIMARY KEY (code) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| sqlite_autoindex_oauth_authorization_codes_1 | PRIMARY KEY (code) | + +## Relations + +```mermaid +erDiagram + +"oauth_authorization_codes" }o--|| "oauth_clients" : "FOREIGN KEY (clientId) REFERENCES oauth_clients (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"oauth_authorization_codes" }o--|| "user" : "FOREIGN KEY (userId) REFERENCES user (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" + +"oauth_authorization_codes" { + varchar clientId FK + varchar_255_ code PK + varchar codeChallenge + varchar_255_ codeChallengeMethod + datetime_3_ createdAt + bigint expiresAt + varchar redirectUri + varchar resource + TEXT scope + varchar state + datetime_3_ updatedAt + boolean used + varchar userId FK +} +"oauth_clients" { + varchar_255_ clientSecret + bigint clientSecretExpiresAt + datetime_3_ createdAt + TEXT grantTypes + varchar id PK + varchar_255_ name + TEXT redirectUris + varchar_255_ tokenEndpointAuthMethod + datetime_3_ updatedAt +} +"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 +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/sqlite-schema/oauth_clients.md b/docs/generated/sqlite-schema/oauth_clients.md new file mode 100644 index 00000000000..d7f41c6b15e --- /dev/null +++ b/docs/generated/sqlite-schema/oauth_clients.md @@ -0,0 +1,101 @@ +# oauth_clients + +## Description + +<details> +<summary><strong>Table Definition</strong></summary> + +```sql +CREATE TABLE "oauth_clients" ("id" varchar PRIMARY KEY NOT NULL, "name" varchar(255) NOT NULL, "redirectUris" text NOT NULL, "grantTypes" text NOT NULL, "clientSecret" varchar(255), "clientSecretExpiresAt" bigint, "tokenEndpointAuthMethod" varchar(255) NOT NULL DEFAULT ('none'), "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'))) +``` + +</details> + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| clientSecret | varchar(255) | | true | | | | +| clientSecretExpiresAt | bigint | | true | | | | +| createdAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | +| grantTypes | TEXT | | false | | | | +| id | varchar | | false | [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) | | | +| name | varchar(255) | | false | | | | +| redirectUris | TEXT | | false | | | | +| tokenEndpointAuthMethod | varchar(255) | 'none' | false | | | | +| updatedAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| id | PRIMARY KEY | PRIMARY KEY (id) | +| sqlite_autoindex_oauth_clients_1 | PRIMARY KEY | PRIMARY KEY (id) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| sqlite_autoindex_oauth_clients_1 | PRIMARY KEY (id) | + +## Relations + +```mermaid +erDiagram + +"oauth_access_tokens" }o--|| "oauth_clients" : "FOREIGN KEY (clientId) REFERENCES oauth_clients (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"oauth_authorization_codes" }o--|| "oauth_clients" : "FOREIGN KEY (clientId) REFERENCES oauth_clients (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"oauth_refresh_tokens" }o--|| "oauth_clients" : "FOREIGN KEY (clientId) REFERENCES oauth_clients (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"oauth_user_consents" }o--|| "oauth_clients" : "FOREIGN KEY (clientId) REFERENCES oauth_clients (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" + +"oauth_clients" { + varchar_255_ clientSecret + bigint clientSecretExpiresAt + datetime_3_ createdAt + TEXT grantTypes + varchar id PK + varchar_255_ name + TEXT redirectUris + varchar_255_ tokenEndpointAuthMethod + datetime_3_ updatedAt +} +"oauth_access_tokens" { + varchar clientId FK + varchar token PK + varchar userId FK +} +"oauth_authorization_codes" { + varchar clientId FK + varchar_255_ code PK + varchar codeChallenge + varchar_255_ codeChallengeMethod + datetime_3_ createdAt + bigint expiresAt + varchar redirectUri + varchar resource + TEXT scope + varchar state + datetime_3_ updatedAt + boolean used + varchar userId FK +} +"oauth_refresh_tokens" { + varchar clientId FK + datetime_3_ createdAt + bigint expiresAt + TEXT scope + varchar_255_ token PK + datetime_3_ updatedAt + varchar userId FK +} +"oauth_user_consents" { + varchar clientId FK + bigint grantedAt + INTEGER id + varchar userId FK +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/sqlite-schema/oauth_refresh_tokens.md b/docs/generated/sqlite-schema/oauth_refresh_tokens.md new file mode 100644 index 00000000000..075a5050cfd --- /dev/null +++ b/docs/generated/sqlite-schema/oauth_refresh_tokens.md @@ -0,0 +1,90 @@ +# oauth_refresh_tokens + +## Description + +<details> +<summary><strong>Table Definition</strong></summary> + +```sql +CREATE TABLE "oauth_refresh_tokens" ("token" varchar(255) PRIMARY KEY NOT NULL, "clientId" varchar NOT NULL, "userId" varchar NOT NULL, "expiresAt" bigint 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')), "scope" text NOT NULL DEFAULT ('["tool:listWorkflows","tool:getWorkflowDetails"]'), CONSTRAINT "FK_a699f3ed9fd0c1b19bc2608ac53" FOREIGN KEY ("userId") REFERENCES "user" ("id") ON DELETE CASCADE ON UPDATE NO ACTION, CONSTRAINT "FK_b388696ce4d8be7ffbe8d3e4b69" FOREIGN KEY ("clientId") REFERENCES "oauth_clients" ("id") ON DELETE CASCADE ON UPDATE NO ACTION) +``` + +</details> + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| clientId | varchar | | false | | [oauth_clients](oauth_clients.md) | | +| createdAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | +| expiresAt | bigint | | false | | | | +| scope | TEXT | '["tool:listWorkflows","tool:getWorkflowDetails"]' | false | | | | +| token | varchar(255) | | false | | | | +| updatedAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | +| userId | varchar | | false | | [user](user.md) | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| - (Foreign key ID: 0) | FOREIGN KEY | FOREIGN KEY (clientId) REFERENCES oauth_clients (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| - (Foreign key ID: 1) | FOREIGN KEY | FOREIGN KEY (userId) REFERENCES user (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| sqlite_autoindex_oauth_refresh_tokens_1 | PRIMARY KEY | PRIMARY KEY (token) | +| token | PRIMARY KEY | PRIMARY KEY (token) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| sqlite_autoindex_oauth_refresh_tokens_1 | PRIMARY KEY (token) | + +## Relations + +```mermaid +erDiagram + +"oauth_refresh_tokens" }o--|| "oauth_clients" : "FOREIGN KEY (clientId) REFERENCES oauth_clients (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"oauth_refresh_tokens" }o--|| "user" : "FOREIGN KEY (userId) REFERENCES user (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" + +"oauth_refresh_tokens" { + varchar clientId FK + datetime_3_ createdAt + bigint expiresAt + TEXT scope + varchar_255_ token PK + datetime_3_ updatedAt + varchar userId FK +} +"oauth_clients" { + varchar_255_ clientSecret + bigint clientSecretExpiresAt + datetime_3_ createdAt + TEXT grantTypes + varchar id PK + varchar_255_ name + TEXT redirectUris + varchar_255_ tokenEndpointAuthMethod + datetime_3_ updatedAt +} +"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 +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/sqlite-schema/oauth_user_consents.md b/docs/generated/sqlite-schema/oauth_user_consents.md new file mode 100644 index 00000000000..9488f8c1ffd --- /dev/null +++ b/docs/generated/sqlite-schema/oauth_user_consents.md @@ -0,0 +1,84 @@ +# oauth_user_consents + +## Description + +<details> +<summary><strong>Table Definition</strong></summary> + +```sql +CREATE TABLE "oauth_user_consents" ("id" integer PRIMARY KEY NOT NULL, "userId" varchar NOT NULL, "clientId" varchar NOT NULL, "grantedAt" bigint NOT NULL, CONSTRAINT "UQ_083721d99ce8db4033e2958ebb4" UNIQUE ("userId", "clientId"), CONSTRAINT "FK_a651acea2f6c97f8c4514935486" FOREIGN KEY ("clientId") REFERENCES "oauth_clients" ("id") ON DELETE CASCADE, CONSTRAINT "FK_21e6c3c2d78a097478fae6aaefa" FOREIGN KEY ("userId") REFERENCES "user" ("id") ON DELETE CASCADE) +``` + +</details> + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| clientId | varchar | | false | | [oauth_clients](oauth_clients.md) | | +| grantedAt | bigint | | false | | | | +| id | INTEGER | | false | | | | +| userId | varchar | | false | | [user](user.md) | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| - (Foreign key ID: 0) | FOREIGN KEY | FOREIGN KEY (userId) REFERENCES user (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| - (Foreign key ID: 1) | FOREIGN KEY | FOREIGN KEY (clientId) REFERENCES oauth_clients (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| id | PRIMARY KEY | PRIMARY KEY (id) | +| sqlite_autoindex_oauth_user_consents_1 | UNIQUE | UNIQUE (userId, clientId) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| sqlite_autoindex_oauth_user_consents_1 | UNIQUE (userId, clientId) | + +## Relations + +```mermaid +erDiagram + +"oauth_user_consents" }o--|| "oauth_clients" : "FOREIGN KEY (clientId) REFERENCES oauth_clients (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"oauth_user_consents" }o--|| "user" : "FOREIGN KEY (userId) REFERENCES user (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" + +"oauth_user_consents" { + varchar clientId FK + bigint grantedAt + INTEGER id + varchar userId FK +} +"oauth_clients" { + varchar_255_ clientSecret + bigint clientSecretExpiresAt + datetime_3_ createdAt + TEXT grantTypes + varchar id PK + varchar_255_ name + TEXT redirectUris + varchar_255_ tokenEndpointAuthMethod + datetime_3_ updatedAt +} +"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 +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/sqlite-schema/processed_data.md b/docs/generated/sqlite-schema/processed_data.md new file mode 100644 index 00000000000..0680dae9992 --- /dev/null +++ b/docs/generated/sqlite-schema/processed_data.md @@ -0,0 +1,79 @@ +# processed_data + +## Description + +<details> +<summary><strong>Table Definition</strong></summary> + +```sql +CREATE TABLE "processed_data" ("workflowId" varchar(36) NOT NULL, "context" varchar(255) 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')), "value" text NOT NULL, CONSTRAINT "FK_06a69a7032c97a763c2c7599464" FOREIGN KEY ("workflowId") REFERENCES "workflow_entity" ("id") ON DELETE CASCADE ON UPDATE NO ACTION, PRIMARY KEY ("workflowId", "context")) +``` + +</details> + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| context | varchar(255) | | false | | | | +| createdAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | +| updatedAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | +| value | TEXT | | false | | | | +| workflowId | varchar(36) | | false | | [workflow_entity](workflow_entity.md) | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| - (Foreign key ID: 0) | FOREIGN KEY | FOREIGN KEY (workflowId) REFERENCES workflow_entity (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| context | PRIMARY KEY | PRIMARY KEY (context) | +| sqlite_autoindex_processed_data_1 | PRIMARY KEY | PRIMARY KEY (workflowId, context) | +| workflowId | PRIMARY KEY | PRIMARY KEY (workflowId) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| sqlite_autoindex_processed_data_1 | PRIMARY KEY (workflowId, context) | + +## Relations + +```mermaid +erDiagram + +"processed_data" |o--|| "workflow_entity" : "FOREIGN KEY (workflowId) REFERENCES workflow_entity (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" + +"processed_data" { + varchar_255_ context PK + datetime_3_ createdAt + datetime_3_ updatedAt + TEXT value + varchar_36_ workflowId PK +} +"workflow_entity" { + boolean active + varchar_36_ activeVersionId FK + TEXT connections + datetime_3_ createdAt + TEXT description + varchar_36_ id PK + boolean isArchived + TEXT meta + varchar_128_ name + TEXT nodeGroups + TEXT nodes + varchar_36_ parentFolderId FK + TEXT pinData + TEXT settings + varchar sourceWorkflowId + TEXT staticData + INTEGER triggerCount + datetime_3_ updatedAt + INTEGER versionCounter + varchar_36_ versionId +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/sqlite-schema/project.md b/docs/generated/sqlite-schema/project.md new file mode 100644 index 00000000000..dae80983604 --- /dev/null +++ b/docs/generated/sqlite-schema/project.md @@ -0,0 +1,196 @@ +# project + +## Description + +<details> +<summary><strong>Table Definition</strong></summary> + +```sql +CREATE TABLE "project" ("id" varchar(36) PRIMARY KEY NOT NULL, "name" varchar(255) NOT NULL, "type" varchar(36) 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')), "icon" text, "description" varchar(512), "creatorId" varchar, "customTelemetryTags" text NOT NULL DEFAULT ('[]'), CONSTRAINT "projects_creatorId_foreign" FOREIGN KEY ("creatorId") REFERENCES "user" ("id") ON DELETE SET NULL ON UPDATE NO ACTION) +``` + +</details> + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| createdAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | +| creatorId | varchar | | true | | [user](user.md) | | +| customTelemetryTags | TEXT | '[]' | false | | | | +| description | varchar(512) | | true | | | | +| icon | TEXT | | true | | | | +| id | varchar(36) | | false | [agent_execution_threads](agent_execution_threads.md) [agents](agents.md) [data_table](data_table.md) [folder](folder.md) [insights_metadata](insights_metadata.md) [instance_ai_threads](instance_ai_threads.md) [project_relation](project_relation.md) [project_secrets_provider_access](project_secrets_provider_access.md) [role_mapping_rule_project](role_mapping_rule_project.md) [shared_credentials](shared_credentials.md) [shared_workflow](shared_workflow.md) [variables](variables.md) | | | +| name | varchar(255) | | false | | | | +| type | varchar(36) | | false | | | | +| updatedAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| - (Foreign key ID: 0) | FOREIGN KEY | FOREIGN KEY (creatorId) REFERENCES user (id) ON UPDATE NO ACTION ON DELETE SET NULL MATCH NONE | +| id | PRIMARY KEY | PRIMARY KEY (id) | +| sqlite_autoindex_project_1 | PRIMARY KEY | PRIMARY KEY (id) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| sqlite_autoindex_project_1 | PRIMARY KEY (id) | + +## Relations + +```mermaid +erDiagram + +"project" }o--o| "user" : "FOREIGN KEY (creatorId) REFERENCES user (id) ON UPDATE NO ACTION ON DELETE SET NULL MATCH NONE" +"agent_execution_threads" }o--|| "project" : "FOREIGN KEY (projectId) REFERENCES project (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" +"data_table" }o--|| "project" : "FOREIGN KEY (projectId) REFERENCES project (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"folder" }o--|| "project" : "FOREIGN KEY (projectId) REFERENCES project (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"insights_metadata" }o--o| "project" : "FOREIGN KEY (projectId) REFERENCES project (id) ON UPDATE NO ACTION ON DELETE SET NULL MATCH NONE" +"instance_ai_threads" }o--|| "project" : "FOREIGN KEY (projectId) REFERENCES project (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"project_relation" |o--|| "project" : "FOREIGN KEY (projectId) REFERENCES project (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"project_secrets_provider_access" |o--|| "project" : "FOREIGN KEY (projectId) REFERENCES project (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"role_mapping_rule_project" |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" +"variables" }o--o| "project" : "FOREIGN KEY (projectId) REFERENCES project (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" + +"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 +} +"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_execution_threads" { + varchar_36_ agentId FK + varchar_255_ agentName + datetime_3_ createdAt + varchar_8_ emoji + varchar_128_ id PK + varchar_36_ parentAgentId + varchar_128_ parentThreadId + varchar_255_ projectId FK + INTEGER sessionNumber + varchar_32_ taskId + varchar_36_ taskVersionId FK + varchar_255_ title + INTEGER totalCompletionTokens + REAL totalCost + INTEGER totalDuration + INTEGER totalPromptTokens + datetime_3_ updatedAt +} +"agents" { + varchar_36_ activeVersionId FK + datetime_3_ createdAt + varchar_512_ description + varchar_36_ id PK + TEXT integrations + varchar_128_ name + varchar_255_ projectId FK + TEXT schema + TEXT skills + TEXT tools + datetime_3_ updatedAt + varchar_36_ versionId +} +"data_table" { + datetime_3_ createdAt + varchar_36_ id PK + varchar_128_ name + varchar_36_ projectId FK + datetime_3_ updatedAt +} +"folder" { + datetime_3_ createdAt + varchar_36_ id PK + varchar_128_ name + varchar_36_ parentFolderId FK + varchar_36_ projectId FK + datetime_3_ updatedAt +} +"insights_metadata" { + INTEGER metaId + varchar_36_ projectId FK + varchar_255_ projectName + varchar_16_ workflowId FK + varchar_128_ workflowName +} +"instance_ai_threads" { + datetime_3_ createdAt + varchar id PK + TEXT metadata + varchar_36_ projectId FK + varchar_255_ resourceId + TEXT title + datetime_3_ updatedAt +} +"project_relation" { + datetime_3_ createdAt + varchar_36_ projectId PK + varchar role FK + datetime_3_ updatedAt + varchar userId PK +} +"project_secrets_provider_access" { + datetime_3_ createdAt + varchar_36_ projectId PK + varchar_128_ role + INTEGER secretsProviderConnectionId PK + datetime_3_ updatedAt +} +"role_mapping_rule_project" { + varchar_36_ projectId PK + varchar_16_ roleMappingRuleId PK +} +"shared_credentials" { + datetime_3_ createdAt + varchar_36_ credentialsId PK + varchar_36_ projectId PK + TEXT role + datetime_3_ updatedAt +} +"shared_workflow" { + datetime_3_ createdAt + varchar_36_ projectId PK + TEXT role + datetime_3_ updatedAt + varchar_36_ workflowId PK +} +"variables" { + varchar_36_ id PK + TEXT key + varchar_36_ projectId FK + TEXT type + TEXT value +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/sqlite-schema/project_relation.md b/docs/generated/sqlite-schema/project_relation.md new file mode 100644 index 00000000000..fa531fcae4f --- /dev/null +++ b/docs/generated/sqlite-schema/project_relation.md @@ -0,0 +1,102 @@ +# project_relation + +## Description + +<details> +<summary><strong>Table Definition</strong></summary> + +```sql +CREATE TABLE "project_relation" ("projectId" varchar(36) NOT NULL, "userId" varchar NOT NULL, "role" varchar 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_5f0643f6717905a05164090dde7" FOREIGN KEY ("userId") REFERENCES "user" ("id") ON DELETE CASCADE ON UPDATE NO ACTION, CONSTRAINT "FK_61448d56d61802b5dfde5cdb002" FOREIGN KEY ("projectId") REFERENCES "project" ("id") ON DELETE CASCADE ON UPDATE NO ACTION, CONSTRAINT "FK_c6b99592dc96b0d836d7a21db91" FOREIGN KEY ("role") REFERENCES "role" ("slug"), PRIMARY KEY ("projectId", "userId")) +``` + +</details> + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| createdAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | +| projectId | varchar(36) | | false | | [project](project.md) | | +| role | varchar | | false | | [role](role.md) | | +| updatedAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | +| userId | varchar | | false | | [user](user.md) | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| - (Foreign key ID: 0) | FOREIGN KEY | FOREIGN KEY (role) REFERENCES role (slug) ON UPDATE NO ACTION ON DELETE NO ACTION MATCH NONE | +| - (Foreign key ID: 1) | FOREIGN KEY | FOREIGN KEY (projectId) REFERENCES project (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| - (Foreign key ID: 2) | FOREIGN KEY | FOREIGN KEY (userId) REFERENCES user (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| projectId | PRIMARY KEY | PRIMARY KEY (projectId) | +| sqlite_autoindex_project_relation_1 | PRIMARY KEY | PRIMARY KEY (projectId, userId) | +| userId | PRIMARY KEY | PRIMARY KEY (userId) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_5f0643f6717905a05164090dde | CREATE INDEX "IDX_5f0643f6717905a05164090dde" ON "project_relation" ("userId") | +| IDX_61448d56d61802b5dfde5cdb00 | CREATE INDEX "IDX_61448d56d61802b5dfde5cdb00" ON "project_relation" ("projectId") | +| project_relation_role_idx | CREATE INDEX "project_relation_role_idx" ON "project_relation" ("role") | +| project_relation_role_project_idx | CREATE INDEX "project_relation_role_project_idx" ON "project_relation" ("projectId", "role") | +| sqlite_autoindex_project_relation_1 | PRIMARY KEY (projectId, userId) | + +## Relations + +```mermaid +erDiagram + +"project_relation" |o--|| "project" : "FOREIGN KEY (projectId) REFERENCES project (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"project_relation" }o--|| "role" : "FOREIGN KEY (role) REFERENCES role (slug) ON UPDATE NO ACTION ON DELETE NO ACTION MATCH NONE" +"project_relation" |o--|| "user" : "FOREIGN KEY (userId) REFERENCES user (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" + +"project_relation" { + datetime_3_ createdAt + varchar_36_ projectId PK + varchar role FK + datetime_3_ updatedAt + varchar userId PK +} +"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 +} +"role" { + datetime_3_ createdAt + TEXT description + TEXT displayName + TEXT roleType + varchar_128_ slug PK + boolean systemRole + datetime_3_ updatedAt +} +"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 +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/sqlite-schema/project_secrets_provider_access.md b/docs/generated/sqlite-schema/project_secrets_provider_access.md new file mode 100644 index 00000000000..094d6f230d9 --- /dev/null +++ b/docs/generated/sqlite-schema/project_secrets_provider_access.md @@ -0,0 +1,80 @@ +# project_secrets_provider_access + +## Description + +<details> +<summary><strong>Table Definition</strong></summary> + +```sql +CREATE TABLE "project_secrets_provider_access" ("secretsProviderConnectionId" integer NOT NULL, "projectId" varchar(36) 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')), "role" varchar(128) NOT NULL DEFAULT ('secretsProviderConnection:user'), CONSTRAINT "CHK_project_secrets_provider_access_role" CHECK ("role" IN ('secretsProviderConnection:owner', 'secretsProviderConnection:user')), CONSTRAINT "FK_bd264b81209355b543878deedb1" FOREIGN KEY ("projectId") REFERENCES "project" ("id") ON DELETE CASCADE ON UPDATE NO ACTION, CONSTRAINT "FK_18e5c27d2524b1638b292904e48" FOREIGN KEY ("secretsProviderConnectionId") REFERENCES "secrets_provider_connection" ("id") ON DELETE CASCADE ON UPDATE NO ACTION, PRIMARY KEY ("secretsProviderConnectionId", "projectId")) +``` + +</details> + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| createdAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | +| projectId | varchar(36) | | false | | [project](project.md) | | +| role | varchar(128) | 'secretsProviderConnection:user' | false | | | | +| secretsProviderConnectionId | INTEGER | | false | | [secrets_provider_connection](secrets_provider_connection.md) | | +| updatedAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| - | CHECK | CHECK ("role" IN ('secretsProviderConnection:owner', 'secretsProviderConnection:user')) | +| - (Foreign key ID: 0) | FOREIGN KEY | FOREIGN KEY (secretsProviderConnectionId) REFERENCES secrets_provider_connection (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| - (Foreign key ID: 1) | FOREIGN KEY | FOREIGN KEY (projectId) REFERENCES project (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| projectId | PRIMARY KEY | PRIMARY KEY (projectId) | +| secretsProviderConnectionId | PRIMARY KEY | PRIMARY KEY (secretsProviderConnectionId) | +| sqlite_autoindex_project_secrets_provider_access_1 | PRIMARY KEY | PRIMARY KEY (secretsProviderConnectionId, projectId) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| sqlite_autoindex_project_secrets_provider_access_1 | PRIMARY KEY (secretsProviderConnectionId, projectId) | + +## Relations + +```mermaid +erDiagram + +"project_secrets_provider_access" |o--|| "project" : "FOREIGN KEY (projectId) REFERENCES project (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"project_secrets_provider_access" |o--|| "secrets_provider_connection" : "FOREIGN KEY (secretsProviderConnectionId) REFERENCES secrets_provider_connection (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" + +"project_secrets_provider_access" { + datetime_3_ createdAt + varchar_36_ projectId PK + varchar_128_ role + INTEGER secretsProviderConnectionId PK + datetime_3_ updatedAt +} +"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 +} +"secrets_provider_connection" { + datetime_3_ createdAt + TEXT encryptedSettings + INTEGER id + boolean isEnabled + varchar_128_ providerKey + varchar_36_ type + datetime_3_ updatedAt +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/sqlite-schema/role.md b/docs/generated/sqlite-schema/role.md new file mode 100644 index 00000000000..2b63304b9c6 --- /dev/null +++ b/docs/generated/sqlite-schema/role.md @@ -0,0 +1,100 @@ +# role + +## Description + +<details> +<summary><strong>Table Definition</strong></summary> + +```sql +CREATE TABLE "role" ("slug" varchar(128) PRIMARY KEY NOT NULL, "displayName" text, "description" text, "roleType" text, "systemRole" boolean NOT NULL DEFAULT (false), "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'))) +``` + +</details> + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| createdAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | +| description | TEXT | | true | | | | +| displayName | TEXT | | true | | | | +| roleType | TEXT | | true | | | | +| slug | varchar(128) | | false | [project_relation](project_relation.md) [role_mapping_rule](role_mapping_rule.md) [role_scope](role_scope.md) [user](user.md) | | | +| systemRole | boolean | false | false | | | | +| updatedAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| slug | PRIMARY KEY | PRIMARY KEY (slug) | +| sqlite_autoindex_role_1 | PRIMARY KEY | PRIMARY KEY (slug) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_UniqueRoleDisplayName | CREATE UNIQUE INDEX "IDX_UniqueRoleDisplayName" ON "role" ("displayName") | +| sqlite_autoindex_role_1 | PRIMARY KEY (slug) | + +## Relations + +```mermaid +erDiagram + +"project_relation" }o--|| "role" : "FOREIGN KEY (role) REFERENCES role (slug) ON UPDATE NO ACTION ON DELETE NO ACTION MATCH NONE" +"role_mapping_rule" }o--|| "role" : "FOREIGN KEY (role) REFERENCES role (slug) ON UPDATE CASCADE ON DELETE CASCADE MATCH NONE" +"role_scope" |o--|| "role" : "FOREIGN KEY (roleSlug) REFERENCES role (slug) ON UPDATE CASCADE ON DELETE CASCADE MATCH NONE" +"user" }o--|| "role" : "FOREIGN KEY (roleSlug) REFERENCES role (slug) ON UPDATE NO ACTION ON DELETE NO ACTION MATCH NONE" + +"role" { + datetime_3_ createdAt + TEXT description + TEXT displayName + TEXT roleType + varchar_128_ slug PK + boolean systemRole + datetime_3_ updatedAt +} +"project_relation" { + datetime_3_ createdAt + varchar_36_ projectId PK + varchar role FK + datetime_3_ updatedAt + varchar userId PK +} +"role_mapping_rule" { + datetime_3_ createdAt + TEXT expression + varchar_16_ id PK + INTEGER order + varchar_128_ role FK + varchar_64_ type + datetime_3_ updatedAt +} +"role_scope" { + VARCHAR_128_ roleSlug PK + VARCHAR_128_ scopeSlug PK +} +"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 +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/sqlite-schema/role_mapping_rule.md b/docs/generated/sqlite-schema/role_mapping_rule.md new file mode 100644 index 00000000000..b45a577f818 --- /dev/null +++ b/docs/generated/sqlite-schema/role_mapping_rule.md @@ -0,0 +1,77 @@ +# role_mapping_rule + +## Description + +<details> +<summary><strong>Table Definition</strong></summary> + +```sql +CREATE TABLE "role_mapping_rule" ("id" varchar(16) PRIMARY KEY NOT NULL, "expression" text NOT NULL, "role" varchar(128) NOT NULL, "type" varchar(64) NOT NULL, "order" integer 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 "UQ_b33ac896ad3099fc8de36fdc1c4" UNIQUE ("type", "order"), CONSTRAINT "FK_bb66e404c35996b0d6946177501" FOREIGN KEY ("role") REFERENCES "role" ("slug") ON DELETE CASCADE ON UPDATE CASCADE) +``` + +</details> + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| createdAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | +| expression | TEXT | | false | | | | +| id | varchar(16) | | false | [role_mapping_rule_project](role_mapping_rule_project.md) | | | +| order | INTEGER | | false | | | | +| role | varchar(128) | | false | | [role](role.md) | | +| type | varchar(64) | | false | | | | +| updatedAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| - (Foreign key ID: 0) | FOREIGN KEY | FOREIGN KEY (role) REFERENCES role (slug) ON UPDATE CASCADE ON DELETE CASCADE MATCH NONE | +| id | PRIMARY KEY | PRIMARY KEY (id) | +| sqlite_autoindex_role_mapping_rule_1 | PRIMARY KEY | PRIMARY KEY (id) | +| sqlite_autoindex_role_mapping_rule_2 | UNIQUE | UNIQUE (type, order) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_bb66e404c35996b0d694617750 | CREATE INDEX "IDX_bb66e404c35996b0d694617750" ON "role_mapping_rule" ("role") | +| sqlite_autoindex_role_mapping_rule_1 | PRIMARY KEY (id) | +| sqlite_autoindex_role_mapping_rule_2 | UNIQUE (type, order) | + +## Relations + +```mermaid +erDiagram + +"role_mapping_rule_project" |o--|| "role_mapping_rule" : "FOREIGN KEY (roleMappingRuleId) REFERENCES role_mapping_rule (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"role_mapping_rule" }o--|| "role" : "FOREIGN KEY (role) REFERENCES role (slug) ON UPDATE CASCADE ON DELETE CASCADE MATCH NONE" + +"role_mapping_rule" { + datetime_3_ createdAt + TEXT expression + varchar_16_ id PK + INTEGER order + varchar_128_ role FK + varchar_64_ type + datetime_3_ updatedAt +} +"role_mapping_rule_project" { + varchar_36_ projectId PK + varchar_16_ roleMappingRuleId PK +} +"role" { + datetime_3_ createdAt + TEXT description + TEXT displayName + TEXT roleType + varchar_128_ slug PK + boolean systemRole + datetime_3_ updatedAt +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/sqlite-schema/role_mapping_rule_project.md b/docs/generated/sqlite-schema/role_mapping_rule_project.md new file mode 100644 index 00000000000..7aac7703163 --- /dev/null +++ b/docs/generated/sqlite-schema/role_mapping_rule_project.md @@ -0,0 +1,74 @@ +# role_mapping_rule_project + +## Description + +<details> +<summary><strong>Table Definition</strong></summary> + +```sql +CREATE TABLE "role_mapping_rule_project" ("roleMappingRuleId" varchar(16) NOT NULL, "projectId" varchar(36) NOT NULL, CONSTRAINT "FK_dd7ce4dfa09e95b36a626bd9de3" FOREIGN KEY ("roleMappingRuleId") REFERENCES "role_mapping_rule" ("id") ON DELETE CASCADE, CONSTRAINT "FK_35a78869286c65d9330d02b88f5" FOREIGN KEY ("projectId") REFERENCES "project" ("id") ON DELETE CASCADE, PRIMARY KEY ("roleMappingRuleId", "projectId")) +``` + +</details> + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| projectId | varchar(36) | | false | | [project](project.md) | | +| roleMappingRuleId | varchar(16) | | false | | [role_mapping_rule](role_mapping_rule.md) | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| - (Foreign key ID: 0) | FOREIGN KEY | FOREIGN KEY (projectId) REFERENCES project (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| - (Foreign key ID: 1) | FOREIGN KEY | FOREIGN KEY (roleMappingRuleId) REFERENCES role_mapping_rule (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| projectId | PRIMARY KEY | PRIMARY KEY (projectId) | +| roleMappingRuleId | PRIMARY KEY | PRIMARY KEY (roleMappingRuleId) | +| sqlite_autoindex_role_mapping_rule_project_1 | PRIMARY KEY | PRIMARY KEY (roleMappingRuleId, projectId) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_35a78869286c65d9330d02b88f | CREATE INDEX "IDX_35a78869286c65d9330d02b88f" ON "role_mapping_rule_project" ("projectId") | +| sqlite_autoindex_role_mapping_rule_project_1 | PRIMARY KEY (roleMappingRuleId, projectId) | + +## Relations + +```mermaid +erDiagram + +"role_mapping_rule_project" |o--|| "project" : "FOREIGN KEY (projectId) REFERENCES project (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"role_mapping_rule_project" |o--|| "role_mapping_rule" : "FOREIGN KEY (roleMappingRuleId) REFERENCES role_mapping_rule (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" + +"role_mapping_rule_project" { + varchar_36_ projectId PK + varchar_16_ roleMappingRuleId PK +} +"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 +} +"role_mapping_rule" { + datetime_3_ createdAt + TEXT expression + varchar_16_ id PK + INTEGER order + varchar_128_ role FK + varchar_64_ type + datetime_3_ updatedAt +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/sqlite-schema/role_scope.md b/docs/generated/sqlite-schema/role_scope.md new file mode 100644 index 00000000000..bc5e294e0ac --- /dev/null +++ b/docs/generated/sqlite-schema/role_scope.md @@ -0,0 +1,74 @@ +# role_scope + +## Description + +<details> +<summary><strong>Table Definition</strong></summary> + +```sql +CREATE TABLE role_scope ( + "roleSlug" VARCHAR(128) NOT NULL, + "scopeSlug" VARCHAR(128) NOT NULL, + CONSTRAINT "PK_role_scope" PRIMARY KEY ("roleSlug", "scopeSlug"), + CONSTRAINT "FK_role" FOREIGN KEY ("roleSlug") REFERENCES role ("slug") ON DELETE CASCADE ON UPDATE CASCADE, + CONSTRAINT "FK_scope" FOREIGN KEY ("scopeSlug") REFERENCES "scope" ("slug") ON DELETE CASCADE ON UPDATE CASCADE + ) +``` + +</details> + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| roleSlug | VARCHAR(128) | | false | | [role](role.md) | | +| scopeSlug | VARCHAR(128) | | false | | [scope](scope.md) | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| - (Foreign key ID: 0) | FOREIGN KEY | FOREIGN KEY (scopeSlug) REFERENCES scope (slug) ON UPDATE CASCADE ON DELETE CASCADE MATCH NONE | +| - (Foreign key ID: 1) | FOREIGN KEY | FOREIGN KEY (roleSlug) REFERENCES role (slug) ON UPDATE CASCADE ON DELETE CASCADE MATCH NONE | +| roleSlug | PRIMARY KEY | PRIMARY KEY (roleSlug) | +| scopeSlug | PRIMARY KEY | PRIMARY KEY (scopeSlug) | +| sqlite_autoindex_role_scope_1 | PRIMARY KEY | PRIMARY KEY (roleSlug, scopeSlug) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_role_scope_scopeSlug | CREATE INDEX "IDX_role_scope_scopeSlug" ON "role_scope" ("scopeSlug") | +| sqlite_autoindex_role_scope_1 | PRIMARY KEY (roleSlug, scopeSlug) | + +## Relations + +```mermaid +erDiagram + +"role_scope" |o--|| "role" : "FOREIGN KEY (roleSlug) REFERENCES role (slug) ON UPDATE CASCADE ON DELETE CASCADE MATCH NONE" +"role_scope" |o--|| "scope" : "FOREIGN KEY (scopeSlug) REFERENCES scope (slug) ON UPDATE CASCADE ON DELETE CASCADE MATCH NONE" + +"role_scope" { + VARCHAR_128_ roleSlug PK + VARCHAR_128_ scopeSlug PK +} +"role" { + datetime_3_ createdAt + TEXT description + TEXT displayName + TEXT roleType + varchar_128_ slug PK + boolean systemRole + datetime_3_ updatedAt +} +"scope" { + TEXT description + TEXT displayName + varchar_128_ slug PK +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/sqlite-schema/scope.md b/docs/generated/sqlite-schema/scope.md new file mode 100644 index 00000000000..f1ef3cb4893 --- /dev/null +++ b/docs/generated/sqlite-schema/scope.md @@ -0,0 +1,55 @@ +# scope + +## Description + +<details> +<summary><strong>Table Definition</strong></summary> + +```sql +CREATE TABLE "scope" ("slug" varchar(128) PRIMARY KEY NOT NULL, "displayName" text, "description" text) +``` + +</details> + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| description | TEXT | | true | | | | +| displayName | TEXT | | true | | | | +| slug | varchar(128) | | false | [role_scope](role_scope.md) | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| slug | PRIMARY KEY | PRIMARY KEY (slug) | +| sqlite_autoindex_scope_1 | PRIMARY KEY | PRIMARY KEY (slug) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| sqlite_autoindex_scope_1 | PRIMARY KEY (slug) | + +## Relations + +```mermaid +erDiagram + +"role_scope" |o--|| "scope" : "FOREIGN KEY (scopeSlug) REFERENCES scope (slug) ON UPDATE CASCADE ON DELETE CASCADE MATCH NONE" + +"scope" { + TEXT description + TEXT displayName + varchar_128_ slug PK +} +"role_scope" { + VARCHAR_128_ roleSlug PK + VARCHAR_128_ scopeSlug PK +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/sqlite-schema/secrets_provider_connection.md b/docs/generated/sqlite-schema/secrets_provider_connection.md new file mode 100644 index 00000000000..11b21b7e753 --- /dev/null +++ b/docs/generated/sqlite-schema/secrets_provider_connection.md @@ -0,0 +1,65 @@ +# secrets_provider_connection + +## Description + +<details> +<summary><strong>Table Definition</strong></summary> + +```sql +CREATE TABLE "secrets_provider_connection" ("id" integer PRIMARY KEY NOT NULL, "providerKey" varchar(128) NOT NULL, "type" varchar(36) NOT NULL, "encryptedSettings" text NOT NULL, "isEnabled" boolean NOT NULL DEFAULT (false), "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'))) +``` + +</details> + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| createdAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | +| encryptedSettings | TEXT | | false | | | | +| id | INTEGER | | false | [project_secrets_provider_access](project_secrets_provider_access.md) | | | +| isEnabled | boolean | false | false | | | | +| providerKey | varchar(128) | | false | | | | +| type | varchar(36) | | false | | | | +| updatedAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| id | PRIMARY KEY | PRIMARY KEY (id) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_secrets_provider_connection_providerKey | CREATE UNIQUE INDEX "IDX_secrets_provider_connection_providerKey" ON "secrets_provider_connection" ("providerKey") | + +## Relations + +```mermaid +erDiagram + +"project_secrets_provider_access" |o--|| "secrets_provider_connection" : "FOREIGN KEY (secretsProviderConnectionId) REFERENCES secrets_provider_connection (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" + +"secrets_provider_connection" { + datetime_3_ createdAt + TEXT encryptedSettings + INTEGER id + boolean isEnabled + varchar_128_ providerKey + varchar_36_ type + datetime_3_ updatedAt +} +"project_secrets_provider_access" { + datetime_3_ createdAt + varchar_36_ projectId PK + varchar_128_ role + INTEGER secretsProviderConnectionId PK + datetime_3_ updatedAt +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/sqlite-schema/settings.md b/docs/generated/sqlite-schema/settings.md new file mode 100644 index 00000000000..8817d556b6f --- /dev/null +++ b/docs/generated/sqlite-schema/settings.md @@ -0,0 +1,50 @@ +# settings + +## Description + +<details> +<summary><strong>Table Definition</strong></summary> + +```sql +CREATE TABLE "settings" ("key" TEXT NOT NULL,"value" TEXT NOT NULL DEFAULT '',"loadOnStartup" boolean NOT NULL default false,PRIMARY KEY("key")) +``` + +</details> + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| key | TEXT | | false | | | | +| loadOnStartup | boolean | false | false | | | | +| value | TEXT | '' | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| key | PRIMARY KEY | PRIMARY KEY (key) | +| sqlite_autoindex_settings_1 | PRIMARY KEY | PRIMARY KEY (key) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| sqlite_autoindex_settings_1 | PRIMARY KEY (key) | + +## Relations + +```mermaid +erDiagram + + +"settings" { + TEXT key PK + boolean loadOnStartup + TEXT value +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/sqlite-schema/shared_credentials.md b/docs/generated/sqlite-schema/shared_credentials.md new file mode 100644 index 00000000000..cfe788dd8f4 --- /dev/null +++ b/docs/generated/sqlite-schema/shared_credentials.md @@ -0,0 +1,83 @@ +# shared_credentials + +## Description + +<details> +<summary><strong>Table Definition</strong></summary> + +```sql +CREATE TABLE "shared_credentials" ("credentialsId" varchar(36) NOT NULL, "projectId" varchar(36) NOT NULL, "role" 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_416f66fc846c7c442970c094ccf" FOREIGN KEY ("credentialsId") REFERENCES "credentials_entity" ("id") ON DELETE CASCADE, CONSTRAINT "FK_812c2852270da1247756e77f5a4" FOREIGN KEY ("projectId") REFERENCES "project" ("id") ON DELETE CASCADE, PRIMARY KEY ("credentialsId", "projectId")) +``` + +</details> + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| createdAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | +| credentialsId | varchar(36) | | false | | [credentials_entity](credentials_entity.md) | | +| projectId | varchar(36) | | false | | [project](project.md) | | +| role | TEXT | | false | | | | +| updatedAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| - (Foreign key ID: 0) | FOREIGN KEY | FOREIGN KEY (projectId) REFERENCES project (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| - (Foreign key ID: 1) | FOREIGN KEY | FOREIGN KEY (credentialsId) REFERENCES credentials_entity (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| credentialsId | PRIMARY KEY | PRIMARY KEY (credentialsId) | +| projectId | PRIMARY KEY | PRIMARY KEY (projectId) | +| sqlite_autoindex_shared_credentials_1 | PRIMARY KEY | PRIMARY KEY (credentialsId, projectId) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| sqlite_autoindex_shared_credentials_1 | PRIMARY KEY (credentialsId, projectId) | + +## Relations + +```mermaid +erDiagram + +"shared_credentials" |o--|| "credentials_entity" : "FOREIGN KEY (credentialsId) REFERENCES credentials_entity (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_credentials" { + datetime_3_ createdAt + varchar_36_ credentialsId PK + varchar_36_ projectId PK + TEXT role + datetime_3_ updatedAt +} +"credentials_entity" { + datetime_3_ createdAt + TEXT data + varchar_36_ id PK + boolean isGlobal + boolean isManaged + boolean isResolvable + varchar_128_ name + boolean resolvableAllowFallback + varchar_16_ resolverId FK + varchar_32_ type + datetime_3_ updatedAt +} +"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/shared_workflow.md b/docs/generated/sqlite-schema/shared_workflow.md new file mode 100644 index 00000000000..4ac894abccd --- /dev/null +++ b/docs/generated/sqlite-schema/shared_workflow.md @@ -0,0 +1,93 @@ +# shared_workflow + +## Description + +<details> +<summary><strong>Table Definition</strong></summary> + +```sql +CREATE TABLE "shared_workflow" ("workflowId" varchar(36) NOT NULL, "projectId" varchar(36) NOT NULL, "role" 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_daa206a04983d47d0a9c34649ce" FOREIGN KEY ("workflowId") REFERENCES "workflow_entity" ("id") ON DELETE CASCADE, CONSTRAINT "FK_a45ea5f27bcfdc21af9b4188560" FOREIGN KEY ("projectId") REFERENCES "project" ("id") ON DELETE CASCADE, PRIMARY KEY ("workflowId", "projectId")) +``` + +</details> + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| createdAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | +| projectId | varchar(36) | | false | | [project](project.md) | | +| role | TEXT | | false | | | | +| updatedAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | +| workflowId | varchar(36) | | false | | [workflow_entity](workflow_entity.md) | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| - (Foreign key ID: 0) | FOREIGN KEY | FOREIGN KEY (projectId) REFERENCES project (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| - (Foreign key ID: 1) | FOREIGN KEY | FOREIGN KEY (workflowId) REFERENCES workflow_entity (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| projectId | PRIMARY KEY | PRIMARY KEY (projectId) | +| sqlite_autoindex_shared_workflow_1 | PRIMARY KEY | PRIMARY KEY (workflowId, projectId) | +| workflowId | PRIMARY KEY | PRIMARY KEY (workflowId) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_shared_workflow_projectId | CREATE INDEX "IDX_shared_workflow_projectId" ON "shared_workflow" ("projectId") | +| sqlite_autoindex_shared_workflow_1 | PRIMARY KEY (workflowId, projectId) | + +## Relations + +```mermaid +erDiagram + +"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" + +"shared_workflow" { + datetime_3_ createdAt + varchar_36_ projectId PK + TEXT role + datetime_3_ updatedAt + varchar_36_ workflowId PK +} +"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 +} +"workflow_entity" { + boolean active + varchar_36_ activeVersionId FK + TEXT connections + datetime_3_ createdAt + TEXT description + varchar_36_ id PK + boolean isArchived + TEXT meta + varchar_128_ name + TEXT nodeGroups + TEXT nodes + varchar_36_ parentFolderId FK + TEXT pinData + TEXT settings + varchar sourceWorkflowId + TEXT staticData + INTEGER triggerCount + datetime_3_ updatedAt + INTEGER versionCounter + varchar_36_ versionId +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/sqlite-schema/tag_entity.md b/docs/generated/sqlite-schema/tag_entity.md new file mode 100644 index 00000000000..442aefb8110 --- /dev/null +++ b/docs/generated/sqlite-schema/tag_entity.md @@ -0,0 +1,63 @@ +# tag_entity + +## Description + +<details> +<summary><strong>Table Definition</strong></summary> + +```sql +CREATE TABLE "tag_entity" ("id" varchar(36) PRIMARY KEY NOT NULL, "name" varchar(24) 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'))) +``` + +</details> + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| createdAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | +| id | varchar(36) | | false | [folder_tag](folder_tag.md) [workflows_tags](workflows_tags.md) | | | +| name | varchar(24) | | false | | | | +| updatedAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| id | PRIMARY KEY | PRIMARY KEY (id) | +| sqlite_autoindex_tag_entity_1 | PRIMARY KEY | PRIMARY KEY (id) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_8f949d7a3a984759044054e89b | CREATE UNIQUE INDEX "IDX_8f949d7a3a984759044054e89b" ON "tag_entity" ("name") | +| sqlite_autoindex_tag_entity_1 | PRIMARY KEY (id) | + +## Relations + +```mermaid +erDiagram + +"folder_tag" |o--|| "tag_entity" : "FOREIGN KEY (tagId) REFERENCES tag_entity (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"workflows_tags" |o--|| "tag_entity" : "FOREIGN KEY (tagId) REFERENCES tag_entity (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" + +"tag_entity" { + datetime_3_ createdAt + varchar_36_ id PK + varchar_24_ name + datetime_3_ updatedAt +} +"folder_tag" { + varchar_36_ folderId PK + varchar_36_ tagId PK +} +"workflows_tags" { + INTEGER tagId PK + varchar_36_ workflowId PK +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/sqlite-schema/test_case_execution.md b/docs/generated/sqlite-schema/test_case_execution.md new file mode 100644 index 00000000000..22bea4de0ed --- /dev/null +++ b/docs/generated/sqlite-schema/test_case_execution.md @@ -0,0 +1,123 @@ +# test_case_execution + +## Description + +<details> +<summary><strong>Table Definition</strong></summary> + +```sql +CREATE TABLE "test_case_execution" ("id" varchar(36) PRIMARY KEY NOT NULL, "testRunId" varchar(36) NOT NULL, "pastExecutionId" integer, "executionId" integer, "evaluationExecutionId" integer, "status" varchar NOT NULL, "runAt" datetime(3), "completedAt" datetime(3), "errorCode" varchar, "errorDetails" text, "metrics" text, "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')), "inputs" text, "outputs" text, "runIndex" INTEGER DEFAULT NULL, CONSTRAINT "FK_dfbe194e3ebdfe49a87bc4692ca" FOREIGN KEY ("evaluationExecutionId") REFERENCES "execution_entity" ("id") ON DELETE SET NULL ON UPDATE NO ACTION, CONSTRAINT "FK_e48965fac35d0f5b9e7f51d8c44" FOREIGN KEY ("executionId") REFERENCES "execution_entity" ("id") ON DELETE SET NULL ON UPDATE NO ACTION, CONSTRAINT "FK_258d954733841d51edd826a562b" FOREIGN KEY ("pastExecutionId") REFERENCES "execution_entity" ("id") ON DELETE SET NULL ON UPDATE NO ACTION, CONSTRAINT "FK_8e4b4774db42f1e6dda3452b2af" FOREIGN KEY ("testRunId") REFERENCES "test_run" ("id") ON DELETE CASCADE ON UPDATE NO ACTION) +``` + +</details> + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| completedAt | datetime(3) | | true | | | | +| createdAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | +| errorCode | varchar | | true | | | | +| errorDetails | TEXT | | true | | | | +| evaluationExecutionId | INTEGER | | true | | [execution_entity](execution_entity.md) | | +| executionId | INTEGER | | true | | [execution_entity](execution_entity.md) | | +| id | varchar(36) | | false | | | | +| inputs | TEXT | | true | | | | +| metrics | TEXT | | true | | | | +| outputs | TEXT | | true | | | | +| pastExecutionId | INTEGER | | true | | [execution_entity](execution_entity.md) | | +| runAt | datetime(3) | | true | | | | +| runIndex | INTEGER | NULL | true | | | | +| status | varchar | | false | | | | +| testRunId | varchar(36) | | false | | [test_run](test_run.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 (testRunId) REFERENCES test_run (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| - (Foreign key ID: 1) | FOREIGN KEY | FOREIGN KEY (pastExecutionId) REFERENCES execution_entity (id) ON UPDATE NO ACTION ON DELETE SET NULL MATCH NONE | +| - (Foreign key ID: 2) | FOREIGN KEY | FOREIGN KEY (executionId) REFERENCES execution_entity (id) ON UPDATE NO ACTION ON DELETE SET NULL MATCH NONE | +| - (Foreign key ID: 3) | FOREIGN KEY | FOREIGN KEY (evaluationExecutionId) REFERENCES execution_entity (id) ON UPDATE NO ACTION ON DELETE SET NULL MATCH NONE | +| id | PRIMARY KEY | PRIMARY KEY (id) | +| sqlite_autoindex_test_case_execution_1 | PRIMARY KEY | PRIMARY KEY (id) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_8e4b4774db42f1e6dda3452b2a | CREATE INDEX "IDX_8e4b4774db42f1e6dda3452b2a" ON "test_case_execution" ("testRunId") | +| sqlite_autoindex_test_case_execution_1 | PRIMARY KEY (id) | + +## Relations + +```mermaid +erDiagram + +"test_case_execution" }o--o| "execution_entity" : "FOREIGN KEY (evaluationExecutionId) 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" +"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--|| "test_run" : "FOREIGN KEY (testRunId) REFERENCES test_run (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" + +"test_case_execution" { + datetime_3_ completedAt + datetime_3_ createdAt + varchar errorCode + TEXT errorDetails + INTEGER evaluationExecutionId FK + INTEGER executionId FK + varchar_36_ id PK + TEXT inputs + TEXT metrics + TEXT outputs + INTEGER pastExecutionId FK + datetime_3_ runAt + INTEGER runIndex + varchar status + varchar_36_ testRunId FK + datetime_3_ updatedAt +} +"execution_entity" { + BIGINT binaryDataSizeBytes + datetime_3_ createdAt + varchar_255_ deduplicationKey + datetime_3_ deletedAt + boolean finished + INTEGER id + BIGINT jsonSizeBytes + varchar mode + varchar retryOf + varchar retrySuccessId + datetime startedAt + varchar status + datetime stoppedAt + varchar_2_ storedAt + TEXT tracingContext + datetime waitTill + varchar_36_ workflowId FK + VARCHAR_36_ workflowVersionId +} +"test_run" { + boolean cancelRequested + varchar_36_ collectionId FK + datetime_3_ completedAt + datetime_3_ createdAt + varchar errorCode + TEXT errorDetails + varchar_36_ evaluationConfigId FK + TEXT evaluationConfigSnapshot + varchar_36_ id PK + TEXT metrics + datetime_3_ runAt + varchar_255_ runningInstanceId + varchar status + datetime_3_ updatedAt + varchar_36_ workflowId FK + varchar_36_ workflowVersionId +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/sqlite-schema/test_run.md b/docs/generated/sqlite-schema/test_run.md new file mode 100644 index 00000000000..7a909962508 --- /dev/null +++ b/docs/generated/sqlite-schema/test_run.md @@ -0,0 +1,151 @@ +# test_run + +## Description + +<details> +<summary><strong>Table Definition</strong></summary> + +```sql +CREATE TABLE "test_run" ("id" varchar(36) PRIMARY KEY NOT NULL, "workflowId" varchar(36) NOT NULL, "status" varchar NOT NULL, "errorCode" varchar, "errorDetails" text, "runAt" datetime(3), "completedAt" datetime(3), "metrics" text, "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')), "runningInstanceId" varchar(255), "cancelRequested" boolean NOT NULL DEFAULT (FALSE), "workflowVersionId" varchar(36), "evaluationConfigId" varchar(36), "evaluationConfigSnapshot" text, "collectionId" varchar(36), CONSTRAINT "FK_test_run_evaluation_config_id" FOREIGN KEY ("evaluationConfigId") REFERENCES "evaluation_config" ("id") ON DELETE SET NULL ON UPDATE NO ACTION, CONSTRAINT "FK_d6870d3b6e4c185d33926f423c8" FOREIGN KEY ("workflowId") REFERENCES "workflow_entity" ("id") ON DELETE CASCADE ON UPDATE NO ACTION, CONSTRAINT "FK_test_run_collection_id" FOREIGN KEY ("collectionId") REFERENCES "evaluation_collection" ("id") ON DELETE SET NULL) +``` + +</details> + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| cancelRequested | boolean | FALSE | false | | | | +| collectionId | varchar(36) | | true | | [evaluation_collection](evaluation_collection.md) | | +| completedAt | datetime(3) | | true | | | | +| createdAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | +| errorCode | varchar | | true | | | | +| errorDetails | TEXT | | true | | | | +| evaluationConfigId | varchar(36) | | true | | [evaluation_config](evaluation_config.md) | | +| evaluationConfigSnapshot | TEXT | | true | | | | +| id | varchar(36) | | false | [test_case_execution](test_case_execution.md) | | | +| metrics | TEXT | | true | | | | +| runAt | datetime(3) | | true | | | | +| runningInstanceId | varchar(255) | | true | | | | +| status | varchar | | false | | | | +| updatedAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | +| workflowId | varchar(36) | | false | | [workflow_entity](workflow_entity.md) | | +| workflowVersionId | varchar(36) | | true | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| - (Foreign key ID: 0) | FOREIGN KEY | FOREIGN KEY (collectionId) REFERENCES evaluation_collection (id) ON UPDATE NO ACTION ON DELETE SET NULL MATCH NONE | +| - (Foreign key ID: 1) | FOREIGN KEY | FOREIGN KEY (workflowId) REFERENCES workflow_entity (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| - (Foreign key ID: 2) | FOREIGN KEY | FOREIGN KEY (evaluationConfigId) REFERENCES evaluation_config (id) ON UPDATE NO ACTION ON DELETE SET NULL MATCH NONE | +| id | PRIMARY KEY | PRIMARY KEY (id) | +| sqlite_autoindex_test_run_1 | PRIMARY KEY | PRIMARY KEY (id) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_d6870d3b6e4c185d33926f423c | CREATE INDEX "IDX_d6870d3b6e4c185d33926f423c" ON "test_run" ("workflowId") | +| IDX_test_run_collectionId | CREATE INDEX "IDX_test_run_collectionId" ON "test_run" ("collectionId") | +| IDX_test_run_evaluationConfigId | CREATE INDEX "IDX_test_run_evaluationConfigId" ON "test_run" ("evaluationConfigId") | +| sqlite_autoindex_test_run_1 | PRIMARY KEY (id) | + +## Relations + +```mermaid +erDiagram + +"test_run" }o--o| "evaluation_collection" : "FOREIGN KEY (collectionId) REFERENCES evaluation_collection (id) ON UPDATE NO ACTION ON DELETE SET NULL MATCH NONE" +"test_run" }o--o| "evaluation_config" : "FOREIGN KEY (evaluationConfigId) REFERENCES evaluation_config (id) ON UPDATE NO ACTION ON DELETE SET NULL 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_run" }o--|| "workflow_entity" : "FOREIGN KEY (workflowId) REFERENCES workflow_entity (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" + +"test_run" { + boolean cancelRequested + varchar_36_ collectionId FK + datetime_3_ completedAt + datetime_3_ createdAt + varchar errorCode + TEXT errorDetails + varchar_36_ evaluationConfigId FK + TEXT evaluationConfigSnapshot + varchar_36_ id PK + TEXT metrics + datetime_3_ runAt + varchar_255_ runningInstanceId + varchar status + datetime_3_ updatedAt + varchar_36_ workflowId FK + varchar_36_ workflowVersionId +} +"evaluation_collection" { + datetime_3_ createdAt + varchar createdById FK + TEXT description + varchar_36_ evaluationConfigId FK + varchar_36_ id PK + TEXT insightsCache + varchar_128_ name + datetime_3_ updatedAt + varchar_36_ workflowId FK +} +"evaluation_config" { + datetime_3_ createdAt + TEXT datasetRef + varchar_32_ datasetSource + varchar_255_ endNodeName + varchar_36_ id PK + varchar_64_ invalidReason + TEXT metrics + varchar_128_ name + varchar_255_ startNodeName + varchar_16_ status + datetime_3_ updatedAt + varchar_36_ workflowId FK +} +"test_case_execution" { + datetime_3_ completedAt + datetime_3_ createdAt + varchar errorCode + TEXT errorDetails + INTEGER evaluationExecutionId FK + INTEGER executionId FK + varchar_36_ id PK + TEXT inputs + TEXT metrics + TEXT outputs + INTEGER pastExecutionId FK + datetime_3_ runAt + INTEGER runIndex + varchar status + varchar_36_ testRunId FK + datetime_3_ updatedAt +} +"workflow_entity" { + boolean active + varchar_36_ activeVersionId FK + TEXT connections + datetime_3_ createdAt + TEXT description + varchar_36_ id PK + boolean isArchived + TEXT meta + varchar_128_ name + TEXT nodeGroups + TEXT nodes + varchar_36_ parentFolderId FK + TEXT pinData + TEXT settings + varchar sourceWorkflowId + TEXT staticData + INTEGER triggerCount + datetime_3_ updatedAt + INTEGER versionCounter + varchar_36_ versionId +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/sqlite-schema/token_exchange_jti.md b/docs/generated/sqlite-schema/token_exchange_jti.md new file mode 100644 index 00000000000..de093b03f1f --- /dev/null +++ b/docs/generated/sqlite-schema/token_exchange_jti.md @@ -0,0 +1,50 @@ +# token_exchange_jti + +## Description + +<details> +<summary><strong>Table Definition</strong></summary> + +```sql +CREATE TABLE "token_exchange_jti" ("jti" varchar(255) PRIMARY KEY NOT NULL, "expiresAt" datetime(3) NOT NULL, "createdAt" datetime(3) NOT NULL) +``` + +</details> + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| createdAt | datetime(3) | | false | | | | +| expiresAt | datetime(3) | | false | | | | +| jti | varchar(255) | | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| jti | PRIMARY KEY | PRIMARY KEY (jti) | +| sqlite_autoindex_token_exchange_jti_1 | PRIMARY KEY | PRIMARY KEY (jti) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| sqlite_autoindex_token_exchange_jti_1 | PRIMARY KEY (jti) | + +## Relations + +```mermaid +erDiagram + + +"token_exchange_jti" { + datetime_3_ createdAt + datetime_3_ expiresAt + varchar_255_ jti PK +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/sqlite-schema/trusted_key.md b/docs/generated/sqlite-schema/trusted_key.md new file mode 100644 index 00000000000..843326d5203 --- /dev/null +++ b/docs/generated/sqlite-schema/trusted_key.md @@ -0,0 +1,65 @@ +# trusted_key + +## Description + +<details> +<summary><strong>Table Definition</strong></summary> + +```sql +CREATE TABLE "trusted_key" ("sourceId" varchar(36) NOT NULL, "kid" varchar(255) NOT NULL, "data" text NOT NULL, "createdAt" datetime(3) NOT NULL DEFAULT (STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW')), CONSTRAINT "FK_8c2938d746943dd8f608d23c891" FOREIGN KEY ("sourceId") REFERENCES "trusted_key_source" ("id") ON DELETE CASCADE, PRIMARY KEY ("sourceId", "kid")) +``` + +</details> + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| createdAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | +| data | TEXT | | false | | | | +| kid | varchar(255) | | false | | | | +| sourceId | varchar(36) | | false | | [trusted_key_source](trusted_key_source.md) | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| - (Foreign key ID: 0) | FOREIGN KEY | FOREIGN KEY (sourceId) REFERENCES trusted_key_source (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| kid | PRIMARY KEY | PRIMARY KEY (kid) | +| sourceId | PRIMARY KEY | PRIMARY KEY (sourceId) | +| sqlite_autoindex_trusted_key_1 | PRIMARY KEY | PRIMARY KEY (sourceId, kid) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| sqlite_autoindex_trusted_key_1 | PRIMARY KEY (sourceId, kid) | + +## Relations + +```mermaid +erDiagram + +"trusted_key" |o--|| "trusted_key_source" : "FOREIGN KEY (sourceId) REFERENCES trusted_key_source (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" + +"trusted_key" { + datetime_3_ createdAt + TEXT data + varchar_255_ kid PK + varchar_36_ sourceId PK +} +"trusted_key_source" { + TEXT config + datetime_3_ createdAt + varchar_36_ id PK + TEXT lastError + datetime_3_ lastRefreshedAt + varchar_32_ status + varchar_32_ type + datetime_3_ updatedAt +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/sqlite-schema/trusted_key_source.md b/docs/generated/sqlite-schema/trusted_key_source.md new file mode 100644 index 00000000000..a5a291564ec --- /dev/null +++ b/docs/generated/sqlite-schema/trusted_key_source.md @@ -0,0 +1,67 @@ +# trusted_key_source + +## Description + +<details> +<summary><strong>Table Definition</strong></summary> + +```sql +CREATE TABLE "trusted_key_source" ("id" varchar(36) PRIMARY KEY NOT NULL, "type" varchar(32) NOT NULL, "config" text NOT NULL, "status" varchar(32) NOT NULL DEFAULT ('pending'), "lastError" text, "lastRefreshedAt" datetime(3), "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'))) +``` + +</details> + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| config | TEXT | | false | | | | +| createdAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | +| id | varchar(36) | | false | [trusted_key](trusted_key.md) | | | +| lastError | TEXT | | true | | | | +| lastRefreshedAt | datetime(3) | | true | | | | +| status | varchar(32) | 'pending' | false | | | | +| type | varchar(32) | | false | | | | +| updatedAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| id | PRIMARY KEY | PRIMARY KEY (id) | +| sqlite_autoindex_trusted_key_source_1 | PRIMARY KEY | PRIMARY KEY (id) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| sqlite_autoindex_trusted_key_source_1 | PRIMARY KEY (id) | + +## Relations + +```mermaid +erDiagram + +"trusted_key" |o--|| "trusted_key_source" : "FOREIGN KEY (sourceId) REFERENCES trusted_key_source (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" + +"trusted_key_source" { + TEXT config + datetime_3_ createdAt + varchar_36_ id PK + TEXT lastError + datetime_3_ lastRefreshedAt + varchar_32_ status + varchar_32_ type + datetime_3_ updatedAt +} +"trusted_key" { + datetime_3_ createdAt + TEXT data + varchar_255_ kid PK + varchar_36_ sourceId PK +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/sqlite-schema/user.md b/docs/generated/sqlite-schema/user.md new file mode 100644 index 00000000000..9f1e5b06d2d --- /dev/null +++ b/docs/generated/sqlite-schema/user.md @@ -0,0 +1,297 @@ +# user + +## Description + +<details> +<summary><strong>Table Definition</strong></summary> + +```sql +CREATE TABLE "user" ("id" varchar PRIMARY KEY, "email" varchar(255), "firstName" varchar(32), "lastName" varchar(32), "password" varchar, "personalizationAnswers" text, "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')), "settings" text, "disabled" boolean NOT NULL DEFAULT (FALSE), "mfaEnabled" boolean NOT NULL DEFAULT (FALSE), "mfaSecret" text, "mfaRecoveryCodes" text, "lastActiveAt" date, "roleSlug" varchar(128) NOT NULL DEFAULT ('global:member'), CONSTRAINT "UQ_e12875dfb3b1d92d7d7c5377e22" UNIQUE ("email"), CONSTRAINT "FK_eaea92ee7bfb9c1b6cd01505d56" FOREIGN KEY ("roleSlug") REFERENCES "role" ("slug")) +``` + +</details> + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| createdAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | +| disabled | boolean | FALSE | false | | | | +| email | varchar(255) | | true | | | | +| firstName | varchar(32) | | true | | | | +| id | varchar | | true | [agent_history](agent_history.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) [instance_ai_mcp_registry_connections](instance_ai_mcp_registry_connections.md) [instance_ai_pending_confirmations](instance_ai_pending_confirmations.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) [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) | | | +| lastActiveAt | date | | true | | | | +| lastName | varchar(32) | | true | | | | +| mfaEnabled | boolean | FALSE | false | | | | +| mfaRecoveryCodes | TEXT | | true | | | | +| mfaSecret | TEXT | | true | | | | +| password | varchar | | true | | | | +| personalizationAnswers | TEXT | | true | | | | +| roleSlug | varchar(128) | 'global:member' | false | | [role](role.md) | | +| settings | TEXT | | true | | | | +| updatedAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| - (Foreign key ID: 0) | FOREIGN KEY | FOREIGN KEY (roleSlug) REFERENCES role (slug) ON UPDATE NO ACTION ON DELETE NO ACTION MATCH NONE | +| id | PRIMARY KEY | PRIMARY KEY (id) | +| sqlite_autoindex_user_1 | PRIMARY KEY | PRIMARY KEY (id) | +| sqlite_autoindex_user_2 | UNIQUE | UNIQUE (email) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| sqlite_autoindex_user_1 | PRIMARY KEY (id) | +| sqlite_autoindex_user_2 | UNIQUE (email) | +| user_role_idx | CREATE INDEX "user_role_idx" ON "user" ("roleSlug") | + +## Relations + +```mermaid +erDiagram + +"agent_history" }o--o| "user" : "FOREIGN KEY (publishedById) REFERENCES user (id) ON UPDATE NO ACTION ON DELETE SET NULL MATCH NONE" +"auth_identity" }o--o| "user" : "FOREIGN KEY (userId) REFERENCES user (id) ON UPDATE NO ACTION ON DELETE NO ACTION MATCH NONE" +"chat_hub_agents" }o--|| "user" : "FOREIGN KEY (ownerId) REFERENCES user (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"chat_hub_sessions" }o--|| "user" : "FOREIGN KEY (ownerId) REFERENCES user (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"chat_hub_tools" }o--|| "user" : "FOREIGN KEY (ownerId) REFERENCES user (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"dynamic_credential_user_entry" |o--|| "user" : "FOREIGN KEY (userId) REFERENCES user (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"evaluation_collection" }o--o| "user" : "FOREIGN KEY (createdById) REFERENCES user (id) ON UPDATE NO ACTION ON DELETE SET NULL MATCH NONE" +"instance_ai_mcp_registry_connections" }o--|| "user" : "FOREIGN KEY (userId) REFERENCES user (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"instance_ai_pending_confirmations" }o--|| "user" : "FOREIGN KEY (userId) REFERENCES user (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"oauth_access_tokens" }o--|| "user" : "FOREIGN KEY (userId) REFERENCES user (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"oauth_authorization_codes" }o--|| "user" : "FOREIGN KEY (userId) REFERENCES user (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"oauth_refresh_tokens" }o--|| "user" : "FOREIGN KEY (userId) REFERENCES user (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"oauth_user_consents" }o--|| "user" : "FOREIGN KEY (userId) REFERENCES user (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"project" }o--o| "user" : "FOREIGN KEY (creatorId) REFERENCES user (id) ON UPDATE NO ACTION ON DELETE SET NULL MATCH NONE" +"project_relation" |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" +"workflow_builder_session" }o--|| "user" : "FOREIGN KEY (userId) REFERENCES user (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"workflow_publish_history" }o--o| "user" : "FOREIGN KEY (userId) REFERENCES user (id) ON UPDATE NO ACTION ON DELETE SET NULL MATCH NONE" +"user" }o--|| "role" : "FOREIGN KEY (roleSlug) REFERENCES role (slug) ON UPDATE NO ACTION ON DELETE NO ACTION MATCH NONE" + +"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_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 +} +"auth_identity" { + timestamp createdAt + VARCHAR_64_ providerId PK + VARCHAR_32_ providerType PK + timestamp updatedAt + VARCHAR_36_ userId FK +} +"chat_hub_agents" { + datetime_3_ createdAt + varchar_36_ credentialId FK + varchar_512_ description + TEXT files + TEXT icon + varchar id PK + varchar_64_ model + varchar_256_ name + varchar ownerId FK + varchar_16_ provider + TEXT suggestedPrompts + TEXT systemPrompt + datetime_3_ updatedAt +} +"chat_hub_sessions" { + varchar_36_ agentId FK + varchar_128_ agentName + datetime_3_ createdAt + varchar_36_ credentialId FK + varchar id PK + datetime_3_ lastMessageAt + varchar_64_ model + varchar ownerId FK + varchar_16_ provider + varchar_256_ title + varchar_16_ type + datetime_3_ updatedAt + varchar_36_ workflowId FK +} +"chat_hub_tools" { + datetime_3_ createdAt + TEXT definition + boolean enabled + varchar id PK + varchar_255_ name + varchar ownerId FK + varchar_255_ type + REAL typeVersion + datetime_3_ updatedAt +} +"dynamic_credential_user_entry" { + datetime_3_ createdAt + varchar_16_ credentialId PK + TEXT data + varchar_16_ resolverId PK + datetime_3_ updatedAt + varchar userId PK +} +"evaluation_collection" { + datetime_3_ createdAt + varchar createdById FK + TEXT description + varchar_36_ evaluationConfigId FK + varchar_36_ id PK + TEXT insightsCache + varchar_128_ name + datetime_3_ updatedAt + varchar_36_ workflowId FK +} +"instance_ai_mcp_registry_connections" { + datetime_3_ createdAt + varchar_36_ credentialId FK + varchar id PK + varchar_255_ serverSlug FK + TEXT toolFilter + datetime_3_ updatedAt + varchar userId FK +} +"instance_ai_pending_confirmations" { + varchar_255_ checkpointKey FK + varchar_36_ checkpointTaskId + datetime_3_ createdAt + datetime_3_ expiresAt + varchar_16_ kind + varchar_36_ messageGroupId + varchar_36_ requestId PK + varchar_36_ runId + varchar threadId FK + varchar_64_ toolCallId + datetime_3_ updatedAt + varchar userId FK +} +"oauth_access_tokens" { + varchar clientId FK + varchar token PK + varchar userId FK +} +"oauth_authorization_codes" { + varchar clientId FK + varchar_255_ code PK + varchar codeChallenge + varchar_255_ codeChallengeMethod + datetime_3_ createdAt + bigint expiresAt + varchar redirectUri + varchar resource + TEXT scope + varchar state + datetime_3_ updatedAt + boolean used + varchar userId FK +} +"oauth_refresh_tokens" { + varchar clientId FK + datetime_3_ createdAt + bigint expiresAt + TEXT scope + varchar_255_ token PK + datetime_3_ updatedAt + varchar userId FK +} +"oauth_user_consents" { + varchar clientId FK + bigint grantedAt + INTEGER id + varchar userId FK +} +"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 +} +"project_relation" { + datetime_3_ createdAt + varchar_36_ projectId PK + varchar role FK + datetime_3_ updatedAt + varchar userId PK +} +"user_api_keys" { + varchar apiKey + varchar audience + datetime_3_ createdAt + varchar_36_ id PK + varchar_100_ label + datetime_3_ lastUsedAt + TEXT scopes + datetime_3_ updatedAt + varchar userId FK +} +"user_favorites" { + INTEGER id + varchar_255_ resourceId + varchar_64_ resourceType + varchar userId FK +} +"workflow_builder_session" { + varchar_255_ activeVersionCardId + datetime_3_ createdAt + varchar id PK + TEXT messages + TEXT previousSummary + varchar_255_ resumeAfterRestoreMessageId + datetime_3_ updatedAt + varchar userId FK + varchar_36_ workflowId FK +} +"workflow_publish_history" { + datetime_3_ createdAt + varchar_36_ event + INTEGER id + varchar userId FK + varchar_36_ versionId FK + varchar_36_ workflowId FK +} +"role" { + datetime_3_ createdAt + TEXT description + TEXT displayName + TEXT roleType + varchar_128_ slug PK + boolean systemRole + datetime_3_ updatedAt +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/sqlite-schema/user_api_keys.md b/docs/generated/sqlite-schema/user_api_keys.md new file mode 100644 index 00000000000..8bf2bcff06c --- /dev/null +++ b/docs/generated/sqlite-schema/user_api_keys.md @@ -0,0 +1,85 @@ +# user_api_keys + +## Description + +<details> +<summary><strong>Table Definition</strong></summary> + +```sql +CREATE TABLE "user_api_keys" ("id" varchar(36) PRIMARY KEY NOT NULL, "userId" varchar NOT NULL, "label" varchar(100) NOT NULL, "apiKey" varchar 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')), "scopes" text, "audience" varchar NOT NULL DEFAULT ('public-api'), "lastUsedAt" datetime(3), CONSTRAINT "UQ_1ef35bac35d20bdae979d917a36" UNIQUE ("apiKey"), CONSTRAINT "UQ_63d7bbae72c767cf162d459fccd" UNIQUE ("userId", "label"), CONSTRAINT "FK_e131705cbbc8fb589889b02d457" FOREIGN KEY ("userId") REFERENCES "user" ("id") ON DELETE CASCADE ON UPDATE NO ACTION) +``` + +</details> + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| apiKey | varchar | | false | | | | +| audience | varchar | 'public-api' | false | | | | +| createdAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | +| id | varchar(36) | | false | | | | +| label | varchar(100) | | false | | | | +| lastUsedAt | datetime(3) | | true | | | | +| scopes | TEXT | | true | | | | +| updatedAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | +| userId | varchar | | false | | [user](user.md) | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| - (Foreign key ID: 0) | FOREIGN KEY | FOREIGN KEY (userId) REFERENCES user (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| id | PRIMARY KEY | PRIMARY KEY (id) | +| sqlite_autoindex_user_api_keys_1 | PRIMARY KEY | PRIMARY KEY (id) | +| sqlite_autoindex_user_api_keys_2 | UNIQUE | UNIQUE (apiKey) | +| sqlite_autoindex_user_api_keys_3 | UNIQUE | UNIQUE (userId, label) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| sqlite_autoindex_user_api_keys_1 | PRIMARY KEY (id) | +| sqlite_autoindex_user_api_keys_2 | UNIQUE (apiKey) | +| sqlite_autoindex_user_api_keys_3 | UNIQUE (userId, label) | + +## Relations + +```mermaid +erDiagram + +"user_api_keys" }o--|| "user" : "FOREIGN KEY (userId) REFERENCES user (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" + +"user_api_keys" { + varchar apiKey + varchar audience + datetime_3_ createdAt + varchar_36_ id PK + varchar_100_ label + datetime_3_ lastUsedAt + TEXT scopes + datetime_3_ updatedAt + varchar userId FK +} +"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 +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/sqlite-schema/user_favorites.md b/docs/generated/sqlite-schema/user_favorites.md new file mode 100644 index 00000000000..e33d05b6f69 --- /dev/null +++ b/docs/generated/sqlite-schema/user_favorites.md @@ -0,0 +1,73 @@ +# user_favorites + +## Description + +<details> +<summary><strong>Table Definition</strong></summary> + +```sql +CREATE TABLE "user_favorites" ("id" integer PRIMARY KEY NOT NULL, "userId" varchar NOT NULL, "resourceId" varchar(255) NOT NULL, "resourceType" varchar(64) NOT NULL, CONSTRAINT "UQ_cf6ae658ead9ffc124723413c65" UNIQUE ("userId", "resourceId", "resourceType"), CONSTRAINT "FK_1dd5c393ad0517be3c31a7af836" FOREIGN KEY ("userId") REFERENCES "user" ("id") ON DELETE CASCADE) +``` + +</details> + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| id | INTEGER | | false | | | | +| resourceId | varchar(255) | | false | | | | +| resourceType | varchar(64) | | false | | | | +| userId | varchar | | false | | [user](user.md) | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| - (Foreign key ID: 0) | FOREIGN KEY | FOREIGN KEY (userId) REFERENCES user (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| id | PRIMARY KEY | PRIMARY KEY (id) | +| sqlite_autoindex_user_favorites_1 | UNIQUE | UNIQUE (userId, resourceId, resourceType) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_1d11050a381548c42c32cc25c4 | CREATE INDEX "IDX_1d11050a381548c42c32cc25c4" ON "user_favorites" ("resourceType", "resourceId") | +| IDX_1dd5c393ad0517be3c31a7af83 | CREATE INDEX "IDX_1dd5c393ad0517be3c31a7af83" ON "user_favorites" ("userId") | +| sqlite_autoindex_user_favorites_1 | UNIQUE (userId, resourceId, resourceType) | + +## Relations + +```mermaid +erDiagram + +"user_favorites" }o--|| "user" : "FOREIGN KEY (userId) REFERENCES user (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" + +"user_favorites" { + INTEGER id + varchar_255_ resourceId + varchar_64_ resourceType + varchar userId FK +} +"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 +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/sqlite-schema/variables.md b/docs/generated/sqlite-schema/variables.md new file mode 100644 index 00000000000..6f6622d0043 --- /dev/null +++ b/docs/generated/sqlite-schema/variables.md @@ -0,0 +1,69 @@ +# variables + +## Description + +<details> +<summary><strong>Table Definition</strong></summary> + +```sql +CREATE TABLE "variables" ("id" varchar(36) PRIMARY KEY NOT NULL, "key" text NOT NULL, "type" text NOT NULL DEFAULT ('string'), "value" text, "projectId" varchar(36), CONSTRAINT "FK_a0f13eaa709a21b77a3a9721319" FOREIGN KEY ("projectId") REFERENCES "project" ("id") ON DELETE CASCADE) +``` + +</details> + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| id | varchar(36) | | false | | | | +| key | TEXT | | false | | | | +| projectId | varchar(36) | | true | | [project](project.md) | | +| type | TEXT | 'string' | false | | | | +| value | TEXT | | true | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| - (Foreign key ID: 0) | 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_variables_1 | PRIMARY KEY | PRIMARY KEY (id) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| sqlite_autoindex_variables_1 | PRIMARY KEY (id) | +| variables_global_key_unique | CREATE UNIQUE INDEX "variables_global_key_unique"<br /> ON "variables" ("key")<br /> WHERE projectId IS NULL | +| variables_project_key_unique | CREATE UNIQUE INDEX "variables_project_key_unique" ON "variables" ("projectId", "key") | + +## Relations + +```mermaid +erDiagram + +"variables" }o--o| "project" : "FOREIGN KEY (projectId) REFERENCES project (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" + +"variables" { + varchar_36_ id PK + TEXT key + varchar_36_ projectId FK + TEXT type + TEXT value +} +"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/webhook_entity.md b/docs/generated/sqlite-schema/webhook_entity.md new file mode 100644 index 00000000000..6baff78a601 --- /dev/null +++ b/docs/generated/sqlite-schema/webhook_entity.md @@ -0,0 +1,58 @@ +# webhook_entity + +## Description + +<details> +<summary><strong>Table Definition</strong></summary> + +```sql +CREATE TABLE "webhook_entity" ("workflowId" varchar(36) NOT NULL, "webhookPath" varchar NOT NULL, "method" varchar NOT NULL, "node" varchar NOT NULL, "webhookId" varchar, "pathLength" integer, PRIMARY KEY ("webhookPath", "method")) +``` + +</details> + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| method | varchar | | false | | | | +| node | varchar | | false | | | | +| pathLength | INTEGER | | true | | | | +| webhookId | varchar | | true | | | | +| webhookPath | varchar | | false | | | | +| workflowId | varchar(36) | | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| method | PRIMARY KEY | PRIMARY KEY (method) | +| sqlite_autoindex_webhook_entity_1 | PRIMARY KEY | PRIMARY KEY (webhookPath, method) | +| webhookPath | PRIMARY KEY | PRIMARY KEY (webhookPath) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| idx_webhook_entity_webhook_path_method | CREATE INDEX "idx_webhook_entity_webhook_path_method" ON "webhook_entity" ("webhookId","method","pathLength") | +| sqlite_autoindex_webhook_entity_1 | PRIMARY KEY (webhookPath, method) | + +## Relations + +```mermaid +erDiagram + + +"webhook_entity" { + varchar method PK + varchar node + INTEGER pathLength + varchar webhookId + varchar webhookPath PK + varchar_36_ workflowId +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/sqlite-schema/workflow_builder_session.md b/docs/generated/sqlite-schema/workflow_builder_session.md new file mode 100644 index 00000000000..dc75530201c --- /dev/null +++ b/docs/generated/sqlite-schema/workflow_builder_session.md @@ -0,0 +1,107 @@ +# workflow_builder_session + +## Description + +<details> +<summary><strong>Table Definition</strong></summary> + +```sql +CREATE TABLE "workflow_builder_session" ("id" varchar PRIMARY KEY NOT NULL, "workflowId" varchar(36) NOT NULL, "userId" varchar NOT NULL, "messages" text NOT NULL DEFAULT ('[]'), "previousSummary" text, "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')), "activeVersionCardId" varchar(255), "resumeAfterRestoreMessageId" varchar(255), CONSTRAINT "UQ_ec2aa73632932d485a1d5192ce1" UNIQUE ("workflowId", "userId"), CONSTRAINT "FK_00290cdeee4d4d7db84709be936" FOREIGN KEY ("userId") REFERENCES "user" ("id") ON DELETE CASCADE ON UPDATE NO ACTION, CONSTRAINT "FK_7983c618db48f47bf5a4cc1e1e4" FOREIGN KEY ("workflowId") REFERENCES "workflow_entity" ("id") ON DELETE CASCADE ON UPDATE NO ACTION) +``` + +</details> + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| activeVersionCardId | varchar(255) | | true | | | | +| createdAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | +| id | varchar | | false | | | | +| messages | TEXT | '[]' | false | | | | +| previousSummary | TEXT | | true | | | | +| resumeAfterRestoreMessageId | varchar(255) | | true | | | | +| updatedAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | +| userId | varchar | | false | | [user](user.md) | | +| workflowId | varchar(36) | | false | | [workflow_entity](workflow_entity.md) | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| - (Foreign key ID: 0) | FOREIGN KEY | FOREIGN KEY (workflowId) REFERENCES workflow_entity (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| - (Foreign key ID: 1) | FOREIGN KEY | FOREIGN KEY (userId) REFERENCES user (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| id | PRIMARY KEY | PRIMARY KEY (id) | +| sqlite_autoindex_workflow_builder_session_1 | PRIMARY KEY | PRIMARY KEY (id) | +| sqlite_autoindex_workflow_builder_session_2 | UNIQUE | UNIQUE (workflowId, userId) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| sqlite_autoindex_workflow_builder_session_1 | PRIMARY KEY (id) | +| sqlite_autoindex_workflow_builder_session_2 | UNIQUE (workflowId, userId) | + +## Relations + +```mermaid +erDiagram + +"workflow_builder_session" }o--|| "user" : "FOREIGN KEY (userId) REFERENCES user (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"workflow_builder_session" }o--|| "workflow_entity" : "FOREIGN KEY (workflowId) REFERENCES workflow_entity (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" + +"workflow_builder_session" { + varchar_255_ activeVersionCardId + datetime_3_ createdAt + varchar id PK + TEXT messages + TEXT previousSummary + varchar_255_ resumeAfterRestoreMessageId + datetime_3_ updatedAt + varchar userId FK + varchar_36_ workflowId FK +} +"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 +} +"workflow_entity" { + boolean active + varchar_36_ activeVersionId FK + TEXT connections + datetime_3_ createdAt + TEXT description + varchar_36_ id PK + boolean isArchived + TEXT meta + varchar_128_ name + TEXT nodeGroups + TEXT nodes + varchar_36_ parentFolderId FK + TEXT pinData + TEXT settings + varchar sourceWorkflowId + TEXT staticData + INTEGER triggerCount + datetime_3_ updatedAt + INTEGER versionCounter + varchar_36_ versionId +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/sqlite-schema/workflow_dependency.md b/docs/generated/sqlite-schema/workflow_dependency.md new file mode 100644 index 00000000000..45d6e85d7c4 --- /dev/null +++ b/docs/generated/sqlite-schema/workflow_dependency.md @@ -0,0 +1,88 @@ +# workflow_dependency + +## Description + +<details> +<summary><strong>Table Definition</strong></summary> + +```sql +CREATE TABLE "workflow_dependency" ("id" integer PRIMARY KEY NOT NULL, "workflowId" varchar(36) NOT NULL, "workflowVersionId" integer NOT NULL, "dependencyType" varchar(32) NOT NULL, "dependencyKey" varchar(255) NOT NULL, "indexVersionId" smallint NOT NULL DEFAULT (1), "createdAt" datetime(3) NOT NULL DEFAULT (STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW')), "dependencyInfo" text, "publishedVersionId" varchar(36), CONSTRAINT "FK_a4ff2d9b9628ea988fa9e7d0bf8" FOREIGN KEY ("workflowId") REFERENCES "workflow_entity" ("id") ON DELETE CASCADE ON UPDATE NO ACTION) +``` + +</details> + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| createdAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | +| dependencyInfo | TEXT | | true | | | | +| dependencyKey | varchar(255) | | false | | | | +| dependencyType | varchar(32) | | false | | | | +| id | INTEGER | | false | | | | +| indexVersionId | smallint | 1 | false | | | | +| publishedVersionId | varchar(36) | | true | | | | +| workflowId | varchar(36) | | false | | [workflow_entity](workflow_entity.md) | | +| workflowVersionId | INTEGER | | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| - (Foreign key ID: 0) | FOREIGN KEY | FOREIGN KEY (workflowId) REFERENCES workflow_entity (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| id | PRIMARY KEY | PRIMARY KEY (id) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_a4ff2d9b9628ea988fa9e7d0bf | CREATE INDEX "IDX_a4ff2d9b9628ea988fa9e7d0bf" ON "workflow_dependency" ("workflowId") | +| IDX_e48a201071ab85d9d09119d640 | CREATE INDEX "IDX_e48a201071ab85d9d09119d640" ON "workflow_dependency" ("dependencyKey") | +| IDX_e7fe1cfda990c14a445937d0b9 | CREATE INDEX "IDX_e7fe1cfda990c14a445937d0b9" ON "workflow_dependency" ("dependencyType") | +| IDX_workflow_dependency_publishedVersionId | CREATE INDEX "IDX_workflow_dependency_publishedVersionId" ON "workflow_dependency" ("publishedVersionId") | + +## Relations + +```mermaid +erDiagram + +"workflow_dependency" }o--|| "workflow_entity" : "FOREIGN KEY (workflowId) REFERENCES workflow_entity (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" + +"workflow_dependency" { + datetime_3_ createdAt + TEXT dependencyInfo + varchar_255_ dependencyKey + varchar_32_ dependencyType + INTEGER id + smallint indexVersionId + varchar_36_ publishedVersionId + varchar_36_ workflowId FK + INTEGER workflowVersionId +} +"workflow_entity" { + boolean active + varchar_36_ activeVersionId FK + TEXT connections + datetime_3_ createdAt + TEXT description + varchar_36_ id PK + boolean isArchived + TEXT meta + varchar_128_ name + TEXT nodeGroups + TEXT nodes + varchar_36_ parentFolderId FK + TEXT pinData + TEXT settings + varchar sourceWorkflowId + TEXT staticData + INTEGER triggerCount + datetime_3_ updatedAt + INTEGER versionCounter + varchar_36_ versionId +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/sqlite-schema/workflow_entity.md b/docs/generated/sqlite-schema/workflow_entity.md new file mode 100644 index 00000000000..e9702532b6e --- /dev/null +++ b/docs/generated/sqlite-schema/workflow_entity.md @@ -0,0 +1,298 @@ +# workflow_entity + +## Description + +<details> +<summary><strong>Table Definition</strong></summary> + +```sql +CREATE TABLE "workflow_entity" ("id" varchar(36) PRIMARY KEY NOT NULL, "name" varchar(128) NOT NULL, "active" boolean NOT NULL, "nodes" text, "connections" text, "settings" text, "staticData" text, "pinData" text, "versionId" varchar(36) NOT NULL, "triggerCount" integer DEFAULT (0), "meta" text, "parentFolderId" varchar(36), "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')), "isArchived" boolean NOT NULL DEFAULT (FALSE), "versionCounter" integer NOT NULL DEFAULT (1), "description" text, "activeVersionId" varchar(36), "nodeGroups" text NOT NULL DEFAULT ('[]'), "sourceWorkflowId" varchar, CONSTRAINT "FK_04a4db5906fbc5606c71448d912" FOREIGN KEY ("parentFolderId") REFERENCES "folder" ("id") ON DELETE CASCADE ON UPDATE NO ACTION, CONSTRAINT "FK_08d6c67b7f722b0039d9d5ed620" FOREIGN KEY ("activeVersionId") REFERENCES "workflow_history" ("versionId") ON DELETE RESTRICT ON UPDATE NO ACTION) +``` + +</details> + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| active | boolean | | false | | | | +| activeVersionId | varchar(36) | | true | | [workflow_history](workflow_history.md) | | +| connections | TEXT | | true | | | | +| createdAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | +| description | TEXT | | true | | | | +| id | varchar(36) | | false | [ai_builder_temporary_workflow](ai_builder_temporary_workflow.md) [chat_hub_messages](chat_hub_messages.md) [chat_hub_sessions](chat_hub_sessions.md) [evaluation_collection](evaluation_collection.md) [evaluation_config](evaluation_config.md) [execution_entity](execution_entity.md) [insights_metadata](insights_metadata.md) [processed_data](processed_data.md) [shared_workflow](shared_workflow.md) [test_run](test_run.md) [workflow_builder_session](workflow_builder_session.md) [workflow_dependency](workflow_dependency.md) [workflow_history](workflow_history.md) [workflow_publish_history](workflow_publish_history.md) [workflow_published_version](workflow_published_version.md) [workflows_tags](workflows_tags.md) | | | +| isArchived | boolean | FALSE | false | | | | +| meta | TEXT | | true | | | | +| name | varchar(128) | | false | | | | +| nodeGroups | TEXT | '[]' | false | | | | +| nodes | TEXT | | true | | | | +| parentFolderId | varchar(36) | | true | | [folder](folder.md) | | +| pinData | TEXT | | true | | | | +| settings | TEXT | | true | | | | +| sourceWorkflowId | varchar | | true | | | | +| staticData | TEXT | | true | | | | +| triggerCount | INTEGER | 0 | true | | | | +| updatedAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | +| versionCounter | INTEGER | 1 | false | | | | +| versionId | varchar(36) | | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| - (Foreign key ID: 0) | FOREIGN KEY | FOREIGN KEY (activeVersionId) REFERENCES workflow_history (versionId) ON UPDATE NO ACTION ON DELETE RESTRICT MATCH NONE | +| - (Foreign key ID: 1) | FOREIGN KEY | FOREIGN KEY (parentFolderId) REFERENCES folder (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| id | PRIMARY KEY | PRIMARY KEY (id) | +| sqlite_autoindex_workflow_entity_1 | PRIMARY KEY | PRIMARY KEY (id) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_e10425f6ab9964c4c1623a4a03 | CREATE INDEX "IDX_e10425f6ab9964c4c1623a4a03" ON "workflow_entity" ("name") | +| IDX_workflow_entity_sourceWorkflowId | CREATE INDEX "IDX_workflow_entity_sourceWorkflowId" ON "workflow_entity" ("sourceWorkflowId") WHERE "sourceWorkflowId" IS NOT NULL | +| sqlite_autoindex_workflow_entity_1 | PRIMARY KEY (id) | + +## Triggers + +| Name | Definition | +| ---- | ---------- | +| workflow_version_increment | CREATE TRIGGER "workflow_version_increment"<br /> AFTER UPDATE ON "workflow_entity"<br /> FOR EACH ROW<br /> WHEN OLD."versionCounter" = NEW."versionCounter"<br /> AND (OLD."nodes" IS NOT NEW."nodes" OR OLD."settings" IS NOT NEW."settings")<br /> BEGIN<br /> UPDATE "workflow_entity"<br /> SET "versionCounter" = "versionCounter" + 1<br /> WHERE "id" = NEW."id";<br /> END | + +## Relations + +```mermaid +erDiagram + +"workflow_entity" }o--o| "workflow_history" : "FOREIGN KEY (activeVersionId) REFERENCES workflow_history (versionId) ON UPDATE NO ACTION ON DELETE RESTRICT MATCH NONE" +"ai_builder_temporary_workflow" |o--|| "workflow_entity" : "FOREIGN KEY (workflowId) REFERENCES workflow_entity (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"chat_hub_messages" }o--o| "workflow_entity" : "FOREIGN KEY (workflowId) REFERENCES workflow_entity (id) ON UPDATE NO ACTION ON DELETE SET NULL MATCH NONE" +"chat_hub_sessions" }o--o| "workflow_entity" : "FOREIGN KEY (workflowId) REFERENCES workflow_entity (id) ON UPDATE NO ACTION ON DELETE SET NULL MATCH NONE" +"evaluation_collection" }o--|| "workflow_entity" : "FOREIGN KEY (workflowId) REFERENCES workflow_entity (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"evaluation_config" }o--|| "workflow_entity" : "FOREIGN KEY (workflowId) REFERENCES workflow_entity (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"execution_entity" }o--|| "workflow_entity" : "FOREIGN KEY (workflowId) REFERENCES workflow_entity (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"insights_metadata" }o--o| "workflow_entity" : "FOREIGN KEY (workflowId) REFERENCES workflow_entity (id) ON UPDATE NO ACTION ON DELETE SET NULL MATCH NONE" +"processed_data" |o--|| "workflow_entity" : "FOREIGN KEY (workflowId) REFERENCES workflow_entity (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" +"test_run" }o--|| "workflow_entity" : "FOREIGN KEY (workflowId) REFERENCES workflow_entity (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"workflow_builder_session" }o--|| "workflow_entity" : "FOREIGN KEY (workflowId) REFERENCES workflow_entity (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"workflow_dependency" }o--|| "workflow_entity" : "FOREIGN KEY (workflowId) REFERENCES workflow_entity (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"workflow_history" }o--|| "workflow_entity" : "FOREIGN KEY (workflowId) REFERENCES workflow_entity (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"workflow_publish_history" }o--|| "workflow_entity" : "FOREIGN KEY (workflowId) REFERENCES workflow_entity (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"workflow_published_version" |o--|| "workflow_entity" : "FOREIGN KEY (workflowId) REFERENCES workflow_entity (id) ON UPDATE NO ACTION ON DELETE RESTRICT MATCH NONE" +"workflow_published_version" |o--|| "workflow_entity" : "FOREIGN KEY (workflowId) REFERENCES workflow_entity (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"workflows_tags" |o--|| "workflow_entity" : "FOREIGN KEY (workflowId) REFERENCES workflow_entity (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"workflow_entity" }o--o| "folder" : "FOREIGN KEY (parentFolderId) REFERENCES folder (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" + +"workflow_entity" { + boolean active + varchar_36_ activeVersionId FK + TEXT connections + datetime_3_ createdAt + TEXT description + varchar_36_ id PK + boolean isArchived + TEXT meta + varchar_128_ name + TEXT nodeGroups + TEXT nodes + varchar_36_ parentFolderId FK + TEXT pinData + TEXT settings + varchar sourceWorkflowId + TEXT staticData + INTEGER triggerCount + datetime_3_ updatedAt + INTEGER versionCounter + varchar_36_ versionId +} +"workflow_history" { + varchar_255_ authors + boolean autosaved + TEXT connections + datetime_3_ createdAt + TEXT description + varchar_128_ name + TEXT nodeGroups + TEXT nodes + datetime_3_ updatedAt + varchar_36_ versionId PK + varchar_36_ workflowId FK +} +"ai_builder_temporary_workflow" { + datetime_3_ createdAt + varchar threadId FK + datetime_3_ updatedAt + varchar_36_ workflowId PK +} +"chat_hub_messages" { + varchar_36_ agentId FK + TEXT attachments + TEXT content + datetime_3_ createdAt + INTEGER executionId FK + varchar id PK + VARCHAR_256_ model + varchar_128_ name + varchar previousMessageId FK + varchar_16_ provider + varchar retryOfMessageId FK + varchar revisionOfMessageId FK + varchar sessionId FK + varchar_16_ status + varchar_16_ type + datetime_3_ updatedAt + varchar_36_ workflowId FK +} +"chat_hub_sessions" { + varchar_36_ agentId FK + varchar_128_ agentName + datetime_3_ createdAt + varchar_36_ credentialId FK + varchar id PK + datetime_3_ lastMessageAt + varchar_64_ model + varchar ownerId FK + varchar_16_ provider + varchar_256_ title + varchar_16_ type + datetime_3_ updatedAt + varchar_36_ workflowId FK +} +"evaluation_collection" { + datetime_3_ createdAt + varchar createdById FK + TEXT description + varchar_36_ evaluationConfigId FK + varchar_36_ id PK + TEXT insightsCache + varchar_128_ name + datetime_3_ updatedAt + varchar_36_ workflowId FK +} +"evaluation_config" { + datetime_3_ createdAt + TEXT datasetRef + varchar_32_ datasetSource + varchar_255_ endNodeName + varchar_36_ id PK + varchar_64_ invalidReason + TEXT metrics + varchar_128_ name + varchar_255_ startNodeName + varchar_16_ status + datetime_3_ updatedAt + varchar_36_ workflowId FK +} +"execution_entity" { + BIGINT binaryDataSizeBytes + datetime_3_ createdAt + varchar_255_ deduplicationKey + datetime_3_ deletedAt + boolean finished + INTEGER id + BIGINT jsonSizeBytes + varchar mode + varchar retryOf + varchar retrySuccessId + datetime startedAt + varchar status + datetime stoppedAt + varchar_2_ storedAt + TEXT tracingContext + datetime waitTill + varchar_36_ workflowId FK + VARCHAR_36_ workflowVersionId +} +"insights_metadata" { + INTEGER metaId + varchar_36_ projectId FK + varchar_255_ projectName + varchar_16_ workflowId FK + varchar_128_ workflowName +} +"processed_data" { + varchar_255_ context PK + datetime_3_ createdAt + datetime_3_ updatedAt + TEXT value + varchar_36_ workflowId PK +} +"shared_workflow" { + datetime_3_ createdAt + varchar_36_ projectId PK + TEXT role + datetime_3_ updatedAt + varchar_36_ workflowId PK +} +"test_run" { + boolean cancelRequested + varchar_36_ collectionId FK + datetime_3_ completedAt + datetime_3_ createdAt + varchar errorCode + TEXT errorDetails + varchar_36_ evaluationConfigId FK + TEXT evaluationConfigSnapshot + varchar_36_ id PK + TEXT metrics + datetime_3_ runAt + varchar_255_ runningInstanceId + varchar status + datetime_3_ updatedAt + varchar_36_ workflowId FK + varchar_36_ workflowVersionId +} +"workflow_builder_session" { + varchar_255_ activeVersionCardId + datetime_3_ createdAt + varchar id PK + TEXT messages + TEXT previousSummary + varchar_255_ resumeAfterRestoreMessageId + datetime_3_ updatedAt + varchar userId FK + varchar_36_ workflowId FK +} +"workflow_dependency" { + datetime_3_ createdAt + TEXT dependencyInfo + varchar_255_ dependencyKey + varchar_32_ dependencyType + INTEGER id + smallint indexVersionId + varchar_36_ publishedVersionId + varchar_36_ workflowId FK + INTEGER workflowVersionId +} +"workflow_publish_history" { + datetime_3_ createdAt + varchar_36_ event + INTEGER id + varchar userId FK + varchar_36_ versionId FK + varchar_36_ workflowId FK +} +"workflow_published_version" { + datetime_3_ createdAt + varchar_36_ publishedVersionId FK + datetime_3_ updatedAt + varchar_36_ workflowId PK +} +"workflows_tags" { + INTEGER tagId PK + varchar_36_ workflowId PK +} +"folder" { + datetime_3_ createdAt + varchar_36_ id PK + varchar_128_ name + varchar_36_ parentFolderId FK + varchar_36_ projectId FK + datetime_3_ updatedAt +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/sqlite-schema/workflow_history.md b/docs/generated/sqlite-schema/workflow_history.md new file mode 100644 index 00000000000..2762dae636b --- /dev/null +++ b/docs/generated/sqlite-schema/workflow_history.md @@ -0,0 +1,110 @@ +# workflow_history + +## Description + +<details> +<summary><strong>Table Definition</strong></summary> + +```sql +CREATE TABLE "workflow_history" ("versionId" varchar(36) PRIMARY KEY NOT NULL, "workflowId" varchar(36) NOT NULL, "authors" varchar(255) 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')), "nodes" text NOT NULL, "connections" text NOT NULL, "name" varchar(128), "autosaved" boolean NOT NULL DEFAULT (false), "description" text, "nodeGroups" text NOT NULL DEFAULT ('[]'), CONSTRAINT "FK_1e31657f5fe46816c34be7c1b4b" FOREIGN KEY ("workflowId") REFERENCES "workflow_entity" ("id") ON DELETE CASCADE ON UPDATE NO ACTION) +``` + +</details> + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| authors | varchar(255) | | false | | | | +| autosaved | boolean | false | false | | | | +| connections | TEXT | | false | | | | +| createdAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | +| description | TEXT | | true | | | | +| name | varchar(128) | | true | | | | +| nodeGroups | TEXT | '[]' | false | | | | +| nodes | TEXT | | false | | | | +| updatedAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | +| versionId | varchar(36) | | false | [workflow_entity](workflow_entity.md) [workflow_publish_history](workflow_publish_history.md) [workflow_published_version](workflow_published_version.md) | | | +| workflowId | varchar(36) | | false | | [workflow_entity](workflow_entity.md) | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| - (Foreign key ID: 0) | FOREIGN KEY | FOREIGN KEY (workflowId) REFERENCES workflow_entity (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| sqlite_autoindex_workflow_history_1 | PRIMARY KEY | PRIMARY KEY (versionId) | +| versionId | PRIMARY KEY | PRIMARY KEY (versionId) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_1e31657f5fe46816c34be7c1b4 | CREATE INDEX "IDX_1e31657f5fe46816c34be7c1b4" ON "workflow_history" ("workflowId") | +| sqlite_autoindex_workflow_history_1 | PRIMARY KEY (versionId) | + +## Relations + +```mermaid +erDiagram + +"workflow_entity" }o--o| "workflow_history" : "FOREIGN KEY (activeVersionId) REFERENCES workflow_history (versionId) ON UPDATE NO ACTION ON DELETE RESTRICT MATCH NONE" +"workflow_publish_history" }o--o| "workflow_history" : "FOREIGN KEY (versionId) REFERENCES workflow_history (versionId) ON UPDATE NO ACTION ON DELETE SET NULL MATCH NONE" +"workflow_publish_history" }o--o| "workflow_history" : "FOREIGN KEY (versionId) REFERENCES workflow_history (versionId) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"workflow_published_version" }o--|| "workflow_history" : "FOREIGN KEY (publishedVersionId) REFERENCES workflow_history (versionId) ON UPDATE NO ACTION ON DELETE RESTRICT MATCH NONE" +"workflow_published_version" }o--|| "workflow_history" : "FOREIGN KEY (publishedVersionId) REFERENCES workflow_history (versionId) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"workflow_history" }o--|| "workflow_entity" : "FOREIGN KEY (workflowId) REFERENCES workflow_entity (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" + +"workflow_history" { + varchar_255_ authors + boolean autosaved + TEXT connections + datetime_3_ createdAt + TEXT description + varchar_128_ name + TEXT nodeGroups + TEXT nodes + datetime_3_ updatedAt + varchar_36_ versionId PK + varchar_36_ workflowId FK +} +"workflow_entity" { + boolean active + varchar_36_ activeVersionId FK + TEXT connections + datetime_3_ createdAt + TEXT description + varchar_36_ id PK + boolean isArchived + TEXT meta + varchar_128_ name + TEXT nodeGroups + TEXT nodes + varchar_36_ parentFolderId FK + TEXT pinData + TEXT settings + varchar sourceWorkflowId + TEXT staticData + INTEGER triggerCount + datetime_3_ updatedAt + INTEGER versionCounter + varchar_36_ versionId +} +"workflow_publish_history" { + datetime_3_ createdAt + varchar_36_ event + INTEGER id + varchar userId FK + varchar_36_ versionId FK + varchar_36_ workflowId FK +} +"workflow_published_version" { + datetime_3_ createdAt + varchar_36_ publishedVersionId FK + datetime_3_ updatedAt + varchar_36_ workflowId PK +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/sqlite-schema/workflow_publication_outbox.md b/docs/generated/sqlite-schema/workflow_publication_outbox.md new file mode 100644 index 00000000000..cabe5eb35de --- /dev/null +++ b/docs/generated/sqlite-schema/workflow_publication_outbox.md @@ -0,0 +1,58 @@ +# workflow_publication_outbox + +## Description + +<details> +<summary><strong>Table Definition</strong></summary> + +```sql +CREATE TABLE "workflow_publication_outbox" ("id" integer PRIMARY KEY NOT NULL, "workflowId" varchar(36) NOT NULL, "publishedVersionId" varchar(36) NOT NULL, "status" varchar(20) NOT NULL, "errorMessage" text, "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_workflow_publication_outbox_status" CHECK ("status" IN ('pending', 'in_progress', 'completed', 'partial_success', 'failed'))) +``` + +</details> + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| createdAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | +| errorMessage | TEXT | | true | | | | +| id | INTEGER | | false | | | | +| publishedVersionId | varchar(36) | | false | | | | +| status | varchar(20) | | false | | | | +| updatedAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | +| workflowId | varchar(36) | | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| - | CHECK | CHECK ("status" IN ('pending', 'in_progress', 'completed', 'partial_success', 'failed')) | +| id | PRIMARY KEY | PRIMARY KEY (id) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_workflow_publication_outbox_active_workflow_status | CREATE UNIQUE INDEX "IDX_workflow_publication_outbox_active_workflow_status" ON "workflow_publication_outbox" ("workflowId", "status") WHERE status IN ('pending', 'in_progress') | + +## Relations + +```mermaid +erDiagram + + +"workflow_publication_outbox" { + datetime_3_ createdAt + TEXT errorMessage + INTEGER id + varchar_36_ publishedVersionId + varchar_20_ status + datetime_3_ updatedAt + varchar_36_ workflowId +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/sqlite-schema/workflow_publish_history.md b/docs/generated/sqlite-schema/workflow_publish_history.md new file mode 100644 index 00000000000..d9cdb14ff19 --- /dev/null +++ b/docs/generated/sqlite-schema/workflow_publish_history.md @@ -0,0 +1,116 @@ +# workflow_publish_history + +## Description + +<details> +<summary><strong>Table Definition</strong></summary> + +```sql +CREATE TABLE "workflow_publish_history" ("id" integer PRIMARY KEY NOT NULL, "workflowId" varchar(36) NOT NULL, "versionId" varchar(36), "event" varchar(36) NOT NULL, "userId" varchar, "createdAt" datetime(3) NOT NULL DEFAULT (STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW')), CONSTRAINT "CHK_workflow_publish_history_event" CHECK ((("event" IN ('activated', 'deactivated')))), CONSTRAINT "FK_c01316f8c2d7101ec4fa9809267" FOREIGN KEY ("workflowId") REFERENCES "workflow_entity" ("id") ON DELETE CASCADE ON UPDATE NO ACTION, CONSTRAINT "FK_b4cfbc7556d07f36ca177f5e473" FOREIGN KEY ("versionId") REFERENCES "workflow_history" ("versionId") ON DELETE CASCADE ON UPDATE NO ACTION, CONSTRAINT "FK_6eab5bd9eedabe9c54bd879fc40" FOREIGN KEY ("userId") REFERENCES "user" ("id") ON DELETE SET NULL ON UPDATE NO ACTION, CONSTRAINT "FK_b4cfbc7556d07f36ca177f5e473" FOREIGN KEY ("versionId") REFERENCES "workflow_history" ("versionId") ON DELETE SET NULL) +``` + +</details> + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| createdAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | +| event | varchar(36) | | false | | | | +| id | INTEGER | | false | | | | +| userId | varchar | | true | | [user](user.md) | | +| versionId | varchar(36) | | true | | [workflow_history](workflow_history.md) | | +| workflowId | varchar(36) | | false | | [workflow_entity](workflow_entity.md) | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| - | CHECK | CHECK ((("event" IN ('activated', 'deactivated')))) | +| - (Foreign key ID: 0) | FOREIGN KEY | FOREIGN KEY (versionId) REFERENCES workflow_history (versionId) ON UPDATE NO ACTION ON DELETE SET NULL MATCH NONE | +| - (Foreign key ID: 1) | FOREIGN KEY | FOREIGN KEY (userId) REFERENCES user (id) ON UPDATE NO ACTION ON DELETE SET NULL MATCH NONE | +| - (Foreign key ID: 2) | FOREIGN KEY | FOREIGN KEY (versionId) REFERENCES workflow_history (versionId) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| - (Foreign key ID: 3) | FOREIGN KEY | FOREIGN KEY (workflowId) REFERENCES workflow_entity (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| id | PRIMARY KEY | PRIMARY KEY (id) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_070b5de842ece9ccdda0d9738b | CREATE INDEX "IDX_070b5de842ece9ccdda0d9738b" ON "workflow_publish_history" ("workflowId", "versionId") | + +## Relations + +```mermaid +erDiagram + +"workflow_publish_history" }o--o| "user" : "FOREIGN KEY (userId) REFERENCES user (id) ON UPDATE NO ACTION ON DELETE SET NULL MATCH NONE" +"workflow_publish_history" }o--o| "workflow_history" : "FOREIGN KEY (versionId) REFERENCES workflow_history (versionId) ON UPDATE NO ACTION ON DELETE SET NULL MATCH NONE" +"workflow_publish_history" }o--o| "workflow_history" : "FOREIGN KEY (versionId) REFERENCES workflow_history (versionId) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"workflow_publish_history" }o--|| "workflow_entity" : "FOREIGN KEY (workflowId) REFERENCES workflow_entity (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" + +"workflow_publish_history" { + datetime_3_ createdAt + varchar_36_ event + INTEGER id + varchar userId FK + varchar_36_ versionId FK + varchar_36_ workflowId FK +} +"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 +} +"workflow_history" { + varchar_255_ authors + boolean autosaved + TEXT connections + datetime_3_ createdAt + TEXT description + varchar_128_ name + TEXT nodeGroups + TEXT nodes + datetime_3_ updatedAt + varchar_36_ versionId PK + varchar_36_ workflowId FK +} +"workflow_entity" { + boolean active + varchar_36_ activeVersionId FK + TEXT connections + datetime_3_ createdAt + TEXT description + varchar_36_ id PK + boolean isArchived + TEXT meta + varchar_128_ name + TEXT nodeGroups + TEXT nodes + varchar_36_ parentFolderId FK + TEXT pinData + TEXT settings + varchar sourceWorkflowId + TEXT staticData + INTEGER triggerCount + datetime_3_ updatedAt + INTEGER versionCounter + varchar_36_ versionId +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/sqlite-schema/workflow_published_version.md b/docs/generated/sqlite-schema/workflow_published_version.md new file mode 100644 index 00000000000..d8cf659448c --- /dev/null +++ b/docs/generated/sqlite-schema/workflow_published_version.md @@ -0,0 +1,95 @@ +# workflow_published_version + +## Description + +<details> +<summary><strong>Table Definition</strong></summary> + +```sql +CREATE TABLE "workflow_published_version" ("workflowId" varchar(36) PRIMARY KEY NOT NULL, "publishedVersionId" varchar(36) 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_df3428a541b802d6a63ac56e330" FOREIGN KEY ("publishedVersionId") REFERENCES "workflow_history" ("versionId") ON DELETE CASCADE ON UPDATE NO ACTION, CONSTRAINT "FK_5c76fb7ee939fe2530374d3f75a" FOREIGN KEY ("workflowId") REFERENCES "workflow_entity" ("id") ON DELETE CASCADE ON UPDATE NO ACTION, CONSTRAINT "FK_5c76fb7ee939fe2530374d3f75a" FOREIGN KEY ("workflowId") REFERENCES "workflow_entity" ("id") ON DELETE RESTRICT, CONSTRAINT "FK_df3428a541b802d6a63ac56e330" FOREIGN KEY ("publishedVersionId") REFERENCES "workflow_history" ("versionId") ON DELETE RESTRICT) +``` + +</details> + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| createdAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | +| publishedVersionId | varchar(36) | | false | | [workflow_history](workflow_history.md) | | +| updatedAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | +| workflowId | varchar(36) | | false | | [workflow_entity](workflow_entity.md) | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| - (Foreign key ID: 0) | FOREIGN KEY | FOREIGN KEY (publishedVersionId) REFERENCES workflow_history (versionId) ON UPDATE NO ACTION ON DELETE RESTRICT MATCH NONE | +| - (Foreign key ID: 1) | FOREIGN KEY | FOREIGN KEY (workflowId) REFERENCES workflow_entity (id) ON UPDATE NO ACTION ON DELETE RESTRICT MATCH NONE | +| - (Foreign key ID: 2) | FOREIGN KEY | FOREIGN KEY (workflowId) REFERENCES workflow_entity (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| - (Foreign key ID: 3) | FOREIGN KEY | FOREIGN KEY (publishedVersionId) REFERENCES workflow_history (versionId) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| sqlite_autoindex_workflow_published_version_1 | PRIMARY KEY | PRIMARY KEY (workflowId) | +| workflowId | PRIMARY KEY | PRIMARY KEY (workflowId) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| sqlite_autoindex_workflow_published_version_1 | PRIMARY KEY (workflowId) | + +## Relations + +```mermaid +erDiagram + +"workflow_published_version" }o--|| "workflow_history" : "FOREIGN KEY (publishedVersionId) REFERENCES workflow_history (versionId) ON UPDATE NO ACTION ON DELETE RESTRICT MATCH NONE" +"workflow_published_version" }o--|| "workflow_history" : "FOREIGN KEY (publishedVersionId) REFERENCES workflow_history (versionId) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"workflow_published_version" |o--|| "workflow_entity" : "FOREIGN KEY (workflowId) REFERENCES workflow_entity (id) ON UPDATE NO ACTION ON DELETE RESTRICT MATCH NONE" +"workflow_published_version" |o--|| "workflow_entity" : "FOREIGN KEY (workflowId) REFERENCES workflow_entity (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" + +"workflow_published_version" { + datetime_3_ createdAt + varchar_36_ publishedVersionId FK + datetime_3_ updatedAt + varchar_36_ workflowId PK +} +"workflow_history" { + varchar_255_ authors + boolean autosaved + TEXT connections + datetime_3_ createdAt + TEXT description + varchar_128_ name + TEXT nodeGroups + TEXT nodes + datetime_3_ updatedAt + varchar_36_ versionId PK + varchar_36_ workflowId FK +} +"workflow_entity" { + boolean active + varchar_36_ activeVersionId FK + TEXT connections + datetime_3_ createdAt + TEXT description + varchar_36_ id PK + boolean isArchived + TEXT meta + varchar_128_ name + TEXT nodeGroups + TEXT nodes + varchar_36_ parentFolderId FK + TEXT pinData + TEXT settings + varchar sourceWorkflowId + TEXT staticData + INTEGER triggerCount + datetime_3_ updatedAt + INTEGER versionCounter + varchar_36_ versionId +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/sqlite-schema/workflow_statistics.md b/docs/generated/sqlite-schema/workflow_statistics.md new file mode 100644 index 00000000000..58fdbd5a521 --- /dev/null +++ b/docs/generated/sqlite-schema/workflow_statistics.md @@ -0,0 +1,65 @@ +# workflow_statistics + +## Description + +<details> +<summary><strong>Table Definition</strong></summary> + +```sql +CREATE TABLE "workflow_statistics" ( + "id" INTEGER PRIMARY KEY AUTOINCREMENT, + "count" INTEGER DEFAULT 0, + "latestEvent" DATETIME, + "name" VARCHAR(128) NOT NULL, + "workflowId" VARCHAR(36) NOT NULL, + "workflowName" VARCHAR(128), + "rootCount" INTEGER DEFAULT 0 + ) +``` + +</details> + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| count | INTEGER | 0 | true | | | | +| id | INTEGER | | true | | | | +| latestEvent | DATETIME | | true | | | | +| name | VARCHAR(128) | | false | | | | +| rootCount | INTEGER | 0 | true | | | | +| workflowId | VARCHAR(36) | | false | | | | +| workflowName | VARCHAR(128) | | true | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| id | PRIMARY KEY | PRIMARY KEY (id) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_workflow_statistics_workflow_name | CREATE UNIQUE INDEX "IDX_workflow_statistics_workflow_name" ON "workflow_statistics" ("workflowId", "name") | + +## Relations + +```mermaid +erDiagram + + +"workflow_statistics" { + INTEGER count + INTEGER id + DATETIME latestEvent + VARCHAR_128_ name + INTEGER rootCount + VARCHAR_36_ workflowId + VARCHAR_128_ workflowName +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/sqlite-schema/workflows_tags.md b/docs/generated/sqlite-schema/workflows_tags.md new file mode 100644 index 00000000000..1accdaef678 --- /dev/null +++ b/docs/generated/sqlite-schema/workflows_tags.md @@ -0,0 +1,83 @@ +# workflows_tags + +## Description + +<details> +<summary><strong>Table Definition</strong></summary> + +```sql +CREATE TABLE "workflows_tags" ("workflowId" varchar(36) NOT NULL, "tagId" integer NOT NULL, CONSTRAINT "FK_workflows_tags_workflow_entity" FOREIGN KEY ("workflowId") REFERENCES "workflow_entity" ("id") ON DELETE CASCADE ON UPDATE NO ACTION, CONSTRAINT "FK_workflows_tags_tag_entity" FOREIGN KEY ("tagId") REFERENCES "tag_entity" ("id") ON DELETE CASCADE ON UPDATE NO ACTION, PRIMARY KEY ("workflowId", "tagId")) +``` + +</details> + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| tagId | INTEGER | | false | | [tag_entity](tag_entity.md) | | +| workflowId | varchar(36) | | false | | [workflow_entity](workflow_entity.md) | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| - (Foreign key ID: 0) | FOREIGN KEY | FOREIGN KEY (tagId) REFERENCES tag_entity (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| - (Foreign key ID: 1) | FOREIGN KEY | FOREIGN KEY (workflowId) REFERENCES workflow_entity (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| sqlite_autoindex_workflows_tags_1 | PRIMARY KEY | PRIMARY KEY (workflowId, tagId) | +| tagId | PRIMARY KEY | PRIMARY KEY (tagId) | +| workflowId | PRIMARY KEY | PRIMARY KEY (workflowId) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| idx_workflows_tags_tag_id | CREATE INDEX "idx_workflows_tags_tag_id" ON "workflows_tags" ("tagId") | +| idx_workflows_tags_workflow_id | CREATE INDEX "idx_workflows_tags_workflow_id" ON "workflows_tags" ("workflowId") | +| sqlite_autoindex_workflows_tags_1 | PRIMARY KEY (workflowId, tagId) | + +## Relations + +```mermaid +erDiagram + +"workflows_tags" |o--|| "tag_entity" : "FOREIGN KEY (tagId) REFERENCES tag_entity (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"workflows_tags" |o--|| "workflow_entity" : "FOREIGN KEY (workflowId) REFERENCES workflow_entity (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" + +"workflows_tags" { + INTEGER tagId PK + varchar_36_ workflowId PK +} +"tag_entity" { + datetime_3_ createdAt + varchar_36_ id PK + varchar_24_ name + datetime_3_ updatedAt +} +"workflow_entity" { + boolean active + varchar_36_ activeVersionId FK + TEXT connections + datetime_3_ createdAt + TEXT description + varchar_36_ id PK + boolean isArchived + TEXT meta + varchar_128_ name + TEXT nodeGroups + TEXT nodes + varchar_36_ parentFolderId FK + TEXT pinData + TEXT settings + varchar sourceWorkflowId + TEXT staticData + INTEGER triggerCount + datetime_3_ updatedAt + INTEGER versionCounter + varchar_36_ versionId +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/jest.config.js b/jest.config.js index 2df544e621d..cc751127344 100644 --- a/jest.config.js +++ b/jest.config.js @@ -1,6 +1,7 @@ const { pathsToModuleNameMapper } = require('ts-jest'); const { compilerOptions } = require('get-tsconfig').getTsconfig().config; const { resolve } = require('path'); +const coverageExcludes = require('./jest.coverage-excludes'); /** @type {import('ts-jest').TsJestTransformerOptions} */ const tsJestOptions = { @@ -100,9 +101,9 @@ const config = { }; if (process.env.CI === 'true') { - config.collectCoverageFrom = ['src/**/*.ts']; + config.collectCoverageFrom = ['src/**/*.ts', ...coverageExcludes]; config.reporters = ['default', 'jest-junit']; - config.coverageReporters = ['cobertura']; + config.coverageReporters = ['lcov']; } module.exports = config; diff --git a/jest.coverage-excludes.js b/jest.coverage-excludes.js new file mode 100644 index 00000000000..d08713457a7 --- /dev/null +++ b/jest.coverage-excludes.js @@ -0,0 +1,11 @@ +// Shared `collectCoverageFrom` exclusions for all jest packages. `**`-anchored +// so they apply regardless of the source roots a package collects from. +// Mirrored by packages/@n8n/vitest-config/coverage-excludes.ts (vitest) and the +// V8 path filter in packages/testing/playwright/coverage-options.ts — keep in sync. +module.exports = [ + '!**/*.spec.ts', + '!**/*.test.ts', + '!**/__tests__/**', + '!**/__mocks__/**', + '!**/*.d.ts', +]; diff --git a/lefthook.yml b/lefthook.yml index 1aae733948a..794a4925d2c 100644 --- a/lefthook.yml +++ b/lefthook.yml @@ -32,6 +32,18 @@ pre-commit: skip: - merge - rebase + skill_links_check: + glob: '.agents/skills/**' + run: node scripts/sync-agent-skill-links.mjs --check + skip: + - merge + - rebase + skill_links_check_plugin: + glob: '.claude/plugins/n8n/skills/**' + run: node scripts/sync-agent-skill-links.mjs --check + skip: + - merge + - rebase migration_timestamp_check: glob: 'packages/@n8n/db/src/migrations/{common,postgresdb,sqlite}/*.ts' run: | @@ -40,6 +52,12 @@ pre-commit: skip: - merge - rebase + db_schema_check: + glob: 'packages/@n8n/db/src/migrations/{common,postgresdb,sqlite}/*.ts' + run: pnpm run db:schema:check:sqlite + skip: + - merge + - rebase playwright_janitor: glob: 'packages/testing/playwright/**/*.ts' run: | diff --git a/package.json b/package.json index 2b4e53b6426..6428483e764 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "n8n-monorepo", - "version": "2.25.1", + "version": "2.27.0", "private": true, "engines": { "node": ">=22.22", @@ -31,6 +31,7 @@ "reset": "node scripts/ensure-zx.mjs && zx scripts/reset.mjs", "format": "turbo run format && node scripts/format.mjs", "grind": "node scripts/grind.mjs", + "agent:setup": "node scripts/agent-setup.mjs", "format:check": "turbo run format:check", "lint": "turbo run lint", "lint:styles": "turbo run lint:styles", @@ -38,6 +39,8 @@ "lint:affected": "turbo run lint --affected", "lint:fix": "turbo run lint:fix", "lint:ci": "turbo run lint lint:styles", + "sync:skill-links": "node scripts/sync-agent-skill-links.mjs", + "check:skill-links": "node scripts/sync-agent-skill-links.mjs --check", "optimize-svg": "find ./packages -name '*.svg' ! -name 'pipedrive.svg' -print0 | xargs -0 -P16 -L20 npx svgo", "setup-backend-module": "node scripts/ensure-zx.mjs && zx scripts/backend-module/setup.mjs", "start": "node scripts/os-normalize.mjs --dir packages/cli/bin n8n", @@ -51,6 +54,9 @@ "test:ci:backend:integration": "turbo run test:integration --continue --concurrency=1 --filter='!./packages/frontend/**'", "test:ci:backend:integration:changed": "turbo run test:integration:changed --continue --concurrency=1 --filter='!./packages/frontend/**'", "test:affected": "turbo run test --affected --concurrency=1", + "db:schema:docs": "turbo run build --filter=@n8n/db && pnpm --filter=@n8n/db schema:docs", + "db:schema:check": "turbo run build --filter=@n8n/db && pnpm --filter=@n8n/db schema:check", + "db:schema:check:sqlite": "turbo run build --filter=@n8n/db && pnpm --filter=@n8n/db schema:check:sqlite", "test:with:docker": "pnpm --filter=n8n-playwright test:container:standard", "test:show:report": "pnpm --filter=n8n-playwright exec playwright show-report", "watch": "turbo run watch --concurrency=64", @@ -88,7 +94,7 @@ "ts-jest": "^29.4.9", "tsc-alias": "^1.8.10", "tsc-watch": "^6.2.0", - "turbo": "2.9.4", + "turbo": "2.9.15", "typescript": "*", "zx": "^8.8.5" }, @@ -108,6 +114,7 @@ "@lezer/common": "^1.2.0", "@mistralai/mistralai": "^1.10.0", "@n8n/typeorm>@sentry/node": "catalog:sentry", + "@opentelemetry/api": "1.9.0", "@types/node": "^20.17.50", "chokidar": "4.0.3", "esbuild": "^0.25.0", @@ -125,10 +132,10 @@ "ws": ">=8.20.1", "date-fns": "2.30.0", "date-fns-tz": "2.0.0", - "form-data": "4.0.4", + "form-data": "4.0.6", "pdf-parse": "catalog:", - "tmp": "0.2.6", - "nodemailer": "7.0.11", + "tmp": "0.2.7", + "nodemailer": "8.0.10", "validator": "13.15.26", "zod": "3.25.67", "js-yaml": "4.1.1", @@ -137,14 +144,14 @@ "glob@7": "7.2.3", "jws@3": "3.2.2", "jws@4": "4.0.1", - "qs@6": "6.15.2", + "qs": "catalog:", "@smithy/config-resolver": ">=4.4.0", "@rudderstack/rudder-sdk-node@<=3.0.0": "3.0.0", "diff": "8.0.3", - "undici@5": "^6.24.0", - "undici@6": "^6.24.0", - "undici@7": "^7.24.0", - "tar": "^7.5.11", + "undici@5": "catalog:undici-v6", + "undici@6": "catalog:undici-v6", + "undici@7": "catalog:undici-v7", + "tar": "^7.5.16", "ajv@6": "6.14.0", "ajv@7": "8.18.0", "ajv@8": "8.18.0", @@ -170,18 +177,19 @@ "yaml@<=2.8.3": "2.8.3", "axios": "1.16.1", "fast-xml-parser": "5.7.2", - "hono": "4.12.18", + "postcss@<=8.5.9": "8.5.10", "@anthropic-ai/sdk@<=0.91.1": "0.91.1", "uuid@<=13.0.1": "13.0.1", "fast-uri": "3.1.2", "cjs-module-lexer@<2.2.0": "2.2.0", - "protobufjs": "7.5.8", + "protobufjs": "7.6.1", "ip-address@10": "10.1.1", "brace-expansion@5": "5.0.6", "@tootallnate/once@2": "2.0.1", "@opentelemetry/exporter-prometheus@<=0.217.0": "0.217.0", "@opentelemetry/sdk-node@<=0.217.0": "0.217.0", - "langsmith": "0.6.0" + "langsmith": "0.6.0", + "hono": "4.12.25" }, "patchedDependencies": { "bull@4.16.4": "patches/bull@4.16.4.patch", diff --git a/packages/@n8n/agents/AGENTS.md b/packages/@n8n/agents/AGENTS.md index 7f152401aa3..78d04e995f1 100644 --- a/packages/@n8n/agents/AGENTS.md +++ b/packages/@n8n/agents/AGENTS.md @@ -122,9 +122,8 @@ class EngineAgent extends Agent { ## Documentation -- Runtime architecture notes: `docs/agent-runtime-architecture.md` (this package). -- Spec-driven work in the wider repo may use `.claude/specs/` (see repo - `.claude/skills/spec-driven-development`). +- Spec-driven work in the wider repo may use `.agents/specs/` (see repo skill + `.agents/skills/spec-driven-development`). ## Building diff --git a/packages/@n8n/agents/docs/agent-runtime-architecture.md b/packages/@n8n/agents/docs/agent-runtime-architecture.md deleted file mode 100644 index 3d5e59767e4..00000000000 --- a/packages/@n8n/agents/docs/agent-runtime-architecture.md +++ /dev/null @@ -1,501 +0,0 @@ -# Agent Runtime Architecture - -This document describes the internal architecture of the `@n8n/agents` agent -runtime — the execution engine that drives a single agent turn from input to -final response. - ---- - -## Overview - -`AgentRuntime` (`src/runtime/agent-runtime.ts`) is the core execution engine -for a single agent turn. It uses the Vercel AI SDK directly (`generateText` / -`streamText`) and is responsible for: - -- Building the LLM message context (memory history, working - memory in the system prompt, user input) -- Stripping orphaned tool-call/tool-result pairs before LLM calls - (`stripOrphanedToolMessages`) -- Running the agentic tool-call loop (default **20** iterations, - `MAX_LOOP_ITERATIONS`) -- **Configurable tool-call concurrency** — tools in one LLM turn run in batches - of `toolCallConcurrency` (default `1`; `Infinity` runs all executable calls - in parallel) -- Suspending and resuming runs for Human-in-the-Loop (HITL) **and** for tools - that return a branded suspend result (`suspendSchema` / `resumeSchema`) -- Persisting new messages to a memory store at the end of each completed turn -- Extracting and persisting **working memory** from assistant output when - configured -- Optional **structured output** (`Output.object` + Zod), **thinking** / - reasoning provider options, **title generation**, and **telemetry** (AI SDK - `experimental_telemetry`) -- **Token usage and cost** (catalog pricing via `getModelCost` / `computeCost`) -- Emitting lifecycle events via `AgentEventBus` -- Tracking run state (`idle` → `running` → `success / failed / suspended / cancelled`) - -There are two parallel execution paths — non-streaming (`generate`) and -streaming (`stream`) — that mirror each other in structure. - -```mermaid -graph TD - A[User Input] --> B[normalizeInput] - B --> C[buildMessageList] - C --> D{generate or stream?} - D -->|generate| E[runGenerateLoop] - D -->|stream| F[startStreamLoop → runStreamLoop] - E --> G[saveToMemory] - F --> G - G --> H[Return Result] -``` - ---- - -## Public API — BuiltAgent - -`Agent` implements `BuiltAgent`, which exposes the full public surface: - -| Method | Description | -|--------|-------------| -| `generate(input, options?)` | Non-streaming run; returns `GenerateResult` (errors often surface as `finishReason: 'error'` and `error` instead of throwing) | -| `stream(input, options?)` | Streaming run; returns `StreamResult` with `runId` and `stream` | -| `resume(method, data, options)` | Resume a suspended tool with payload `data`; `options` must include `runId` and `toolCallId` | -| `approve(method, options)` | HITL approval — calls `resume` with `{ approved: true }` | -| `deny(method, options)` | HITL decline — calls `resume` with `{ approved: false }` | -| `on(event, handler)` | Register a lifecycle event handler | -| `abort()` | Cancel the currently running agent | -| `getState()` | Return the latest `SerializableAgentState` snapshot | - -`ExecutionOptions` includes `abortSignal?: AbortSignal`, forwarded into -`AgentEventBus.resetAbort()` so callers can cancel via an external signal as -well as `agent.abort()`. - ---- - -## Inline Sub-Agent Delegation - -`createDelegateSubAgentTool()` can be registered directly on an `Agent` without -a host `runSubAgent` callback. In that mode, `Agent.build()` completes the tool -with the SDK's inline child runner after the parent model and effective tool -surface have been resolved. - -```typescript -const agent = new Agent('parent') - .model('anthropic/claude-sonnet-4-5') - .instructions('...') - .tool(searchTool) - .tool(createDelegateSubAgentTool()); -``` - -The model selects the default inline path by passing `subAgentId: "inline"`. -When a host supplies a `runSubAgent` callback, `Agent.build()` routes every -delegation (including `"inline"`) through that callback and passes -`helpers.runInlineSubAgent` so the host can reuse the SDK inline runner. Without a -host callback, `"inline"` is handled by the SDK inline runner directly. Both paths -return the same `DelegateSubAgentToolOutput` shape and emit the same sub-agent -lifecycle events. - -Inline children: - -- reuse the parent model config for this first implementation -- start from the parent agent's effective local/deferred tool list -- always drop SDK-blocked tools such as `delegate_subagent`, `write_todos`, and memory recall -- may drop additional host-blocked local/deferred tool names configured on the delegate tool -- inherit parent provider tools after the same blocklist filtering -- run in a fresh context using the shared delegated-task prompt - ---- - -## Event system - -### AgentEventBus - -`AgentEventBus` (`src/runtime/event-bus.ts`) is the internal publish/subscribe -channel shared between `Agent` (registers handlers via `on()`) and -`AgentRuntime` (emits events during the loop). A single bus instance is created -when the SDK wires the runtime and passed in via `AgentRuntimeConfig`. - -```mermaid -flowchart LR - UserCode -->|"agent.on(event, handler)"| AgentEventBus - AgentEventBus -->|"passed via config"| AgentRuntime - AgentRuntime -->|"bus.emit(data)"| AgentEventBus - AgentEventBus -->|"calls handlers synchronously"| UserCode -``` - -Handlers have the signature `(data: AgentEventData) => void` — there is **no** -separate “controls” object; cancellation is done with `agent.abort()` on the -same bus that holds the `AbortController`. - -`AgentMiddleware` in `types/runtime/event.ts` is a small alias type -(`on` mirrors the agent) for future middleware-style composition. - -### Event types - -| Event | When emitted | Payload | -|-------|----------------|---------| -| `AgentStart` | Start of `initRun`, right after `status: running`; before `ensureModelCost` / `buildMessageList` | — | -| `AgentEnd` | Successful completion after persistence / cleanup; payload is assistant-facing messages (`finalized.messages` in `generate`, `list.responseDelta()` in `stream`) | `{ messages }` | -| `TurnStart` | Top of each loop iteration, before the LLM call | — | -| `TurnEnd` | After tool calls for the iteration are processed; requires an assistant message in the new messages | `{ message, toolResults }` | -| `ToolExecutionStart` | Before `processToolCall` runs the handler | `{ toolCallId, toolName, args }` | -| `ToolExecutionEnd` | After the tool returns, errors, or is satisfied from an existing AI SDK tool-result | `{ toolCallId, toolName, result, isError }` | -| `Error` | Unhandled failures (not user **abort**); also emitted on some stream failures | `{ message, error }` | - ---- - -## abort() - -`agent.abort()` synchronously aborts the internal `AbortController`. The -resulting signal is passed to `generateText` / `streamText` as `abortSignal` -so in-flight HTTP cancels promptly. The loop also checks `bus.isAborted` at -batch boundaries. - -`AgentEventBus.resetAbort(externalSignal?)` runs at the start of each run: it -replaces the controller and, if `ExecutionOptions.abortSignal` is set, forwards -that signal’s abort to the internal controller. - -### Abort behaviour - -| Mode | Behaviour on abort | -|------|-------------------| -| `generate` | Catches abort and returns `{ runId, messages, finishReason: 'error', ... }` without emitting `AgentEvent.Error` | -| `stream` | Writes `{ type: 'error', error }` then finishes / closes cleanly | - -State becomes `cancelled`. `resetAbort()` supplies a fresh controller per run -so the same `Agent` instance can run again. - ---- - -## getState() - -`agent.getState()` returns a shallow copy of `SerializableAgentState`. Before -the first `generate()` / `stream()`, the `Agent` builder returns a minimal idle -state with an empty `messageList` (`messages`, `historyIds`, `inputIds`, -`responseIds` all empty). - -### State machine - -```mermaid -stateDiagram-v2 - [*] --> idle: constructed - idle --> running: generate() / stream() / resume() - running --> success: loop completes normally - running --> failed: unhandled error - running --> suspended: tool suspends (HITL or suspend/resume) - running --> cancelled: abort() / external signal - suspended --> running: resume() / approve() / deny() loads checkpoint -``` - -### AgentRunState values - -| Status | Meaning | -|--------|---------| -| `idle` | No run yet (or builder before first lazy build) | -| `running` | Loop in progress | -| `success` | Turn finished and checkpoint cleaned up when applicable | -| `failed` | Unrecoverable error path | -| `suspended` | Awaiting resume (checkpoint stored under `runId`) | -| `cancelled` | Aborted | -| `waiting` | Reserved | - -### SerializableAgentState - -Important fields (see `types/sdk/agent.ts`): - -```typescript -interface SerializableAgentState { - persistence?: AgentPersistenceOptions; // threadId + resourceId when using memory - status: AgentRunState; - messageList: SerializedMessageList; - resumeData?: AgentResumeData; - pendingToolCalls: Record<string, PendingToolCall>; - finishReason?: FinishReason; - usage?: TokenUsage; - executionOptions?: PersistedExecutionOptions; // maxIterations only — persisted on suspend -} -``` - -`PendingToolCall` distinguishes tools already suspended (`suspended: true`, -`suspendPayload`, `resumeSchema`) from calls not yet executed (`suspended: -false`) when a batch stops at the first suspension. - -## Message types - -| Type | Definition | Purpose | -|------|------------|---------| -| `AgentMessage` | `Message \| CustomMessage` | Internal representation; custom messages are UI-facing | -| `ModelMessage` (AI SDK) | Roles wired to the provider | LLM-facing; custom messages never appear here | - -**Custom messages** are stripped for the model via `filterLlmMessages()` before -`toAiMessages()`. - -`messages.ts` provides `toAiMessages`, `fromAiMessages`, and consumers rely on -`filterLlmMessages` from `sdk/message.ts`. - -**Tool results vs model:** optional `BuiltTool.toModelOutput` maps the stored / -event result before building the `tool-result` the LLM sees; `toMessage` still -uses the raw result for custom DB messages. - ---- - -## AgentMessageList - -`AgentMessageList` (`src/runtime/message-list.ts`) is the central structure for -one turn. It keeps a single append-only array and **three Sets** for -provenance: history, input, response. - -### Sources - -| Source | Added by | `turnDelta()` | `responseDelta()` | `forLlm()` | -|--------|----------|---------------|-------------------|------------| -| **history** | `addHistory()` | No | No | Yes (after filters) | -| **input** | `addInput()` | Yes | No | Yes (after filters) | -| **response** | `addResponse()` | Yes | Yes | Yes (after filters) | - -### Key methods - -``` -forLlm(baseInstructions, instructionProviderOptions?) - → [system + working memory block, ...toAiMessages(filterLlm(stripOrphaned(all)))] -turnDelta() → input ∪ response messages (memory persistence) -responseDelta() → response only (user-facing / GenerateResult.messages) -serialize() → { messages, historyIds, inputIds, responseIds } -deserialize() → restores all three sets via stable message ids -``` - -### Serialization - -Serialized state stores **message id arrays** per set (`historyIds`, -`inputIds`, `responseIds`), not a single `historyCount`. After a round-trip, -history / input / response classification is fully restored — required for -correct `turnDelta()` after suspend/resume. - -`stripOrphanedToolMessages` runs on loaded history and inside `forLlm()` so -incomplete tool pairs do not reach the model. - -**Ordering note:** The in-memory list is append-only; LLM context follows array -order. Persisted threads, however, are loaded with **`ORDER BY createdAt`** (and -a `seq` tiebreaker in SQL backends). Every message therefore needs a -**unique, monotonically increasing `createdAt`** while it flows through -`AgentMessageList` so reloads and `before`-filtered fetches match the turn’s -true sequence. See [Monotonic `createdAt`](#monotonic-createdat-for-persisted-order). - ---- - -## Agentic loop - -Both `runGenerateLoop` and `runStreamLoop` follow the same high-level pattern: -emit `TurnStart`, call the model with `list.forLlm(...)`, append assistant / -tool traffic via `addResponse`, process tool calls through -`iterateToolCallsConcurrent` (batched by `toolCallConcurrency`), handle -suspension / persistence, repeat until finish or max iterations. - -### Tool execution and concurrency - -- Executable tool calls (non–provider-executed) are processed in windows of size - `this.concurrency` (`toolCallConcurrency ?? 1`). -- Each window uses `Promise.allSettled` so all tools in the batch settle; a - suspension in the batch stops **subsequent** batches and records remaining - calls in `pending` without `suspendPayload`. -- **HITL** and **suspend/resume** flows share the same pending-map machinery; - `processToolCall` validates JSON Schema or Zod **input** schemas (Ajv / Zod) - before invoking the handler. - -### Loop invariants - -1. **Single list** — `addResponse` accumulates assistant, tool, and custom - messages for the turn. -2. **System prompt** — rebuilt each call via `forLlm`; working memory content - is injected there, not as separate list rows. -3. **Suspension preserves pending calls** — remaining calls in the batch and - later calls are recorded for resume. -4. **Max iterations** — default 20 (`MAX_LOOP_ITERATIONS`). -5. **Abort** — checked between batches; signal passed into AI SDK calls. - -### Non-streaming vs streaming - -| Aspect | `runGenerateLoop` | `runStreamLoop` | -|--------|-------------------|-----------------| -| AI SDK | `generateText()` | `streamText()` | -| Output | `GenerateResult` | `StreamChunk`s via `WritableStream` | -| Errors | Returned on `GenerateResult` (`error`, `finishReason: 'error'`) for many paths | Error chunks + `closeStreamWithError` | -| Suspension | `pendingSuspend` array on `GenerateResult` | `tool-call-suspended` chunks, then `finish` | - ---- - -## HITL and suspend/resume - -**HITL (approval):** tools can require approval (`requiresApproval` / -`needsApprovalFn`). The runtime treats approval outcomes like resume data: -`approve()` / `deny()` delegate to `resume()` with `{ approved: true | false }`. - -**Programmatic suspend:** tools can return a branded suspend object; the runtime -requires `resumeSchema` (Zod → JSON Schema for clients) and validates -`suspendPayload` when `suspendSchema` is set. - -```mermaid -sequenceDiagram - participant Caller - participant AgentRuntime - participant CheckpointStore - participant LLM - - Caller->>AgentRuntime: generate/stream(input) - AgentRuntime->>LLM: generateText/streamText - LLM-->>AgentRuntime: tool calls - Note over AgentRuntime: Suspension: persist pendingToolCalls + messageList - AgentRuntime->>CheckpointStore: suspend(runId, state) - AgentRuntime-->>Caller: pendingSuspend / tool-call-suspended chunks - - Caller->>AgentRuntime: resume/approve/deny(method, …) - AgentRuntime->>CheckpointStore: resume(runId) — load only - AgentRuntime->>AgentRuntime: processToolCall / iteratePendingToolCallsConcurrent - AgentRuntime->>LLM: Continue loop if needed - AgentRuntime->>CheckpointStore: complete(runId) when finished -``` - -With **concurrency > 1**, multiple tools may suspend in the same turn; the -stream can emit **multiple** `tool-call-suspended` chunks, and `GenerateResult` -can carry **`pendingSuspend`** with multiple entries. - ---- - -## RunStateManager - -`RunStateManager` (`src/runtime/run-state.ts`) persists suspended runs through -a **`CheckpointStore`**: - -- Default: in-memory `MemoryCheckpointStore` when `checkpointStorage` is - `'memory'` or omitted. -- Custom: pass a `CheckpointStore` implementation for durability. - -`suspend(runId, state)` writes the state. `resume(runId)` **loads** the state -and returns it with `status: 'running'`; it does **not** delete the key. -`complete(runId)` deletes the checkpoint when the run finishes without remaining -suspensions. - -### Known limitations - -In-memory checkpoints grow until `complete()` runs. Production stores should -implement TTL or eviction as needed. - ---- - -## Memory persistence - -At end of turn, `saveToMemory()` uses `list.turnDelta()` and -`saveMessagesToThread`. - -**Working memory:** when configured, the runtime injects an `update_working_memory` -tool into the agent's tool set. The current state is included in the system prompt -so the model can read it; when new information should be persisted the model calls -the tool, which validates the input and asynchronously persists via -`memory.saveWorkingMemory`. - -**Thread titles:** `titleGeneration` triggers `generateThreadTitle` (fire-and-forget) -after a successful save when persistence and memory are present. - ---- - -## Stream architecture - -The streaming path uses a `TransformStream`: `startStreamLoop` returns the -readable side immediately; the loop writes chunks in the background. - -`stream.ts` **`convertChunk`** maps AI SDK v6 `TextStreamPart` values to our -`StreamChunk` union (including `finish-step` / `finish` consolidation). - -### StreamChunk types (representative) - -| Type | Content | -|------|---------| -| `text-delta` | Incremental text | -| `reasoning-delta` | Thinking / reasoning text | -| `tool-call-delta` | Streaming tool name / arguments | -| `message` | Full assistant or tool message | -| `tool-call-suspended` | Suspension: `runId`, `toolCallId`, tool metadata, optional `resumeSchema`, `suspendPayload` | -| `finish` | `finishReason`, `usage` (with optional **cost**), `model`, optional **`structuredOutput`** | -| `error` | Failure or abort | - ---- - -## File map - -``` -src/ - runtime/ - agent-runtime.ts — AgentRuntime (generate/stream/resume loops, HITL, state) - event-bus.ts — AgentEventBus + AbortController - message-list.ts — AgentMessageList - run-state.ts — RunStateManager, generateRunId - memory-store.ts — saveMessagesToThread helper - messages.ts — AI SDK message conversion - model-factory.ts — createModel / createEmbeddingModel - tool-adapter.ts — buildToolMap, executeTool, toAiSdkTools, suspend guards - stream.ts — convertChunk, toTokenUsage - runtime-helpers.ts — normalizeInput, usage merge, stream error helpers, … - working-memory.ts — instruction text, update_working_memory tool builder - strip-orphaned-tool-messages.ts - title-generation.ts - logger.ts - types/ - sdk/agent.ts — BuiltAgent, GenerateResult, StreamChunk, SerializableAgentState, … - sdk/tool.ts, sdk/memory.ts, … — Public SDK contracts - runtime/event.ts — AgentEvent enum + AgentEventData - runtime/message-list.ts — SerializedMessageList - telemetry.ts — BuiltTelemetry shape -``` - ---- - -## Design decisions (selected) - -### Set-based message list + id serialization - -Three Sets plus stable **`id` on each message** allow `turnDelta()` / -`responseDelta()` without losing custom tool messages, and checkpointed runs -restore history vs turn data correctly after resume. - -### `responseDelta()` vs `turnDelta()` - -User input must not appear in `GenerateResult.messages`; memory persistence -must store the full turn including input — hence two views over the same list. - -### Concurrency preserves suspension semantics - -Batches run in parallel when configured, but the first suspension still -captures **unexecuted** tool calls in `pending` so nothing is dropped. Approval -tools and programmatic suspends use the same pending-map format. - -### Why one event bus per agent - -The bus is shared between `Agent` and `AgentRuntime` so `on()` registrations and -`abort()` always target the controller used by the active loop. - -### Why `AbortSignal` - -Signals cancel HTTP immediately in the AI SDK and compose with caller-provided -`abortSignal` via `resetAbort`. - -### Monotonic `createdAt` for persisted order - -**Problem.** Live messages often used `Date.now()` (or no timestamp). Several -messages added in the same millisecond (multi-part input, batched tool results, -fast loops) produced **identical `createdAt` values**. SQL stores mitigate ties -with a `seq` column, but ordering was still ambiguous for consumers that sort -only by time, and **in-memory `BuiltMemory`** (`InMemoryMemory`) keyed ordering -off the stored timestamp. Duplicate timestamps made **pagination windows** (`before`, -`limit`) and reload order **non-deterministic** relative to insertion order — -message history could appear to **shuffle** between turns or after resume. - -**Approach.** `AgentMessageList` tracks `lastCreatedAt` and assigns each **live** -message (`input` / `response`) a `createdAt` of -`max(hint, lastCreatedAt + 1)`, where `hint` is any existing timestamp or -`Date.now()`. **`history` messages** keep the database timestamp exactly; -`lastCreatedAt` advances to `max` so new live rows stay strictly later (handles -clock skew and prior monotonic runs). **`deserialize()`** recomputes -`lastCreatedAt` from all restored rows so suspend/resume continues the sequence. - -**Downstream.** `saveMessages` / Postgres / SQLite persist the message-owned -`createdAt`, and in-memory storage uses that same value for filtering so -`getMessages` stays aligned with `AgentMessageList`’s ordering guarantees. diff --git a/packages/@n8n/agents/package.json b/packages/@n8n/agents/package.json index 6f165f9faaf..85b9089efac 100644 --- a/packages/@n8n/agents/package.json +++ b/packages/@n8n/agents/package.json @@ -1,6 +1,6 @@ { "name": "@n8n/agents", - "version": "0.10.0", + "version": "0.12.0", "description": "AI agent SDK for n8n's code-first execution engine", "main": "dist/index.js", "module": "dist/index.js", @@ -12,6 +12,9 @@ ], "catalog": [ "dist/sdk/catalog.d.ts" + ], + "sandbox": [ + "dist/workspace/sandbox/index.d.ts" ] } }, @@ -28,6 +31,10 @@ "./catalog": { "types": "./dist/sdk/catalog.d.ts", "default": "./dist/sdk/catalog.js" + }, + "./sandbox": { + "types": "./dist/workspace/sandbox/index.d.ts", + "default": "./dist/workspace/sandbox/index.js" } }, "files": [ @@ -56,26 +63,29 @@ "@ai-sdk/cohere": "catalog:", "@ai-sdk/deepseek": "catalog:", "@ai-sdk/gateway": "catalog:", - "@ai-sdk/google": "^3.0.43", + "@ai-sdk/google": "catalog:", "@ai-sdk/groq": "catalog:", "@ai-sdk/mistral": "catalog:", - "@ai-sdk/openai": "^3.0.41", + "@ai-sdk/openai": "catalog:", "@ai-sdk/openai-compatible": "catalog:", - "@ai-sdk/provider-utils": "^4.0.21", - "@ai-sdk/xai": "^3.0.67", + "@ai-sdk/provider-utils": "catalog:", + "@ai-sdk/xai": "catalog:", + "@daytonaio/sdk": "catalog:", "@modelcontextprotocol/sdk": "catalog:", + "@n8n/sandbox-client": "0.0.4", "@n8n/ai-utilities": "workspace:*", + "@n8n/utils": "workspace:*", "@openrouter/ai-sdk-provider": "catalog:", - "ai": "^6.0.116", - "ajv": "^8.18.0", - "yaml": "catalog:", - "zod": "catalog:" - }, - "peerDependencies": { "@opentelemetry/exporter-trace-otlp-http": ">=0.50.0", "@opentelemetry/sdk-trace-base": ">=1.0.0", "@opentelemetry/sdk-trace-node": ">=1.0.0", - "langsmith": "catalog:" + "ai": "^6.0.197", + "ajv": "^8.18.0", + "langsmith": "catalog:", + "undici": "catalog:undici-v7", + "yaml": "catalog:", + "zod": "catalog:", + "zod-to-json-schema": "catalog:" }, "peerDependenciesMeta": { "langsmith": { @@ -98,5 +108,6 @@ "@vitest/coverage-v8": "catalog:", "vitest": "catalog:", "vitest-mock-extended": "catalog:" - } + }, + "license": "LicenseRef-n8n-sustainable-use" } diff --git a/packages/@n8n/agents/src/__tests__/agent-configuration.test.ts b/packages/@n8n/agents/src/__tests__/agent-configuration.test.ts index dafd630beca..31c8d07d58d 100644 --- a/packages/@n8n/agents/src/__tests__/agent-configuration.test.ts +++ b/packages/@n8n/agents/src/__tests__/agent-configuration.test.ts @@ -8,6 +8,13 @@ type WithPrivates = { }; describe('Agent.configuration()', () => { + it('does not expose an agent-wide tool approval setting', () => { + const agent = new Agent('test'); + + expect('requireToolApproval' in agent).toBe(false); + expect(agent.snapshot).not.toHaveProperty('requireToolApproval'); + }); + it('is chainable', () => { const agent = new Agent('test'); expect(agent.configuration({ maxIterations: 5 })).toBe(agent); diff --git a/packages/@n8n/agents/src/__tests__/integration/agent-runtime-conversion.test.ts b/packages/@n8n/agents/src/__tests__/integration/agent-runtime-conversion.test.ts index 46b7ccc69b7..2d93f950b01 100644 --- a/packages/@n8n/agents/src/__tests__/integration/agent-runtime-conversion.test.ts +++ b/packages/@n8n/agents/src/__tests__/integration/agent-runtime-conversion.test.ts @@ -14,7 +14,7 @@ */ import { describe, it, expect } from 'vitest'; -import { toAiMessages, fromAiMessages } from '../../runtime/messages'; +import { toAiMessages, fromAiMessages } from '../../runtime/model/messages'; import type { Message } from '../../types/sdk/message'; describe('toAiMessages + fromAiMessages — round-trip', () => { @@ -93,6 +93,58 @@ describe('toAiMessages + fromAiMessages — round-trip', () => { expect(toolCallPart.providerMetadata).toEqual(providerMetadata); }); + it('sanitizes replayed non-object tool-call inputs for provider requests', () => { + const input: Message[] = [ + { + role: 'assistant', + content: [ + { + type: 'tool-call', + toolCallId: 'tc-json', + toolName: 'search', + input: '{"query":"n8n"}', + state: 'resolved', + output: {}, + }, + { + type: 'tool-call', + toolCallId: 'tc-array', + toolName: 'batch', + input: '["a","b"]', + state: 'resolved', + output: {}, + }, + { + type: 'tool-call', + toolCallId: 'tc-null', + toolName: 'noop', + input: null, + state: 'resolved', + output: {}, + }, + { + type: 'tool-call', + toolCallId: 'tc-string', + toolName: 'legacy', + input: 'plain-text', + state: 'resolved', + output: {}, + }, + ], + }, + ]; + + const aiMessages = toAiMessages(input); + const assistantParts = ( + aiMessages[0] as { + role: string; + content: Array<{ type: string; input: unknown }>; + } + ).content; + + expect(assistantParts.map((part) => part.input)).toEqual([{ query: 'n8n' }, {}, {}, {}]); + }); + it('preserves content tool outputs when building tool ModelMessages', () => { const contentOutput = { type: 'content' as const, diff --git a/packages/@n8n/agents/src/__tests__/integration/double-suspension.test.ts b/packages/@n8n/agents/src/__tests__/integration/double-suspension.test.ts new file mode 100644 index 00000000000..a10808ab5f8 --- /dev/null +++ b/packages/@n8n/agents/src/__tests__/integration/double-suspension.test.ts @@ -0,0 +1,170 @@ +import { expect, it } from 'vitest'; + +import { + collectStreamChunks, + chunksOfType, + createAgentWithDoubleSuspendTool, + describeIf, +} from './helpers'; +import type { StreamChunk } from './helpers'; + +const describe = describeIf('anthropic'); + +describe('double suspension integration', () => { + it('generate: tool suspends twice then completes on second resume', async () => { + const { agent, handlerCalls } = createAgentWithDoubleSuspendTool('anthropic'); + + // 1. Initial call → tool suspends (step 1) + const first = await agent.generate('Deploy the app "my-service"'); + + expect(first.finishReason).toBe('tool-calls'); + expect(first.pendingSuspend).toHaveLength(1); + expect(first.pendingSuspend![0].toolName).toBe('deploy_app'); + expect(first.pendingSuspend![0].suspendPayload).toEqual(expect.objectContaining({ step: 1 })); + expect(handlerCalls()).toBe(1); + + const { runId, toolCallId } = first.pendingSuspend![0]; + + // 2. First resume (approved) → tool re-suspends (step 2) + const second = await agent.resume('generate', { confirmed: true }, { runId, toolCallId }); + + expect(second.finishReason).toBe('tool-calls'); + expect(second.pendingSuspend).toHaveLength(1); + expect(second.pendingSuspend![0].toolCallId).toBe(toolCallId); + expect(second.pendingSuspend![0].suspendPayload).toEqual(expect.objectContaining({ step: 2 })); + expect(handlerCalls()).toBe(2); + + // 3. Second resume (approved) → tool completes, LLM responds + const third = await agent.resume( + 'generate', + { confirmed: true }, + { runId: second.pendingSuspend![0].runId, toolCallId }, + ); + + expect(third.finishReason).toBe('stop'); + expect(third.pendingSuspend).toBeUndefined(); + expect(handlerCalls()).toBe(3); + + const hasText = third.messages.some( + (m) => + 'role' in m && + m.role === 'assistant' && + 'content' in m && + m.content.some((c) => c.type === 'text'), + ); + expect(hasText).toBe(true); + }); + + it('generate: tool suspends twice, denial on second resume completes without deploying', async () => { + const { agent, handlerCalls } = createAgentWithDoubleSuspendTool('anthropic'); + + const first = await agent.generate('Deploy the app "risky-service"'); + expect(first.pendingSuspend).toHaveLength(1); + + const { runId, toolCallId } = first.pendingSuspend![0]; + + // First resume: approve step 1 → re-suspends at step 2 + const second = await agent.resume('generate', { confirmed: true }, { runId, toolCallId }); + expect(second.pendingSuspend).toHaveLength(1); + + // Second resume: deny step 2 → tool returns deployed: false + const third = await agent.resume( + 'generate', + { confirmed: false }, + { runId: second.pendingSuspend![0].runId, toolCallId }, + ); + + expect(third.finishReason).toBe('stop'); + expect(third.pendingSuspend).toBeUndefined(); + expect(handlerCalls()).toBe(3); + }); + + it('stream: tool suspends twice then completes on second resume', async () => { + const { agent, handlerCalls } = createAgentWithDoubleSuspendTool('anthropic'); + + // 1. Initial stream → tool suspends (step 1) + const { stream: stream1 } = await agent.stream('Deploy the app "stream-service"'); + const chunks1 = await collectStreamChunks(stream1); + + const suspended1 = chunksOfType(chunks1, 'tool-call-suspended'); + expect(suspended1).toHaveLength(1); + + const s1 = suspended1[0] as StreamChunk & { type: 'tool-call-suspended' }; + expect(s1.toolName).toBe('deploy_app'); + expect(s1.suspendPayload).toEqual(expect.objectContaining({ step: 1 })); + expect(handlerCalls()).toBe(1); + + // 2. First resume → tool re-suspends (step 2) + const { stream: stream2 } = await agent.resume( + 'stream', + { confirmed: true }, + { runId: s1.runId, toolCallId: s1.toolCallId }, + ); + const chunks2 = await collectStreamChunks(stream2); + + const suspended2 = chunksOfType(chunks2, 'tool-call-suspended'); + expect(suspended2).toHaveLength(1); + + const s2 = suspended2[0] as StreamChunk & { type: 'tool-call-suspended' }; + expect(s2.toolCallId).toBe(s1.toolCallId); + expect(s2.suspendPayload).toEqual(expect.objectContaining({ step: 2 })); + expect(handlerCalls()).toBe(2); + + // No tool-result chunk on re-suspension + expect(chunksOfType(chunks2, 'tool-result')).toHaveLength(0); + + // 3. Second resume → tool completes, LLM responds + const { stream: stream3 } = await agent.resume( + 'stream', + { confirmed: true }, + { runId: s2.runId, toolCallId: s2.toolCallId }, + ); + const chunks3 = await collectStreamChunks(stream3); + + expect(handlerCalls()).toBe(3); + + const errors = chunks3.filter((c) => c.type === 'error'); + expect(errors).toHaveLength(0); + + const toolResults = chunksOfType(chunks3, 'tool-result'); + expect(toolResults.length).toBeGreaterThan(0); + + const finishChunks = chunksOfType(chunks3, 'finish') as Array<StreamChunk & { type: 'finish' }>; + expect(finishChunks.length).toBeGreaterThan(0); + expect(finishChunks[0].finishReason).not.toBe('error'); + + const textDeltas = chunksOfType(chunks3, 'text-delta'); + expect(textDeltas.length).toBeGreaterThan(0); + }); + + it('stream: no suspended chunks leak into the final completion stream', async () => { + const { agent } = createAgentWithDoubleSuspendTool('anthropic'); + + const { stream: stream1 } = await agent.stream('Deploy "leak-check-app"'); + const chunks1 = await collectStreamChunks(stream1); + const s1 = chunksOfType(chunks1, 'tool-call-suspended')[0] as StreamChunk & { + type: 'tool-call-suspended'; + }; + + const { stream: stream2 } = await agent.resume( + 'stream', + { confirmed: true }, + { runId: s1.runId, toolCallId: s1.toolCallId }, + ); + const chunks2 = await collectStreamChunks(stream2); + const s2 = chunksOfType(chunks2, 'tool-call-suspended')[0] as StreamChunk & { + type: 'tool-call-suspended'; + }; + + const { stream: stream3 } = await agent.resume( + 'stream', + { confirmed: true }, + { runId: s2.runId, toolCallId: s2.toolCallId }, + ); + const chunks3 = await collectStreamChunks(stream3); + + // Final stream should have no suspended chunks — the tool completed + const finalSuspended = chunksOfType(chunks3, 'tool-call-suspended'); + expect(finalSuspended).toHaveLength(0); + }); +}); diff --git a/packages/@n8n/agents/src/__tests__/integration/events-and-abort.test.ts b/packages/@n8n/agents/src/__tests__/integration/events-and-abort.test.ts index 522c6b70d53..0eb136ac91a 100644 --- a/packages/@n8n/agents/src/__tests__/integration/events-and-abort.test.ts +++ b/packages/@n8n/agents/src/__tests__/integration/events-and-abort.test.ts @@ -28,6 +28,42 @@ function createAgentWithTool(provider: 'openai' | 'anthropic' = 'anthropic'): Ag .tool(addTool); } +function createAgentWithAbortAwareTool({ + onToolStart, + onToolAbort, +}: { + onToolStart: () => void; + onToolAbort: () => void; +}): Agent { + const abortAwareTool = new Tool('wait_for_abort') + .description( + 'Wait until the current run is aborted, then report whether the abort signal fired.', + ) + .input(z.object({ reason: z.string().optional() })) + .handler(async (_input, ctx) => { + const signal = ctx.abortSignal; + onToolStart(); + await new Promise<void>((resolve) => { + signal?.addEventListener( + 'abort', + () => { + onToolAbort(); + resolve(); + }, + { once: true }, + ); + }); + return { aborted: signal?.aborted === true }; + }); + + return new Agent('events-abort-tool-agent') + .model(getModel('anthropic')) + .instructions( + 'You must call wait_for_abort exactly once before answering. Do not answer directly.', + ) + .tool(abortAwareTool); +} + // --------------------------------------------------------------------------- // Event system — generate path // --------------------------------------------------------------------------- @@ -136,6 +172,63 @@ describe('event system — generate', () => { }); }); +// --------------------------------------------------------------------------- +// Abort signal propagation — public Agent API +// --------------------------------------------------------------------------- + +describe('abort signal propagation to tools', () => { + it('passes an aborting signal to tool context during generate()', async () => { + const external = new AbortController(); + let toolStarted!: () => void; + const waitForToolStart = new Promise<void>((resolve) => { + toolStarted = resolve; + }); + let toolAborted!: () => void; + const waitForToolAbort = new Promise<void>((resolve) => { + toolAborted = resolve; + }); + const agent = createAgentWithAbortAwareTool({ + onToolStart: toolStarted, + onToolAbort: toolAborted, + }); + + const run = agent.generate('Call wait_for_abort now.', { abortSignal: external.signal }); + await waitForToolStart; + + external.abort(); + + await waitForToolAbort; + await run; + }); + + it('passes an aborting signal to tool context during stream()', async () => { + const external = new AbortController(); + let toolStarted!: () => void; + const waitForToolStart = new Promise<void>((resolve) => { + toolStarted = resolve; + }); + let toolAborted!: () => void; + const waitForToolAbort = new Promise<void>((resolve) => { + toolAborted = resolve; + }); + const agent = createAgentWithAbortAwareTool({ + onToolStart: toolStarted, + onToolAbort: toolAborted, + }); + + const { stream } = await agent.stream('Call wait_for_abort now.', { + abortSignal: external.signal, + }); + const drain = collectStreamChunks(stream); + await waitForToolStart; + + external.abort(); + + await waitForToolAbort; + await drain; + }); +}); + // --------------------------------------------------------------------------- // Event system — stream path // --------------------------------------------------------------------------- diff --git a/packages/@n8n/agents/src/__tests__/integration/helpers.ts b/packages/@n8n/agents/src/__tests__/integration/helpers.ts index ef63e7c41cd..5968826456e 100644 --- a/packages/@n8n/agents/src/__tests__/integration/helpers.ts +++ b/packages/@n8n/agents/src/__tests__/integration/helpers.ts @@ -9,7 +9,7 @@ import { type StreamChunk, type AgentMessage, } from '../../index'; -import { InMemoryMemory } from '../../runtime/memory-store'; +import { InMemoryMemory } from '../../runtime/memory/memory-store'; export type { StreamChunk }; @@ -415,6 +415,55 @@ export const collectTextDeltas = (chunks: StreamChunk[]): string => { .join(''); }; +/** + * Create an agent with a tool that suspends twice before completing. + * The handler uses a closure counter to track invocations: + * call 1 (no resumeData) → suspend with step 1 + * call 2 (first resume) → suspend with step 2 + * call 3 (second resume) → complete + * + * Returns the agent and a `handlerCalls` accessor for assertions. + */ +export function createAgentWithDoubleSuspendTool(provider: 'anthropic' | 'openai'): { + agent: Agent; + handlerCalls: () => number; +} { + let calls = 0; + + const deployTool = new Tool('deploy_app') + .description('Deploy an application. Requires two rounds of confirmation before proceeding.') + .input(z.object({ app: z.string().describe('Application name to deploy') })) + .output(z.object({ deployed: z.boolean(), app: z.string(), steps: z.number() })) + .suspend(z.object({ step: z.number(), message: z.string() })) + .resume(z.object({ confirmed: z.boolean() })) + .handler(async ({ app }, ctx) => { + calls++; + if (!ctx.resumeData) { + return await ctx.suspend({ step: 1, message: `Confirm deployment of "${app}"?` }); + } + if (!ctx.resumeData.confirmed) { + return { deployed: false, app, steps: calls }; + } + if (calls <= 2) { + return await ctx.suspend({ + step: 2, + message: `Final confirmation: deploy "${app}" to production?`, + }); + } + return { deployed: true, app, steps: calls }; + }); + + const agent = new Agent('test-double-suspend-agent') + .model(getModel(provider)) + .instructions( + 'You are a deployment manager. When asked to deploy, use the deploy_app tool. Be concise.', + ) + .tool(deployTool) + .checkpoint('memory'); + + return { agent, handlerCalls: () => calls }; +} + export function createInMemoryAgentMemory(): { memory: InMemoryMemory; cleanup: () => void; diff --git a/packages/@n8n/agents/src/__tests__/integration/mcp-connection.test.ts b/packages/@n8n/agents/src/__tests__/integration/mcp-connection.test.ts index b3a1037eed1..46f095366f5 100644 --- a/packages/@n8n/agents/src/__tests__/integration/mcp-connection.test.ts +++ b/packages/@n8n/agents/src/__tests__/integration/mcp-connection.test.ts @@ -2,16 +2,15 @@ * Unit-style tests for McpConnection.listTools() approval wrapping. * * These tests use a real in-process MCP SSE server but do NOT require an LLM. - * They verify that the `requireApproval` field on McpServerConfig (and the - * global `shouldRequireToolApproval` constructor flag) correctly wrap the - * appropriate tools with a suspend/resume approval gate. + * They verify that the `requireApproval` field on McpServerConfig correctly + * wraps the appropriate tools with a suspend/resume approval gate. * * Tool names from the test server: echo, add, image (prefixed: tools_echo, tools_add, tools_image). */ import { afterAll, afterEach, beforeAll, describe, expect, it, vi } from 'vitest'; import { startSseServer, type TestServer } from './mcp-server-helpers'; -import { McpConnection } from '../../runtime/mcp-connection'; +import { McpConnection } from '../../runtime/mcp/mcp-connection'; // --------------------------------------------------------------------------- // Helpers @@ -149,38 +148,31 @@ describe('McpConnection.listTools() — requireApproval config', () => { expect(isApprovalWrapped(image!)).toBe(true); }); - // ----------------------------------------------------------------------- - // global shouldRequireToolApproval flag - // ----------------------------------------------------------------------- + it('ignores the removed legacy global flag and only uses server approval config', async () => { + type LegacyMcpConnectionConstructor = new ( + config: ConstructorParameters<typeof McpConnection>[0], + legacyGlobalApproval: boolean, + ) => McpConnection; + const LegacyMcpConnection = McpConnection as unknown as LegacyMcpConnectionConstructor; - it('wraps all tools when global shouldRequireToolApproval flag is true', async () => { - connection = new McpConnection({ name: 'tools', url: server.url }, true); - await connection.connect(); - const tools = await connection.listTools(); - - expect(tools.every((t) => isApprovalWrapped(t))).toBe(true); - }); - - // ----------------------------------------------------------------------- - // global flag + config.requireApproval interaction - // ----------------------------------------------------------------------- - - it('wraps all tools when global flag is true even if config.requireApproval names only some tools', async () => { - connection = new McpConnection( + connection = new LegacyMcpConnection( { name: 'tools', url: server.url, requireApproval: ['echo'] }, true, ); await connection.connect(); const tools = await connection.listTools(); - expect(tools.every((t) => isApprovalWrapped(t))).toBe(true); + const echo = tools.find((t) => t.name === 'tools_echo'); + const add = tools.find((t) => t.name === 'tools_add'); + const image = tools.find((t) => t.name === 'tools_image'); + + expect(isApprovalWrapped(echo!)).toBe(true); + expect(isApprovalWrapped(add!)).toBe(false); + expect(isApprovalWrapped(image!)).toBe(false); }); - it('wraps all tools when config.requireApproval: true even if global flag is false', async () => { - connection = new McpConnection( - { name: 'tools', url: server.url, requireApproval: true }, - false, - ); + it('wraps all tools when config.requireApproval: true', async () => { + connection = new McpConnection({ name: 'tools', url: server.url, requireApproval: true }); await connection.connect(); const tools = await connection.listTools(); diff --git a/packages/@n8n/agents/src/__tests__/integration/mcp-runtime.test.ts b/packages/@n8n/agents/src/__tests__/integration/mcp-runtime.test.ts index f13983f9fa0..afaf787f8ea 100644 --- a/packages/@n8n/agents/src/__tests__/integration/mcp-runtime.test.ts +++ b/packages/@n8n/agents/src/__tests__/integration/mcp-runtime.test.ts @@ -1,7 +1,7 @@ /** * Integration tests for MCP lifecycle via McpClient and the Agent builder. * Covers: McpClient constructor validation, connect/listTools/close, tool merge, - * name collision, requireToolApproval, and rich content handling. + * name collision, per-server approval, and rich content handling. * * Tests that don't require a real LLM run unconditionally. * Tests that call agent.generate() / agent.stream() are gated on ANTHROPIC_API_KEY. @@ -295,41 +295,6 @@ describe('MCP tool name collision detection', () => { }); }); -// --------------------------------------------------------------------------- -// requireToolApproval with MCP tools — requires ANTHROPIC_API_KEY -// --------------------------------------------------------------------------- - -describe_llm('requireToolApproval() with MCP tools', () => { - let server: TestServer; - - beforeAll(async () => { - server = await startSseServer(); - }); - - afterAll(async () => { - await server.close(); - }); - - it('suspends the MCP tool call when requireToolApproval is enabled', async () => { - const client = new McpClient([{ name: 'tools', url: server.url }]); - const agent = new Agent('approval-mcp-agent') - .model(getModel('anthropic')) - .instructions('Use tools_echo to echo messages. Be concise.') - .mcp(client) - .requireToolApproval() - .checkpoint('memory'); - - const { stream } = await agent.stream('Echo "needs approval" using tools_echo.'); - const chunks = await collectStreamChunks(stream); - - const suspendedChunks = chunksOfType(chunks, 'tool-call-suspended'); - expect(suspendedChunks.length).toBeGreaterThanOrEqual(1); - expect(suspendedChunks[0].toolName).toBe('tools_echo'); - - await client.close(); - }); -}); - // --------------------------------------------------------------------------- // McpServerConfig.requireApproval — builder validation (no LLM needed) // --------------------------------------------------------------------------- diff --git a/packages/@n8n/agents/src/__tests__/integration/mcp-sse-transport.test.ts b/packages/@n8n/agents/src/__tests__/integration/mcp-sse-transport.test.ts index 899267ccc6f..bc792df8f10 100644 --- a/packages/@n8n/agents/src/__tests__/integration/mcp-sse-transport.test.ts +++ b/packages/@n8n/agents/src/__tests__/integration/mcp-sse-transport.test.ts @@ -6,7 +6,7 @@ import { afterAll, beforeAll, describe, expect, it } from 'vitest'; import { startSseServer, TINY_PNG, type TestServer } from './mcp-server-helpers'; -import { McpConnection } from '../../runtime/mcp-connection'; +import { McpConnection } from '../../runtime/mcp/mcp-connection'; import type { ContentFile, ContentText, Message } from '../../types/sdk/message'; import { isZodSchema } from '../../utils/zod'; diff --git a/packages/@n8n/agents/src/__tests__/integration/mcp-stdio-transport.test.ts b/packages/@n8n/agents/src/__tests__/integration/mcp-stdio-transport.test.ts index 9f1fb0c8060..de49f18b1a3 100644 --- a/packages/@n8n/agents/src/__tests__/integration/mcp-stdio-transport.test.ts +++ b/packages/@n8n/agents/src/__tests__/integration/mcp-stdio-transport.test.ts @@ -7,7 +7,7 @@ import path from 'path'; import { describe, expect, it } from 'vitest'; import { TINY_PNG } from './mcp-server-helpers'; -import { McpConnection } from '../../runtime/mcp-connection'; +import { McpConnection } from '../../runtime/mcp/mcp-connection'; // vitest injects __dirname for TypeScript test files in the node environment. const FIXTURE_PATH = path.resolve(__dirname, '../fixtures/mcp-stdio-server.mjs'); diff --git a/packages/@n8n/agents/src/__tests__/integration/mcp-streamable-http-transport.test.ts b/packages/@n8n/agents/src/__tests__/integration/mcp-streamable-http-transport.test.ts index df57ca74398..53672b4fb72 100644 --- a/packages/@n8n/agents/src/__tests__/integration/mcp-streamable-http-transport.test.ts +++ b/packages/@n8n/agents/src/__tests__/integration/mcp-streamable-http-transport.test.ts @@ -6,7 +6,7 @@ import { afterAll, beforeAll, describe, expect, it } from 'vitest'; import { startStreamableHttpServer, TINY_PNG, type TestServer } from './mcp-server-helpers'; -import { McpConnection } from '../../runtime/mcp-connection'; +import { McpConnection } from '../../runtime/mcp/mcp-connection'; import type { ContentFile, ContentText, Message } from '../../types/sdk/message'; describe('McpConnection — Streamable HTTP transport', () => { diff --git a/packages/@n8n/agents/src/__tests__/integration/structured-output.test.ts b/packages/@n8n/agents/src/__tests__/integration/structured-output.test.ts index 51ff4ab0ae5..dde5a8c8ca8 100644 --- a/packages/@n8n/agents/src/__tests__/integration/structured-output.test.ts +++ b/packages/@n8n/agents/src/__tests__/integration/structured-output.test.ts @@ -20,6 +20,30 @@ function createStructuredAgent(provider: 'anthropic' | 'openai'): Agent { .structuredOutput(answerSchema); } +// Raw JSON Schema equivalent of `answerSchema` — exercises the JSON Schema path +// (as used when a workflow node supplies the schema dynamically). +const answerJsonSchema = { + type: 'object' as const, + properties: { + city: { type: 'string' as const, description: 'The name of the city' }, + country: { type: 'string' as const, description: 'The country the city is in' }, + population_millions: { + type: 'number' as const, + description: 'Approximate population in millions', + }, + }, + required: ['city', 'country', 'population_millions'], +}; + +function createJsonSchemaStructuredAgent(provider: 'anthropic' | 'openai'): Agent { + return new Agent('structured-output-json-schema-test') + .model(getModel(provider)) + .instructions( + 'You answer geography questions. Always respond with the structured output schema. Be precise and factual.', + ) + .structuredOutput(answerJsonSchema); +} + function createStructuredAgentWithTool(provider: 'anthropic' | 'openai'): Agent { const lookupTool = new Tool('lookup_capital') .description('Look up the capital city of a country') @@ -93,6 +117,24 @@ describe('structured output integration', () => { } }); + it('returns parsed structuredOutput when configured with a raw JSON Schema', async () => { + const agent = createJsonSchemaStructuredAgent('anthropic'); + + const result = await agent.generate('What is the capital of France?'); + + expect(result.finishReason).toBe('stop'); + expect(result.structuredOutput).toBeDefined(); + + // The output still conforms to the equivalent Zod shape. + const parsed = answerSchema.safeParse(result.structuredOutput); + expect(parsed.success).toBe(true); + if (parsed.success) { + expect(parsed.data.city.toLowerCase()).toContain('paris'); + expect(parsed.data.country.toLowerCase()).toContain('france'); + expect(parsed.data.population_millions).toBeGreaterThan(0); + } + }); + it('returns parsed structuredOutput in stream finish chunk', async () => { const agent = createStructuredAgent('anthropic'); diff --git a/packages/@n8n/agents/src/__tests__/integration/tool-transform-error-resilience.test.ts b/packages/@n8n/agents/src/__tests__/integration/tool-transform-error-resilience.test.ts new file mode 100644 index 00000000000..c1738b7930c --- /dev/null +++ b/packages/@n8n/agents/src/__tests__/integration/tool-transform-error-resilience.test.ts @@ -0,0 +1,133 @@ +import { expect, it } from 'vitest'; +import { z } from 'zod'; + +import { describeIf, getModel, collectStreamChunks, chunksOfType } from './helpers'; +import { Agent, Memory, Tool } from '../../index'; + +const describe = describeIf('anthropic'); + +/** + * Integration tests for error resilience in processToolCall transforms. + * + * Two bugs under test: + * + * 1. toModelOutput throwing during a normal tool call — the agent should treat it + * as a tool error and let the LLM self-correct, not crash. + * + * 2. toModelOutput throwing during a RESUMED tool call — without the fix, this + * causes iteratePendingToolCallsConcurrent to propagate the rejection, which + * closes the stream via closeStreamWithError and skips memory persistence. + * With the fix, the error is captured and the stream continues normally. + */ +describe('tool transform error resilience', () => { + it('toModelOutput throwing during normal tool call — agent continues and finishes cleanly', async () => { + const fetchTool = new Tool('fetch_data') + .description('Fetch some data. Always succeeds but transform throws.') + .input(z.object({ id: z.string().describe('Resource ID') })) + .handler(async ({ id }) => ({ id, value: 42 })) + .toModelOutput(() => { + throw new Error('toModelOutput failed intentionally'); + }); + + const agent = new Agent('transform-error-normal-test') + .model(getModel('anthropic')) + .instructions( + 'You are a data fetcher. Use fetch_data to get data. ' + + 'If the tool fails with an error, acknowledge it and say what happened. Be concise.', + ) + .tool(fetchTool); + + const result = await agent.generate('Fetch data with id "test-1"'); + + // The agent must not throw — it should continue and acknowledge the error + expect(result.finishReason).toBe('stop'); + expect(result.messages.length).toBeGreaterThan(0); + }); + + it('toModelOutput throwing during normal tool call in stream() — stream finishes with stop, not error', async () => { + const fetchTool = new Tool('fetch_data') + .description('Fetch some data. Transform always throws.') + .input(z.object({ id: z.string().describe('Resource ID') })) + .handler(async ({ id }) => ({ id, value: 99 })) + .toModelOutput(() => { + throw new Error('toModelOutput failed in stream'); + }); + + const agent = new Agent('transform-error-stream-test') + .model(getModel('anthropic')) + .instructions( + 'You are a data fetcher. Use fetch_data to get data. ' + + 'If the tool errors, acknowledge it. Be concise.', + ) + .tool(fetchTool); + + const { stream } = await agent.stream('Fetch data with id "stream-1"'); + const chunks = await collectStreamChunks(stream); + + const finishChunks = chunksOfType(chunks, 'finish'); + expect(finishChunks.length).toBeGreaterThan(0); + expect(finishChunks[finishChunks.length - 1].finishReason).not.toBe('error'); + }); + + it('toModelOutput throwing during resumed tool call — stream does not close with error and messages are saved to memory', async () => { + const { memory } = { memory: new Memory().storage('memory') }; + + const approveTool = new Tool('approve_action') + .description('Request approval for an action. Suspends for human review.') + .input(z.object({ action: z.string().describe('Action to approve') })) + .output(z.object({ approved: z.boolean(), action: z.string() })) + .suspend(z.object({ question: z.string() })) + .resume(z.object({ confirmed: z.boolean() })) + .handler(async ({ action }, ctx) => { + if (!ctx.resumeData) { + return await ctx.suspend({ question: `Approve "${action}"?` }); + } + return { approved: ctx.resumeData.confirmed, action }; + }) + .toModelOutput(() => { + // Always throws — simulates a broken transform on the resumed call + throw new Error('toModelOutput failed on resume intentionally'); + }); + + const agent = new Agent('transform-error-resume-test') + .model(getModel('anthropic')) + .instructions( + 'You are an approval manager. Use approve_action when asked to perform an action. ' + + 'If the tool errors, acknowledge it and say what happened. Be concise.', + ) + .tool(approveTool) + .memory(memory) + .checkpoint('memory'); + + const threadId = `test-transform-resume-${Date.now()}`; + const options = { persistence: { threadId, resourceId: 'test-user' } }; + + // Turn 1: stream — agent should call the tool, which suspends + const result1 = await agent.stream('Please approve the action "deploy to production"', options); + const chunks1 = await collectStreamChunks(result1.stream); + + const suspendChunk = chunksOfType(chunks1, 'tool-call-suspended')[0]; + expect(suspendChunk).toBeDefined(); + + // Turn 2: resume — tool returns a result, but toModelOutput throws + // Bug (without fix): stream closes with finishReason 'error' via closeStreamWithError + // Fix: error is captured as a tool error, stream continues, LLM responds + const result2 = await agent.resume( + 'stream', + { confirmed: true }, + { runId: suspendChunk.runId, toolCallId: suspendChunk.toolCallId }, + ); + const chunks2 = await collectStreamChunks(result2.stream); + + const finishChunks = chunksOfType(chunks2, 'finish'); + expect(finishChunks.length).toBeGreaterThan(0); + // The stream must NOT end with 'error' — the transform error must be contained + expect(finishChunks[finishChunks.length - 1].finishReason).not.toBe('error'); + + // The tool-result chunk in the resumed stream should carry isError: true + const toolResults = chunksOfType(chunks2, 'tool-result'); + const approveResult = toolResults.find((c) => c.toolName === 'approve_action'); + expect(approveResult).toBeDefined(); + expect(approveResult!.isError).toBe(true); + }); +}); diff --git a/packages/@n8n/agents/src/__tests__/workspace/sandbox/create-workspace.test.ts b/packages/@n8n/agents/src/__tests__/workspace/sandbox/create-workspace.test.ts new file mode 100644 index 00000000000..16fe232ed62 --- /dev/null +++ b/packages/@n8n/agents/src/__tests__/workspace/sandbox/create-workspace.test.ts @@ -0,0 +1,188 @@ +vi.mock('@n8n/utils', () => ({ + getJwtExpiry: vi.fn(() => undefined), +})); + +import { DaytonaFilesystem } from '../../../workspace/filesystem/daytona-filesystem'; +import { N8nSandboxFilesystem } from '../../../workspace/filesystem/n8n-sandbox-filesystem'; +import { createFilesystem, createSandbox } from '../../../workspace/sandbox/create-workspace'; +import { DaytonaSandbox } from '../../../workspace/sandbox/daytona-sandbox'; +import { N8nSandboxServiceSandbox } from '../../../workspace/sandbox/n8n-sandbox-sandbox'; +import type { SandboxConfig } from '../../../workspace/sandbox/types'; + +describe('createSandbox', () => { + it('returns undefined when sandbox is disabled', async () => { + const config: SandboxConfig = { enabled: false, provider: 'n8n-sandbox' }; + + const result = await createSandbox(config); + + expect(result).toBeUndefined(); + }); + + it('returns a DaytonaSandbox for daytona provider', async () => { + const config: SandboxConfig = { + enabled: true, + provider: 'daytona', + id: 'instance-ai-thread-thread-1', + name: 'instance-ai-thread-thread-1', + daytonaApiUrl: 'https://api.daytona.io', + daytonaApiKey: 'test-key', + image: 'node:20', + snapshot: 'n8n-instance-ai-1.0.0', + timeout: 60_000, + createTimeoutSeconds: 900, + }; + + const result = await createSandbox(config); + + expect(result).toBeInstanceOf(DaytonaSandbox); + expect(result?.id).toBe('instance-ai-thread-thread-1'); + expect(result?.provider).toBe('daytona'); + }); + + it('passes ephemeral through to the DaytonaSandbox', async () => { + const config: SandboxConfig = { + enabled: true, + provider: 'daytona', + daytonaApiUrl: 'https://api.daytona.io', + daytonaApiKey: 'test-key', + ephemeral: true, + timeout: 60_000, + }; + + const result = await createSandbox(config); + + expect(result).toBeInstanceOf(DaytonaSandbox); + expect((result as unknown as { options: { ephemeral?: boolean } }).options.ephemeral).toBe( + true, + ); + }); + + it('passes stop, archive and delete intervals through to the DaytonaSandbox', async () => { + const config: SandboxConfig = { + enabled: true, + provider: 'daytona', + daytonaApiUrl: 'https://api.daytona.io', + daytonaApiKey: 'test-key', + autoStopInterval: 30, + autoArchiveInterval: 1440, + autoDeleteInterval: 43_200, + timeout: 60_000, + }; + + const result = await createSandbox(config); + + expect( + ( + result as unknown as { + options: { + autoStopInterval?: number; + autoArchiveInterval?: number; + autoDeleteInterval?: number; + }; + } + ).options, + ).toMatchObject({ + autoStopInterval: 30, + autoArchiveInterval: 1440, + autoDeleteInterval: 43_200, + }); + }); + + it('omits ephemeral from the DaytonaSandbox when not configured', async () => { + const config: SandboxConfig = { + enabled: true, + provider: 'daytona', + daytonaApiUrl: 'https://api.daytona.io', + daytonaApiKey: 'test-key', + timeout: 60_000, + }; + + const result = await createSandbox(config); + + expect( + (result as unknown as { options: { ephemeral?: boolean } }).options.ephemeral, + ).toBeUndefined(); + }); + + it('passes getAuthToken through to DaytonaSandbox in proxy mode', async () => { + const getAuthToken = vi.fn().mockResolvedValue('jwt-token-123'); + const config: SandboxConfig = { + enabled: true, + provider: 'daytona', + daytonaApiUrl: 'https://proxy.example.com', + getAuthToken, + timeout: 60_000, + }; + + const result = await createSandbox(config); + + expect(getAuthToken).not.toHaveBeenCalled(); + expect(result).toBeInstanceOf(DaytonaSandbox); + }); + + it('returns an N8nSandboxServiceSandbox for n8n-sandbox provider', async () => { + const config: SandboxConfig = { + enabled: true, + provider: 'n8n-sandbox', + serviceUrl: 'https://sandbox.example.com', + apiKey: 'sandbox-key', + timeout: 45_000, + }; + + const result = await createSandbox(config); + + expect(result).toBeInstanceOf(N8nSandboxServiceSandbox); + expect(result?.provider).toBe('n8n-sandbox'); + }); + + it('does not include sandbox secrets in unsupported provider errors', async () => { + const config = { + enabled: true, + provider: 'unsupported', + daytonaApiKey: 'daytona-secret', + apiKey: 'sandbox-secret', + } as unknown as SandboxConfig; + + let error: unknown; + try { + await createSandbox(config); + } catch (caught) { + error = caught; + } + + expect(error).toBeInstanceOf(Error); + if (!(error instanceof Error)) return; + expect(error.message).toBe('Unsupported sandbox provider: unsupported'); + expect(error.message).not.toContain('daytona-secret'); + expect(error.message).not.toContain('sandbox-secret'); + }); +}); + +describe('createFilesystem', () => { + it('returns undefined when sandbox is undefined', () => { + const result = createFilesystem(undefined); + + expect(result).toBeUndefined(); + }); + + it('creates a DaytonaFilesystem for DaytonaSandbox', () => { + const sandbox = new DaytonaSandbox({ apiKey: 'key' }); + + const result = createFilesystem(sandbox); + + expect(result).toBeInstanceOf(DaytonaFilesystem); + expect(result.id).toBe(`daytona-fs-${sandbox.id}`); + }); + + it('creates an N8nSandboxFilesystem for N8nSandboxServiceSandbox', () => { + const sandbox = new N8nSandboxServiceSandbox({ + apiKey: 'key', + serviceUrl: 'https://sandbox.example.com', + }); + + const result = createFilesystem(sandbox); + + expect(result).toBeInstanceOf(N8nSandboxFilesystem); + expect(result.provider).toBe('n8n-sandbox'); + }); +}); diff --git a/packages/@n8n/instance-ai/src/workspace/__tests__/daytona-auth-manager.test.ts b/packages/@n8n/agents/src/__tests__/workspace/sandbox/daytona-auth-manager.test.ts similarity index 97% rename from packages/@n8n/instance-ai/src/workspace/__tests__/daytona-auth-manager.test.ts rename to packages/@n8n/agents/src/__tests__/workspace/sandbox/daytona-auth-manager.test.ts index f85cf120232..b5a8537fada 100644 --- a/packages/@n8n/instance-ai/src/workspace/__tests__/daytona-auth-manager.test.ts +++ b/packages/@n8n/agents/src/__tests__/workspace/sandbox/daytona-auth-manager.test.ts @@ -2,7 +2,7 @@ const { daytonaInstances } = vi.hoisted(() => ({ daytonaInstances: [] as Array<{ config: unknown }>, })); -vi.mock('../lazy-daytona', () => { +vi.mock('../../../workspace/sandbox/lazy-daytona', () => { class Daytona { constructor(public config: unknown) { daytonaInstances.push({ config }); @@ -11,7 +11,7 @@ vi.mock('../lazy-daytona', () => { return { loadDaytona: () => ({ Daytona }) }; }); -import { DaytonaAuthManager } from '../daytona-auth-manager'; +import { DaytonaAuthManager } from '../../../workspace/sandbox/daytona-auth-manager'; function base64url(input: string): string { return Buffer.from(input, 'utf8').toString('base64url'); diff --git a/packages/@n8n/instance-ai/src/workspace/__tests__/daytona-sandbox.test.ts b/packages/@n8n/agents/src/__tests__/workspace/sandbox/daytona-sandbox.test.ts similarity index 61% rename from packages/@n8n/instance-ai/src/workspace/__tests__/daytona-sandbox.test.ts rename to packages/@n8n/agents/src/__tests__/workspace/sandbox/daytona-sandbox.test.ts index 75ab3f34c25..39f2b7e034c 100644 --- a/packages/@n8n/instance-ai/src/workspace/__tests__/daytona-sandbox.test.ts +++ b/packages/@n8n/agents/src/__tests__/workspace/sandbox/daytona-sandbox.test.ts @@ -32,6 +32,7 @@ interface DaytonaClientLog { const { clientLog, queuedGetErrors, + queuedGetResults, queuedCreateResults, makeMockSandbox, Daytona, @@ -43,6 +44,7 @@ const { let nextClientId = 1; let nextSandboxId = 1; const queuedGetErrors: Error[] = []; + const queuedGetResults: MockSandbox[] = []; const queuedCreateResults: Array<MockSandbox | Error> = []; function makeMockSandbox(id: string, state = 'started'): MockSandbox { @@ -86,6 +88,10 @@ const { if (queued !== undefined) { return await Promise.reject(queued); } + const queuedResult = queuedGetResults.shift(); + if (queuedResult !== undefined) { + return await Promise.resolve(queuedResult); + } return await Promise.resolve(makeMockSandbox(`sb-${id}-${nextSandboxId++}`)); }); const create = vi @@ -137,12 +143,14 @@ const { nextClientId = 1; nextSandboxId = 1; queuedGetErrors.length = 0; + queuedGetResults.length = 0; queuedCreateResults.length = 0; } return { clientLog, queuedGetErrors, + queuedGetResults, queuedCreateResults, makeMockSandbox, Daytona, @@ -152,12 +160,13 @@ const { }; }); -vi.mock('../lazy-daytona', () => ({ +vi.mock('../../../workspace/sandbox/lazy-daytona', () => ({ loadDaytona: () => ({ Daytona, DaytonaError, DaytonaNotFoundError }), })); -import type { ErrorReporter, Logger } from '../../logger'; -import { DaytonaSandbox } from '../daytona-sandbox'; +import { DaytonaFilesystem } from '../../../workspace/filesystem/daytona-filesystem'; +import { DaytonaSandbox } from '../../../workspace/sandbox/daytona-sandbox'; +import type { ErrorReporter, Logger } from '../../../workspace/sandbox/logger'; function base64url(input: string): string { return Buffer.from(input, 'utf8').toString('base64url'); @@ -190,7 +199,7 @@ beforeEach(() => { }); describe('DaytonaSandbox (creation strategies)', () => { - it('falls back from snapshot creation to image creation and preserves sandbox labels', async () => { + it('falls back from snapshot creation to image creation and preserves caller-provided labels', async () => { const logger = makeLogger(); const errorReporter: ErrorReporter = { error: vi.fn() }; const snapshotError = new Error('snapshot missing'); @@ -223,7 +232,6 @@ describe('DaytonaSandbox (creation strategies)', () => { ephemeral: true, labels: { 'n8n-builder': 'builder-run', - 'n8n-instance-ai-sandbox-id': 'sandbox-id', run_id: 'run-1', thread_id: 'thread-1', }, @@ -237,7 +245,6 @@ describe('DaytonaSandbox (creation strategies)', () => { image: 'node:20', labels: { 'n8n-builder': 'builder-run', - 'n8n-instance-ai-sandbox-id': 'sandbox-id', run_id: 'run-1', thread_id: 'thread-1', }, @@ -431,8 +438,157 @@ describe('DaytonaSandbox (remote sandbox gone during refetch)', () => { await expect(sandbox.destroy()).resolves.toBeUndefined(); }); - it('executeCommand() propagates NotFound rather than NPE-ing on a silently-cleared cache', async () => { + it('executeCommand() recovers by recreating the sandbox when the remote was deleted', async () => { const sandbox = await startAndStageRemoteGone(); - await expect(sandbox.executeCommand('echo', ['hi'])).rejects.toThrow(/not found/i); + // The remote stays gone: the recovery's findExistingSandbox() lookup also 404s, so + // it falls through to creating a fresh sandbox. + queueNotFound(); + + // The staged refetch throws NotFound (a 404 short-circuits as recoverable); recovery + // resets the handle and re-runs start() → findExistingSandbox() → create. + const result = await sandbox.executeCommand('echo', ['hi']); + + expect(result.success).toBe(true); + expect(result.stdout).toBe('ok'); + expect(clientLog.some((c) => c.create.mock.calls.length > 0)).toBe(true); + }); + + it('executeCommand() recovers a stopped remote from its state, even on a 403', async () => { + // Direct mode (static key) — no JWT rotation, so recovery cannot rely on the + // getDaytona refetch; it must come from the state probe in recoverAndRetry. + const failing = makeMockSandbox('sb-stale', 'started'); + // A stopped/unreachable container surfaces as "Endpoint not allowed; 403" (which also + // looks like an auth error). Recovery must be driven by the probed remote state, not + // by the error code — otherwise this 403 is misread as auth and never recovers. + failing.process.executeCommand = vi + .fn() + .mockRejectedValue(new DaytonaError('Endpoint not allowed', 403)); + const probeStopped = makeMockSandbox('sb-probe', 'stopped'); + const resumed = makeMockSandbox('sb-resumed', 'stopped'); + // get order: start() → failing; isRecoverable probe → stopped; retry start() → resumed. + queuedGetResults.push(failing, probeStopped, resumed); + + const sandbox = new DaytonaSandbox({ name: 'thread-1', apiKey: 'key' }); + const result = await sandbox.executeCommand('echo', ['resumed']); + + expect(result.success).toBe(true); + expect(resumed.start).toHaveBeenCalled(); + }); + + it('executeCommand() does not recover when auth is genuinely failing', async () => { + vi.useFakeTimers().setSystemTime(new Date(1_700_000_000_000)); + const getAuthToken = vi.fn<(...args: []) => Promise<string>>().mockImplementation(async () => { + await Promise.resolve(); + return makeJwt(Date.now() + HOUR_MS); + }); + const sandbox = new DaytonaSandbox({ name: 'thread-1', getAuthToken }); + await sandbox.start(); + + vi.setSystemTime(new Date(Date.now() + HOUR_MS - SKEW_MS + 1)); + // Both the op's refetch and the recovery probe fail auth — the probe can't confirm a + // not-running state, so the original error propagates and nothing is recreated. + queuedGetErrors.push( + new DaytonaError('unauthorized', 401), + new DaytonaError('unauthorized', 401), + ); + + await expect(sandbox.executeCommand('echo', ['hi'])).rejects.toThrow(/unauthorized/i); + expect(clientLog.every((c) => c.create.mock.calls.length === 0)).toBe(true); + }); + + it('executeCommand() propagates when the remote is still running (no false recovery)', async () => { + // op fails but the probe finds the sandbox healthy → original error must surface. + const healthy = makeMockSandbox('sb-healthy', 'started'); + healthy.process.executeCommand = vi + .fn() + .mockRejectedValue(new Error('genuine command failure')); + const probeStarted = makeMockSandbox('sb-probe', 'started'); + queuedGetResults.push(healthy, probeStarted); + + const sandbox = new DaytonaSandbox({ name: 'thread-1', apiKey: 'key' }); + + await expect(sandbox.executeCommand('echo', ['hi'])).rejects.toThrow( + /genuine command failure/i, + ); + expect(clientLog.every((c) => c.create.mock.calls.length === 0)).toBe(true); + }); + + it('executeCommand() does not recover from a failed (error) state', async () => { + // A non-running but non-recoverable state (error/build_failed/transient) must not + // trigger a resume/recreate — only stopped/archived/gone are recoverable. + const failing = makeMockSandbox('sb-stale', 'started'); + failing.process.executeCommand = vi.fn().mockRejectedValue(new Error('boom')); + const probeError = makeMockSandbox('sb-probe', 'error'); + queuedGetResults.push(failing, probeError); + + const sandbox = new DaytonaSandbox({ name: 'thread-1', apiKey: 'key' }); + + await expect(sandbox.executeCommand('echo', ['hi'])).rejects.toThrow(/boom/i); + expect(clientLog.every((c) => c.create.mock.calls.length === 0)).toBe(true); + }); + + it('executeCommand() retries recovery at most once', async () => { + const sandbox = await startAndStageRemoteGone(); + + // The recovery retry also fails: findExistingSandbox() get → NotFound (→ create) and + // the create rejects. The second failure propagates instead of looping. + queueNotFound(); + queuedCreateResults.push(new Error('create failed')); + + await expect(sandbox.executeCommand('echo', ['hi'])).rejects.toThrow(/create failed/i); + }); + + it('DaytonaFilesystem reuses the same recovery when the remote was deleted', async () => { + const sandbox = await startAndStageRemoteGone(); + // findExistingSandbox() lookup also 404s during recovery → create a fresh sandbox. + queueNotFound(); + const filesystem = new DaytonaFilesystem(sandbox); + + // readFile() → withFilesystem() → recoverAndRetry: the staged NotFound triggers a + // reset + recreate, then the op runs against the fresh fs handle. + await expect(filesystem.readFile('/workspace/file.txt')).resolves.toBeUndefined(); + expect(clientLog.some((c) => c.create.mock.calls.length > 0)).toBe(true); + }); + + it('DaytonaFilesystem.exists() recovers a stopped sandbox instead of reporting missing', async () => { + // getFileDetails on a stopped sandbox fails with a non-404 — it must bubble to + // recovery, not be swallowed as "file does not exist". + const failing = makeMockSandbox('sb-stale', 'started'); + failing.fs.getFileDetails = vi + .fn() + .mockRejectedValue(new DaytonaError('Endpoint not allowed', 403)); + const probeStopped = makeMockSandbox('sb-probe', 'stopped'); + const resumed = makeMockSandbox('sb-resumed', 'stopped'); + queuedGetResults.push(failing, probeStopped, resumed); + + const sandbox = new DaytonaSandbox({ name: 'thread-1', apiKey: 'key' }); + const filesystem = new DaytonaFilesystem(sandbox); + + await expect(filesystem.exists('/workspace/marker')).resolves.toBe(true); + expect(resumed.start).toHaveBeenCalled(); + }); + + it('DaytonaFilesystem.exists() returns false for a genuine 404 without recovering', async () => { + const handle = makeMockSandbox('sb-1', 'started'); + handle.fs.getFileDetails = vi.fn().mockRejectedValue(new DaytonaError('file not found', 404)); + queuedGetResults.push(handle); + + const sandbox = new DaytonaSandbox({ name: 'thread-1', apiKey: 'key' }); + const filesystem = new DaytonaFilesystem(sandbox); + + await expect(filesystem.exists('/workspace/missing')).resolves.toBe(false); + expect(clientLog.every((c) => c.create.mock.calls.length === 0)).toBe(true); + }); + + it('DaytonaFilesystem.appendFile() treats a genuine 404 as an empty file', async () => { + const handle = makeMockSandbox('sb-1', 'started'); + handle.fs.downloadFile = vi.fn().mockRejectedValue(new DaytonaError('file not found', 404)); + queuedGetResults.push(handle); + + const sandbox = new DaytonaSandbox({ name: 'thread-1', apiKey: 'key' }); + const filesystem = new DaytonaFilesystem(sandbox); + + await filesystem.appendFile('/workspace/log.txt', 'entry'); + expect(handle.fs.uploadFile).toHaveBeenCalled(); }); }); diff --git a/packages/@n8n/agents/src/__tests__/workspace/sandbox/n8n-sandbox-filesystem.test.ts b/packages/@n8n/agents/src/__tests__/workspace/sandbox/n8n-sandbox-filesystem.test.ts new file mode 100644 index 00000000000..fef7b486406 --- /dev/null +++ b/packages/@n8n/agents/src/__tests__/workspace/sandbox/n8n-sandbox-filesystem.test.ts @@ -0,0 +1,111 @@ +import { SandboxServiceError } from '@n8n/sandbox-client'; + +import { N8nSandboxFilesystem } from '../../../workspace/filesystem/n8n-sandbox-filesystem'; +import { N8nSandboxServiceSandbox } from '../../../workspace/sandbox/n8n-sandbox-sandbox'; + +const mockMkdir = vi.fn(); +const mockWriteFile = vi.fn(); +const mockReadFile = vi.fn(); +const mockStat = vi.fn(); + +vi.mock('@n8n/sandbox-client', () => { + class MockSandboxServiceError extends Error { + readonly status: number; + + constructor(message: string, status: number) { + super(message); + this.name = 'SandboxServiceError'; + this.status = status; + } + } + + return { + SandboxServiceError: MockSandboxServiceError, + SandboxClient: class { + mkdir = mockMkdir; + writeFile = mockWriteFile; + readFile = mockReadFile; + stat = mockStat; + }, + }; +}); + +function createFilesystem() { + const sandbox = new N8nSandboxServiceSandbox({ + id: 'sb-test', + apiKey: 'key', + serviceUrl: 'https://sandbox.test', + }); + vi.spyOn(sandbox, 'ensureRunning').mockResolvedValue(undefined); + return new N8nSandboxFilesystem(sandbox); +} + +describe('N8nSandboxFilesystem', () => { + beforeEach(() => { + vi.clearAllMocks(); + mockMkdir.mockResolvedValue(undefined); + mockWriteFile.mockResolvedValue(undefined); + mockReadFile.mockResolvedValue(Buffer.from('file content')); + mockStat.mockResolvedValue({ + name: 'file.txt', + path: '/workspace/file.txt', + type: 'file', + size: 12, + createdAt: '2024-01-01T00:00:00.000Z', + modifiedAt: '2024-01-02T00:00:00.000Z', + }); + }); + + it('calls mkdir for parent directory before writeFile when recursive is true', async () => { + const filesystem = createFilesystem(); + + await filesystem.writeFile('/workspace/nested/file.txt', 'hello', { recursive: true }); + + expect(mockMkdir).toHaveBeenCalledWith('sb-test', '/workspace/nested', true); + expect(mockWriteFile).toHaveBeenCalledWith( + 'sb-test', + '/workspace/nested/file.txt', + 'hello', + true, + ); + }); + + it('returns string content when readFile is called with utf8 encoding', async () => { + const filesystem = createFilesystem(); + + const content = await filesystem.readFile('/workspace/file.txt', { encoding: 'utf8' }); + + expect(content).toBe('file content'); + expect(mockReadFile).toHaveBeenCalledWith('sb-test', '/workspace/file.txt'); + }); + + it('returns false from exists on SandboxServiceError 404', async () => { + mockStat.mockRejectedValue(new SandboxServiceError('not found', 404)); + const filesystem = createFilesystem(); + + await expect(filesystem.exists('/workspace/missing.txt')).resolves.toBe(false); + }); + + it('rethrows non-404 errors from exists', async () => { + const error = new SandboxServiceError('server error', 500); + mockStat.mockRejectedValue(error); + const filesystem = createFilesystem(); + + await expect(filesystem.exists('/workspace/file.txt')).rejects.toBe(error); + }); + + it('maps sandbox client stat fields into FileStat', async () => { + const filesystem = createFilesystem(); + + const result = await filesystem.stat('/workspace/file.txt'); + + expect(result).toEqual({ + name: 'file.txt', + path: '/workspace/file.txt', + type: 'file', + size: 12, + createdAt: new Date('2024-01-01T00:00:00.000Z'), + modifiedAt: new Date('2024-01-02T00:00:00.000Z'), + }); + }); +}); diff --git a/packages/@n8n/instance-ai/src/workspace/__tests__/n8n-sandbox-sandbox.test.ts b/packages/@n8n/agents/src/__tests__/workspace/sandbox/n8n-sandbox-sandbox.test.ts similarity index 98% rename from packages/@n8n/instance-ai/src/workspace/__tests__/n8n-sandbox-sandbox.test.ts rename to packages/@n8n/agents/src/__tests__/workspace/sandbox/n8n-sandbox-sandbox.test.ts index 8bd005e676b..e81a7c9413e 100644 --- a/packages/@n8n/instance-ai/src/workspace/__tests__/n8n-sandbox-sandbox.test.ts +++ b/packages/@n8n/agents/src/__tests__/workspace/sandbox/n8n-sandbox-sandbox.test.ts @@ -1,6 +1,6 @@ import { SandboxServiceError } from '@n8n/sandbox-client'; -import { N8nSandboxServiceSandbox } from '../n8n-sandbox-sandbox'; +import { N8nSandboxServiceSandbox } from '../../../workspace/sandbox/n8n-sandbox-sandbox'; // --------------------------------------------------------------------------- // Mocks diff --git a/packages/@n8n/agents/src/__tests__/workspace/sandbox/provider.test.ts b/packages/@n8n/agents/src/__tests__/workspace/sandbox/provider.test.ts new file mode 100644 index 00000000000..edd27079633 --- /dev/null +++ b/packages/@n8n/agents/src/__tests__/workspace/sandbox/provider.test.ts @@ -0,0 +1,43 @@ +import { + DEFAULT_SANDBOX_PROVIDER, + isSandboxProvider, + normalizeSandboxProvider, +} from '../../../workspace/sandbox/provider'; + +describe('normalizeSandboxProvider', () => { + it('returns n8n-sandbox for undefined', () => { + expect(normalizeSandboxProvider(undefined)).toBe('n8n-sandbox'); + }); + + it('returns n8n-sandbox for empty string', () => { + expect(normalizeSandboxProvider('')).toBe('n8n-sandbox'); + }); + + it('returns n8n-sandbox for valid n8n-sandbox value', () => { + expect(normalizeSandboxProvider('n8n-sandbox')).toBe('n8n-sandbox'); + }); + + it('returns daytona for valid daytona value', () => { + expect(normalizeSandboxProvider('daytona')).toBe('daytona'); + }); + + it('returns n8n-sandbox for unrecognized value', () => { + expect(normalizeSandboxProvider('bad-value')).toBe('n8n-sandbox'); + }); +}); + +describe('isSandboxProvider', () => { + it('returns true for daytona', () => { + expect(isSandboxProvider('daytona')).toBe(true); + }); + + it('returns false for bad value', () => { + expect(isSandboxProvider('bad-value')).toBe(false); + }); +}); + +describe('DEFAULT_SANDBOX_PROVIDER', () => { + it('is n8n-sandbox', () => { + expect(DEFAULT_SANDBOX_PROVIDER).toBe('n8n-sandbox'); + }); +}); diff --git a/packages/@n8n/agents/src/__tests__/workspace/sandbox/workspace-root.test.ts b/packages/@n8n/agents/src/__tests__/workspace/sandbox/workspace-root.test.ts new file mode 100644 index 00000000000..2c634030532 --- /dev/null +++ b/packages/@n8n/agents/src/__tests__/workspace/sandbox/workspace-root.test.ts @@ -0,0 +1,157 @@ +import { + DAYTONA_HOME, + N8N_SANDBOX_HOME, + getPromptWorkspaceRoot, + getWorkspaceRoot, + WORKSPACE_DIR, + type SandboxWorkspace, +} from '../../../workspace/sandbox/workspace-root'; + +describe('getPromptWorkspaceRoot', () => { + it('returns daytona workspace root', () => { + expect(getPromptWorkspaceRoot('daytona')).toBe('/home/daytona/workspace'); + }); + + it('returns n8n-sandbox workspace root', () => { + expect(getPromptWorkspaceRoot('n8n-sandbox')).toBe('/home/user/workspace'); + }); +}); + +describe('getWorkspaceRoot', () => { + it('returns local filesystem basePath when provider is local', async () => { + const workspace = { + filesystem: { + provider: 'local', + basePath: '/local/workspace', + }, + } as SandboxWorkspace; + + await expect(getWorkspaceRoot(workspace)).resolves.toBe('/local/workspace'); + }); + + it('initializes lazy filesystem and returns its basePath', async () => { + let initialized = false; + const executeCommand = vi.fn(); + const init = vi.fn<(...args: []) => Promise<void>>(async () => { + await Promise.resolve(); + initialized = true; + }); + const workspace = { + filesystem: { + provider: 'lazy', + get basePath() { + return initialized ? '/sandbox' : undefined; + }, + init, + }, + sandbox: { + executeCommand, + }, + } as SandboxWorkspace; + + await expect(getWorkspaceRoot(workspace)).resolves.toBe('/sandbox'); + + expect(init).toHaveBeenCalledTimes(1); + expect(executeCommand).not.toHaveBeenCalled(); + }); + + it('falls back to echo $HOME through sandbox command execution', async () => { + const executeCommand = vi.fn().mockResolvedValue({ + exitCode: 0, + stdout: '/custom/home\n', + stderr: '', + }); + const workspace = { + sandbox: { + executeCommand, + }, + } as SandboxWorkspace; + + await expect(getWorkspaceRoot(workspace)).resolves.toBe('/custom/home/workspace'); + + expect(executeCommand).toHaveBeenCalledWith('echo $HOME', [], { cwd: undefined }); + }); + + it('uses DAYTONA_HOME when echo $HOME returns empty stdout for Daytona', async () => { + const executeCommand = vi.fn().mockResolvedValue({ + exitCode: 0, + stdout: ' \n', + stderr: '', + }); + const workspace = { + sandbox: { + provider: 'daytona', + executeCommand, + }, + } as SandboxWorkspace; + + await expect(getWorkspaceRoot(workspace)).resolves.toBe(`${DAYTONA_HOME}/${WORKSPACE_DIR}`); + }); + + it('uses N8N_SANDBOX_HOME when echo $HOME returns empty stdout for n8n-sandbox', async () => { + const executeCommand = vi.fn().mockResolvedValue({ + exitCode: 0, + stdout: ' \n', + stderr: '', + }); + const workspace = { + sandbox: { + provider: 'n8n-sandbox', + executeCommand, + }, + } as SandboxWorkspace; + + await expect(getWorkspaceRoot(workspace)).resolves.toBe(`${N8N_SANDBOX_HOME}/${WORKSPACE_DIR}`); + }); + + it('uses DAYTONA_HOME when echo $HOME returns empty stdout without provider metadata', async () => { + const executeCommand = vi.fn().mockResolvedValue({ + exitCode: 0, + stdout: ' \n', + stderr: '', + }); + const workspace = { + sandbox: { + executeCommand, + }, + } as SandboxWorkspace; + + await expect(getWorkspaceRoot(workspace)).resolves.toBe(`${DAYTONA_HOME}/${WORKSPACE_DIR}`); + }); + + it('uses DAYTONA_HOME when echo $HOME is empty for an unsupported provider', async () => { + const executeCommand = vi.fn().mockResolvedValue({ + exitCode: 0, + stdout: ' \n', + stderr: '', + }); + const workspace = { + sandbox: { + provider: 'unknown', + executeCommand, + }, + } as SandboxWorkspace; + + await expect(getWorkspaceRoot(workspace)).resolves.toBe(`${DAYTONA_HOME}/${WORKSPACE_DIR}`); + }); + + it('caches result per workspace object', async () => { + const executeCommand = vi.fn().mockResolvedValue({ + exitCode: 0, + stdout: '/cached/home\n', + stderr: '', + }); + const workspace = { + sandbox: { + executeCommand, + }, + } as SandboxWorkspace; + + const first = await getWorkspaceRoot(workspace); + const second = await getWorkspaceRoot(workspace); + + expect(first).toBe('/cached/home/workspace'); + expect(second).toBe('/cached/home/workspace'); + expect(executeCommand).toHaveBeenCalledTimes(1); + }); +}); diff --git a/packages/@n8n/agents/src/index.ts b/packages/@n8n/agents/src/index.ts index 0999112cd61..3e4fa0dbb6b 100644 --- a/packages/@n8n/agents/src/index.ts +++ b/packages/@n8n/agents/src/index.ts @@ -5,6 +5,7 @@ export type { BuiltMemory, BuiltEpisodicMemoryStore, BuiltGuardrail, + PiiDetectionType, BuiltEval, RunOptions, AgentResult, @@ -103,6 +104,23 @@ export type { Cancellation } from './sdk/cancellation'; export { Tool, wrapToolForApproval } from './sdk/tool'; export { Memory } from './sdk/memory'; export { Guardrail } from './sdk/guardrail'; +export { + redactText, + redactDeep, + redactionOptionsFromGuardrail, + DEFAULT_PLACEHOLDER, + StreamingRedactor, + resolvePatterns, + passesLuhn, + SUPPORTED_PII_CATEGORIES, +} from './sdk/guardrails'; +export type { + RedactionOptions, + RedactionResult, + DeepRedactionResult, + RedactionCategory, + RedactionPattern, +} from './sdk/guardrails'; export { Eval } from './sdk/eval'; export { evaluate } from './sdk/evaluate'; export type { DatasetRow, EvaluateConfig } from './sdk/evaluate'; @@ -197,26 +215,27 @@ export type { export { BaseMemory } from './storage/base-memory'; export type { ToolDescriptor } from './types/sdk/tool-descriptor'; -export { createModel } from './runtime/model-factory'; +export { createModel } from './runtime/model/model-factory'; export { + DEFAULT_SUB_AGENT_MAX_CHILDREN, ROOT_SUB_AGENT_TASK_PATH, - assertSubAgentPolicyAllowsChildCount, assertSubAgentTaskPath, createChildSubAgentTaskPath, isSubAgentTaskPath, sanitizeSubAgentTaskName, -} from './runtime/sub-agent-task-path'; -export type { SubAgentTaskPath, SubAgentTaskPathPolicy } from './runtime/sub-agent-task-path'; +} from './runtime/tools/sub-agent-task-path'; +export type { SubAgentTaskPath, SubAgentTaskPathPolicy } from './runtime/tools/sub-agent-task-path'; export { DELEGATE_SUB_AGENT_TOOL_NAME, DELEGATED_CHILD_SUSPEND_UNSUPPORTED_MESSAGE, INLINE_SUB_AGENT_ID, + SUB_AGENT_TASK_DIFFICULTIES, createDelegateSubAgentTool, failedDelegatedChildSuspendOutput, generateResultToDelegateSubAgentOutput, getInlineDelegateSubAgentToolOptions, renderDelegateSubAgentPrompt, -} from './runtime/delegate-sub-agent-tool'; +} from './runtime/tools/delegate-sub-agent-tool'; export type { CreateDelegateSubAgentToolOptions, DelegateSubAgentInput, @@ -225,10 +244,12 @@ export type { DelegateSubAgentRunner, DelegateSubAgentRunnerHelpers, DelegateSubAgentToolOutput, -} from './runtime/delegate-sub-agent-tool'; -export { WRITE_TODOS_TOOL_NAME, createWriteTodosTool } from './runtime/write-todos-tool'; -export { createEmbeddingModel } from './runtime/model-factory'; -export { generateTitleFromMessage } from './runtime/title-generation'; + InlineSubAgentProviderToolsResolver, + SubAgentTaskDifficulty, +} from './runtime/tools/delegate-sub-agent-tool'; +export { WRITE_TODOS_TOOL_NAME, createWriteTodosTool } from './runtime/tools/write-todos-tool'; +export { createEmbeddingModel } from './runtime/model/model-factory'; +export { generateTitleFromMessage } from './runtime/memory/title-generation'; export { activeLifecycleState, droppedLifecycleState, @@ -238,7 +259,7 @@ export { normalizeFlatReflectionActions, supersededLifecycleState, uniqueStrings, -} from './runtime/memory-lifecycle'; +} from './runtime/memory/memory-lifecycle'; export { RECALL_MEMORY_TOOL_NAME, createRecallMemoryTool, @@ -250,7 +271,7 @@ export { rankEpisodicMemoryEntries, runEpisodicMemoryIndexer, withEpisodicMemoryDefaults, -} from './runtime/episodic-memory'; +} from './runtime/memory/episodic-memory'; export { DEFAULT_EPISODIC_MEMORY_EMBEDDING_MODEL, DEFAULT_EPISODIC_MEMORY_EXTRACTION_PROMPT, @@ -262,24 +283,27 @@ export { buildEpisodicMemoryReflectorPrompt, createEpisodicMemoryExtractFn, createEpisodicMemoryReflectFn, -} from './runtime/episodic-memory-defaults'; +} from './runtime/memory/episodic-memory-defaults'; export type { CreateEpisodicMemoryExtractFnOptions, CreateEpisodicMemoryReflectFnOptions, -} from './runtime/episodic-memory-defaults'; -export type { MemoryLifecycleState, MemoryLifecycleStatus } from './runtime/memory-lifecycle'; +} from './runtime/memory/episodic-memory-defaults'; +export type { + MemoryLifecycleState, + MemoryLifecycleStatus, +} from './runtime/memory/memory-lifecycle'; export { parseObservationLogMarkdown, renderObserverTranscript, runObservationLogObserver, -} from './runtime/observation-log-observer'; +} from './runtime/memory/observation-log-observer'; export { normalizeObservationLogReflection, parseObservationLogReflectionJson, renderObservationLogForReflection, runObservationLogReflector, -} from './runtime/observation-log-reflector'; -export { ScopedMemoryTaskRunner } from './runtime/scoped-memory-task-runner'; +} from './runtime/memory/observation-log-reflector'; +export { ScopedMemoryTaskRunner } from './runtime/memory/scoped-memory-task-runner'; export { buildObservationLogReflectorPrompt, buildObservationLogObserverPrompt, @@ -292,11 +316,11 @@ export { DEFAULT_OBSERVATION_LOG_REFLECTOR_THRESHOLD_TOKENS, DEFAULT_OBSERVATION_LOG_RENDER_TOKEN_BUDGET, DEFAULT_OBSERVATION_LOG_TAIL_LIMIT, -} from './runtime/observation-log-defaults'; +} from './runtime/memory/observation-log-defaults'; export type { CreateObservationLogObserveFnOptions, CreateObservationLogReflectFnOptions, -} from './runtime/observation-log-defaults'; +} from './runtime/memory/observation-log-defaults'; export type { ObservationLogObserveFn, ObservationLogObserverInput, @@ -306,7 +330,7 @@ export type { RenderObserverTranscriptOptions, RunObservationLogObserverOpts, RunObservationLogObserverResult, -} from './runtime/observation-log-observer'; +} from './runtime/memory/observation-log-observer'; export type { ObservationLogReflectFn, ObservationLogReflectorInput, @@ -314,7 +338,7 @@ export type { ObservationLogReflectorWarning, RunObservationLogReflectorOpts, RunObservationLogReflectorResult, -} from './runtime/observation-log-reflector'; +} from './runtime/memory/observation-log-reflector'; export type { ScopedMemoryTaskDescriptor, ScopedMemoryTaskError, @@ -324,7 +348,7 @@ export type { ScopedMemoryTaskResult, ScopedMemoryTaskRunnerOptions, ScopedMemoryTaskStatus, -} from './runtime/scoped-memory-task-runner'; +} from './runtime/memory/scoped-memory-task-runner'; export { Workspace } from './workspace'; export { BaseFilesystem } from './workspace'; diff --git a/packages/@n8n/agents/src/runtime/__tests__/agent-runtime.test.ts b/packages/@n8n/agents/src/runtime/__tests__/agent-runtime.test.ts index 98ed512ae99..74bcc336cae 100644 --- a/packages/@n8n/agents/src/runtime/__tests__/agent-runtime.test.ts +++ b/packages/@n8n/agents/src/runtime/__tests__/agent-runtime.test.ts @@ -1,4 +1,5 @@ import * as aiModule from 'ai'; +import type { JSONSchema7 } from 'json-schema'; import type { Mock, MockedFunction } from 'vitest'; import { z } from 'zod'; @@ -11,10 +12,16 @@ import type { StreamChunk } from '../../types/sdk/agent'; import type { ContentToolCall, Message } from '../../types/sdk/message'; import type { BuiltTool, InterruptibleToolContext, ToolContext } from '../../types/sdk/tool'; import type { BuiltTelemetry } from '../../types/telemetry'; -import { AgentRuntime } from '../agent-runtime'; -import { AgentEventBus } from '../event-bus'; -import { InMemoryMemory } from '../memory-store'; -import { toAiSdkTools } from '../tool-adapter'; +import { AgentRuntime } from '../loop/agent-runtime'; +import { InMemoryMemory } from '../memory/memory-store'; +import { AgentEventBus } from '../state/event-bus'; +import { + DELEGATE_SUB_AGENT_TOOL_NAME, + INLINE_DELEGATE_SUB_AGENT_TOOL_METADATA_KEY, + createDelegateSubAgentTool, + type DelegateSubAgentRunner, +} from '../tools/delegate-sub-agent-tool'; +import { toAiSdkTools } from '../tools/tool-adapter'; // --------------------------------------------------------------------------- // Module mocks @@ -49,6 +56,7 @@ vi.mock('ai', async () => { generateText: vi.fn(), streamText: vi.fn(), tool: vi.fn((config: unknown) => config), + jsonSchema: vi.fn((schema: unknown) => ({ _type: 'jsonSchema', schema })), Output: { object: vi.fn(({ schema }: { schema: unknown }) => ({ _type: 'object', schema })), }, @@ -59,11 +67,12 @@ vi.mock('ai', async () => { // Helpers // --------------------------------------------------------------------------- -const { embed, embedMany, generateText, streamText } = aiModule as unknown as { +const { embed, embedMany, generateText, streamText, jsonSchema } = aiModule as unknown as { embed: Mock; embedMany: Mock; generateText: Mock; streamText: Mock; + jsonSchema: Mock; }; /** Minimal successful generateText response. */ @@ -212,6 +221,12 @@ function createRuntime(eventBus?: AgentEventBus) { const testSchema = z.object({ answer: z.string(), score: z.number() }); +const testJsonSchema: JSONSchema7 = { + type: 'object', + properties: { answer: { type: 'string' }, score: { type: 'number' } }, + required: ['answer', 'score'], +}; + /** Build a runtime configured with structuredOutput. */ function createStructuredRuntime(options?: { tools?: BuiltTool[]; eventBus?: AgentEventBus }) { const bus = options?.eventBus ?? new AgentEventBus(); @@ -226,6 +241,19 @@ function createStructuredRuntime(options?: { tools?: BuiltTool[]; eventBus?: Age return { runtime, bus }; } +/** Build a runtime configured with a raw JSON Schema structuredOutput. */ +function createJsonSchemaStructuredRuntime() { + const bus = new AgentEventBus(); + const runtime = new AgentRuntime({ + name: 'test-structured-json', + model: 'openai/gpt-4o-mini', + instructions: 'You are a test assistant.', + structuredOutput: testJsonSchema, + eventBus: bus, + }); + return { runtime, bus }; +} + /** Minimal successful generateText response with structured output. */ function makeGenerateSuccessWithOutput(output: unknown, text = 'OK') { return { ...makeGenerateSuccess(text), output }; @@ -245,7 +273,7 @@ function makeGenerateWithToolCall(toolCallId: string, toolName: string, input: u messages: [ { role: 'assistant', - content: [{ type: 'tool-call', toolCallId, toolName, args: input }], + content: [{ type: 'tool-call', toolCallId, toolName, args: input, input }], }, ], }, @@ -253,6 +281,20 @@ function makeGenerateWithToolCall(toolCallId: string, toolName: string, input: u }; } +function getFirstReplayedToolCallInput(callIndex: number) { + const callArgs = generateText.mock.calls[callIndex][0] as { + messages: Array<{ role: string; content: unknown }>; + }; + const assistantMessage = callArgs.messages.find((message) => message.role === 'assistant'); + if (!assistantMessage || !Array.isArray(assistantMessage.content)) return undefined; + + const toolCall = assistantMessage.content.find( + (part): part is { type: 'tool-call'; input?: unknown } => + typeof part === 'object' && part !== null && Reflect.get(part, 'type') === 'tool-call', + ); + return toolCall?.input; +} + /** Build an interruptible tool that suspends on first call and returns on resume. */ function makeInterruptibleTool(): BuiltTool { return { @@ -306,6 +348,29 @@ describe('AgentRuntime — execution counters', () => { expect(counter.incrementTokenCount).toHaveBeenCalledWith(15); }); + it('forwards onStepStart and onStepFinish to generateText and streamText', async () => { + generateText.mockResolvedValue(makeGenerateSuccess()); + streamText.mockReturnValue(makeStreamSuccess()); + const onStepStart = vi.fn(); + const onStepFinish = vi.fn(); + + const { runtime } = createRuntime(); + await runtime.generate('hi', { onStepStart, onStepFinish }); + const streamResult = await runtime.stream('hi', { onStepStart, onStepFinish }); + await collectChunks(streamResult.stream); + + for (const call of generateText.mock.calls) { + const args = call[0] as Record<string, unknown>; + expect(args.experimental_onStepStart).toBe(onStepStart); + expect(args.onStepFinish).toBe(onStepFinish); + } + for (const call of streamText.mock.calls) { + const args = call[0] as Record<string, unknown>; + expect(args.experimental_onStepStart).toBe(onStepStart); + expect(args.onStepFinish).toBe(onStepFinish); + } + }); + it('counts provider-executed tool calls when surfaced by the model', async () => { generateText .mockResolvedValueOnce({ @@ -353,6 +418,145 @@ describe('AgentRuntime — execution counters', () => { expect(counter.incrementToolCallCount).toHaveBeenCalledTimes(1); expect(counter.incrementTokenCount).toHaveBeenCalledTimes(2); }); + + it('keeps delegate_subagent output usage per tool call without adding it to generate result usage', async () => { + const delegateTool: BuiltTool = { + name: DELEGATE_SUB_AGENT_TOOL_NAME, + description: 'Delegate work', + inputSchema: z.object({ value: z.string().optional() }), + handler: async () => + await Promise.resolve({ + status: 'completed', + answer: 'child answer', + usage: { promptTokens: 3, completionTokens: 4, totalTokens: 7, cost: 0.01 }, + }), + }; + const counter = makeExecutionCounter(); + const { runtime } = createRuntimeWithTools([delegateTool], 1); + + generateText + .mockResolvedValueOnce( + makeGenerateWithToolCalls([ + { + toolCallId: 'tc-delegate', + toolName: DELEGATE_SUB_AGENT_TOOL_NAME, + args: { value: 'research' }, + }, + ]), + ) + .mockResolvedValueOnce(makeGenerateSuccess('done')); + + const result = await runtime.generate('delegate', { executionCounter: counter }); + + expect(result.usage).toMatchObject({ + promptTokens: 20, + completionTokens: 10, + totalTokens: 30, + }); + expect(result.toolCalls?.[0]?.output).toEqual( + expect.objectContaining({ + usage: { promptTokens: 3, completionTokens: 4, totalTokens: 7, cost: 0.01 }, + }), + ); + expect(counter.incrementTokenCount).toHaveBeenCalledTimes(2); + expect(counter.incrementTokenCount).toHaveBeenNthCalledWith(1, 15); + expect(counter.incrementTokenCount).toHaveBeenNthCalledWith(2, 15); + }); + + it('does not roll normal tool output usage-like fields into generate result usage', async () => { + const normalTool: BuiltTool = { + name: 'normal_tool', + description: 'Normal tool', + inputSchema: z.object({ value: z.string().optional() }), + handler: async () => + await Promise.resolve({ + usage: { promptTokens: 3, completionTokens: 4, totalTokens: 7 }, + }), + }; + const { runtime } = createRuntimeWithTools([normalTool], 1); + + generateText + .mockResolvedValueOnce( + makeGenerateWithToolCalls([ + { toolCallId: 'tc-normal', toolName: 'normal_tool', args: { value: 'run' } }, + ]), + ) + .mockResolvedValueOnce(makeGenerateSuccess('done')); + + const result = await runtime.generate('use normal tool'); + + expect(result.usage).toMatchObject({ + promptTokens: 20, + completionTokens: 10, + totalTokens: 30, + }); + }); + + it('keeps delegate_subagent output usage per stream tool result without adding it to finish usage', async () => { + const delegateTool: BuiltTool = { + name: DELEGATE_SUB_AGENT_TOOL_NAME, + description: 'Delegate work', + inputSchema: z.object({ value: z.string().optional() }), + handler: async () => + await Promise.resolve({ + status: 'completed', + answer: 'child answer', + usage: { promptTokens: 3, completionTokens: 4, totalTokens: 7, cost: 0.01 }, + }), + }; + const { runtime } = createRuntimeWithTools([delegateTool], 1); + + streamText + .mockReturnValueOnce({ + fullStream: makeChunkStream([{ type: 'text-delta', textDelta: 'thinking...' }]), + finishReason: Promise.resolve('tool-calls'), + usage: Promise.resolve({ inputTokens: 10, outputTokens: 5, totalTokens: 15 }), + response: Promise.resolve({ + messages: [ + { + role: 'assistant', + content: [ + { + type: 'tool-call', + toolCallId: 'tc-delegate', + toolName: DELEGATE_SUB_AGENT_TOOL_NAME, + args: { value: 'research' }, + }, + ], + }, + ], + }), + toolCalls: Promise.resolve([ + { + toolCallId: 'tc-delegate', + toolName: DELEGATE_SUB_AGENT_TOOL_NAME, + input: { value: 'research' }, + }, + ]), + }) + .mockReturnValueOnce(makeStreamSuccess('done')); + + const result = await runtime.stream('delegate'); + const chunks = await collectChunks(result.stream); + const finishChunks = chunks.filter((chunk) => chunk.type === 'finish'); + const finish = finishChunks[finishChunks.length - 1] as + | (StreamChunk & { type: 'finish' }) + | undefined; + const toolResult = chunks.find( + (chunk) => chunk.type === 'tool-result' && chunk.toolName === DELEGATE_SUB_AGENT_TOOL_NAME, + ) as (StreamChunk & { type: 'tool-result' }) | undefined; + + expect(finish?.usage).toMatchObject({ + promptTokens: 20, + completionTokens: 10, + totalTokens: 30, + }); + expect(toolResult?.output).toEqual( + expect.objectContaining({ + usage: { promptTokens: 3, completionTokens: 4, totalTokens: 7, cost: 0.01 }, + }), + ); + }); }); // --------------------------------------------------------------------------- @@ -482,6 +686,43 @@ describe('AgentRuntime.generate() — graceful error contract', () => { }); }); +// --------------------------------------------------------------------------- +// stream() — fallback error observability +// --------------------------------------------------------------------------- + +describe('AgentRuntime.stream() — fallback error observability', () => { + beforeEach(() => { + vi.clearAllMocks(); + }); + + it('emits AgentEvent.Error and sets failed state when post-loop persistence throws', async () => { + const memory = { + getMessages: vi.fn().mockResolvedValue([]), + saveMessages: vi.fn().mockRejectedValue(new Error('memory write failed')), + } as unknown as InMemoryMemory; + const { runtime, bus } = createRuntime(); + const errorEvents: unknown[] = []; + bus.on(AgentEvent.Error, (event) => errorEvents.push(event)); + + (runtime as unknown as { config: { memory: unknown } }).config.memory = memory; + streamText.mockReturnValue(makeStreamSuccess('done')); + + const result = await runtime.stream('hello', { + persistence: { threadId: 'thread-1', resourceId: 'resource-1' }, + }); + const chunks = await collectChunks(result.stream); + + expect(chunks).toContainEqual( + expect.objectContaining({ + type: 'finish', + finishReason: 'error', + }), + ); + expect(errorEvents).toHaveLength(1); + expect(runtime.getState().status).toBe('failed'); + }); +}); + // --------------------------------------------------------------------------- // stream() — graceful error contract // --------------------------------------------------------------------------- @@ -747,6 +988,7 @@ function makeGenerateWithToolCalls( toolCallId: tc.toolCallId, toolName: tc.toolName, args: tc.args, + input: tc.args, })), }, ], @@ -970,6 +1212,59 @@ describe('AgentRuntime — concurrent tool execution', () => { streamText.mockReset(); }); + it('keeps abort signals scoped to overlapping generate runs', async () => { + let firstModelSignal: AbortSignal | undefined; + let secondModelSignal: AbortSignal | undefined; + let firstToolSignal: AbortSignal | undefined; + let resolveFirstModel!: (value: unknown) => void; + const firstModel = new Promise((resolve) => { + resolveFirstModel = resolve; + }); + let firstModelCalled!: () => void; + const waitForFirstModelCall = new Promise<void>((resolve) => { + firstModelCalled = resolve; + }); + + const signalTool: BuiltTool = { + name: 'signal_tool', + description: 'Captures the run signal', + inputSchema: z.object({ value: z.string().optional() }), + handler: async (_input, ctx) => { + firstToolSignal = (ctx as ToolContext).abortSignal; + return await Promise.resolve({ done: true }); + }, + }; + const { runtime } = createRuntimeWithTools([signalTool], 1); + + generateText + .mockImplementationOnce(async (options: { abortSignal?: AbortSignal }) => { + firstModelSignal = options.abortSignal; + firstModelCalled(); + return await firstModel; + }) + .mockImplementationOnce(async (options: { abortSignal?: AbortSignal }) => { + secondModelSignal = options.abortSignal; + return await Promise.resolve(makeGenerateSuccess('second done')); + }) + .mockResolvedValueOnce(makeGenerateSuccess('first done')); + + const firstRun = runtime.generate('first'); + await waitForFirstModelCall; + + const secondRun = runtime.generate('second'); + await secondRun; + + resolveFirstModel( + makeGenerateWithToolCalls([ + { toolCallId: 'tc-1', toolName: 'signal_tool', args: { value: 'first' } }, + ]), + ); + await firstRun; + + expect(firstToolSignal).toBe(firstModelSignal); + expect(firstToolSignal).not.toBe(secondModelSignal); + }); + it('runs tools concurrently when concurrency > 1', async () => { let peakConcurrency = 0; let activeConcurrency = 0; @@ -1343,6 +1638,164 @@ describe('AgentRuntime — concurrent tool execution', () => { expect(Math.max(...batchSizes)).toBeLessThanOrEqual(2); }); + it('runs consecutive delegate_subagent calls in parallel up to maxChildren when toolCallConcurrency is 1', async () => { + let activeDelegations = 0; + let peakDelegations = 0; + + const runSubAgent: DelegateSubAgentRunner = async (request) => { + activeDelegations++; + peakDelegations = Math.max(peakDelegations, activeDelegations); + await new Promise((resolve) => setTimeout(resolve, 30)); + activeDelegations--; + return { + status: 'completed', + taskPath: request.taskPath, + answer: `done:${request.taskName}`, + }; + }; + + const delegateTool = createDelegateSubAgentTool({ + policy: { maxChildren: 5 }, + runSubAgent, + }); + const { runtime } = createRuntimeWithTools([delegateTool], 1); + + generateText + .mockResolvedValueOnce( + makeGenerateWithToolCalls( + Array.from({ length: 5 }, (_, index) => ({ + toolCallId: `tc-${index + 1}`, + toolName: DELEGATE_SUB_AGENT_TOOL_NAME, + args: { + subAgentId: 'inline', + taskName: `ping_${index + 1}`, + goal: 'Reply with ping.', + }, + })), + ), + ) + .mockResolvedValueOnce(makeGenerateSuccess('Done')); + + const result = await runtime.generate('spawn 5 sub agents'); + + expect(result.finishReason).toBe('stop'); + expect(peakDelegations).toBe(5); + }); + + it('batches delegate_subagent parallelism by maxChildren when more calls are issued than the parallel limit', async () => { + let activeDelegations = 0; + let peakDelegations = 0; + + const runSubAgent: DelegateSubAgentRunner = async (request) => { + activeDelegations++; + peakDelegations = Math.max(peakDelegations, activeDelegations); + await new Promise((resolve) => setTimeout(resolve, 30)); + activeDelegations--; + return { + status: 'completed', + taskPath: request.taskPath, + answer: `done:${request.taskName}`, + }; + }; + + const delegateTool = createDelegateSubAgentTool({ + policy: { maxChildren: 2 }, + runSubAgent, + }); + const { runtime } = createRuntimeWithTools([delegateTool], 1); + + generateText + .mockResolvedValueOnce( + makeGenerateWithToolCalls( + Array.from({ length: 4 }, (_, index) => ({ + toolCallId: `tc-${index + 1}`, + toolName: DELEGATE_SUB_AGENT_TOOL_NAME, + args: { + subAgentId: 'inline', + taskName: `ping_${index + 1}`, + goal: 'Reply with ping.', + }, + })), + ), + ) + .mockResolvedValueOnce(makeGenerateSuccess('Done')); + + const result = await runtime.generate('spawn 4 sub agents'); + + expect(result.finishReason).toBe('stop'); + expect(peakDelegations).toBe(2); + expect(result.toolCalls).toHaveLength(4); + for (const entry of result.toolCalls ?? []) { + expect(JSON.stringify(entry.output)).toContain('"status":"completed"'); + } + }); + + it('fails fast when delegate metadata has an invalid maxChildren batch size', async () => { + const malformedDelegateTool: BuiltTool = { + name: DELEGATE_SUB_AGENT_TOOL_NAME, + description: 'Malformed delegate tool', + inputSchema: z.object({}), + handler: async () => await Promise.resolve({ done: true }), + metadata: { + [INLINE_DELEGATE_SUB_AGENT_TOOL_METADATA_KEY]: { + policy: { maxChildren: 0 }, + }, + }, + }; + const { runtime } = createRuntimeWithTools([malformedDelegateTool], 1); + + generateText.mockResolvedValueOnce( + makeGenerateWithToolCalls([ + { + toolCallId: 'tc-1', + toolName: DELEGATE_SUB_AGENT_TOOL_NAME, + args: { + subAgentId: 'inline', + taskName: 'ping', + goal: 'Reply with ping.', + }, + }, + ]), + ); + + const result = await runtime.generate('spawn sub agent'); + + expect(result.finishReason).toBe('error'); + expect(result.error).toBeInstanceOf(Error); + if (result.error instanceof Error) { + expect(result.error.message).toBe('Invalid tool-call batch size for delegate_subagent: 0'); + } + }); + + it('keeps non-delegate tools sequential when toolCallConcurrency is 1', async () => { + let active = 0; + let peak = 0; + + const slowTool = makeMockTool('slow_tool', async () => { + active++; + peak = Math.max(peak, active); + await new Promise((resolve) => setTimeout(resolve, 30)); + active--; + return { done: true }; + }); + + const { runtime } = createRuntimeWithTools([slowTool], 1); + + generateText + .mockResolvedValueOnce( + makeGenerateWithToolCalls([ + { toolCallId: 'tc-1', toolName: 'slow_tool', args: { value: 'a' } }, + { toolCallId: 'tc-2', toolName: 'slow_tool', args: { value: 'b' } }, + ]), + ) + .mockResolvedValueOnce(makeGenerateSuccess('Done')); + + const result = await runtime.generate('run tools'); + + expect(result.finishReason).toBe('stop'); + expect(peak).toBe(1); + }); + it('tool error becomes LLM-visible message — loop continues and slow tool completes', async () => { const completedTools: string[] = []; @@ -1756,6 +2209,73 @@ describe('AgentRuntime.generate() — structured output', () => { expect(callArgs.output).toBeUndefined(); }); + it('returns structuredOutput when a raw JSON Schema is configured', async () => { + const expected = { answer: 'Paris', score: 0.95 }; + generateText.mockResolvedValue(makeGenerateSuccessWithOutput(expected)); + + const { runtime } = createJsonSchemaStructuredRuntime(); + const result = await runtime.generate('What is the capital of France?'); + + expect(result.structuredOutput).toEqual(expected); + expect(result.finishReason).toBe('stop'); + }); + + it('wraps a provider-strict JSON Schema output spec via jsonSchema() before passing to generateText', async () => { + generateText.mockResolvedValue(makeGenerateSuccessWithOutput({ answer: 'x', score: 1 })); + + const { runtime } = createJsonSchemaStructuredRuntime(); + await runtime.generate('hello'); + + // Raw JSON Schema is made provider-strict (additionalProperties: false) and + // wrapped with the AI SDK's jsonSchema() helper, rather than passed through + // directly (which is what Zod schemas do). + const strictTestJsonSchema = { ...testJsonSchema, additionalProperties: false }; + expect(jsonSchema).toHaveBeenCalledWith(strictTestJsonSchema); + + const callArgs = (generateText.mock.calls[0] as [unknown, unknown])[0] as Record< + string, + unknown + >; + expect(callArgs.output).toEqual( + expect.objectContaining({ + _type: 'object', + schema: { _type: 'jsonSchema', schema: strictTestJsonSchema }, + }), + ); + }); + + it('disables strict JSON Schema validation for OpenAI/Groq when a raw JSON Schema is configured', async () => { + generateText.mockResolvedValue(makeGenerateSuccessWithOutput({ answer: 'x', score: 1 })); + + const { runtime } = createJsonSchemaStructuredRuntime(); + await runtime.generate('hello'); + + const callArgs = (generateText.mock.calls[0] as [unknown, unknown])[0] as Record< + string, + unknown + >; + expect(callArgs.providerOptions).toEqual( + expect.objectContaining({ + openai: { strictJsonSchema: false }, + groq: { strictJsonSchema: false }, + }), + ); + }); + + it('keeps strict JSON Schema validation (no relaxation) for a Zod schema', async () => { + generateText.mockResolvedValue(makeGenerateSuccessWithOutput({ answer: 'x', score: 1 })); + + const { runtime } = createStructuredRuntime(); + await runtime.generate('hello'); + + const callArgs = (generateText.mock.calls[0] as [unknown, unknown])[0] as Record< + string, + unknown + >; + // No thinking/provider options configured and Zod output → no strict override. + expect(callArgs.providerOptions).toBeUndefined(); + }); + it('preserves structuredOutput through tool-call iterations', async () => { const tool: BuiltTool = { name: 'add', @@ -2243,6 +2763,109 @@ describe('AgentRuntime — runtime JSON Schema input validation', () => { expect(call.state).toBe('resolved'); }); + it('parses stringified JSON object tool input before validating and replaying', async () => { + const handlerFn = vi.fn().mockResolvedValue({ ok: true }); + const tool: BuiltTool = { + name: 'json_tool', + description: 'json tool', + inputSchema: { + type: 'object', + properties: { id: { type: 'string' } }, + required: ['id'], + }, + handler: handlerFn, + }; + + generateText + .mockResolvedValueOnce(makeGenerateWithToolCall('tc-1', 'json_tool', '{"id":"abc"}')) + .mockResolvedValueOnce(makeGenerateSuccess('done')); + + const runtime = new AgentRuntime({ + name: 'test', + model: 'openai/gpt-4o-mini', + instructions: 'test', + tools: [tool], + }); + + const result = await runtime.generate('go'); + expect(result.finishReason).toBe('stop'); + expect(handlerFn).toHaveBeenCalledWith( + expect.objectContaining({ id: 'abc' }), + expect.anything(), + ); + expect(getFirstReplayedToolCallInput(1)).toEqual({ id: 'abc' }); + }); + + it('surfaces malformed string tool input as a retryable tool error', async () => { + const handlerFn = vi.fn().mockResolvedValue({ ok: true }); + const tool: BuiltTool = { + name: 'json_tool', + description: 'json tool', + handler: handlerFn, + }; + + generateText + .mockResolvedValueOnce(makeGenerateWithToolCall('tc-1', 'json_tool', '{bad json')) + .mockResolvedValueOnce(makeGenerateSuccess('done')); + + const runtime = new AgentRuntime({ + name: 'test', + model: 'openai/gpt-4o-mini', + instructions: 'test', + tools: [tool], + }); + + const result = await runtime.generate('go'); + expect(result.finishReason).toBe('stop'); + expect(handlerFn).not.toHaveBeenCalled(); + expect(getFirstReplayedToolCallInput(1)).toEqual({}); + + const assistantMsg = result.messages.find( + (m) => + isLlmMessage(m) && m.role === 'assistant' && m.content.some((c) => c.type === 'tool-call'), + ) as Message; + const call = assistantMsg.content.find((c) => c.type === 'tool-call') as ContentToolCall; + expect(call.state).toBe('rejected'); + expect(call.state === 'rejected' && call.error).toContain( + 'Tool input must be a valid JSON object string.', + ); + }); + + it('surfaces stringified non-object tool input as a retryable tool error', async () => { + const handlerFn = vi.fn().mockResolvedValue({ ok: true }); + const tool: BuiltTool = { + name: 'json_tool', + description: 'json tool', + handler: handlerFn, + }; + + generateText + .mockResolvedValueOnce(makeGenerateWithToolCall('tc-1', 'json_tool', '["not an object"]')) + .mockResolvedValueOnce(makeGenerateSuccess('done')); + + const runtime = new AgentRuntime({ + name: 'test', + model: 'openai/gpt-4o-mini', + instructions: 'test', + tools: [tool], + }); + + const result = await runtime.generate('go'); + expect(result.finishReason).toBe('stop'); + expect(handlerFn).not.toHaveBeenCalled(); + expect(getFirstReplayedToolCallInput(1)).toEqual({}); + + const assistantMsg = result.messages.find( + (m) => + isLlmMessage(m) && m.role === 'assistant' && m.content.some((c) => c.type === 'tool-call'), + ) as Message; + const call = assistantMsg.content.find((c) => c.type === 'tool-call') as ContentToolCall; + expect(call.state).toBe('rejected'); + expect(call.state === 'rejected' && call.error).toContain( + 'Tool input must be a JSON object, got array.', + ); + }); + it('surfaces a validation error as a tool error outcome when LLM provides the wrong type', async () => { const tool: BuiltTool = { name: 'json_tool', @@ -2533,7 +3156,7 @@ describe('AgentRuntime — tool approval (HITL wrapper)', () => { }); it('suspends when a tool has .requireApproval() set', async () => { - const approvalTool = new ToolBuilder('delete') + const builtApprovalTool = new ToolBuilder('delete') .description('Delete a record') .input(z.object({ id: z.string() })) .requireApproval() @@ -2541,6 +3164,10 @@ describe('AgentRuntime — tool approval (HITL wrapper)', () => { return await Promise.resolve({ deleted: id }); }) .build(); + const approvalTool = { + ...builtApprovalTool, + metadata: { displayName: 'Delete record' }, + }; generateText.mockResolvedValueOnce(makeGenerateWithToolCall('tc-1', 'delete', { id: 'rec-1' })); @@ -2559,6 +3186,7 @@ describe('AgentRuntime — tool approval (HITL wrapper)', () => { expect(result.pendingSuspend![0].suspendPayload).toMatchObject({ type: 'approval', toolName: 'delete', + displayName: 'Delete record', args: { id: 'rec-1' }, }); }); @@ -2634,6 +3262,136 @@ describe('AgentRuntime — tool approval (HITL wrapper)', () => { ); expect(resumeResult.finishReason).toBe('stop'); }); + + it('does not start tool execution before approval is granted', async () => { + const handler = vi.fn(async ({ id }: { id: string }) => { + return await Promise.resolve({ deleted: id }); + }); + const approvalTool = new ToolBuilder('delete') + .description('Delete a record') + .input(z.object({ id: z.string() })) + .requireApproval() + .handler(handler) + .build(); + + streamText.mockReturnValue({ + fullStream: makeChunkStream([{ type: 'text-delta', textDelta: 'checking...' }]), + finishReason: Promise.resolve('tool-calls'), + usage: Promise.resolve({ inputTokens: 10, outputTokens: 5, totalTokens: 15 }), + response: Promise.resolve({ + messages: [ + { + role: 'assistant', + content: [ + { + type: 'tool-call', + toolCallId: 'tc-1', + toolName: 'delete', + args: { id: 'rec-1' }, + }, + ], + }, + ], + }), + toolCalls: Promise.resolve([ + { toolCallId: 'tc-1', toolName: 'delete', input: { id: 'rec-1' } }, + ]), + }); + + const runtime = new AgentRuntime({ + name: 'test', + model: 'openai/gpt-4o-mini', + instructions: 'test', + tools: [approvalTool], + checkpointStorage: 'memory', + }); + + const { stream: readableStream } = await runtime.stream('Delete record rec-1'); + const chunks = await collectChunks(readableStream); + + expect(handler).not.toHaveBeenCalled(); + expect(chunks.map((c) => c.type)).toContain('tool-call-suspended'); + expect(chunks.map((c) => c.type)).not.toContain('tool-execution-start'); + }); + + it('starts tool execution when conditional approval allows the call immediately', async () => { + const handler = vi.fn(async ({ id }: { id: string }) => { + return await Promise.resolve({ found: id }); + }); + const conditionalApprovalTool = new ToolBuilder('lookup') + .description('Look up a record') + .input( + z.object({ + id: z.string(), + password: z.string(), + nested: z.object({ apiKey: z.string() }), + }), + ) + .needsApprovalFn(async ({ id }: { id: string }) => { + return await Promise.resolve(id === 'secret'); + }) + .handler(handler) + .build(); + const startEvents: Array<AgentEventData & { type: AgentEvent.ToolExecutionStart }> = []; + const eventBus = new AgentEventBus(); + eventBus.on(AgentEvent.ToolExecutionStart, (event) => { + startEvents.push(event as AgentEventData & { type: AgentEvent.ToolExecutionStart }); + }); + const toolInput = { + id: 'public', + password: 'plain-secret-password', + nested: { apiKey: 'secret-api-key' }, + }; + + streamText + .mockReturnValueOnce({ + fullStream: makeChunkStream([{ type: 'text-delta', textDelta: 'checking...' }]), + finishReason: Promise.resolve('tool-calls'), + usage: Promise.resolve({ inputTokens: 10, outputTokens: 5, totalTokens: 15 }), + response: Promise.resolve({ + messages: [ + { + role: 'assistant', + content: [ + { + type: 'tool-call', + toolCallId: 'tc-1', + toolName: 'lookup', + args: toolInput, + }, + ], + }, + ], + }), + toolCalls: Promise.resolve([{ toolCallId: 'tc-1', toolName: 'lookup', input: toolInput }]), + }) + .mockReturnValueOnce(makeStreamSuccess('Done')); + + const runtime = new AgentRuntime({ + name: 'test', + model: 'openai/gpt-4o-mini', + instructions: 'test', + tools: [conditionalApprovalTool], + eventBus, + checkpointStorage: 'memory', + }); + + const { stream: readableStream } = await runtime.stream('Look up public'); + const chunks = await collectChunks(readableStream); + + expect(handler).toHaveBeenCalledWith( + toolInput, + expect.objectContaining({ toolCallId: 'tc-1' }), + ); + expect(startEvents[0]?.args).toEqual({ + id: 'public', + password: 'plain-secret-password', + nested: { apiKey: 'secret-api-key' }, + }); + expect(chunks.map((c) => c.type)).toContain('tool-execution-start'); + expect(chunks.map((c) => c.type)).toContain('tool-execution-end'); + expect(chunks.map((c) => c.type)).not.toContain('tool-call-suspended'); + }); }); // --------------------------------------------------------------------------- @@ -2677,6 +3435,379 @@ describe('external abort signal', () => { const result = await resultPromise; expect(result.finishReason).toBe('error'); }); + + it('marks tool ctx abortSignal as aborted when a generate run is aborted', async () => { + const external = new AbortController(); + let toolSignal: AbortSignal | undefined; + let toolStarted!: () => void; + const waitForToolStart = new Promise<void>((resolve) => { + toolStarted = resolve; + }); + let toolObservedAbort!: () => void; + const waitForToolAbort = new Promise<void>((resolve) => { + toolObservedAbort = resolve; + }); + const abortAwareTool: BuiltTool = { + name: 'wait_for_abort', + description: 'Waits until the run aborts', + inputSchema: z.object({}), + handler: async (_input, ctx) => { + toolSignal = (ctx as ToolContext).abortSignal; + toolStarted(); + await new Promise<void>((resolve) => { + toolSignal?.addEventListener( + 'abort', + () => { + toolObservedAbort(); + resolve(); + }, + { once: true }, + ); + }); + return { aborted: toolSignal?.aborted }; + }, + }; + + generateText + .mockResolvedValueOnce( + makeGenerateWithToolCalls([{ toolCallId: 'tc-1', toolName: 'wait_for_abort', args: {} }]), + ) + .mockResolvedValueOnce(makeGenerateSuccess('done')); + + const { runtime } = createRuntimeWithTools([abortAwareTool], 1); + const resultPromise = runtime.generate('start tool', { abortSignal: external.signal }); + + await waitForToolStart; + expect(toolSignal?.aborted).toBe(false); + + external.abort(); + await waitForToolAbort; + expect(toolSignal?.aborted).toBe(true); + + await resultPromise; + }); + + it('marks tool ctx abortSignal as aborted when a stream run is aborted', async () => { + const external = new AbortController(); + let toolSignal: AbortSignal | undefined; + let toolStarted!: () => void; + const waitForToolStart = new Promise<void>((resolve) => { + toolStarted = resolve; + }); + let toolObservedAbort!: () => void; + const waitForToolAbort = new Promise<void>((resolve) => { + toolObservedAbort = resolve; + }); + const abortAwareTool: BuiltTool = { + name: 'wait_for_abort', + description: 'Waits until the run aborts', + inputSchema: z.object({}), + handler: async (_input, ctx) => { + toolSignal = (ctx as ToolContext).abortSignal; + toolStarted(); + await new Promise<void>((resolve) => { + toolSignal?.addEventListener( + 'abort', + () => { + toolObservedAbort(); + resolve(); + }, + { once: true }, + ); + }); + return { aborted: toolSignal?.aborted }; + }, + }; + + streamText + .mockReturnValueOnce({ + fullStream: makeChunkStream([{ type: 'text-delta', textDelta: 'checking...' }]), + finishReason: Promise.resolve('tool-calls'), + usage: Promise.resolve({ inputTokens: 10, outputTokens: 5, totalTokens: 15 }), + response: Promise.resolve({ + messages: [ + { + role: 'assistant', + content: [ + { + type: 'tool-call', + toolCallId: 'tc-1', + toolName: 'wait_for_abort', + args: {}, + }, + ], + }, + ], + }), + toolCalls: Promise.resolve([{ toolCallId: 'tc-1', toolName: 'wait_for_abort', input: {} }]), + }) + .mockReturnValueOnce(makeStreamSuccess('done')); + + const { runtime } = createRuntimeWithTools([abortAwareTool], 1); + const { stream } = await runtime.stream('start tool', { abortSignal: external.signal }); + const collectPromise = collectChunks(stream); + + await waitForToolStart; + expect(toolSignal?.aborted).toBe(false); + + external.abort(); + await waitForToolAbort; + expect(toolSignal?.aborted).toBe(true); + + await collectPromise; + }); + + it('removes external abort listener after a stream completes', async () => { + const external = new AbortController(); + const removeListener = vi.spyOn(external.signal, 'removeEventListener'); + streamText.mockReturnValue(makeStreamSuccess('done')); + + const runtime = new AgentRuntime({ + name: 'test', + model: 'openai/gpt-4o-mini', + instructions: 'You are a test assistant.', + }); + + const result = await runtime.stream('hello', { + persistence: { resourceId: 'user1', threadId: 'thread1' }, + abortSignal: external.signal, + }); + await collectChunks(result.stream); + await new Promise((resolve) => setTimeout(resolve, 0)); + + expect(removeListener).toHaveBeenCalledTimes(1); + external.abort(); + expect(runtime.getState().status).toBe('success'); + }); +}); + +// --------------------------------------------------------------------------- +// Abort during a tool batch (generate/stream parity) +// --------------------------------------------------------------------------- + +describe('AgentRuntime — abort during a tool batch', () => { + beforeEach(() => { + generateText.mockReset(); + streamText.mockReset(); + }); + + // Two sequential (concurrency 1) tool calls where the FIRST aborts the run. + // Batch 0 settles, then the executor hits the abort at the next batch + // boundary and throws. This is the path that used to make the stream report + // `failed` + an Error event; it must now resolve to `cancelled` with no Error + // event — matching how generate has always handled it. + function makeAbortingToolPair(bus: AgentEventBus) { + const secondHandler = vi.fn(async () => { + await Promise.resolve(); + return 'second'; + }); + const tools: BuiltTool[] = [ + { + name: 'abort_now', + description: 'Aborts the run while the batch is executing', + inputSchema: z.object({}), + handler: async () => { + await Promise.resolve(); + bus.abort(); + return 'ok'; + }, + }, + { + name: 'second_tool', + description: 'Should never run once an earlier tool in the batch aborts', + inputSchema: z.object({}), + handler: secondHandler, + }, + ]; + return { tools, secondHandler }; + } + + const TOOL_CALLS = [ + { toolCallId: 'tc-1', toolName: 'abort_now', args: {} }, + { toolCallId: 'tc-2', toolName: 'second_tool', args: {} }, + ]; + + function makeStreamWithToolCalls( + toolCalls: Array<{ toolCallId: string; toolName: string; args: Record<string, unknown> }>, + ) { + return { + fullStream: makeChunkStream([{ type: 'text-delta', textDelta: 'calling tools...' }]), + finishReason: Promise.resolve('tool-calls'), + usage: Promise.resolve({ inputTokens: 10, outputTokens: 5, totalTokens: 15 }), + response: Promise.resolve({ + messages: [ + { + role: 'assistant', + content: toolCalls.map((tc) => ({ + type: 'tool-call', + toolCallId: tc.toolCallId, + toolName: tc.toolName, + args: tc.args, + })), + }, + ], + }), + toolCalls: Promise.resolve( + toolCalls.map((tc) => ({ + toolCallId: tc.toolCallId, + toolName: tc.toolName, + input: tc.args, + })), + ), + }; + } + + it('stream: resolves to "cancelled" (not "failed") and emits no Error event', async () => { + const bus = new AgentEventBus(); + const { tools, secondHandler } = makeAbortingToolPair(bus); + const { runtime } = createRuntimeWithTools(tools, 1, bus); + + streamText.mockReturnValueOnce(makeStreamWithToolCalls(TOOL_CALLS)); + + const errorEvents: AgentEventData[] = []; + bus.on(AgentEvent.Error, (d) => errorEvents.push(d)); + + const { stream } = await runtime.stream('go'); + await collectChunks(stream); + + expect(runtime.getState().status).toBe('cancelled'); + // A user abort is not an error: no AgentEvent.Error must be emitted. + expect(errorEvents).toHaveLength(0); + // Processing stops at the first suspension/abort, so the later tool in the + // batch never executes. + expect(secondHandler).not.toHaveBeenCalled(); + }); + + it('stream: still closes cleanly with an error chunk then a finish chunk', async () => { + const bus = new AgentEventBus(); + const { tools } = makeAbortingToolPair(bus); + const { runtime } = createRuntimeWithTools(tools, 1, bus); + + streamText.mockReturnValueOnce(makeStreamWithToolCalls(TOOL_CALLS)); + + const { stream } = await runtime.stream('go'); + const chunks = await collectChunks(stream); + + expect(chunks.some((c) => c.type === 'error')).toBe(true); + + const finishChunks = chunks.filter((c) => c.type === 'finish'); + expect(finishChunks.length).toBeGreaterThan(0); + const finish = finishChunks[finishChunks.length - 1] as StreamChunk & { + type: 'finish'; + finishReason: string; + }; + expect(finish.finishReason).toBe('error'); + }); + + it('generate: resolves to "cancelled" with no Error event (parity with stream)', async () => { + const bus = new AgentEventBus(); + const { tools, secondHandler } = makeAbortingToolPair(bus); + const { runtime } = createRuntimeWithTools(tools, 1, bus); + + generateText.mockResolvedValueOnce(makeGenerateWithToolCalls(TOOL_CALLS)); + + const errorEvents: AgentEventData[] = []; + bus.on(AgentEvent.Error, (d) => errorEvents.push(d)); + + const result = await runtime.generate('go'); + + expect(result.finishReason).toBe('error'); + expect(runtime.getState().status).toBe('cancelled'); + expect(errorEvents).toHaveLength(0); + expect(secondHandler).not.toHaveBeenCalled(); + }); +}); + +// --------------------------------------------------------------------------- +// Resume checkpoint lifecycle (cleanup owned by the sinks) +// --------------------------------------------------------------------------- + +describe('AgentRuntime.resume() — checkpoint lifecycle', () => { + beforeEach(() => { + generateText.mockReset(); + streamText.mockReset(); + }); + + function makeApprovalTool() { + return makeSuspendingTool('suspend_tool', async (_input, ctx) => { + if (ctx.resumeData) return { approved: true }; + return await ctx.suspend({ reason: 'needs approval' }); + }); + } + + it('deletes the checkpoint after a resumed generate run completes', async () => { + const { runtime } = createRuntimeWithTools([makeApprovalTool()], 1); + + generateText.mockResolvedValueOnce( + makeGenerateWithToolCalls([{ toolCallId: 'tc-1', toolName: 'suspend_tool', args: {} }]), + ); + const first = await runtime.generate('run tool'); + const { runId, toolCallId } = first.pendingSuspend![0]; + + // Resume to completion (no re-suspend) — the sink should tear down the checkpoint. + generateText.mockResolvedValueOnce(makeGenerateSuccess('done')); + const resumed = await runtime.resume('generate', { approved: true }, { runId, toolCallId }); + expect(resumed.pendingSuspend).toBeUndefined(); + expect(resumed.finishReason).toBe('stop'); + + // Checkpoint is gone: resuming the same runId again must fail. + await expect( + runtime.resume('generate', { approved: true }, { runId, toolCallId }), + ).rejects.toThrow(`No suspended run found for runId: ${runId}`); + }); + + it('keeps the checkpoint when a resumed generate run re-suspends', async () => { + const { runtime } = createRuntimeWithTools([makeApprovalTool()], Infinity); + + generateText.mockResolvedValueOnce( + makeGenerateWithToolCalls([ + { toolCallId: 'tc-1', toolName: 'suspend_tool', args: {} }, + { toolCallId: 'tc-2', toolName: 'suspend_tool', args: {} }, + ]), + ); + const first = await runtime.generate('run tools'); + const { runId } = first.pendingSuspend![0]; + + // Resume only tc-1 — tc-2 stays pending, so the run re-suspends and the + // checkpoint must survive (finishSuspended must NOT clean up). + const second = await runtime.resume( + 'generate', + { approved: true }, + { runId, toolCallId: 'tc-1' }, + ); + expect(second.pendingSuspend!.length).toBe(1); + + // Still resumable: tc-2 completes the run without throwing. + generateText.mockResolvedValueOnce(makeGenerateSuccess('done')); + const third = await runtime.resume( + 'generate', + { approved: true }, + { runId, toolCallId: 'tc-2' }, + ); + expect(third.pendingSuspend).toBeUndefined(); + expect(third.finishReason).toBe('stop'); + }); + + it('deletes the checkpoint after a resumed stream run completes', async () => { + const { runtime } = createRuntimeWithTools([makeApprovalTool()], 1); + + // Suspend via a generate run (so we can capture runId synchronously), then + // resume as a stream and drain it. + generateText.mockResolvedValueOnce( + makeGenerateWithToolCalls([{ toolCallId: 'tc-1', toolName: 'suspend_tool', args: {} }]), + ); + const first = await runtime.generate('run tool'); + const { runId, toolCallId } = first.pendingSuspend![0]; + + streamText.mockReturnValueOnce(makeStreamSuccess('done')); + const resumed = await runtime.resume('stream', { approved: true }, { runId, toolCallId }); + await collectChunks(resumed.stream); + + // Checkpoint is gone once the streamed run completed. + await expect( + runtime.resume('stream', { approved: true }, { runId, toolCallId }), + ).rejects.toThrow(`No suspended run found for runId: ${runId}`); + }); }); // --------------------------------------------------------------------------- @@ -2726,8 +3857,7 @@ describe('tool systemInstruction merging', () => { function getSystemMessageText(): string { const callArgs = generateText.mock.calls[0][0] as Record<string, unknown>; - const messages = callArgs.messages as Array<Record<string, unknown>>; - const systemMsg = messages[0]; + const systemMsg = callArgs.system as Record<string, unknown>; expect(systemMsg.role).toBe('system'); return String(systemMsg.content); } @@ -2848,8 +3978,7 @@ describe('instruction providerOptions', () => { }); const callArgs = generateText.mock.calls[0][0] as Record<string, unknown>; - const messages = callArgs.messages as Array<Record<string, unknown>>; - const systemMsg = messages[0]; + const systemMsg = callArgs.system as Record<string, unknown>; expect(systemMsg.role).toBe('system'); expect(systemMsg.providerOptions).toEqual({ anthropic: { cacheControl: { type: 'ephemeral' } }, @@ -3101,10 +4230,10 @@ describe('AgentRuntime — observation log jobs', () => { }); const callArgs = (generateText.mock.calls[0] as [unknown])[0] as { - messages: Array<{ content: string }>; + system: { content: string }; tools: Record<string, unknown>; }; - const systemPrompt = callArgs.messages[0]?.content ?? ''; + const systemPrompt = callArgs.system?.content ?? ''; expect(systemPrompt).not.toContain('<episodic_memory>'); expect(systemPrompt).not.toContain('Postgres'); expect(systemPrompt).not.toContain('SQLite'); @@ -3224,16 +4353,16 @@ describe('AgentRuntime — observation log jobs', () => { const generateTextMock = generateText as MockedFunction< (input: { + system: { content: string }; messages: Array<{ role: string; content: unknown; }>; }) => unknown >; - const [{ messages }] = generateTextMock.mock.calls[0]; - const systemPrompt = messages[0].content; - expect(systemPrompt).toContain('Resource one memory.'); - expect(systemPrompt).toContain('Resource two memory.'); + const [{ system, messages }] = generateTextMock.mock.calls[0]; + expect(system.content).toContain('Resource one memory.'); + expect(system.content).toContain('Resource two memory.'); expect(JSON.stringify(messages)).not.toContain('remember resource-one preference'); await runtime.dispose(); @@ -4109,3 +5238,203 @@ describe('AgentRuntime.resume() with createCancellation() — manual handling (h expect(callCtx.resumeData).toBeUndefined(); }); }); + +// --------------------------------------------------------------------------- +// toModelOutput error resilience — processToolCall must never re-throw +// --------------------------------------------------------------------------- + +describe('AgentRuntime — toModelOutput error resilience', () => { + beforeEach(() => { + vi.clearAllMocks(); + }); + + function makeTransformErrorTool(name = 'transform_tool'): BuiltTool { + return { + name, + description: 'A tool whose toModelOutput always throws', + inputSchema: z.object({ value: z.string().optional() }), + handler: async () => await Promise.resolve({ raw: 'data' }), + toModelOutput: () => { + throw new Error('toModelOutput failed'); + }, + }; + } + + function makeSuspendingTransformErrorTool(name = 'suspend_tool'): BuiltTool { + return { + name, + description: 'A suspending tool whose toModelOutput throws on the resumed call', + inputSchema: z.object({ value: z.string().optional() }), + suspendSchema: z.object({ reason: z.string() }), + resumeSchema: z.object({ approved: z.boolean() }), + handler: async (_input, ctx) => { + const suspendCtx = ctx as InterruptibleToolContext; + if (!suspendCtx.resumeData) { + return await suspendCtx.suspend({ reason: 'needs approval' }); + } + return { done: true }; + }, + toModelOutput: () => { + throw new Error('toModelOutput failed on resume'); + }, + }; + } + + it('generate(): toModelOutput throwing is treated as a tool error — loop continues', async () => { + const tool = makeTransformErrorTool(); + const { runtime } = createRuntimeWithTools([tool], 1); + + generateText + .mockResolvedValueOnce( + makeGenerateWithToolCalls([{ toolCallId: 'tc-1', toolName: 'transform_tool', args: {} }]), + ) + .mockResolvedValueOnce(makeGenerateSuccess('I see the tool errored')); + + const result = await runtime.generate('run the tool'); + + // The agent loop must not crash — it continues and the LLM finishes + expect(result.finishReason).toBe('stop'); + // Two LLM calls: tool-call turn + follow-up after error + expect(generateText).toHaveBeenCalledTimes(2); + }); + + it('stream(): toModelOutput throwing surfaces as isError tool-result — loop continues', async () => { + const tool = makeTransformErrorTool(); + const { runtime } = createRuntimeWithTools([tool], 1); + + streamText + .mockReturnValueOnce({ + fullStream: makeChunkStream([{ type: 'text-delta', textDelta: 'thinking...' }]), + finishReason: Promise.resolve('tool-calls'), + usage: Promise.resolve({ inputTokens: 10, outputTokens: 5, totalTokens: 15 }), + response: Promise.resolve({ + messages: [ + { + role: 'assistant', + content: [ + { + type: 'tool-call', + toolCallId: 'tc-1', + toolName: 'transform_tool', + args: {}, + }, + ], + }, + ], + }), + toolCalls: Promise.resolve([{ toolCallId: 'tc-1', toolName: 'transform_tool', input: {} }]), + }) + .mockReturnValueOnce(makeStreamSuccess('I see the tool errored')); + + const { stream } = await runtime.stream('run the tool'); + const chunks = await collectChunks(stream); + + const finishChunk = chunks.find((c) => c.type === 'finish') as + | (StreamChunk & { type: 'finish' }) + | undefined; + expect(finishChunk?.finishReason).toBe('stop'); + + const toolResultChunk = chunks.find( + (c) => c.type === 'tool-result' && c.toolCallId === 'tc-1', + ) as (StreamChunk & { type: 'tool-result' }) | undefined; + expect(toolResultChunk?.isError).toBe(true); + }); + + it('generate() resume: toModelOutput throwing in resumed tool call is captured — loop continues', async () => { + const tool = makeSuspendingTransformErrorTool(); + const { runtime } = createRuntimeWithTools([tool], 1); + + generateText + .mockResolvedValueOnce( + makeGenerateWithToolCalls([{ toolCallId: 'tc-1', toolName: 'suspend_tool', args: {} }]), + ) + .mockResolvedValueOnce(makeGenerateSuccess('Handled the resume error')); + + // First call: tool suspends + const firstResult = await runtime.generate('run the tool'); + expect(firstResult.finishReason).toBe('tool-calls'); + expect(firstResult.pendingSuspend).toHaveLength(1); + + const { runId, toolCallId } = firstResult.pendingSuspend![0]; + + // Resume: tool returns a result but toModelOutput throws + // Bug: without fix this propagates out of iteratePendingToolCallsConcurrent and + // causes generate() to return with finishReason 'error' instead of 'stop'. + const resumeResult = await runtime.resume( + 'generate', + { approved: true }, + { + runId, + toolCallId, + }, + ); + + expect(resumeResult.finishReason).toBe('stop'); + // Two LLM calls: initial + after resume error + expect(generateText).toHaveBeenCalledTimes(2); + }); + + it('stream() resume: toModelOutput throwing in resumed tool call does not close the stream with error', async () => { + const tool = makeSuspendingTransformErrorTool(); + const { runtime } = createRuntimeWithTools([tool], 1); + + // First stream: agent calls the tool and suspends + streamText.mockReturnValueOnce({ + fullStream: makeChunkStream([{ type: 'text-delta', textDelta: 'thinking...' }]), + finishReason: Promise.resolve('tool-calls'), + usage: Promise.resolve({ inputTokens: 10, outputTokens: 5, totalTokens: 15 }), + response: Promise.resolve({ + messages: [ + { + role: 'assistant', + content: [ + { + type: 'tool-call', + toolCallId: 'tc-1', + toolName: 'suspend_tool', + args: {}, + }, + ], + }, + ], + }), + toolCalls: Promise.resolve([{ toolCallId: 'tc-1', toolName: 'suspend_tool', input: {} }]), + }); + + const firstResult = await runtime.stream('run the tool'); + const firstChunks = await collectChunks(firstResult.stream); + + const suspendChunk = firstChunks.find((c) => c.type === 'tool-call-suspended') as + | (StreamChunk & { type: 'tool-call-suspended' }) + | undefined; + expect(suspendChunk).toBeDefined(); + + // Resume: toModelOutput throws + // Bug: without fix this closes the stream with finishReason 'error' via closeStreamWithError. + streamText.mockReturnValueOnce(makeStreamSuccess('Handled the resume error')); + + const resumed = await runtime.resume( + 'stream', + { approved: true }, + { + runId: suspendChunk!.runId, + toolCallId: suspendChunk!.toolCallId, + }, + ); + const resumedChunks = await collectChunks(resumed.stream); + + const finishChunk = resumedChunks.find((c) => c.type === 'finish') as + | (StreamChunk & { type: 'finish' }) + | undefined; + expect(finishChunk).toBeDefined(); + // Must NOT be 'error' — the tool error should be contained, not kill the stream + expect(finishChunk!.finishReason).not.toBe('error'); + + // The resumed stream should contain a tool-result with isError: true + const toolResultChunk = resumedChunks.find( + (c) => c.type === 'tool-result' && c.toolCallId === 'tc-1', + ) as (StreamChunk & { type: 'tool-result' }) | undefined; + expect(toolResultChunk).toBeDefined(); + expect(toolResultChunk!.isError).toBe(true); + }); +}); diff --git a/packages/@n8n/agents/src/runtime/__tests__/background-task-tracker.test.ts b/packages/@n8n/agents/src/runtime/__tests__/background-task-tracker.test.ts index 93415f4e014..858549c3979 100644 --- a/packages/@n8n/agents/src/runtime/__tests__/background-task-tracker.test.ts +++ b/packages/@n8n/agents/src/runtime/__tests__/background-task-tracker.test.ts @@ -1,4 +1,4 @@ -import { BackgroundTaskTracker } from '../background-task-tracker'; +import { BackgroundTaskTracker } from '../state/background-task-tracker'; describe('BackgroundTaskTracker', () => { it('flushes a single in-flight promise', async () => { 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 13e5e2d35cd..78bbea919cc 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 @@ -1,15 +1,17 @@ -import { vi } from 'vitest'; +import { describe, expect, it, vi } from 'vitest'; import { AgentEvent, type AgentEventData } from '../../types/runtime/event'; import type { GenerateResult } from '../../types/sdk/agent'; +import { isZodSchema } from '../../utils/zod'; import { DELEGATE_SUB_AGENT_TOOL_NAME, INLINE_SUB_AGENT_ID, createDelegateSubAgentTool, generateResultToDelegateSubAgentOutput, + getInlineDelegateSubAgentToolOptions, renderDelegateSubAgentPrompt, type DelegateSubAgentRunner, -} from '../delegate-sub-agent-tool'; +} from '../tools/delegate-sub-agent-tool'; const input = { subAgentId: INLINE_SUB_AGENT_ID, @@ -41,6 +43,68 @@ describe('createDelegateSubAgentTool', () => { expect(tool.outputSchema).toBeDefined(); }); + it('accepts optional difficulty on the delegate input schema', () => { + const tool = createDelegateSubAgentTool({ + runSubAgent: async () => + await Promise.resolve({ + status: 'completed', + taskPath: '/root/research_api_0', + answer: 'done', + }), + }); + + expect(isZodSchema(tool.inputSchema)).toBe(true); + if (!isZodSchema(tool.inputSchema)) return; + + expect( + tool.inputSchema.safeParse({ + ...input, + difficulty: 'medium', + }).success, + ).toBe(true); + expect( + tool.inputSchema.safeParse({ + ...input, + difficulty: 'extreme', + }).success, + ).toBe(false); + }); + + it('preserves inlineSubAgentModelsByDifficulty in delegate tool metadata', () => { + const tool = createDelegateSubAgentTool({ + inlineSubAgentModelsByDifficulty: { + high: 'anthropic/claude-sonnet-4-5', + }, + runSubAgent: async () => + await Promise.resolve({ + status: 'completed', + taskPath: '/root/research_api_0', + answer: 'done', + }), + }); + + expect(getInlineDelegateSubAgentToolOptions(tool)?.inlineSubAgentModelsByDifficulty).toEqual({ + high: 'anthropic/claude-sonnet-4-5', + }); + }); + + it('preserves resolveInlineSubAgentProviderTools in delegate tool metadata', () => { + const resolveInlineSubAgentProviderTools = () => []; + const tool = createDelegateSubAgentTool({ + resolveInlineSubAgentProviderTools, + runSubAgent: async () => + await Promise.resolve({ + status: 'completed', + taskPath: '/root/research_api_0', + answer: 'done', + }), + }); + + expect(getInlineDelegateSubAgentToolOptions(tool)?.resolveInlineSubAgentProviderTools).toBe( + resolveInlineSubAgentProviderTools, + ); + }); + it('can be created without a host runner for SDK inline execution', async () => { const tool = createDelegateSubAgentTool(); @@ -84,6 +148,32 @@ describe('createDelegateSubAgentTool', () => { ); }); + it('forwards difficulty to the runner callback when provided', async () => { + const runSubAgent = vi.fn<DelegateSubAgentRunner>().mockResolvedValue({ + status: 'completed', + taskPath: '/root/research_api_0', + answer: 'done', + }); + const tool = createDelegateSubAgentTool({ runSubAgent }); + + await tool.handler?.( + { ...input, difficulty: 'high' }, + { + runId: 'parent-run-1', + toolCallId: 'tool-call-1', + }, + ); + + expect(runSubAgent).toHaveBeenCalledWith( + expect.objectContaining({ + difficulty: 'high', + }), + expect.objectContaining({ + runInlineSubAgent: expect.any(Function), + }), + ); + }); + it('passes runInlineSubAgent helpers to the host runner callback', async () => { const runSubAgent = vi.fn<DelegateSubAgentRunner>(async (_request, helpers) => { expect(helpers.runInlineSubAgent).toEqual(expect.any(Function)); @@ -101,6 +191,33 @@ describe('createDelegateSubAgentTool', () => { expect(runSubAgent).toHaveBeenCalledOnce(); }); + it('forwards the parent execution counter to the runner callback', async () => { + const runSubAgent = vi + .fn<DelegateSubAgentRunner>() + .mockResolvedValue({ status: 'completed', taskPath: '/root/research_api', answer: 'done' }); + const tool = createDelegateSubAgentTool({ runSubAgent }); + const executionCounter = { + incrementMessageCount: vi.fn(), + incrementToolCallCount: vi.fn(), + incrementTokenCount: vi.fn(), + }; + + await tool.handler?.(input, { + runId: 'parent-run-1', + toolCallId: 'tool-call-1', + executionCounter, + }); + + expect(runSubAgent).toHaveBeenCalledWith( + expect.objectContaining({ + parentExecutionCounter: executionCounter, + }), + expect.objectContaining({ + runInlineSubAgent: expect.any(Function), + }), + ); + }); + it('forwards the parent persistence thread id and resource id', async () => { const runSubAgent = vi .fn<DelegateSubAgentRunner>() @@ -134,6 +251,7 @@ describe('createDelegateSubAgentTool', () => { expect(runSubAgent.mock.calls[0]?.[0]).not.toHaveProperty('parentThreadId'); expect(runSubAgent.mock.calls[0]?.[0]).not.toHaveProperty('parentResourceId'); expect(runSubAgent.mock.calls[0]?.[0]).not.toHaveProperty('parentAbortSignal'); + expect(runSubAgent.mock.calls[0]?.[0]).not.toHaveProperty('parentExecutionCounter'); }); it('forwards the parent run abort signal to the runner callback', async () => { @@ -197,7 +315,73 @@ describe('createDelegateSubAgentTool', () => { }); }); - it('tracks child count per parent run id', async () => { + it('defaults maxChildren to 10 when policy is omitted', () => { + const tool = createDelegateSubAgentTool({ + runSubAgent: async () => + await Promise.resolve({ + status: 'completed', + taskPath: '/root/research_api_0', + answer: 'done', + }), + }); + + expect(tool.systemInstruction).toContain('DELEGATION PARALLELISM'); + expect(tool.systemInstruction).toContain('Up to 10 child sub-agent runs'); + }); + + it.each([0, -1, 1.5, Number.NaN, Number.POSITIVE_INFINITY])( + 'rejects invalid maxChildren policy value %s', + (maxChildren) => { + expect(() => + createDelegateSubAgentTool({ + policy: { maxChildren }, + runSubAgent: async () => + await Promise.resolve({ + status: 'completed', + taskPath: '/root/research_api_0', + answer: 'done', + }), + }), + ).toThrow('delegate_subagent policy.maxChildren'); + }, + ); + + it('describes maxChildren as a parallelism limit in model-facing instructions', () => { + const tool = createDelegateSubAgentTool({ + policy: { maxChildren: 2 }, + runSubAgent: async () => + await Promise.resolve({ + status: 'completed', + taskPath: '/root/research_api_0', + answer: 'done', + }), + }); + + expect(tool.systemInstruction).toContain('DELEGATION PARALLELISM'); + expect(tool.systemInstruction).toContain('Up to 2 child sub-agent runs'); + expect(tool.systemInstruction).toContain('limits parallelism, not the total number'); + }); + + it('does not promise inline provider tools when no resolver is configured', () => { + const tool = createDelegateSubAgentTool(); + + expect(tool.systemInstruction).toContain( + 'Inline children do not inherit provider-defined tools.', + ); + expect(tool.systemInstruction).not.toContain('Provider-defined tools are loaded'); + }); + + it('describes inline provider tools when a resolver is configured', () => { + const tool = createDelegateSubAgentTool({ + resolveInlineSubAgentProviderTools: async () => await Promise.resolve([]), + }); + + expect(tool.systemInstruction).toContain( + "Provider-defined tools are loaded for the inline child's selected model provider.", + ); + }); + + it('assigns distinct task paths for repeated delegations in the same parent run', async () => { const runSubAgent = vi.fn<DelegateSubAgentRunner>().mockResolvedValue({ status: 'completed', taskPath: '/root/research_api', @@ -213,14 +397,16 @@ describe('createDelegateSubAgentTool', () => { status: 'completed', }); await expect(tool.handler?.(input, { runId: 'parent-run-1' })).resolves.toMatchObject({ - status: 'failed', - error: 'Sub-agent child count 2 exceeds maxChildren 1', + status: 'completed', }); await expect(tool.handler?.(input, { runId: 'parent-run-2' })).resolves.toMatchObject({ status: 'completed', }); - expect(runSubAgent).toHaveBeenCalledTimes(2); + expect(runSubAgent).toHaveBeenCalledTimes(3); + expect(runSubAgent.mock.calls[0]?.[0]).toMatchObject({ taskPath: '/root/research_api_0' }); + expect(runSubAgent.mock.calls[1]?.[0]).toMatchObject({ taskPath: '/root/research_api_1' }); + expect(runSubAgent.mock.calls[2]?.[0]).toMatchObject({ taskPath: '/root/research_api_0' }); }); it('returns a failed output when the runner callback throws', async () => { @@ -314,6 +500,7 @@ describe('generateResultToDelegateSubAgentOutput', () => { }, ], finishReason: 'stop', + model: 'anthropic/claude-haiku-4-5', usage: { promptTokens: 3, completionTokens: 2, totalTokens: 5 }, getState: () => ({ status: 'success', @@ -330,6 +517,7 @@ describe('generateResultToDelegateSubAgentOutput', () => { runId: 'child-run-1', threadId: 'child-thread-1', answer: 'preamble\nanswer', + model: 'anthropic/claude-haiku-4-5', usage: { promptTokens: 3, completionTokens: 2, totalTokens: 5 }, finishReason: 'stop', }); @@ -356,7 +544,7 @@ describe('generateResultToDelegateSubAgentOutput', () => { }); it('returns a failed delegate output for delegated child suspension stopgap', async () => { - const { failedDelegatedChildSuspendOutput } = await import('../delegate-sub-agent-tool'); + const { failedDelegatedChildSuspendOutput } = await import('../tools/delegate-sub-agent-tool'); expect(failedDelegatedChildSuspendOutput('/root/x_0')).toEqual({ status: 'failed', @@ -364,6 +552,13 @@ describe('generateResultToDelegateSubAgentOutput', () => { answer: '', error: 'agents.chat.delegate.childSuspendUnsupported', }); + expect(failedDelegatedChildSuspendOutput('/root/x_0', 'anthropic/claude-haiku-4-5')).toEqual({ + status: 'failed', + taskPath: '/root/x_0', + answer: '', + error: 'agents.chat.delegate.childSuspendUnsupported', + model: 'anthropic/claude-haiku-4-5', + }); }); it('maps a suspended child result to suspended with pendingSuspend metadata', () => { diff --git a/packages/@n8n/agents/src/runtime/__tests__/episodic-memory-defaults.test.ts b/packages/@n8n/agents/src/runtime/__tests__/episodic-memory-defaults.test.ts index 08e1275afb7..f9f0dc2fb02 100644 --- a/packages/@n8n/agents/src/runtime/__tests__/episodic-memory-defaults.test.ts +++ b/packages/@n8n/agents/src/runtime/__tests__/episodic-memory-defaults.test.ts @@ -9,7 +9,7 @@ import { buildEpisodicMemoryReflectorPrompt, createEpisodicMemoryExtractFn, createEpisodicMemoryReflectFn, -} from '../episodic-memory-defaults'; +} from '../memory/episodic-memory-defaults'; type GenerateObjectCall = { schema: { diff --git a/packages/@n8n/agents/src/runtime/__tests__/episodic-memory.test.ts b/packages/@n8n/agents/src/runtime/__tests__/episodic-memory.test.ts index 5f8ad3b48bb..cb34256844e 100644 --- a/packages/@n8n/agents/src/runtime/__tests__/episodic-memory.test.ts +++ b/packages/@n8n/agents/src/runtime/__tests__/episodic-memory.test.ts @@ -12,8 +12,8 @@ import { getEpisodicMemoryScope, rankEpisodicMemoryEntries, runEpisodicMemoryIndexer, -} from '../episodic-memory'; -import { InMemoryMemory } from '../memory-store'; +} from '../memory/episodic-memory'; +import { InMemoryMemory } from '../memory/memory-store'; vi.mock('ai', () => ({ embed: vi.fn(), diff --git a/packages/@n8n/agents/src/runtime/__tests__/event-bus.test.ts b/packages/@n8n/agents/src/runtime/__tests__/event-bus.test.ts index 9b18352c633..1ecd2596018 100644 --- a/packages/@n8n/agents/src/runtime/__tests__/event-bus.test.ts +++ b/packages/@n8n/agents/src/runtime/__tests__/event-bus.test.ts @@ -1,4 +1,4 @@ -import { AgentEventBus } from '../event-bus'; +import { AgentEventBus } from '../state/event-bus'; describe('AgentEventBus', () => { describe('resetAbort', () => { @@ -48,4 +48,30 @@ describe('AgentEventBus', () => { expect(bus.isAborted).toBe(false); }); }); + + describe('createAbortScope', () => { + it('should abort active run scopes when the bus aborts', () => { + const bus = new AgentEventBus(); + const first = bus.createAbortScope(); + const second = bus.createAbortScope(); + + bus.abort(); + + expect(first.isAborted).toBe(true); + expect(second.isAborted).toBe(true); + }); + + it('should remove external abort listeners when a scope is disposed', () => { + const bus = new AgentEventBus(); + const external = new AbortController(); + const removeListener = vi.spyOn(external.signal, 'removeEventListener'); + + const scope = bus.createAbortScope(external.signal); + scope.dispose(); + external.abort(); + + expect(removeListener).toHaveBeenCalledTimes(1); + expect(scope.isAborted).toBe(false); + }); + }); }); diff --git a/packages/@n8n/agents/src/runtime/__tests__/fix-tool-call.test.ts b/packages/@n8n/agents/src/runtime/__tests__/fix-tool-call.test.ts index e24063280df..fb1ef950ac6 100644 --- a/packages/@n8n/agents/src/runtime/__tests__/fix-tool-call.test.ts +++ b/packages/@n8n/agents/src/runtime/__tests__/fix-tool-call.test.ts @@ -2,7 +2,7 @@ import type { InvalidToolInputError, NoSuchToolError } from 'ai'; import { z } from 'zod'; import type { BuiltTool } from '../../types'; -import { fixToolCall } from '../fix-tool-call'; +import { fixToolCall } from '../tools/fix-tool-call'; function makeTool(overrides: Partial<BuiltTool> = {}): BuiltTool { return { diff --git a/packages/@n8n/agents/src/runtime/__tests__/inmemory-messages.test.ts b/packages/@n8n/agents/src/runtime/__tests__/inmemory-messages.test.ts index a4d091e3417..d5dd3ae12fc 100644 --- a/packages/@n8n/agents/src/runtime/__tests__/inmemory-messages.test.ts +++ b/packages/@n8n/agents/src/runtime/__tests__/inmemory-messages.test.ts @@ -1,5 +1,5 @@ import type { AgentDbMessage, AgentMessage, Message } from '../../types/sdk/message'; -import { InMemoryMemory } from '../memory-store'; +import { InMemoryMemory } from '../memory/memory-store'; function makeMsg(role: 'user' | 'assistant', text: string, createdAt = new Date()): AgentDbMessage { return { 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 cf1009a860c..5d330a71e60 100644 --- a/packages/@n8n/agents/src/runtime/__tests__/mcp-connection.test.ts +++ b/packages/@n8n/agents/src/runtime/__tests__/mcp-connection.test.ts @@ -1,4 +1,4 @@ -import { McpConnection } from '../mcp-connection'; +import { McpConnection } from '../mcp/mcp-connection'; const sseCtor = vi.fn(); const streamableHttpCtor = vi.fn(); @@ -118,3 +118,84 @@ describe('McpConnection — custom fetch forwarding', () => { expect(options.eventSourceInit).toBeUndefined(); }); }); + +describe('McpConnection — tool filtering', () => { + beforeEach(() => { + clientConnect.mockClear(); + clientListTools.mockClear(); + clientListTools.mockResolvedValue({ + tools: [ + { name: 'echo', description: '', inputSchema: { type: 'object' } }, + { name: 'add', description: '', inputSchema: { type: 'object' } }, + { name: 'subtract', description: '', inputSchema: { type: 'object' } }, + ], + }); + }); + + it('returns all tools when no filter is configured', async () => { + const conn = new McpConnection({ + name: 's1', + url: 'https://example.test/mcp', + transport: 'streamableHttp', + }); + + await conn.connect(); + const tools = await conn.listTools(); + + expect(tools.map((tool) => tool.name)).toEqual(['s1_echo', 's1_add', 's1_subtract']); + }); + + it('keeps only allowed tools when allow filter is configured', async () => { + const conn = new McpConnection({ + name: 's1', + url: 'https://example.test/mcp', + transport: 'streamableHttp', + toolFilter: { mode: 'allow', tools: ['echo', 'subtract'] }, + }); + + await conn.connect(); + const tools = await conn.listTools(); + + expect(tools.map((tool) => tool.name)).toEqual(['s1_echo', 's1_subtract']); + }); + + it('removes excluded tools when exclude filter is configured', async () => { + const conn = new McpConnection({ + name: 's1', + url: 'https://example.test/mcp', + transport: 'streamableHttp', + toolFilter: { mode: 'exclude', tools: ['add'] }, + }); + + await conn.connect(); + const tools = await conn.listTools(); + + expect(tools.map((tool) => tool.name)).toEqual(['s1_echo', 's1_subtract']); + }); + + it('returns no tools for allow mode with an empty list', async () => { + const allowConn = new McpConnection({ + name: 's1', + url: 'https://example.test/mcp', + transport: 'streamableHttp', + toolFilter: { mode: 'allow', tools: [] }, + }); + await allowConn.connect(); + const allowTools = await allowConn.listTools(); + + expect(allowTools).toHaveLength(0); + }); + + it('keeps all tools for exclude mode with an empty list', async () => { + const excludeConn = new McpConnection({ + name: 's2', + url: 'https://example.test/mcp', + transport: 'streamableHttp', + toolFilter: { mode: 'exclude', tools: [] }, + }); + await excludeConn.connect(); + const excludeTools = await excludeConn.listTools(); + + expect(excludeTools.map((tool) => tool.name)).toEqual(['s2_echo', 's2_add', 's2_subtract']); + }); +}); diff --git a/packages/@n8n/agents/src/runtime/__tests__/message-list.test.ts b/packages/@n8n/agents/src/runtime/__tests__/message-list.test.ts index 87415dc77fb..a66a04dca49 100644 --- a/packages/@n8n/agents/src/runtime/__tests__/message-list.test.ts +++ b/packages/@n8n/agents/src/runtime/__tests__/message-list.test.ts @@ -5,7 +5,7 @@ import type { ContentToolCall, Message, } from '../../types/sdk/message'; -import { AgentMessageList } from '../message-list'; +import { AgentMessageList } from '../model/message-list'; function makeUserMsg(text: string): AgentMessage { return { role: 'user', content: [{ type: 'text', text }] }; @@ -115,9 +115,9 @@ describe('AgentMessageList — preserving DB timestamps', () => { // --------------------------------------------------------------------------- function systemContent(list: AgentMessageList): string { - const [system] = list.forLlm('Base instructions'); + const { system } = list.forLlm('Base instructions'); expect(system.role).toBe('system'); - return system.content as string; + return system.content; } describe('AgentMessageList — forLlm observation memory', () => { @@ -125,11 +125,10 @@ describe('AgentMessageList — forLlm observation memory', () => { const list = new AgentMessageList(); list.addInput([makeUserMsg('hello')]); - const messages = list.forLlm('Base instructions'); - const prompt = messages[0].content as string; + const { system, messages } = list.forLlm('Base instructions'); - expect(prompt).toContain('Base instructions'); - expect(prompt).not.toContain('## Memory'); + expect(system.content).toContain('Base instructions'); + expect(system.content).not.toContain('## Memory'); expect(messages).toEqual( expect.arrayContaining([ expect.objectContaining({ @@ -162,7 +161,7 @@ describe('AgentMessageList — forLlm observation memory', () => { list.addHistory([makeDbMsg('recent history', new Date('2024-01-01T00:00:00.000Z'))]); list.addInput([makeUserMsg('new request')]); - const messages = list.forLlm('Base instructions'); + const { messages } = list.forLlm('Base instructions'); expect(messages).toEqual( expect.arrayContaining([ 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 f898dfc6f6f..8e6447f145d 100644 --- a/packages/@n8n/agents/src/runtime/__tests__/model-factory.test.ts +++ b/packages/@n8n/agents/src/runtime/__tests__/model-factory.test.ts @@ -1,6 +1,6 @@ import type { LanguageModel } from 'ai'; -import { createEmbeddingModel, createModel } from '../model-factory'; +import { createEmbeddingModel, createModel } from '../model/model-factory'; type ProviderOpts = { apiKey?: string; diff --git a/packages/@n8n/agents/src/runtime/__tests__/observation-log-observer.test.ts b/packages/@n8n/agents/src/runtime/__tests__/observation-log-observer.test.ts index edf3bf4e5c6..0337c80db16 100644 --- a/packages/@n8n/agents/src/runtime/__tests__/observation-log-observer.test.ts +++ b/packages/@n8n/agents/src/runtime/__tests__/observation-log-observer.test.ts @@ -1,19 +1,19 @@ import type * as AiImport from 'ai'; import type { AgentDbMessage } from '../../types/sdk/message'; -import { InMemoryMemory } from '../memory-store'; +import { InMemoryMemory } from '../memory/memory-store'; import { buildObservationLogObserverPrompt, createObservationLogObserveFn, DEFAULT_OBSERVATION_LOG_OBSERVER_PROMPT, DEFAULT_OBSERVATION_LOG_OBSERVER_THRESHOLD_TOKENS, DEFAULT_OBSERVATION_LOG_TAIL_LIMIT, -} from '../observation-log-defaults'; +} from '../memory/observation-log-defaults'; import { parseObservationLogMarkdown, renderObserverTranscript, runObservationLogObserver, -} from '../observation-log-observer'; +} from '../memory/observation-log-observer'; type GenerateTextCall = Record<string, unknown>; type GenerateTextResult = { text: string; usage?: { totalTokens?: number } }; diff --git a/packages/@n8n/agents/src/runtime/__tests__/observation-log-reflector.test.ts b/packages/@n8n/agents/src/runtime/__tests__/observation-log-reflector.test.ts index 34bd36649d3..223b6283e10 100644 --- a/packages/@n8n/agents/src/runtime/__tests__/observation-log-reflector.test.ts +++ b/packages/@n8n/agents/src/runtime/__tests__/observation-log-reflector.test.ts @@ -1,19 +1,19 @@ import type * as AiImport from 'ai'; import type { ObservationLogEntry } from '../../types/sdk/observation-log'; -import { InMemoryMemory } from '../memory-store'; +import { InMemoryMemory } from '../memory/memory-store'; import { buildObservationLogReflectorPrompt, createObservationLogReflectFn, DEFAULT_OBSERVATION_LOG_REFLECTOR_PROMPT, DEFAULT_OBSERVATION_LOG_REFLECTOR_THRESHOLD_TOKENS, -} from '../observation-log-defaults'; +} from '../memory/observation-log-defaults'; import { normalizeObservationLogReflection, parseObservationLogReflectionJson, renderObservationLogForReflection, runObservationLogReflector, -} from '../observation-log-reflector'; +} from '../memory/observation-log-reflector'; type GenerateTextCall = Record<string, unknown>; type GenerateTextResult = { text: string; usage?: { totalTokens?: number } }; diff --git a/packages/@n8n/agents/src/runtime/__tests__/observation-log-renderer.test.ts b/packages/@n8n/agents/src/runtime/__tests__/observation-log-renderer.test.ts index 6b9fc8f7811..09d4fc38cae 100644 --- a/packages/@n8n/agents/src/runtime/__tests__/observation-log-renderer.test.ts +++ b/packages/@n8n/agents/src/runtime/__tests__/observation-log-renderer.test.ts @@ -1,5 +1,5 @@ import type { ObservationLogEntry, ObservationLogMarker } from '../../types/sdk/observation-log'; -import { renderObservationLog } from '../observation-log-renderer'; +import { renderObservationLog } from '../memory/observation-log-renderer'; function entry(overrides: Partial<ObservationLogEntry> = {}): ObservationLogEntry { const marker: ObservationLogMarker = overrides.marker ?? 'important'; diff --git a/packages/@n8n/agents/src/runtime/__tests__/observation-log-store.test.ts b/packages/@n8n/agents/src/runtime/__tests__/observation-log-store.test.ts index 09b8f54e999..a2108b1f299 100644 --- a/packages/@n8n/agents/src/runtime/__tests__/observation-log-store.test.ts +++ b/packages/@n8n/agents/src/runtime/__tests__/observation-log-store.test.ts @@ -1,5 +1,5 @@ import { estimateObservationTokens } from '../../types/sdk/observation-log'; -import { InMemoryMemory } from '../memory-store'; +import { InMemoryMemory } from '../memory/memory-store'; describe('observation log store', () => { it('persists marker-based active observations with default mechanics', async () => { diff --git a/packages/@n8n/agents/src/runtime/__tests__/scoped-memory-task-runner.test.ts b/packages/@n8n/agents/src/runtime/__tests__/scoped-memory-task-runner.test.ts index 41719c8bc0b..4d47ccb0cb3 100644 --- a/packages/@n8n/agents/src/runtime/__tests__/scoped-memory-task-runner.test.ts +++ b/packages/@n8n/agents/src/runtime/__tests__/scoped-memory-task-runner.test.ts @@ -3,7 +3,7 @@ import type { ObservationLogTaskKind, ObservationLogTaskLockHandle, } from '../../types/sdk/observation-log'; -import { ScopedMemoryTaskRunner } from '../scoped-memory-task-runner'; +import { ScopedMemoryTaskRunner } from '../memory/scoped-memory-task-runner'; function deferred(): { promise: Promise<void>; resolve: () => void } { let resolve!: () => void; diff --git a/packages/@n8n/agents/src/runtime/__tests__/stream.test.ts b/packages/@n8n/agents/src/runtime/__tests__/stream.test.ts index 868d8275bc3..9b1db8cc3d3 100644 --- a/packages/@n8n/agents/src/runtime/__tests__/stream.test.ts +++ b/packages/@n8n/agents/src/runtime/__tests__/stream.test.ts @@ -1,6 +1,6 @@ import type { TextStreamPart, ToolSet } from 'ai'; -import { convertChunk } from '../stream'; +import { convertChunk } from '../streaming/stream'; type ToolCallChunk = Extract<TextStreamPart<ToolSet>, { type: 'tool-call' }>; type ToolErrorChunk = Extract<TextStreamPart<ToolSet>, { type: 'tool-error' }>; diff --git a/packages/@n8n/agents/src/runtime/__tests__/strip-orphaned-tool-messages.test.ts b/packages/@n8n/agents/src/runtime/__tests__/strip-orphaned-tool-messages.test.ts index 3539012f5de..07032d85e03 100644 --- a/packages/@n8n/agents/src/runtime/__tests__/strip-orphaned-tool-messages.test.ts +++ b/packages/@n8n/agents/src/runtime/__tests__/strip-orphaned-tool-messages.test.ts @@ -1,5 +1,5 @@ import type { AgentMessage, Message } from '../../types/sdk/message'; -import { stripOrphanedToolMessages } from '../strip-orphaned-tool-messages'; +import { stripOrphanedToolMessages } from '../memory/strip-orphaned-tool-messages'; describe('stripOrphanedToolMessages', () => { it('returns messages unchanged when all tool-calls are settled', () => { diff --git a/packages/@n8n/agents/src/runtime/__tests__/sub-agent-task-path.test.ts b/packages/@n8n/agents/src/runtime/__tests__/sub-agent-task-path.test.ts index 787f2992552..03c3f833ca0 100644 --- a/packages/@n8n/agents/src/runtime/__tests__/sub-agent-task-path.test.ts +++ b/packages/@n8n/agents/src/runtime/__tests__/sub-agent-task-path.test.ts @@ -1,11 +1,10 @@ import { ROOT_SUB_AGENT_TASK_PATH, - assertSubAgentPolicyAllowsChildCount, assertSubAgentTaskPath, createChildSubAgentTaskPath, isSubAgentTaskPath, sanitizeSubAgentTaskName, -} from '../sub-agent-task-path'; +} from '../tools/sub-agent-task-path'; describe('sub-agent task paths', () => { it('sanitizes display task names into path segments', () => { @@ -54,11 +53,4 @@ describe('sub-agent task paths', () => { expect(second).toBe('/root/research_1'); expect(first).not.toBe(second); }); - - it('enforces max child count policy', () => { - expect(() => assertSubAgentPolicyAllowsChildCount(1, { maxChildren: 2 })).not.toThrow(); - expect(() => assertSubAgentPolicyAllowsChildCount(2, { maxChildren: 2 })).toThrow( - 'exceeds maxChildren', - ); - }); }); diff --git a/packages/@n8n/agents/src/runtime/__tests__/title-generation.test.ts b/packages/@n8n/agents/src/runtime/__tests__/title-generation.test.ts index 8af64eb41f2..db644c93cbc 100644 --- a/packages/@n8n/agents/src/runtime/__tests__/title-generation.test.ts +++ b/packages/@n8n/agents/src/runtime/__tests__/title-generation.test.ts @@ -2,9 +2,13 @@ import type * as AiImport from 'ai'; import type { LanguageModel } from 'ai'; import type { BuiltTelemetry } from '../../types'; -import { generateTitleFromMessage } from '../title-generation'; +import { + generateTitleAndEmojiFromMessage, + generateTitleFromMessage, +} from '../memory/title-generation'; type GenerateTextCall = { + system?: string; messages: Array<{ role: string; content: string }>; experimental_telemetry?: Record<string, unknown>; }; @@ -113,9 +117,8 @@ describe('generateTitleFromMessage', () => { mockGenerateText.mockResolvedValue({ text: 'Berlin rain alert' }); await generateTitleFromMessage(fakeModel, 'Build a daily Berlin rain alert workflow'); const call = mockGenerateText.mock.calls[0][0]; - expect(call.messages[0].role).toBe('system'); - expect(call.messages[0].content).toContain('markdown'); - expect(call.messages[0].content).toContain('sentence case'); + expect(call.system).toContain('markdown'); + expect(call.system).toContain('sentence case'); }); it('accepts custom instructions', async () => { @@ -124,7 +127,7 @@ describe('generateTitleFromMessage', () => { instructions: 'Custom system prompt', }); const call = mockGenerateText.mock.calls[0][0]; - expect(call.messages[0].content).toBe('Custom system prompt'); + expect(call.system).toBe('Custom system prompt'); }); it('passes generic telemetry to the title LLM call', async () => { @@ -176,11 +179,11 @@ describe('generateTitleFromMessage', () => { mockGenerateText.mockResolvedValue({ text: 'Berlin rain alert' }); await generateTitleFromMessage(fakeModel, 'Build a daily Berlin rain alert workflow'); const call = mockGenerateText.mock.calls[0][0]; - expect(call.messages[1].role).toBe('user'); - expect(call.messages[1].content).toContain('Generate a title'); - expect(call.messages[1].content).toContain('<message>'); - expect(call.messages[1].content).toContain('Build a daily Berlin rain alert workflow'); - expect(call.messages[1].content).toContain('</message>'); + expect(call.messages[0].role).toBe('user'); + expect(call.messages[0].content).toContain('Generate a title'); + expect(call.messages[0].content).toContain('<message>'); + expect(call.messages[0].content).toContain('Build a daily Berlin rain alert workflow'); + expect(call.messages[0].content).toContain('</message>'); }); it('drops a streamed code fence and everything after it', async () => { @@ -207,3 +210,24 @@ describe('generateTitleFromMessage', () => { expect(result).toBe('Scryfall random card workflow'); }); }); + +describe('generateTitleAndEmojiFromMessage', () => { + beforeEach(() => { + mockGenerateText.mockReset(); + }); + + it('wraps the user message as conversation context so the model does not answer it', async () => { + mockGenerateText.mockResolvedValue({ text: '{"title":"Berlin rain alert","emoji":"rain"}' }); + await generateTitleAndEmojiFromMessage(fakeModel, 'Build a daily Berlin rain alert workflow'); + + const call = mockGenerateText.mock.calls[0][0]; + expect(call.messages[0]).toEqual({ + role: 'user', + content: ` +Here's the conversation: +<conversation> +Build a daily Berlin rain alert workflow +</conversation>`, + }); + }); +}); diff --git a/packages/@n8n/agents/src/runtime/__tests__/tool-adapter.test.ts b/packages/@n8n/agents/src/runtime/__tests__/tool-adapter.test.ts index 505540dcf6b..cb02863dc47 100644 --- a/packages/@n8n/agents/src/runtime/__tests__/tool-adapter.test.ts +++ b/packages/@n8n/agents/src/runtime/__tests__/tool-adapter.test.ts @@ -2,7 +2,7 @@ import type { JSONSchema7 } from 'json-schema'; import { z } from 'zod'; import type { BuiltTool } from '../../types'; -import { executeTool, toAiSdkTools } from '../tool-adapter'; +import { executeTool, toAiSdkTools } from '../tools/tool-adapter'; // --------------------------------------------------------------------------- // Module mocks @@ -221,4 +221,37 @@ describe('executeTool — context propagation', () => { expect(handler).toHaveBeenCalledWith({}, expect.objectContaining({ abortSignal: signal })); }); + + it('passes the execution counter to the tool handler', async () => { + const handler = vi.fn().mockResolvedValue('ok'); + const tool: BuiltTool = { name: 'counted', description: 'd', handler }; + const executionCounter = { + incrementMessageCount: vi.fn(), + incrementToolCallCount: vi.fn(), + incrementTokenCount: vi.fn(), + }; + + await executeTool({}, tool, undefined, undefined, 'call-1', { executionCounter }); + + expect(handler).toHaveBeenCalledWith({}, expect.objectContaining({ executionCounter })); + }); + + it('passes the execution counter to interruptible tool handlers', async () => { + const handler = vi.fn().mockResolvedValue('ok'); + const tool: BuiltTool = { + name: 'interruptible-counted', + description: 'd', + handler, + suspendSchema: z.object({}), + }; + const executionCounter = { + incrementMessageCount: vi.fn(), + incrementToolCallCount: vi.fn(), + incrementTokenCount: vi.fn(), + }; + + await executeTool({}, tool, undefined, undefined, 'call-1', { executionCounter }); + + expect(handler).toHaveBeenCalledWith({}, expect.objectContaining({ executionCounter })); + }); }); diff --git a/packages/@n8n/agents/src/runtime/__tests__/write-todos-tool.test.ts b/packages/@n8n/agents/src/runtime/__tests__/write-todos-tool.test.ts index 2220e81f331..96fecc3f2d3 100644 --- a/packages/@n8n/agents/src/runtime/__tests__/write-todos-tool.test.ts +++ b/packages/@n8n/agents/src/runtime/__tests__/write-todos-tool.test.ts @@ -1,13 +1,14 @@ import { describe, expect, it } from 'vitest'; import { isZodSchema } from '../../utils/zod'; -import { WRITE_TODOS_TOOL_NAME, createWriteTodosTool } from '../write-todos-tool'; +import { WRITE_TODOS_TOOL_NAME, createWriteTodosTool } from '../tools/write-todos-tool'; const sampleTodos = [ { id: 'research', content: 'Research API authentication options', status: 'in_progress' as const, + difficulty: 'high' as const, delegateHint: { subAgentId: 'inline', expectedOutput: 'Short comparison of auth methods', @@ -17,6 +18,7 @@ const sampleTodos = [ id: 'synthesize', content: 'Synthesize findings into a recommendation', status: 'pending' as const, + difficulty: 'medium' as const, }, ]; @@ -29,6 +31,11 @@ describe('createWriteTodosTool', () => { expect(tool.description).toContain('delegate_subagent'); expect(tool.inputSchema).toBeDefined(); expect(tool.outputSchema).toBeDefined(); + expect(tool.systemInstruction).toContain('low'); + expect(tool.systemInstruction).toContain('medium'); + expect(tool.systemInstruction).toContain('high'); + expect(tool.systemInstruction).toContain('delegate_subagent'); + expect(tool.systemInstruction).toContain('same difficulty'); }); it('returns the provided todo list with a count', async () => { @@ -46,6 +53,34 @@ describe('createWriteTodosTool', () => { }); }); + it('requires difficulty on every todo item', () => { + const tool = createWriteTodosTool(); + expect(isZodSchema(tool.inputSchema)).toBe(true); + if (!isZodSchema(tool.inputSchema)) { + throw new Error('Expected Zod input schema'); + } + + expect( + tool.inputSchema.safeParse({ + todos: [{ id: 'a', content: 'Task', status: 'pending' }], + }).success, + ).toBe(false); + }); + + it('rejects invalid todo difficulty values', () => { + const tool = createWriteTodosTool(); + expect(isZodSchema(tool.inputSchema)).toBe(true); + if (!isZodSchema(tool.inputSchema)) { + throw new Error('Expected Zod input schema'); + } + + expect( + tool.inputSchema.safeParse({ + todos: [{ id: 'a', content: 'Task', status: 'pending', difficulty: 'extreme' }], + }).success, + ).toBe(false); + }); + it('rejects duplicate todo ids in a single update', () => { const tool = createWriteTodosTool(); expect(tool.inputSchema).toBeDefined(); @@ -56,8 +91,8 @@ describe('createWriteTodosTool', () => { const result = tool.inputSchema.safeParse({ todos: [ - { id: 'dup', content: 'First', status: 'pending' }, - { id: 'dup', content: 'Second', status: 'pending' }, + { id: 'dup', content: 'First', status: 'pending', difficulty: 'low' }, + { id: 'dup', content: 'Second', status: 'pending', difficulty: 'medium' }, ], }); diff --git a/packages/@n8n/agents/src/runtime/agent-runtime.ts b/packages/@n8n/agents/src/runtime/agent-runtime.ts deleted file mode 100644 index 2ba8cf72794..00000000000 --- a/packages/@n8n/agents/src/runtime/agent-runtime.ts +++ /dev/null @@ -1,2521 +0,0 @@ -import type { ProviderOptions } from '@ai-sdk/provider-utils'; -import type { StreamTextTransform, TelemetrySettings, ToolCallRepairFunction, ToolSet } from 'ai'; -import type { z } from 'zod'; -import { zodToJsonSchema, type JsonSchema7Type } from 'zod-to-json-schema'; - -import { computeCost, getModelCost, type ModelCost } from '../sdk/catalog'; -import { isLlmMessage } from '../sdk/message'; -import type { - AgentExecutionCounter, - AgentRunState, - AnthropicThinkingConfig, - AttributeValue, - BuiltMemory, - BuiltProviderTool, - BuiltTelemetry, - BuiltTool, - CheckpointStore, - EpisodicMemoryConfig, - EpisodicMemoryTaskLockHandle, - EpisodicMemoryTaskLockMethods, - FinishReason, - GenerateResult, - GoogleThinkingConfig, - ObservationalMemoryConfig, - ObservationLogMemoryConfig, - OpenAIThinkingConfig, - PendingToolCall, - RunOptions, - SerializableAgentState, - StreamChunk, - StreamResult, - ThinkingConfig, - TitleGenerationConfig, - TokenUsage, - XaiThinkingConfig, -} from '../types'; -import { BackgroundTaskTracker } from './background-task-tracker'; -import { DeferredToolManager } from './deferred-tool-manager'; -import { - createRecallMemoryTool, - getEpisodicMemoryScope, - hasEpisodicMemoryStore, - isEpisodicMemoryEnabled, - RECALL_MEMORY_TOOL_NAME, - runEpisodicMemoryIndexer, -} from './episodic-memory'; -import { AgentEventBus } from './event-bus'; -import { incrementTokenCountFromUsage } from './execution-counter'; -import { fixToolCall } from './fix-tool-call'; -import { toJsonValue } from './json-value'; -import { loadAi } from './lazy-ai'; -import { createFilteredLogger } from './logger'; -import { saveMessagesToThread } from './memory-store'; -import { AgentMessageList, type SerializedMessageList } from './message-list'; -import { fromAiFinishReason, fromAiMessages } from './messages'; -import { createModel } from './model-factory'; -import { - runObservationLogObserver, - type ObservationLogObserverMemory, -} from './observation-log-observer'; -import { runObservationLogReflector } from './observation-log-reflector'; -import { renderObservationLog } from './observation-log-renderer'; -import { hasObservationLogStore, hasObservationLogTaskLockStore } from './observation-log-store'; -import { generateRunId, RunStateManager } from './run-state'; -import { - accumulateUsage, - extractSettledToolCalls, - makeErrorStream, - normalizeInput, -} from './runtime-helpers'; -import { ScopedMemoryTaskRunner } from './scoped-memory-task-runner'; -import { convertChunk } from './stream'; -import { stripOrphanedToolMessages } from './strip-orphaned-tool-messages'; -import { generateThreadTitle } from './title-generation'; -import { - buildToolMap, - executeTool, - isSuspendedToolResult, - toAiSdkProviderTools, - toAiSdkTools, -} from './tool-adapter'; -import { isCancellation } from '../sdk/cancellation'; -import { Telemetry } from '../sdk/telemetry'; -import { AgentEvent } from '../types/runtime/event'; -import type { AgentEventData } from '../types/runtime/event'; -import type { - AgentPersistenceOptions, - ExecutionOptions, - ModelConfig, - PersistedExecutionOptions, - ToolResultEntry, -} from '../types/sdk/agent'; -import type { AgentDbMessage, AgentMessage, ContentToolCall, Message } from '../types/sdk/message'; -import type { ObservationLogScope, ObservationLogTaskKind } from '../types/sdk/observation-log'; -import type { JSONObject, JSONValue } from '../types/utils/json'; -import { parseWithSchema } from '../utils/parse'; -import { isZodSchema } from '../utils/zod'; - -interface TelemetrySpan { - end(): void; - recordException?(error: unknown): void; - setAttributes?(attributes: Record<string, AttributeValue>): void; - setStatus?(status: { code: number; message?: string }): void; -} - -interface ActiveSpanTracer { - startActiveSpan<T>( - name: string, - options: { attributes?: Record<string, AttributeValue> }, - fn: (span: TelemetrySpan) => T, - ): T; -} - -function isActiveSpanTracer(value: unknown): value is ActiveSpanTracer { - return ( - value !== null && - typeof value === 'object' && - typeof Reflect.get(value, 'startActiveSpan') === 'function' - ); -} - -function stringifyTelemetryValue(value: unknown): string | undefined { - try { - return JSON.stringify(value); - } catch { - return undefined; - } -} - -function getToolInputSchema(tool: BuiltTool | BuiltProviderTool): unknown { - if (!tool.inputSchema) { - return undefined; - } - - return isZodSchema(tool.inputSchema) ? zodToJsonSchema(tool.inputSchema) : tool.inputSchema; -} - -function summarizeToolForTelemetry(tool: BuiltTool): Record<string, unknown> { - return { - name: tool.name, - description: tool.description, - type: tool.mcpTool ? 'mcp' : 'local', - ...(tool.mcpServerName ? { mcp_server: tool.mcpServerName } : {}), - ...(tool.suspendSchema || tool.resumeSchema || tool.withDefaultApproval - ? { approval: true } - : {}), - ...(tool.inputSchema ? { input_schema: getToolInputSchema(tool) } : {}), - }; -} - -function summarizeProviderToolForTelemetry(tool: BuiltProviderTool): Record<string, unknown> { - const [provider] = tool.name.split('.'); - return { - name: tool.name, - provider, - type: 'provider', - args: tool.args, - ...(tool.inputSchema ? { input_schema: getToolInputSchema(tool) } : {}), - }; -} - -function buildAgentRootInputAttributes(config: AgentRuntimeConfig): Record<string, AttributeValue> { - const localTools = (config.tools ?? []).map(summarizeToolForTelemetry); - const providerTools = (config.providerTools ?? []).map(summarizeProviderToolForTelemetry); - const tools = [...localTools, ...providerTools]; - const toolNames = tools - .map((tool) => (typeof tool.name === 'string' ? tool.name : undefined)) - .filter((name): name is string => name !== undefined); - - const serialized = stringifyTelemetryValue({ - agent: config.name, - tool_count: tools.length, - tools, - }); - - return { - ...(toolNames.length > 0 ? { 'langsmith.metadata.available_tools': toolNames } : {}), - ...(serialized ? { 'gen_ai.prompt': serialized } : {}), - }; -} - -export interface AgentRuntimeConfig { - name: string; - model: ModelConfig; - instructions: string; - instructionProviderOptions?: ProviderOptions; - tools?: BuiltTool[]; - deferredTools?: BuiltTool[]; - toolSearch?: { - topK?: number; - }; - providerTools?: BuiltProviderTool[]; - memory?: BuiltMemory; - observationLog?: ObservationLogMemoryConfig; - observationalMemory?: ObservationalMemoryConfig; - episodicMemory?: EpisodicMemoryConfig; - structuredOutput?: z.ZodType; - checkpointStorage?: 'memory' | CheckpointStore; - thinking?: ThinkingConfig; - eventBus?: AgentEventBus; - /** Number of tool calls to execute concurrently. Default `1` (sequential). */ - toolCallConcurrency?: number; - titleGeneration?: TitleGenerationConfig; - telemetry?: BuiltTelemetry; - /** Existing run id to continue, used when resuming a suspended run. */ - runId?: string; - /** - * Pre-fetched model cost from the catalog. When provided, skips the per-run - * catalog fetch. Set once during Agent.build() and shared across per-run runtimes. - */ - modelCost?: ModelCost; - /** - * Shared RunStateManager for suspend/resume. When provided, per-run runtimes - * use the same store so resume() can find state from a prior run. - */ - runState?: RunStateManager; -} - -const MAX_LOOP_ITERATIONS = 30; -const DEFAULT_MEMORY_TASK_LOCK_TTL_MS = 30_000; -const logger = createFilteredLogger(); - -function getAiSdk(): ReturnType<typeof loadAi> { - return loadAi(); -} - -const EMPTY_MESSAGE_LIST: SerializedMessageList = { - messages: [], - historyIds: [], - inputIds: [], - responseIds: [], -}; - -function hasFunctionProperty<K extends PropertyKey>( - value: object, - property: K, -): value is Record<K, (...args: never[]) => unknown> { - return property in value && typeof Reflect.get(value, property) === 'function'; -} - -function hasObservationLogObserverMemory( - memory: BuiltMemory, -): memory is ObservationLogObserverMemory { - return ( - hasObservationLogStore(memory) && - hasFunctionProperty(memory, 'getMessagesForObservationScope') && - hasFunctionProperty(memory, 'getCursor') && - hasFunctionProperty(memory, 'setCursor') - ); -} - -/** Pending tool calls from a suspended run, passed into the loop to execute before the first LLM call. */ -interface PendingResume { - pendingToolCalls: Record<string, PendingToolCall>; - /** The tool call being resumed with new data. */ - resumeToolCallId: string; - resumeData: unknown; - /** Message history for resolving tool names via findToolName(). */ - messages: AgentDbMessage[]; -} - -type ToolCallOutcome = - | { - outcome: 'success'; - toolEntry: ToolResultEntry; - /** - * Output as the LLM sees it (after `toModelOutput`). Same as - * `toolEntry.output` when no `toModelOutput` transform is configured. - * Surfaced on the `tool-result` wire chunk so consumers see what the - * LLM saw (rather than the larger raw output). - */ - modelOutput: unknown; - customMessage?: AgentMessage; - } - | { - outcome: 'suspended'; - payload: unknown; - resumeSchema: JsonSchema7Type; - } - | { - outcome: 'cancelled'; - toolEntry: ToolResultEntry; - modelOutput: string; - userMessage: string; - canceled: true; - } - | { outcome: 'error'; error: unknown } - | { outcome: 'noop' }; // tool call shouldn't be saved or logged anywhere, usually means that if was executed by AI SDK - -/** A tool call that completed successfully. */ -interface ToolCallSuccess { - toolCallId: string; - toolName: string; - input: JSONValue; - toolEntry: ToolResultEntry; - modelOutput: unknown; - customMessage?: AgentMessage; -} - -/** Info about a tool call that suspended (before persistence — no runId yet). */ -interface ToolCallSuspension { - toolCallId: string; - toolName: string; - input: JSONValue; - payload: unknown; - /** JSON Schema describing the shape of resume data, derived from the tool's resumeSchema. */ - resumeSchema: JsonSchema7Type; -} - -/** Info about a tool call that failed — carries enough data for stream chunks. */ -interface ToolCallError { - toolCallId: string; - toolName: string; - input: JSONValue; - error: unknown; -} - -/** Result of executing a batch of tool calls (before persistence). */ -interface ToolCallBatchResult { - results: ToolCallSuccess[]; - suspensions: ToolCallSuspension[]; - errors: ToolCallError[]; - /** All items to persist: suspended tools (with suspendPayload) + unexecuted tools (without). */ - pending: Record<string, PendingToolCall>; -} - -type RuntimeExecutionOptions = RunOptions & ExecutionOptions & { iterationCount?: number }; - -/** Shared input for the private generate/stream loops. */ -interface LoopContext { - list: AgentMessageList; - options?: RuntimeExecutionOptions; - pendingResume?: PendingResume; -} - -/** Shared input for the tool-call batch iterators. */ -interface ToolBatchContext { - toolMap: Map<string, BuiltTool>; - list: AgentMessageList; - runId: string; - persistence?: AgentPersistenceOptions; - telemetry?: BuiltTelemetry; - executionCounter?: AgentExecutionCounter; -} - -interface RawTokenUsage { - inputTokens?: number | undefined; - outputTokens?: number | undefined; - totalTokens?: number | undefined; -} - -/** - * Core agent execution engine using the Vercel AI SDK directly. - * - * - `generate()` uses `generateText()` — no streaming internally. - * - `stream()` uses `streamText()` — yields chunks in real time. - * - * Memory strategy: - * - `filterLlmMessages` strips custom messages before sending to the LLM. - * - Memory stores ALL AgentMessages (including custom) unchanged. - * - New messages for each turn are tracked via AgentMessageList.turnDelta(), - * which uses Set-based source tracking to identify turn-only messages. - * The list serializes with a historyCount so it can survive process restarts. - */ -export class AgentRuntime { - private config: AgentRuntimeConfig; - - private runState: RunStateManager; - - private eventBus: AgentEventBus; - - private currentState: SerializableAgentState; - - private modelCost: ModelCost | undefined; - - private backgroundTasks = new BackgroundTaskTracker(); - - private memoryTasks: ScopedMemoryTaskRunner | undefined; - - private episodicMemoryTasksByResource = new Map<string, Promise<unknown>>(); - - private deferredToolManager: DeferredToolManager | undefined; - - private runId: string; - - /** Resolved telemetry for the current run (own config or inherited from parent). */ - - constructor(config: AgentRuntimeConfig) { - this.config = config; - this.runId = config.runId ?? generateRunId(); - if (config.deferredTools && config.deferredTools.length > 0) { - this.deferredToolManager = new DeferredToolManager(config.deferredTools, config.toolSearch); - } - this.runState = config.runState ?? new RunStateManager(config.checkpointStorage); - this.eventBus = config.eventBus ?? new AgentEventBus(); - this.modelCost = config.modelCost; - this.currentState = { - persistence: undefined, - status: 'idle', - messageList: EMPTY_MESSAGE_LIST, - pendingToolCalls: {}, - }; - } - - setTelemetry(telemetry: BuiltTelemetry | undefined): void { - this.config.telemetry = telemetry; - } - - /** - * Wait for in-flight background tasks (title generation, future - * observer cycles) to settle. Safe to call multiple times. - */ - async dispose(): Promise<void> { - this.eventBus.dispose(); - await this.backgroundTasks.flush(); - } - - /** Return the latest state snapshot. */ - getState(): SerializableAgentState { - return { ...this.currentState }; - } - - /** Set the abort flag to cancel the currently running agent. */ - abort(): void { - this.eventBus.abort(); - } - - /** Non-streaming: run the full agent loop using generateText and return the final result. */ - async generate( - input: AgentMessage[] | string, - options?: RunOptions & ExecutionOptions, - ): Promise<GenerateResult> { - let list: AgentMessageList | undefined = undefined; - try { - const initializedList = await this.initRun(input, options); - list = initializedList; - const rawResult = await this.withTelemetryRootSpan( - 'generate', - options, - this.runId, - async () => await this.runGenerateLoop({ list: initializedList, options }), - ); - return this.finalizeGenerate(rawResult, list); - } catch (error) { - await this.flushTelemetry(options); - const isAbort = this.eventBus.isAborted; - this.updateState({ status: isAbort ? 'cancelled' : 'failed' }); - if (!isAbort) { - this.eventBus.emit({ type: AgentEvent.Error, message: String(error), error }); - } - return { - runId: this.runId, - messages: list?.responseDelta() ?? [], - finishReason: 'error', - error, - getState: () => this.getState(), - }; - } - } - - /** Streaming: run the agent loop using streamText, yielding chunks in real time. */ - async stream( - input: AgentMessage[] | string, - options?: RunOptions & ExecutionOptions, - ): Promise<StreamResult> { - let list: AgentMessageList; - try { - list = await this.initRun(input, options); - } catch (error) { - const isAbort = this.eventBus.isAborted; - this.updateState({ status: isAbort ? 'cancelled' : 'failed' }); - if (!isAbort) { - this.eventBus.emit({ type: AgentEvent.Error, message: String(error), error }); - } - return { runId: this.runId, stream: makeErrorStream(error), getState: () => this.getState() }; - } - - return { - runId: this.runId, - stream: this.startStreamLoop({ list, options }), - getState: () => this.getState(), - }; - } - - /** - * Resume a suspended tool call with arbitrary data. - * Restores the suspended run state, passes pending tool calls into the loop - * as pending tool calls, and delegates to the same generate/stream loop used for fresh runs. - * - * - `'generate'` — runs the generate loop after tool execution, returns `GenerateResult`. - * - `'stream'` — runs the stream loop after tool execution, returns `StreamResult`. - */ - async resume( - method: 'generate', - data: unknown, - options: { runId: string; toolCallId: string } & ExecutionOptions, - ): Promise<GenerateResult>; - async resume( - method: 'stream', - data: unknown, - options: { runId: string; toolCallId: string } & ExecutionOptions, - ): Promise<StreamResult>; - async resume( - method: 'generate' | 'stream', - data: unknown, - options: { runId: string; toolCallId: string } & ExecutionOptions, - ): Promise<GenerateResult | StreamResult> { - this.runId = options.runId; - const state = await this.runState.resume(this.runId); - if (!state) throw new Error(`No suspended run found for runId: ${this.runId}`); - - const toolCall = state.pendingToolCalls[options.toolCallId]; - if (!toolCall) throw new Error(`No tool call found for toolCallId: ${options.toolCallId}`); - - const list = AgentMessageList.deserialize(state.messageList); - this.hydrateDeferredToolsFromList(list); - - const toolForValidation = this.getCurrentTools(state.persistence).find( - (t) => t.name === toolCall.toolName, - ); - if (!toolForValidation) throw new Error(`Tool ${toolCall.toolName} not found`); - - let resumeData: unknown = data; - - if (!isCancellation(resumeData) && toolForValidation.resumeSchema) { - const parseResult = await parseWithSchema(toolForValidation.resumeSchema, data); - if (!parseResult.success) { - throw new Error(`Invalid resume payload: ${parseResult.error}`); - } - resumeData = parseResult.data as JSONValue; - } - - try { - // Merge persisted execution options with fresh caller options - const { runId: _rid, toolCallId: _tcid, ...callerExecOptions } = options; - const persisted = state.executionOptions ?? {}; - const persistedMaxIterations = persisted.maxIterations; - const callerMaxIterations = callerExecOptions.maxIterations; - if ( - callerMaxIterations !== undefined && - persistedMaxIterations !== undefined && - callerMaxIterations < persistedMaxIterations - ) { - throw new Error( - `Cannot decrease maxIterations when resuming a run. Expected >= ${persistedMaxIterations}, received ${callerMaxIterations}.`, - ); - } - - const mergedMaxIterations = callerMaxIterations ?? persistedMaxIterations; - const mergedExecOptions: ExecutionOptions & { iterationCount?: number } = { - ...callerExecOptions, - ...(mergedMaxIterations !== undefined ? { maxIterations: mergedMaxIterations } : {}), - ...(state.iterationCount !== undefined ? { iterationCount: state.iterationCount } : {}), - }; - - const tool = this.getCurrentTools(state.persistence, mergedExecOptions.executionCounter).find( - (t) => t.name === toolCall.toolName, - ); - if (!tool) throw new Error(`Tool ${toolCall.toolName} not found`); - - const resumeOptions: RuntimeExecutionOptions = { - persistence: state.persistence, - ...mergedExecOptions, - }; - - // Pass abortSignal to event bus - this.eventBus.resetAbort(resumeOptions.abortSignal); - - const pendingResume: PendingResume = { - pendingToolCalls: state.pendingToolCalls, - resumeToolCallId: options.toolCallId, - resumeData, - messages: state.messageList.messages, - }; - - await this.ensureModelCost(); - - await this.setListObservationLogMemory(list, state.persistence); - - if (method === 'generate') { - const rawResult = await this.withTelemetryRootSpan( - 'generate', - resumeOptions, - this.runId, - async () => - await this.runGenerateLoop({ - list, - options: resumeOptions, - pendingResume, - }), - ); - if (!rawResult.pendingSuspend) { - await this.cleanupRun(); - } - return this.finalizeGenerate(rawResult, list); - } - - return { - runId: this.runId, - stream: this.startStreamLoop({ - list, - options: resumeOptions, - pendingResume, - }), - getState: () => this.getState(), - }; - } catch (error) { - const isAbort = this.eventBus.isAborted; - this.updateState({ status: isAbort ? 'cancelled' : 'failed' }); - if (!isAbort) { - this.eventBus.emit({ type: AgentEvent.Error, message: String(error), error }); - } - if (method === 'generate') { - return { - runId: this.runId, - messages: [], - finishReason: 'error' as const, - error, - getState: () => this.getState(), - }; - } - return { runId: this.runId, stream: makeErrorStream(error), getState: () => this.getState() }; - } - } - - // --- Private --- - - /** - * Build an AgentMessageList for the current turn: - * - Loads memory history (if configured) and adds as historySet - * - Adds raw input (custom messages preserved) as inputSet - * - * The system prompt is NOT stored in the list; list.forLlm(instructions) - * prepends it at every LLM call site. - */ - private async buildMessageList( - input: AgentMessage[], - options?: RunOptions & ExecutionOptions, - ): Promise<AgentMessageList> { - const list = new AgentMessageList(); - - if (this.config.memory && options?.persistence?.threadId) { - const memMessages = await this.loadHistoryMessages(options.persistence); - - if (memMessages.length > 0) { - list.addHistory(stripOrphanedToolMessages(memMessages)); - } - } - - await this.setListObservationLogMemory(list, options?.persistence); - - list.addInput(input); - - return list; - } - - private async loadHistoryMessages( - persistence: AgentPersistenceOptions, - ): Promise<AgentDbMessage[]> { - const memory = this.config.memory; - - if (!memory) return []; - - const { threadId, resourceId } = persistence; - - if (this.config.observationalMemory && hasObservationLogObserverMemory(memory)) { - const cursor = await memory.getCursor(threadId); - - if (cursor) { - return await memory.getMessagesForObservationScope(threadId, { - since: { - sinceCreatedAt: cursor.lastObservedAt, - sinceMessageId: cursor.lastObservedMessageId, - }, - }); - } - } - - return await memory.getMessages(threadId, { - resourceId, - }); - } - - /** - * Common setup for generate() and stream(): reset abort state, transition to running, - * emit AgentStart, fetch model cost, normalize input, and build the message list. - * Throws if buildMessageList fails; callers catch and handle the error. - */ - private async initRun( - input: AgentMessage[] | string, - options?: RunOptions & ExecutionOptions, - ): Promise<AgentMessageList> { - this.eventBus.resetAbort(options?.abortSignal); - this.updateState({ - status: 'running', - persistence: options?.persistence, - }); - this.eventBus.emit({ type: AgentEvent.AgentStart }); - await this.ensureModelCost(); - const normalizedInput = normalizeInput(input); - this.incrementMessageCount(options?.executionCounter); - return await this.buildMessageList(normalizedInput, options); - } - - /** - * Post-loop finalization for generate: apply cost, set model id, roll up sub-agent usage, - * transition to success, and emit AgentEnd. Returns the finalized result. - */ - private finalizeGenerate(result: GenerateResult, list: AgentMessageList): GenerateResult { - result.runId = this.runId; - result.usage = this.applyCost(result.usage); - result.model = this.modelIdString; - this.updateState({ status: 'success', messageList: list.serialize() }); - this.eventBus.emit({ type: AgentEvent.AgentEnd, messages: result.messages }); - return { ...result, getState: () => this.getState() }; - } - - /** Resolve telemetry: own config wins, then inherited from options, then nothing. */ - private resolveTelemetry(options?: ExecutionOptions): BuiltTelemetry | undefined { - if (this.config.telemetry) return this.config.telemetry; - const inherited = options?.telemetry; - if (!inherited) return undefined; - return { ...inherited, functionId: this.config.name }; - } - - /** Best-effort flush of telemetry provider. Never throws. */ - private async flushTelemetry(options?: ExecutionOptions): Promise<void> { - await Telemetry.forceFlush(this.resolveTelemetry(options)); - } - - private buildAiSdkOptions( - toolMap: Map<string, BuiltTool>, - options?: ExecutionOptions, - ): { - experimental_telemetry?: TelemetrySettings; - experimental_repairToolCall?: ToolCallRepairFunction<NoInfer<ToolSet>>; - } { - return { - ...this.buildTelemetryOptions(options), - experimental_repairToolCall: async (options) => { - return await fixToolCall( - { - toolCall: options.toolCall, - error: options.error, - }, - toolMap, - ); - }, - }; - } - - private buildSmoothStreamTransformOptions(options?: ExecutionOptions): { - experimental_transform?: StreamTextTransform<ToolSet>; - } { - if (options?.smoothStream === false) return {}; - - const { smoothStream } = loadAi(); - - return { experimental_transform: smoothStream(options?.smoothStream ?? {}) }; - } - - /** Map resolved telemetry to AI SDK's experimental_telemetry shape. */ - private buildTelemetryOptions(options?: ExecutionOptions): { - experimental_telemetry?: TelemetrySettings; - } { - const t = this.resolveTelemetry(options); - if (!t?.enabled) return {}; - - return { - experimental_telemetry: { - isEnabled: true, - functionId: t.functionId ?? this.config.name, - metadata: t.metadata, - recordInputs: t.recordInputs, - recordOutputs: t.recordOutputs, - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-explicit-any - tracer: t.tracer as any, - integrations: t.integrations.length > 0 ? t.integrations : undefined, - }, - }; - } - - private buildTelemetryRootAttributes( - t: BuiltTelemetry, - spanName: string, - runId: string, - ): Record<string, AttributeValue> { - const metadataAttributes = this.buildTelemetryMetadataAttributes(t, 'langsmith.metadata'); - - return { - 'langsmith.traceable': 'true', - 'langsmith.trace.name': spanName, - 'langsmith.span.kind': 'chain', - 'langsmith.metadata.agent_name': this.config.name, - 'langsmith.metadata.agent_run_id': runId, - ...metadataAttributes, - ...buildAgentRootInputAttributes(this.config), - }; - } - - private buildTelemetryMetadataAttributes( - t: BuiltTelemetry, - prefix: string, - ): Record<string, AttributeValue> { - return Object.fromEntries( - Object.entries(t.metadata ?? {}).map(([key, value]) => [`${prefix}.${key}`, value]), - ); - } - - private buildAiSdkOperationAttributes( - operationId: string, - t: BuiltTelemetry, - ): Record<string, AttributeValue> { - const functionId = t.functionId ?? this.config.name; - return { - 'operation.name': `${operationId} ${functionId}`, - 'resource.name': functionId, - 'ai.operationId': operationId, - 'ai.telemetry.functionId': functionId, - ...this.buildTelemetryMetadataAttributes(t, 'ai.telemetry.metadata'), - }; - } - - private recordExecutionCounter(fn: () => void): void { - try { - fn(); - } catch { - // Aggregate counters are best-effort and must never affect agent execution. - } - } - - private incrementMessageCount(counter: AgentExecutionCounter | undefined): void { - if (!counter) return; - this.recordExecutionCounter(() => counter.incrementMessageCount()); - } - - private incrementToolCallCount(counter: AgentExecutionCounter | undefined): void { - if (!counter) return; - this.recordExecutionCounter(() => counter.incrementToolCallCount()); - } - - private incrementTokenCount( - counter: AgentExecutionCounter | undefined, - usage: RawTokenUsage | undefined, - ): void { - incrementTokenCountFromUsage(counter, usage); - } - - private async withTelemetryRootSpan<T>( - operation: 'generate' | 'stream', - options: ExecutionOptions | undefined, - runId: string, - fn: () => Promise<T>, - ): Promise<T> { - const t = this.resolveTelemetry(options); - if (!t?.enabled || t.runtimeRootSpanEnabled === false || !isActiveSpanTracer(t.tracer)) { - return await fn(); - } - - const spanName = `${t.functionId ?? this.config.name}.${operation}`; - return await t.tracer.startActiveSpan( - spanName, - { attributes: this.buildTelemetryRootAttributes(t, spanName, runId) }, - async (span) => { - try { - return await fn(); - } catch (error) { - span.recordException?.(error); - span.setStatus?.({ code: 2, message: String(error) }); - throw error; - } finally { - span.end(); - } - }, - ); - } - - private async withTelemetryToolSpan<T>( - toolCallId: string, - toolName: string, - input: JSONValue, - t: BuiltTelemetry | undefined, - fn: () => Promise<T>, - ): Promise<T> { - if (!t?.enabled || !isActiveSpanTracer(t.tracer)) { - return await fn(); - } - - const shouldRecordInputs = t.recordInputs ?? true; - const inputValue = shouldRecordInputs ? stringifyTelemetryValue(input) : undefined; - - return await t.tracer.startActiveSpan( - 'ai.toolCall', - { - attributes: { - ...this.buildAiSdkOperationAttributes('ai.toolCall', t), - 'ai.toolCall.name': toolName, - 'ai.toolCall.id': toolCallId, - ...(inputValue !== undefined ? { 'ai.toolCall.args': inputValue } : {}), - }, - }, - async (span) => { - try { - const result = await fn(); - const shouldRecordOutputs = t.recordOutputs ?? true; - const outputValue = shouldRecordOutputs ? stringifyTelemetryValue(result) : undefined; - if (outputValue !== undefined) { - span.setAttributes?.({ 'ai.toolCall.result': outputValue }); - } - return result; - } catch (error) { - span.recordException?.(error); - span.setStatus?.({ code: 2, message: String(error) }); - throw error; - } finally { - span.end(); - } - }, - ); - } - - /** Core generate loop using generateText (non-streaming). */ - private async runGenerateLoop(ctx: LoopContext): Promise<GenerateResult> { - const { list, options, pendingResume } = ctx; - this.hydrateDeferredToolsFromList(list); - - let totalUsage: TokenUsage | undefined; - let lastFinishReason: FinishReason = 'stop'; - let structuredOutput: unknown; - const toolCallSummary: ToolResultEntry[] = []; - - // Resolve pending tool calls from a resumed run before the first LLM call. - const runTelemetry = this.resolveTelemetry(options); - const staticLoopContext = this.buildStaticLoopContext({ - ...options, - persistence: options?.persistence, - }); - const pendingLoopContext = this.buildToolLoopContext( - staticLoopContext.aiProviderTools, - options?.persistence, - options?.executionCounter, - ); - const pendingToolCtx: ToolBatchContext = { - toolMap: pendingLoopContext.toolMap, - list, - runId: this.runId, - persistence: options?.persistence, - telemetry: runTelemetry, - executionCounter: options?.executionCounter, - }; - const maxIterations = options?.maxIterations ?? MAX_LOOP_ITERATIONS; - let iterationCount = options?.iterationCount ?? 0; - let reachedStopCondition = false; - - if (pendingResume) { - const batch = await this.iteratePendingToolCallsConcurrent({ - ...pendingToolCtx, - pendingResume, - }); - - for (const r of batch.results) { - toolCallSummary.push(r.toolEntry); - } - - if (Object.keys(batch.pending).length > 0) { - const suspendRunId = await this.persistSuspension( - batch.pending, - options, - list, - totalUsage, - maxIterations, - iterationCount, - ); - return { - runId: suspendRunId, - messages: list.responseDelta(), - finishReason: 'tool-calls', - usage: totalUsage, - pendingSuspend: batch.suspensions.map((s) => ({ - runId: suspendRunId, - toolCallId: s.toolCallId, - toolName: s.toolName, - input: s.input, - suspendPayload: s.payload, - resumeSchema: s.resumeSchema, - })), - getState: () => this.getState(), - }; - } - } - - const { generateText } = loadAi(); - for (; iterationCount < maxIterations; iterationCount++) { - if (this.eventBus.isAborted) { - this.updateState({ status: 'cancelled' }); - throw new Error('Agent run was aborted'); - } - - this.eventBus.emit({ type: AgentEvent.TurnStart }); - - const { toolMap, aiTools, hasTools, effectiveInstructions } = this.buildToolLoopContext( - staticLoopContext.aiProviderTools, - options?.persistence, - options?.executionCounter, - ); - - const result = await generateText({ - model: staticLoopContext.model, - messages: list.forLlm(effectiveInstructions, this.config.instructionProviderOptions), - abortSignal: this.eventBus.signal, - ...(hasTools ? { tools: aiTools } : {}), - ...(staticLoopContext.providerOptions - ? { providerOptions: staticLoopContext.providerOptions as Record<string, JSONObject> } - : {}), - ...(staticLoopContext.outputSpec ? { output: staticLoopContext.outputSpec } : {}), - ...this.buildAiSdkOptions(toolMap, options), - }); - - const aiFinishReason = result.finishReason; - lastFinishReason = fromAiFinishReason(aiFinishReason); - - totalUsage = accumulateUsage(totalUsage, result.usage); - this.incrementTokenCount(options?.executionCounter, result.usage); - - const responseMessages = result.response.messages; - const newMessages = fromAiMessages(responseMessages); - list.addResponse(newMessages); - - if (aiFinishReason !== 'tool-calls') { - if (staticLoopContext.outputSpec) { - structuredOutput = result.output; - } - this.emitTurnEnd(newMessages, extractSettledToolCalls(newMessages)); - reachedStopCondition = true; - break; - } - - const batch = await this.iterateToolCallsConcurrent({ - toolMap, - list, - runId: this.runId, - persistence: options?.persistence, - telemetry: runTelemetry, - executionCounter: options?.executionCounter, - toolCalls: result.toolCalls, - }); - - for (const r of batch.results) { - toolCallSummary.push(r.toolEntry); - } - - if (Object.keys(batch.pending).length > 0) { - const suspendRunId = await this.persistSuspension( - batch.pending, - options, - list, - totalUsage, - maxIterations, - iterationCount + 1, - ); - return { - runId: suspendRunId, - messages: list.responseDelta(), - finishReason: 'tool-calls', - usage: totalUsage, - pendingSuspend: batch.suspensions.map((s) => ({ - runId: suspendRunId, - toolCallId: s.toolCallId, - toolName: s.toolName, - input: s.input, - suspendPayload: s.payload, - resumeSchema: s.resumeSchema, - })), - getState: () => this.getState(), - }; - } - - // Emit TurnEnd after all tool calls in this iteration are processed - this.emitTurnEnd(newMessages, extractSettledToolCalls(list.responseDelta())); - } - - if (!reachedStopCondition && iterationCount >= maxIterations) { - lastFinishReason = 'max-iterations'; - } - - await this.saveToMemory(list, options); - await this.flushTelemetry(options); - - if (this.config.titleGeneration && options?.persistence?.threadId && this.config.memory) { - const titlePromise = generateThreadTitle({ - memory: this.config.memory, - threadId: options.persistence.threadId, - resourceId: options.persistence.resourceId, - titleConfig: this.config.titleGeneration, - agentModel: this.config.model, - turnDelta: list.turnDelta(), - executionCounter: options.executionCounter, - }); - this.backgroundTasks.track(titlePromise); - if (this.config.titleGeneration.sync) { - await titlePromise; - } - } - - return { - runId: this.runId, - messages: list.responseDelta(), - finishReason: lastFinishReason, - usage: totalUsage, - ...(structuredOutput !== undefined && { structuredOutput }), - ...(toolCallSummary.length > 0 && { toolCalls: toolCallSummary }), - getState: () => this.getState(), - }; - } - - /** - * Wire up a ReadableStream and start the stream loop asynchronously. - * Returns the readable side immediately; the loop runs in the background. - */ - private startStreamLoop(ctx: LoopContext): ReadableStream<StreamChunk> { - const { options } = ctx; - const { readable, writable } = new TransformStream<StreamChunk, StreamChunk>(); - const writer = writable.getWriter(); - - // Bridge tool-execution lifecycle events into the stream so consumers - // can show a mid-flight indicator between the LLM's tool-call message - // and the eventual tool-result message. Writer queues writes in order - // so the fire-and-forget is safe. - const writeEventChunk = (chunk: StreamChunk): void => { - // Swallow rejections: if the writer is already closed/errored (e.g. - // an abort raced ahead of the subscription cleanup) there is nothing - // useful to do with the chunk. - writer.write(chunk).catch(() => {}); - }; - const onToolExecutionStart = (data: AgentEventData): void => { - if (data.type !== AgentEvent.ToolExecutionStart) return; - writeEventChunk({ - type: 'tool-execution-start', - toolCallId: data.toolCallId, - toolName: data.toolName, - startTime: Date.now(), - }); - }; - const onToolExecutionEnd = (data: AgentEventData): void => { - if (data.type !== AgentEvent.ToolExecutionEnd) return; - writeEventChunk({ - type: 'tool-execution-end', - toolCallId: data.toolCallId, - toolName: data.toolName, - isError: data.isError, - endTime: Date.now(), - }); - }; - const onSubAgentStarted = (data: AgentEventData): void => { - if (data.type !== AgentEvent.SubAgentStarted) return; - const { type: _type, ...payload } = data; - writeEventChunk({ type: 'subagent-started', ...payload }); - }; - const onSubAgentCompleted = (data: AgentEventData): void => { - if (data.type !== AgentEvent.SubAgentCompleted) return; - const { type: _type, ...payload } = data; - writeEventChunk({ type: 'subagent-completed', ...payload }); - }; - this.eventBus.on(AgentEvent.ToolExecutionStart, onToolExecutionStart); - this.eventBus.on(AgentEvent.ToolExecutionEnd, onToolExecutionEnd); - this.eventBus.on(AgentEvent.SubAgentStarted, onSubAgentStarted); - this.eventBus.on(AgentEvent.SubAgentCompleted, onSubAgentCompleted); - - this.withTelemetryRootSpan( - 'stream', - options, - this.runId, - async () => await this.runStreamLoop({ ...ctx, writer }), - ) - .catch(async (error: unknown) => { - await this.flushTelemetry(options); - await this.cleanupRun(); - try { - await writer.write({ type: 'error', error }); - await writer.write({ type: 'finish', finishReason: 'error' }); - await writer.close(); - } catch { - writer.abort(error).catch(() => {}); - } - }) - .finally(() => { - this.eventBus.off(AgentEvent.ToolExecutionStart, onToolExecutionStart); - this.eventBus.off(AgentEvent.ToolExecutionEnd, onToolExecutionEnd); - this.eventBus.off(AgentEvent.SubAgentStarted, onSubAgentStarted); - this.eventBus.off(AgentEvent.SubAgentCompleted, onSubAgentCompleted); - }); - - return readable; - } - - /** Core stream loop using streamText. */ - private async runStreamLoop( - ctx: LoopContext & { writer: WritableStreamDefaultWriter<StreamChunk> }, - ): Promise<void> { - const { list, options, pendingResume, writer } = ctx; - this.hydrateDeferredToolsFromList(list); - - const writeChunk = async (chunk: StreamChunk): Promise<void> => { - await writer.write(chunk); - }; - - let totalUsage: TokenUsage | undefined; - let lastFinishReason: FinishReason = 'stop'; - let structuredOutput: unknown; - const maxIterations = options?.maxIterations ?? MAX_LOOP_ITERATIONS; - let iterationCount = options?.iterationCount ?? 0; - let reachedStopCondition = false; - const { streamText } = loadAi(); - - const closeStreamWithError = async (error: unknown, status: AgentRunState): Promise<void> => { - await this.cleanupRun(); - this.updateState({ status }); - await writer.write({ type: 'error', error }); - await writer.write({ type: 'finish', finishReason: 'error' }); - await writer.close(); - }; - - const handleAbort = async (): Promise<boolean> => { - if (!this.eventBus.isAborted) return false; - await closeStreamWithError(new Error('Agent run was aborted'), 'cancelled'); - return true; - }; - - // Resolve pending tool calls from a resumed run before the first LLM call. - const runTelemetry = this.resolveTelemetry(options); - const staticLoopContext = this.buildStaticLoopContext({ - ...options, - persistence: options?.persistence, - }); - const pendingLoopContext = this.buildToolLoopContext( - staticLoopContext.aiProviderTools, - options?.persistence, - options?.executionCounter, - ); - const pendingToolCtx: ToolBatchContext = { - toolMap: pendingLoopContext.toolMap, - list, - runId: this.runId, - persistence: options?.persistence, - telemetry: runTelemetry, - executionCounter: options?.executionCounter, - }; - if (pendingResume) { - try { - const batch = await this.iteratePendingToolCallsConcurrent({ - ...pendingToolCtx, - pendingResume, - }); - - for (const r of batch.results) { - await writer.write({ - type: 'tool-result', - toolCallId: r.toolCallId, - toolName: r.toolName, - output: r.modelOutput, - ...(r.toolEntry.canceled ? { canceled: true } : {}), - }); - if (r.customMessage) { - await writer.write({ type: 'message', message: r.customMessage }); - } - } - - for (const e of batch.errors) { - await writer.write({ - type: 'tool-result', - toolCallId: e.toolCallId, - toolName: e.toolName, - output: e.error, - isError: true, - }); - } - - if (Object.keys(batch.pending).length > 0) { - const suspendRunId = await this.persistSuspension( - batch.pending, - options, - list, - totalUsage, - maxIterations, - iterationCount, - ); - for (const s of batch.suspensions) { - await writer.write({ - type: 'tool-call-suspended', - runId: suspendRunId, - toolCallId: s.toolCallId, - toolName: s.toolName, - input: s.input, - suspendPayload: s.payload, - resumeSchema: s.resumeSchema, - }); - } - await writer.write({ type: 'finish', finishReason: 'tool-calls' }); - await writer.close(); - return; - } - } catch (error) { - this.eventBus.emit({ type: AgentEvent.Error, message: String(error), error }); - await closeStreamWithError(error, 'failed'); - return; - } - } - - for (; iterationCount < maxIterations; iterationCount++) { - if (await handleAbort()) return; - - this.eventBus.emit({ type: AgentEvent.TurnStart }); - const { toolMap, aiTools, hasTools, effectiveInstructions } = this.buildToolLoopContext( - staticLoopContext.aiProviderTools, - options?.persistence, - options?.executionCounter, - ); - const messages = list.forLlm(effectiveInstructions, this.config.instructionProviderOptions); - const result = streamText({ - model: staticLoopContext.model, - messages, - abortSignal: this.eventBus.signal, - ...(hasTools ? { tools: aiTools } : {}), - ...(staticLoopContext.providerOptions - ? { providerOptions: staticLoopContext.providerOptions as Record<string, JSONObject> } - : {}), - ...(staticLoopContext.outputSpec ? { output: staticLoopContext.outputSpec } : {}), - ...this.buildAiSdkOptions(toolMap, options), - ...this.buildSmoothStreamTransformOptions(options), - }); - - // Consume the stream. When the AbortSignal fires mid-stream the - // AI SDK cancels the underlying fetch and the async iterator throws. - // We catch that here and close the consumer stream with an error chunk. - try { - for await (const chunk of result.fullStream) { - // Filter only the SDK's terminal `finish` chunk — the runtime - // emits its own consolidated `finish` after the loop completes. - // `start-step` / `finish-step` are passed through so consumers - // can use them as LLM-iteration boundaries. - if (chunk.type === 'finish') continue; - - // Provider-executed tools (e.g. native web search) skip the - // local execution loop that emits tool-execution lifecycle - // events via the event bus. Stamp them here at chunk-arrival - // time so live chat and the persisted timeline both show a - // duration. A failed call arrives as a `tool-error` part - // (never a `tool-result`), so close its timing there too. - if ( - (chunk.type === 'tool-result' || chunk.type === 'tool-error') && - chunk.providerExecuted - ) { - await writeChunk({ - type: 'tool-execution-end', - toolCallId: chunk.toolCallId, - toolName: chunk.toolName ?? '', - isError: chunk.type === 'tool-error', - endTime: Date.now(), - }); - } - - const converted = convertChunk(chunk); - if (converted) await writeChunk(converted); - - if (chunk.type === 'tool-call' && chunk.providerExecuted) { - await writeChunk({ - type: 'tool-execution-start', - toolCallId: chunk.toolCallId, - toolName: chunk.toolName ?? '', - startTime: Date.now(), - }); - } - } - } catch (streamError) { - if (await handleAbort()) return; - this.eventBus.emit({ - type: AgentEvent.Error, - message: String(streamError), - error: streamError, - }); - await closeStreamWithError(streamError, 'failed'); - return; - } - - if (await handleAbort()) return; - - const aiFinishReason = await result.finishReason; - const usage = await result.usage; - const response = await result.response; - - lastFinishReason = fromAiFinishReason(aiFinishReason); - - totalUsage = accumulateUsage(totalUsage, usage); - this.incrementTokenCount(options?.executionCounter, usage); - - const responseMessages = response.messages; - const newMessages = fromAiMessages(responseMessages); - list.addResponse(newMessages); - - if (aiFinishReason !== 'tool-calls') { - if (staticLoopContext.outputSpec) { - structuredOutput = await result.output; - } - this.emitTurnEnd(newMessages, extractSettledToolCalls(newMessages)); - reachedStopCondition = true; - break; - } - - const toolCalls = await result.toolCalls; - - try { - const batch = await this.iterateToolCallsConcurrent({ - toolMap, - list, - runId: this.runId, - persistence: options?.persistence, - telemetry: runTelemetry, - executionCounter: options?.executionCounter, - toolCalls, - }); - - if (await handleAbort()) return; - - for (const r of batch.results) { - await writer.write({ - type: 'tool-result', - toolCallId: r.toolCallId, - toolName: r.toolName, - output: r.modelOutput, - ...(r.toolEntry.canceled ? { canceled: true } : {}), - }); - if (r.customMessage) { - await writer.write({ type: 'message', message: r.customMessage }); - } - } - - for (const e of batch.errors) { - await writer.write({ - type: 'tool-result', - toolCallId: e.toolCallId, - toolName: e.toolName, - output: e.error, - isError: true, - }); - } - - if (Object.keys(batch.pending).length > 0) { - const suspendRunId = await this.persistSuspension( - batch.pending, - options, - list, - totalUsage, - maxIterations, - iterationCount + 1, - ); - for (const s of batch.suspensions) { - await writer.write({ - type: 'tool-call-suspended', - runId: suspendRunId, - toolCallId: s.toolCallId, - toolName: s.toolName, - input: s.input, - suspendPayload: s.payload, - resumeSchema: s.resumeSchema, - }); - } - await writer.write({ type: 'finish', finishReason: 'tool-calls' }); - await writer.close(); - return; - } - } catch (error) { - this.eventBus.emit({ type: AgentEvent.Error, message: String(error), error }); - await closeStreamWithError(error, 'failed'); - return; - } - - // Emit TurnEnd after all tool calls in this iteration are processed - this.emitTurnEnd(newMessages, extractSettledToolCalls(list.responseDelta())); - } - if (!reachedStopCondition && iterationCount >= maxIterations) { - lastFinishReason = 'max-iterations'; - } - - const costUsage = this.applyCost(totalUsage); - await writer.write({ - type: 'finish', - finishReason: lastFinishReason, - ...(costUsage && { usage: costUsage }), - model: this.modelIdString, - ...(structuredOutput !== undefined && { structuredOutput }), - }); - - try { - await this.saveToMemory(list, options); - - if (this.config.titleGeneration && options?.persistence && this.config.memory) { - const titlePromise = generateThreadTitle({ - memory: this.config.memory, - threadId: options.persistence.threadId, - resourceId: options.persistence.resourceId, - titleConfig: this.config.titleGeneration, - agentModel: this.config.model, - turnDelta: list.turnDelta(), - executionCounter: options.executionCounter, - }); - this.backgroundTasks.track(titlePromise); - if (this.config.titleGeneration.sync) { - await titlePromise; - } - } - - await this.cleanupRun(); - await this.flushTelemetry(options); - - this.updateState({ status: 'success', messageList: list.serialize() }); - this.eventBus.emit({ type: AgentEvent.AgentEnd, messages: list.responseDelta() }); - } finally { - await writer.close(); - } - } - - /** Persist the current-turn delta to memory. */ - private async saveToMemory( - list: AgentMessageList, - options: (RunOptions & ExecutionOptions) | undefined, - ): Promise<void> { - if (!this.config.memory || !options?.persistence) return; - const delta = list.turnDelta(); - if (delta.length === 0) return; - await saveMessagesToThread( - this.config.memory, - options.persistence.threadId, - options.persistence.resourceId, - delta, - ); - - // Memory jobs receive the execution counter so their LLM and embedding - // usage contributes to token_count. - - const observationTasks = this.scheduleObservationLogJobs( - options.persistence, - options.executionCounter, - ); - this.scheduleEpisodicMemoryJob(options.persistence, observationTasks, options.executionCounter); - } - - private scheduleObservationLogJobs( - persistence: AgentPersistenceOptions, - executionCounter?: AgentExecutionCounter, - ): Array<Promise<unknown>> { - const { memory, observationalMemory } = this.config; - if (!memory || !observationalMemory || !hasObservationLogStore(memory)) return []; - - const scope = this.getObservationLogScope(persistence); - const runner = this.getMemoryTaskRunner(memory, observationalMemory.lockTtlMs); - const observe = observationalMemory.observe; - const observerThresholdTokens = observationalMemory.observerThresholdTokens; - const tasks: Array<Promise<unknown>> = []; - - if ( - observe && - observerThresholdTokens !== undefined && - hasObservationLogObserverMemory(memory) - ) { - tasks.push( - this.scheduleMemoryTask( - runner, - scope, - 'observer', - async () => - await runObservationLogObserver({ - memory, - ...scope, - observerThresholdTokens, - observationLogTailLimit: observationalMemory.observationLogTailLimit ?? 0, - observe, - executionCounter, - }), - ), - ); - } - - const reflect = observationalMemory.reflect; - const reflectorThresholdTokens = observationalMemory.reflectorThresholdTokens; - if (reflect && reflectorThresholdTokens !== undefined) { - tasks.push( - this.scheduleMemoryTask( - runner, - scope, - 'reflector', - async () => - await runObservationLogReflector({ - memory, - ...scope, - reflectorThresholdTokens, - reflect, - executionCounter, - }), - ), - ); - } - - return tasks; - } - - private scheduleEpisodicMemoryJob( - persistence: AgentPersistenceOptions, - observationTasks: Array<Promise<unknown>>, - executionCounter?: AgentExecutionCounter, - ): void { - const { memory, episodicMemory } = this.config; - if ( - !memory || - !episodicMemory || - !isEpisodicMemoryEnabled(episodicMemory) || - !hasEpisodicMemoryStore(memory) || - !hasObservationLogStore(memory) || - !episodicMemory.extract - ) { - return; - } - const scope = getEpisodicMemoryScope(persistence); - if (!scope) return; - - const observationScope = this.getObservationLogScope(persistence); - this.scheduleEpisodicMemoryTask(memory, scope.resourceId, async () => { - await Promise.allSettled(observationTasks); - await runEpisodicMemoryIndexer({ - memory, - config: episodicMemory, - scope, - observationScope, - threadId: persistence.threadId, - executionCounter, - }); - }); - } - - private scheduleEpisodicMemoryTask( - memory: BuiltMemory, - resourceId: string, - task: () => Promise<void>, - ): void { - const id = crypto.randomUUID(); - const previous = this.episodicMemoryTasksByResource.get(resourceId) ?? Promise.resolve(); - const done = previous - .catch(() => undefined) - .then(async () => await this.runEpisodicMemoryTask(memory, resourceId, id, task)); - const queued = done.finally(() => { - if (this.episodicMemoryTasksByResource.get(resourceId) === queued) { - this.episodicMemoryTasksByResource.delete(resourceId); - } - }); - this.episodicMemoryTasksByResource.set(resourceId, queued); - this.backgroundTasks.track(queued); - } - - private async runEpisodicMemoryTask( - memory: BuiltMemory, - resourceId: string, - holderId: string, - task: () => Promise<void>, - ): Promise<void> { - const taskLock = memory.episodic?.taskLock; - let lock: EpisodicMemoryTaskLockHandle | null = null; - try { - if (taskLock) { - lock = await taskLock.acquire(resourceId, { - holderId, - ttlMs: this.config.observationalMemory?.lockTtlMs ?? DEFAULT_MEMORY_TASK_LOCK_TTL_MS, - }); - if (!lock) return; - } - await task(); - } catch (error) { - const message = 'Episodic memory indexing task failed'; - logger.warn(message, { error, resourceId }); - this.eventBus.emit({ type: AgentEvent.Error, message, error, source: 'episodic-memory' }); - } finally { - if (lock) { - await this.releaseEpisodicMemoryTaskLock(taskLock, lock, resourceId); - } - } - } - - private async releaseEpisodicMemoryTaskLock( - taskLock: EpisodicMemoryTaskLockMethods | undefined, - lock: EpisodicMemoryTaskLockHandle, - resourceId: string, - ): Promise<void> { - try { - await taskLock?.release(lock); - } catch (error) { - logger.warn('Episodic memory indexing lock release failed', { error, resourceId }); - } - } - - private async scheduleMemoryTask<T>( - runner: ScopedMemoryTaskRunner, - scope: ObservationLogScope, - taskKind: ObservationLogTaskKind, - task: () => Promise<T>, - ): Promise<unknown> { - return await runner.schedule({ ...scope, taskKind }, task).done; - } - - private getMemoryTaskRunner(memory: BuiltMemory, lockTtlMs?: number): ScopedMemoryTaskRunner { - this.memoryTasks ??= new ScopedMemoryTaskRunner({ - tracker: this.backgroundTasks, - lockStore: hasObservationLogTaskLockStore(memory) ? memory : undefined, - lockTtlMs, - onEvent: (event) => { - if (event.type !== 'failed') return; - const source = event.task.taskKind; - const message = `Observation log ${source} task failed`; - logger.warn(message, { - error: event.error, - observationScopeId: event.task.observationScopeId, - }); - this.eventBus.emit({ type: AgentEvent.Error, message, error: event.error, source }); - }, - }); - return this.memoryTasks; - } - - private getObservationLogScope(persistence: AgentPersistenceOptions): ObservationLogScope { - return { - observationScopeId: persistence.threadId, - }; - } - - /** Build the providerOptions object for thinking/reasoning config. */ - private buildThinkingProviderOptions(): Record<string, Record<string, unknown>> | undefined { - if (!this.config.thinking) return undefined; - - const provider = this.modelIdString.split('/')[0]; - const thinking = this.config.thinking; - - switch (provider) { - case 'anthropic': { - const cfg = thinking as AnthropicThinkingConfig; - if (cfg.mode === 'adaptive') { - return { anthropic: { thinking: { type: 'adaptive' } } }; - } - return { - anthropic: { - thinking: { type: 'enabled', budgetTokens: cfg.budgetTokens ?? 10000 }, - }, - }; - } - case 'openai': { - const cfg = thinking as OpenAIThinkingConfig; - return { openai: { reasoningEffort: cfg.reasoningEffort ?? 'medium' } }; - } - case 'google': { - const cfg = thinking as GoogleThinkingConfig; - return { - google: { - thinkingConfig: { - ...(cfg.thinkingBudget !== undefined && { thinkingBudget: cfg.thinkingBudget }), - ...(cfg.thinkingLevel !== undefined && { thinkingLevel: cfg.thinkingLevel }), - }, - }, - }; - } - case 'xai': { - const cfg = thinking as XaiThinkingConfig; - return { xai: { reasoningEffort: cfg.reasoningEffort ?? 'high' } }; - } - default: - return undefined; - } - } - - /** - * Deep-merge thinking providerOptions with caller-supplied providerOptions. - * Per-provider keys are merged shallowly so `.thinking()` + cache control coexist. - */ - private buildCallProviderOptions( - runProviderOptions?: ProviderOptions, - ): Record<string, Record<string, unknown>> | undefined { - const thinkingOpts = this.buildThinkingProviderOptions(); - if (!thinkingOpts && !runProviderOptions) return undefined; - if (!thinkingOpts) return runProviderOptions as Record<string, Record<string, unknown>>; - if (!runProviderOptions) return thinkingOpts; - - const merged: Record<string, Record<string, unknown>> = { ...thinkingOpts }; - for (const [provider, opts] of Object.entries(runProviderOptions)) { - if (provider in merged) { - merged[provider] = { ...merged[provider], ...(opts as Record<string, unknown>) }; - } else { - merged[provider] = opts as Record<string, unknown>; - } - } - return merged; - } - - /** - * Execute tool calls concurrently in batches of `this.concurrency`. - * Provider-executed calls are skipped. - * - * Returns successes, suspension info, and a pending map (for persistence). - * The caller is responsible for persisting the pending map if non-empty. - * - * When any tool in a batch suspends, processing stops — unexecuted tools - * from later batches are added to the pending map without a `suspendPayload`. - * A Set of IDs tracks which tools have not yet been executed. - * - * Error handling: Promise.allSettled waits for all in-flight tools to finish - * even if one throws, then re-throws the first error. - */ - private async iterateToolCallsConcurrent( - ctx: ToolBatchContext & { - toolCalls: Array<{ - toolCallId: string; - toolName: string; - input: unknown; - providerExecuted?: boolean; - }>; - }, - ): Promise<ToolCallBatchResult> { - const { toolCalls, toolMap, list, runId, telemetry: resolvedTelemetry, executionCounter } = ctx; - const executableCalls = toolCalls.filter((tc) => !tc.providerExecuted); - const providerExecutedCount = toolCalls.length - executableCalls.length; - for (let i = 0; i < providerExecutedCount; i++) { - this.incrementToolCallCount(executionCounter); - } - const executableCallsById = new Map(executableCalls.map((tc) => [tc.toolCallId, tc])); - const unexecutedIds = new Set(executableCalls.map((tc) => tc.toolCallId)); - const batchSize = this.concurrency; - const results: ToolCallSuccess[] = []; - const suspensions: ToolCallSuspension[] = []; - const errors: ToolCallError[] = []; - const pending: Record<string, PendingToolCall> = {}; - - for (let batchStart = 0; batchStart < executableCalls.length; batchStart += batchSize) { - if (this.eventBus.isAborted) { - this.updateState({ status: 'cancelled' }); - throw new Error('Agent run was aborted'); - } - - const batch = executableCalls.slice(batchStart, batchStart + batchSize); - - const settledResults = await Promise.allSettled( - batch.map( - async (tc) => - await this.processToolCall( - tc.toolCallId, - tc.toolName, - tc.input as JSONValue, - toolMap, - list, - runId, - ctx.persistence, - undefined, - resolvedTelemetry, - executionCounter, - true, - ), - ), - ); - - for (const tc of batch) { - unexecutedIds.delete(tc.toolCallId); - } - - let hasSuspension = false; - - for (let i = 0; i < settledResults.length; i++) { - const result = settledResults[i]; - const tc = batch[i]; - const toolInput = tc.input as JSONValue; - - if (result.status === 'rejected') { - list.setToolCallError(tc.toolCallId, result.reason); - errors.push({ - toolCallId: tc.toolCallId, - toolName: tc.toolName, - input: toolInput, - error: result.reason, - }); - } else if (result.value.outcome === 'suspended') { - hasSuspension = true; - suspensions.push({ - toolCallId: tc.toolCallId, - toolName: tc.toolName, - input: toolInput, - payload: result.value.payload, - resumeSchema: result.value.resumeSchema, - }); - pending[tc.toolCallId] = { - suspended: true, - toolCallId: tc.toolCallId, - toolName: tc.toolName, - input: toolInput, - suspendPayload: result.value.payload, - resumeSchema: result.value.resumeSchema, - runId, - }; - } else if (result.value.outcome === 'success') { - results.push({ - toolCallId: tc.toolCallId, - toolName: tc.toolName, - input: toolInput, - toolEntry: result.value.toolEntry, - modelOutput: result.value.modelOutput, - customMessage: result.value.customMessage, - }); - } else if (result.value.outcome === 'error') { - errors.push({ - toolCallId: tc.toolCallId, - toolName: tc.toolName, - input: toolInput, - error: result.value.error, - }); - } else if (result.value.outcome === 'noop') { - // noop - } - } - - if (hasSuspension) { - for (const id of unexecutedIds) { - const tc = executableCallsById.get(id)!; - pending[tc.toolCallId] = { - suspended: false, - toolCallId: tc.toolCallId, - toolName: tc.toolName, - input: tc.input as JSONValue, - }; - } - break; - } - } - - return { results, suspensions, errors, pending }; - } - - /** - * Resume flow: re-execute the targeted tool call, then process remaining items. - * - * 1. Execute the resumed tool (with `resumeData`). If it re-suspends, add to pending. - * 2. For remaining items: - * - Already suspended (has `suspendPayload`) → carry forward into pending. - * - Unexecuted (no `suspendPayload`) → execute via `iterateToolCallsConcurrent`. - * - * Returns a `ToolCallBatchResult` — the caller handles persistence. - */ - private async iteratePendingToolCallsConcurrent( - ctx: ToolBatchContext & { pendingResume: PendingResume }, - ): Promise<ToolCallBatchResult> { - const { - pendingResume, - toolMap, - list, - runId, - persistence, - telemetry: resolvedTelemetry, - executionCounter, - } = ctx; - const resumedId = pendingResume.resumeToolCallId; - const resumedEntry = pendingResume.pendingToolCalls[resumedId]; - if (!resumedEntry) { - throw new Error(`No pending tool call found for toolCallId: ${resumedId}`); - } - - const resumedToolName = resumedEntry.toolName; - const results: ToolCallSuccess[] = []; - const suspensions: ToolCallSuspension[] = []; - const errors: ToolCallError[] = []; - const pending: Record<string, PendingToolCall> = {}; - - // 1. Execute the resumed tool - const processResult = await this.processToolCall( - resumedEntry.toolCallId, - resumedToolName, - resumedEntry.input, - toolMap, - list, - runId, - persistence, - pendingResume.resumeData, - resolvedTelemetry, - executionCounter, - false, - ); - - if (processResult.outcome === 'suspended') { - pending[resumedId] = { - ...resumedEntry, - suspended: true, - suspendPayload: processResult.payload, - resumeSchema: processResult.resumeSchema, - runId, - }; - suspensions.push({ - toolCallId: resumedId, - toolName: resumedToolName, - input: resumedEntry.input, - payload: processResult.payload, - resumeSchema: processResult.resumeSchema, - }); - } else if (processResult.outcome === 'success') { - results.push({ - toolCallId: resumedEntry.toolCallId, - toolName: resumedToolName, - input: resumedEntry.input, - toolEntry: processResult.toolEntry, - modelOutput: processResult.modelOutput, - customMessage: processResult.customMessage, - }); - } else if (processResult.outcome === 'cancelled') { - results.push({ - toolCallId: resumedEntry.toolCallId, - toolName: resumedToolName, - input: resumedEntry.input, - toolEntry: processResult.toolEntry, - modelOutput: processResult.modelOutput, - }); - list.addInput([ - { role: 'user', content: [{ type: 'text', text: processResult.userMessage }] }, - ]); - - for (const id of Object.keys(pendingResume.pendingToolCalls)) { - if (id !== resumedId) { - const siblingEntry = pendingResume.pendingToolCalls[id]; - const modelOutput = '[Skipped: a sibling tool call was cancelled]'; - list.setToolCallResult(id, modelOutput, { - canceled: true, - }); - results.push({ - toolCallId: siblingEntry.toolCallId, - toolName: siblingEntry.toolName, - input: siblingEntry.input, - toolEntry: { - tool: siblingEntry.toolName, - input: siblingEntry.input, - output: modelOutput, - transformed: false, - canceled: true, - }, - modelOutput, - }); - } - } - - return { results, suspensions, errors, pending }; - } else if (processResult.outcome === 'error') { - errors.push({ - toolCallId: resumedEntry.toolCallId, - toolName: resumedToolName, - input: resumedEntry.input, - error: processResult.error, - }); - } else if (processResult.outcome === 'noop') { - // noop - } - - // 2. Process remaining items - const unexecuted: Array<{ toolCallId: string; toolName: string; input: unknown }> = []; - - for (const [id, entry] of Object.entries(pendingResume.pendingToolCalls)) { - if (id === resumedId) continue; - - const entryToolName = entry.toolName; - - if (entry.suspended) { - // Already suspended — carry forward - pending[id] = entry; - suspensions.push({ - toolCallId: id, - toolName: entryToolName, - input: entry.input, - payload: entry.suspendPayload, - resumeSchema: entry.resumeSchema, - }); - } else { - // Unexecuted — collect for batch execution - unexecuted.push({ - toolCallId: id, - toolName: entryToolName, - input: entry.input, - }); - } - } - - // Execute unexecuted tools via iterateToolCallsConcurrent - if (unexecuted.length > 0) { - const batch = await this.iterateToolCallsConcurrent({ - toolCalls: unexecuted, - toolMap, - list, - runId, - persistence, - telemetry: resolvedTelemetry, - executionCounter, - }); - results.push(...batch.results); - suspensions.push(...batch.suspensions); - errors.push(...batch.errors); - Object.assign(pending, batch.pending); - } - - return { results, suspensions, errors, pending }; - } - - /** - * Execute a single tool call, emit lifecycle events, record the result in the - * message list, and return the outcome. The caller is responsible for writing - * any stream chunks and for handling suspension (building pendingToolCalls and - * persisting state). - * - * On tool execution errors, emits ToolExecutionEnd with isError=true, adds an - * error tool-result message to the list so the LLM can self-correct, and returns - * `{ outcome: 'error' }` — never re-throws. - */ - private async processToolCall( - toolCallId: string, - toolName: string, - toolInput: JSONValue, - toolMap: Map<string, BuiltTool>, - list: AgentMessageList, - runId: string, - persistence?: AgentPersistenceOptions, - resumeData?: unknown, - resolvedTelemetry?: BuiltTelemetry, - executionCounter?: AgentExecutionCounter, - countToolCall = true, - ): Promise<ToolCallOutcome> { - const builtTool = toolMap.get(toolName); - - this.eventBus.emit({ - type: AgentEvent.ToolExecutionStart, - toolCallId, - toolName, - args: toolInput, - }); - - const makeToolError = (error: unknown): ToolCallOutcome => { - this.eventBus.emit({ - type: AgentEvent.ToolExecutionEnd, - toolCallId, - toolName, - result: error, - isError: true, - }); - list.setToolCallError(toolCallId, error); - return { outcome: 'error', error }; - }; - - if (!builtTool) { - return makeToolError(new Error(`Tool ${toolName} not found`)); - } - - // Check if this tool-call block was already settled (e.g. by provider-executed tools). - // If so, emit ToolExecutionEnd and skip re-execution. - type SettledToolCall = ContentToolCall & { state: 'resolved' | 'rejected' }; - const settledBlock = list - .responseDelta() - .flatMap((m) => (isLlmMessage(m) && 'content' in m ? (m as Message).content : [])) - .find( - (c): c is SettledToolCall => - c.type === 'tool-call' && c.toolCallId === toolCallId && c.state !== 'pending', - ); - - if (settledBlock) { - let settledResult: unknown; - if (settledBlock.state === 'resolved') { - settledResult = settledBlock.output; - } else { - settledResult = settledBlock.error; - } - this.eventBus.emit({ - type: AgentEvent.ToolExecutionEnd, - toolCallId, - toolName, - result: settledResult, - isError: settledBlock.state === 'rejected', - }); - // the error is written to message list earlier, when processing stream output - return { outcome: 'noop' }; - } - - if (isCancellation(resumeData) && !builtTool.handleCancellation) { - const modelOutput = `[Tool call cancelled. User said: "${resumeData.message}"]`; - this.eventBus.emit({ - type: AgentEvent.ToolExecutionEnd, - toolCallId, - toolName, - result: modelOutput, - isError: false, - }); - list.setToolCallResult(toolCallId, modelOutput, { canceled: true }); - return { - outcome: 'cancelled', - toolEntry: { - tool: toolName, - input: toolInput, - output: modelOutput, - transformed: false, - canceled: true, - }, - modelOutput, - userMessage: resumeData.message, - canceled: true, - }; - } - - if (countToolCall) { - this.incrementToolCallCount(executionCounter); - } - - if (builtTool.inputSchema) { - const result = await parseWithSchema(builtTool.inputSchema, toolInput); - if (!result.success) { - return makeToolError(new Error(`Invalid tool input: ${result.error}`)); - } - toolInput = result.data as JSONValue; - } - - let toolResult: unknown; - try { - toolResult = await this.withTelemetryToolSpan( - toolCallId, - toolName, - toolInput, - resolvedTelemetry, - async () => - await executeTool(toolInput, builtTool, resumeData, resolvedTelemetry, toolCallId, { - runId, - persistence, - emitEvent: (event) => this.eventBus.emit(event), - abortSignal: this.eventBus.signal, - }), - ); - } catch (error) { - return makeToolError(error as Error); - } - - if (isSuspendedToolResult(toolResult)) { - if (builtTool?.suspendSchema) { - const parseResult = await parseWithSchema(builtTool.suspendSchema, toolResult.payload); - if (!parseResult.success) { - return makeToolError(new Error(`Invalid suspend payload: ${parseResult.error}`)); - } - toolResult.payload = parseResult.data as JSONValue; - } - if (!builtTool?.resumeSchema) { - const error = new Error(`Tool ${toolName} has no resume schema`); - return makeToolError(error); - } - const resumeSchema = isZodSchema(builtTool.resumeSchema) - ? zodToJsonSchema(builtTool.resumeSchema) - : builtTool.resumeSchema; - if (!resumeSchema) { - return makeToolError(new Error('Invalid resume schema')); - } - return { - outcome: 'suspended', - payload: toolResult.payload, - resumeSchema, - }; - } - - this.eventBus.emit({ - type: AgentEvent.ToolExecutionEnd, - toolCallId, - toolName, - result: toolResult, - isError: false, - }); - - // Apply toModelOutput transform: the raw result goes to history/events, - // but the transformed version is what the LLM sees as the tool result. - const modelResult = builtTool.toModelOutput ? builtTool.toModelOutput(toolResult) : toolResult; - - list.setToolCallResult(toolCallId, toJsonValue(modelResult)); - - const customMessage = builtTool?.toMessage?.(toolResult); - if (customMessage) { - list.addResponse([customMessage]); - } - - return { - outcome: 'success', - toolEntry: { - tool: toolName, - input: toolInput, - output: toolResult, - transformed: !!builtTool.toModelOutput, - }, - modelOutput: modelResult, - customMessage, - }; - } - - /** Build run-stable LLM call dependencies shared by all iterations. */ - private buildStaticLoopContext( - execOptions?: ExecutionOptions & { persistence?: AgentPersistenceOptions }, - ) { - const { Output } = getAiSdk(); - const aiProviderTools = toAiSdkProviderTools(this.config.providerTools); - const model = createModel(this.config.model); - return { - model, - aiProviderTools, - providerOptions: this.buildCallProviderOptions(execOptions?.providerOptions), - outputSpec: this.config.structuredOutput - ? Output.object({ schema: this.config.structuredOutput }) - : undefined, - }; - } - - /** Build the current local tool view; deferred loads can change this between iterations. */ - private buildToolLoopContext( - aiProviderTools: ReturnType<typeof toAiSdkProviderTools>, - persistence?: AgentPersistenceOptions, - executionCounter?: AgentExecutionCounter, - ) { - const allUserTools = this.getCurrentTools(persistence, executionCounter); - const aiTools = toAiSdkTools(allUserTools); - const allTools = { ...aiTools, ...aiProviderTools }; - const aiToolCount = Object.keys(allTools).length; - const toolMap = buildToolMap(allUserTools); - const effectiveInstructions = this.composeEffectiveInstructions(allUserTools); - - return { - toolMap, - aiTools: allTools, - hasTools: aiToolCount > 0, - effectiveInstructions, - }; - } - - private getCurrentTools( - persistence?: AgentPersistenceOptions, - executionCounter?: AgentExecutionCounter, - ): BuiltTool[] { - const baseTools = this.config.tools ?? []; - const tools = [ - ...baseTools, - ...(this.deferredToolManager?.hasTools - ? [ - ...this.deferredToolManager.getControllerTools(), - ...this.deferredToolManager.getLoadedTools(), - ] - : []), - ]; - - const recallTool = this.createRecallMemoryToolForRun(persistence, tools, executionCounter); - return recallTool ? [...tools, recallTool] : tools; - } - - private createRecallMemoryToolForRun( - persistence: AgentPersistenceOptions | undefined, - existingTools: BuiltTool[], - executionCounter?: AgentExecutionCounter, - ): BuiltTool | undefined { - const { memory, episodicMemory } = this.config; - if ( - !memory || - !episodicMemory || - !isEpisodicMemoryEnabled(episodicMemory) || - !hasEpisodicMemoryStore(memory) - ) { - return undefined; - } - const scope = getEpisodicMemoryScope(persistence); - if (!scope) return undefined; - if (existingTools.some((tool) => tool.name === RECALL_MEMORY_TOOL_NAME)) { - throw new Error( - `Tool name "${RECALL_MEMORY_TOOL_NAME}" is reserved while episodic memory is enabled.`, - ); - } - return createRecallMemoryTool({ memory, config: episodicMemory, scope, executionCounter }); - } - - private hydrateDeferredToolsFromList(list: AgentMessageList): void { - if (!this.deferredToolManager?.hasTools) return; - this.deferredToolManager.hydrateLoadedToolsFromMessages(list.serialize().messages); - } - - /** - * Merge tool-attached `systemInstruction` fragments into the agent's - * configured instructions. Fragments are wrapped in a single - * `<built_in_rules>` block, prepended above the user's instructions so - * the user's text remains the dominant tail of the prompt and can still - * override defaults if needed. - */ - private composeEffectiveInstructions(tools: BuiltTool[]): string { - const fragments = tools - .map((t) => t.systemInstruction) - .filter((s): s is string => typeof s === 'string' && s.trim().length > 0); - - const userInstructions = this.config.instructions; - if (fragments.length === 0) return userInstructions; - - const block = `<built_in_rules>\n${fragments.map((f) => `- ${f}`).join('\n')}\n</built_in_rules>`; - return userInstructions ? `${block}\n\n${userInstructions}` : block; - } - - /** - * Persist a suspended run state and update the current state snapshot. - * Returns the runtime's runId. - */ - private async persistSuspension( - pendingToolCalls: Record<string, PendingToolCall>, - options: RuntimeExecutionOptions | undefined, - list: AgentMessageList, - totalUsage: TokenUsage | undefined, - maxIterations?: number, - iterationCount?: number, - ): Promise<string> { - // Persist loop controls only. providerOptions are intentionally excluded - // because they may contain sensitive data (API keys, auth headers). - const resolvedMaxIterations = maxIterations ?? options?.maxIterations; - const resolvedIterationCount = iterationCount ?? options?.iterationCount; - const executionOptions: PersistedExecutionOptions | undefined = - resolvedMaxIterations !== undefined ? { maxIterations: resolvedMaxIterations } : undefined; - - const state: SerializableAgentState = { - persistence: options?.persistence, - status: 'suspended', - messageList: list.serialize(), - pendingToolCalls, - usage: totalUsage, - executionOptions, - ...(resolvedIterationCount !== undefined ? { iterationCount: resolvedIterationCount } : {}), - }; - await this.runState.suspend(this.runId, state); - this.updateState({ status: 'suspended', pendingToolCalls, messageList: list.serialize() }); - return this.runId; - } - - /** Clean up stored state for a run when it finishes without re-suspending. */ - private async cleanupRun(): Promise<void> { - await this.runState.complete(this.runId); - } - - /** Emit a TurnEnd event when an assistant message is present in `newMessages`. */ - private emitTurnEnd(newMessages: AgentMessage[], toolResults: ContentToolCall[]): void { - const assistantMsg = newMessages.find((m) => 'role' in m && m.role === 'assistant'); - if (assistantMsg) { - this.eventBus.emit({ type: AgentEvent.TurnEnd, message: assistantMsg, toolResults }); - } - } - - /** Patch the current state with partial updates. */ - private updateState(patch: Partial<SerializableAgentState>): void { - this.currentState = { ...this.currentState, ...patch }; - } - - /** Get the model ID string. */ - private get modelIdString(): string { - const m = this.config.model; - if (typeof m === 'string') return m; - if ('id' in m && typeof m.id === 'string') return m.id; - if ('modelId' in m && typeof m.modelId === 'string') { - const provider = 'provider' in m ? String(m.provider) : 'unknown'; - return `${provider}/${m.modelId}`; - } - return 'unknown'; - } - - /** Effective tool-call concurrency (default 1 = sequential). */ - private get concurrency(): number { - return this.config.toolCallConcurrency ?? 1; - } - - /** Fetch model cost from catalog. Retries on subsequent calls if the catalog was unavailable. */ - private async ensureModelCost(): Promise<ModelCost | undefined> { - if (this.modelCost) return this.modelCost; - try { - this.modelCost = await getModelCost(this.modelIdString); - } catch { - // Catalog unavailable — proceed without cost data, will retry next call - } - return this.modelCost; - } - - /** Apply cost to a TokenUsage object using catalog pricing. */ - private applyCost(usage: TokenUsage | undefined): TokenUsage | undefined { - if (!usage || !this.modelCost) return usage; - return { ...usage, cost: computeCost(usage, this.modelCost) }; - } - - private async setListObservationLogMemory( - list: AgentMessageList, - options: AgentPersistenceOptions | undefined, - ) { - const memory = this.config.memory; - if (!memory || !options?.threadId || !hasObservationLogStore(memory)) return; - const scope = this.getObservationLogScope(options); - const observations = await memory.getActiveObservationLog({ - ...scope, - order: 'asc', - }); - list.observationLogMemory = - renderObservationLog(observations, { - renderTokenBudget: this.config.observationLog?.renderTokenBudget, - }) ?? undefined; - // Observations are stamped at observer run time, after the messages they - // observed are persisted, so the latest observation's createdAt is a safe - // upper bound on those messages' createdAt. Seeding the list's clock here - // keeps new live messages ordered after the observer cursor's - // lastObservedAt even when resource-filtered history did not surface them - // (e.g. resources sharing a thread on fast back-to-back runs). - if (observations.length > 0) { - list.seedLastCreatedAt(observations[observations.length - 1].createdAt.getTime()); - } - } - - /** - * Configured telemetry handle (build-time). Run-time inheritance via - * `ExecutionOptions.telemetry` only applies inside an active - * agentic loop; out-of-band callers like `agent.reflect()` see the - * builder-time value. - */ - getConfiguredTelemetry(): BuiltTelemetry | undefined { - return this.config.telemetry; - } -} diff --git a/packages/@n8n/agents/src/runtime/execution-counter.ts b/packages/@n8n/agents/src/runtime/execution-counter.ts deleted file mode 100644 index 35f5835f0af..00000000000 --- a/packages/@n8n/agents/src/runtime/execution-counter.ts +++ /dev/null @@ -1,24 +0,0 @@ -import type { AgentExecutionCounter } from '../types/sdk/agent'; - -interface TokenUsageLike { - totalTokens?: number; - inputTokens?: number; - outputTokens?: number; - tokens?: number; -} - -export function incrementTokenCountFromUsage( - counter: AgentExecutionCounter | undefined, - usage: TokenUsageLike | undefined, -): void { - if (!counter || !usage) return; - const tokenCount = - usage.totalTokens ?? usage.tokens ?? (usage.inputTokens ?? 0) + (usage.outputTokens ?? 0); - if (tokenCount <= 0) return; - - try { - counter.incrementTokenCount(tokenCount); - } catch { - // Aggregate counters are best-effort and must never affect agent execution. - } -} diff --git a/packages/@n8n/agents/src/runtime/loop/agent-runtime.ts b/packages/@n8n/agents/src/runtime/loop/agent-runtime.ts new file mode 100644 index 00000000000..27c2f5cdd33 --- /dev/null +++ b/packages/@n8n/agents/src/runtime/loop/agent-runtime.ts @@ -0,0 +1,812 @@ +import type { ProviderOptions } from '@ai-sdk/provider-utils'; +import type { TelemetrySettings, ToolCallRepairFunction, ToolSet } from 'ai'; +import type { JSONSchema7 } from 'json-schema'; +import type { z } from 'zod'; + +import { incrementMessageCount, incrementTokenCountFromUsage } from './execution-counter'; +import { GenerateSink } from './generate-sink'; +import type { RunOutputSink, RunServices } from './run-output-sink'; +import { RuntimeContextBuilder, getModelIdString } from './runtime-context'; +import { + accumulateUsage, + extractSettledToolCalls, + makeErrorStream, + normalizeInput, +} from './runtime-helpers'; +import { StreamSink } from './stream-sink'; +import { isCancellation } from '../../sdk/cancellation'; +import { computeCost, getModelCost, type ModelCost } from '../../sdk/catalog'; +import type { + BuiltMemory, + BuiltProviderTool, + BuiltTelemetry, + BuiltTool, + CheckpointStore, + EpisodicMemoryConfig, + FinishReason, + GenerateResult, + ObservationalMemoryConfig, + ObservationLogMemoryConfig, + PendingToolCall, + RunOptions, + SerializableAgentState, + StreamChunk, + StreamResult, + ThinkingConfig, + TitleGenerationConfig, + TokenUsage, +} from '../../types'; +import { AgentEvent } from '../../types/runtime/event'; +import type { + ExecutionOptions, + ModelConfig, + PersistedExecutionOptions, +} from '../../types/sdk/agent'; +import type { AgentMessage, ContentToolCall } from '../../types/sdk/message'; +import type { JSONValue } from '../../types/utils/json'; +import { parseWithSchema } from '../../utils/parse'; +import { MemoryOrchestrator } from '../memory/memory-orchestrator'; +import { generateThreadTitle } from '../memory/title-generation'; +import { AgentMessageList, type SerializedMessageList } from '../model/message-list'; +import { BackgroundTaskTracker } from '../state/background-task-tracker'; +import { AgentEventBus, type AgentAbortScope } from '../state/event-bus'; +import { generateRunId, RunStateManager } from '../state/run-state'; +import { startStreamSession } from '../streaming/stream-session'; +import { RuntimeTelemetry } from '../telemetry/runtime-telemetry'; +import { DeferredToolManager } from '../tools/deferred-tool-manager'; +import { fixToolCall } from '../tools/fix-tool-call'; +import { + ToolCallExecutor, + type PendingResume, + type ToolBatchContext, +} from '../tools/tool-call-executor'; + +export interface AgentRuntimeConfig { + name: string; + model: ModelConfig; + instructions: string; + instructionProviderOptions?: ProviderOptions; + tools?: BuiltTool[]; + deferredTools?: BuiltTool[]; + toolSearch?: { + topK?: number; + }; + providerTools?: BuiltProviderTool[]; + memory?: BuiltMemory; + observationLog?: ObservationLogMemoryConfig; + observationalMemory?: ObservationalMemoryConfig; + episodicMemory?: EpisodicMemoryConfig; + structuredOutput?: z.ZodType | JSONSchema7; + checkpointStorage?: 'memory' | CheckpointStore; + thinking?: ThinkingConfig; + eventBus?: AgentEventBus; + /** Number of tool calls to execute concurrently. Default `1` (sequential). */ + toolCallConcurrency?: number; + titleGeneration?: TitleGenerationConfig; + telemetry?: BuiltTelemetry; + /** Existing run id to continue, used when resuming a suspended run. */ + runId?: string; + /** + * Pre-fetched model cost from the catalog. When provided, skips the per-run + * catalog fetch. Set once during Agent.build() and shared across per-run runtimes. + */ + modelCost?: ModelCost; + /** + * Shared RunStateManager for suspend/resume. When provided, per-run runtimes + * use the same store so resume() can find state from a prior run. + */ + runState?: RunStateManager; +} + +const MAX_LOOP_ITERATIONS = 30; + +const EMPTY_MESSAGE_LIST: SerializedMessageList = { + messages: [], + historyIds: [], + inputIds: [], + responseIds: [], +}; + +type RuntimeExecutionOptions = RunOptions & ExecutionOptions & { iterationCount?: number }; + +/** Shared input for the private generate/stream loops. */ +interface LoopContext { + list: AgentMessageList; + options?: RuntimeExecutionOptions; + abortScope: AgentAbortScope; + pendingResume?: PendingResume; +} + +/** + * Core agent execution engine using the Vercel AI SDK directly. + * + * - `generate()` uses `generateText()` — no streaming internally. + * - `stream()` uses `streamText()` — yields chunks in real time. + * + * Memory strategy: + * - `filterLlmMessages` strips custom messages before sending to the LLM. + * - Memory stores ALL AgentMessages (including custom) unchanged. + * - New messages for each turn are tracked via AgentMessageList.turnDelta(), + * which uses Set-based source tracking to identify turn-only messages. + * The list serializes with id-based sets so it can survive process restarts. + */ +export class AgentRuntime { + private config: AgentRuntimeConfig; + + private runState: RunStateManager; + + private eventBus: AgentEventBus; + + private currentState: SerializableAgentState; + + private modelCost: ModelCost | undefined; + + private backgroundTasks = new BackgroundTaskTracker(); + + private deferredToolManager: DeferredToolManager | undefined; + + private runId: string; + + private telemetry: RuntimeTelemetry; + + private memory: MemoryOrchestrator; + + private context: RuntimeContextBuilder; + + private toolExecutor: ToolCallExecutor; + + constructor(config: AgentRuntimeConfig) { + this.config = config; + this.telemetry = new RuntimeTelemetry(config); + this.runId = config.runId ?? generateRunId(); + if (config.deferredTools && config.deferredTools.length > 0) { + this.deferredToolManager = new DeferredToolManager(config.deferredTools, config.toolSearch); + } + this.context = new RuntimeContextBuilder(config, this.deferredToolManager); + this.runState = config.runState ?? new RunStateManager(config.checkpointStorage); + this.eventBus = config.eventBus ?? new AgentEventBus(); + this.memory = new MemoryOrchestrator(config, this.backgroundTasks, this.eventBus); + this.toolExecutor = new ToolCallExecutor({ + telemetry: this.telemetry, + eventBus: this.eventBus, + concurrency: config.toolCallConcurrency ?? 1, + onCancelled: () => this.updateState({ status: 'cancelled' }), + }); + this.modelCost = config.modelCost; + this.currentState = { + persistence: undefined, + status: 'idle', + messageList: EMPTY_MESSAGE_LIST, + pendingToolCalls: {}, + }; + } + + setTelemetry(telemetry: BuiltTelemetry | undefined): void { + this.config.telemetry = telemetry; + } + + /** + * Wait for in-flight background tasks (title generation, future + * observer cycles) to settle. Safe to call multiple times. + */ + async dispose(): Promise<void> { + this.eventBus.dispose(); + await this.backgroundTasks.flush(); + } + + /** Return the latest state snapshot. */ + getState(): SerializableAgentState { + return { ...this.currentState }; + } + + /** Set the abort flag to cancel the currently running agent. */ + abort(): void { + this.eventBus.abort(); + } + + /** + * Non-streaming: run the full agent loop using generateText and return the + * final result. Errors are returned on the result (`finishReason: 'error'`, + * `error` field) rather than thrown, so callers always receive a + * `GenerateResult`. The streaming path (`stream()`) emits error + finish + * chunks instead. + */ + async generate( + input: AgentMessage[] | string, + options?: RunOptions & ExecutionOptions, + ): Promise<GenerateResult> { + const abortScope = this.eventBus.createAbortScope(options?.abortSignal); + let list: AgentMessageList | undefined = undefined; + try { + const initializedList = await this.initRun(input, options); + list = initializedList; + const sink = new GenerateSink(this.createRunServices()); + const rawResult = await this.telemetry.withRootSpan( + 'generate', + options, + this.runId, + async () => + await this.runAgentLoop<GenerateResult>( + { list: initializedList, options, abortScope }, + sink, + ), + ); + return this.finalizeGenerate(rawResult, list); + } catch (error) { + await this.telemetry.flush(options); + const isAbort = abortScope.isAborted; + this.updateState({ status: isAbort ? 'cancelled' : 'failed' }); + if (!isAbort) { + this.eventBus.emit({ type: AgentEvent.Error, message: String(error), error }); + } + return { + runId: this.runId, + messages: list?.responseDelta() ?? [], + finishReason: 'error', + error, + getState: () => this.getState(), + }; + } finally { + abortScope.dispose(); + } + } + + /** Streaming: run the agent loop using streamText, yielding chunks in real time. */ + async stream( + input: AgentMessage[] | string, + options?: RunOptions & ExecutionOptions, + ): Promise<StreamResult> { + const abortScope = this.eventBus.createAbortScope(options?.abortSignal); + let list: AgentMessageList; + try { + list = await this.initRun(input, options); + } catch (error) { + const isAbort = abortScope.isAborted; + this.updateState({ status: isAbort ? 'cancelled' : 'failed' }); + if (!isAbort) { + this.eventBus.emit({ type: AgentEvent.Error, message: String(error), error }); + } + abortScope.dispose(); + return { runId: this.runId, stream: makeErrorStream(error), getState: () => this.getState() }; + } + + return { + runId: this.runId, + stream: this.startStream({ list, options, abortScope }), + getState: () => this.getState(), + }; + } + + /** + * Resume a suspended tool call with arbitrary data. + * Restores the suspended run state, passes pending tool calls into the loop + * as pending tool calls, and delegates to the same generate/stream loop used for fresh runs. + * + * - `'generate'` — runs the generate loop after tool execution, returns `GenerateResult`. + * - `'stream'` — runs the stream loop after tool execution, returns `StreamResult`. + */ + async resume( + method: 'generate', + data: unknown, + options: { runId: string; toolCallId: string } & ExecutionOptions, + ): Promise<GenerateResult>; + async resume( + method: 'stream', + data: unknown, + options: { runId: string; toolCallId: string } & ExecutionOptions, + ): Promise<StreamResult>; + async resume( + method: 'generate' | 'stream', + data: unknown, + options: { runId: string; toolCallId: string } & ExecutionOptions, + ): Promise<GenerateResult | StreamResult> { + this.runId = options.runId; + const state = await this.runState.resume(this.runId); + if (!state) throw new Error(`No suspended run found for runId: ${this.runId}`); + + const toolCall = state.pendingToolCalls[options.toolCallId]; + if (!toolCall) throw new Error(`No tool call found for toolCallId: ${options.toolCallId}`); + + const list = AgentMessageList.deserialize(state.messageList); + this.context.hydrateDeferredToolsFromList(list); + + const toolForValidation = this.context + .getCurrentTools(state.persistence) + .find((t) => t.name === toolCall.toolName); + if (!toolForValidation) throw new Error(`Tool ${toolCall.toolName} not found`); + + let resumeData: unknown = data; + let abortScope: AgentAbortScope | undefined; + + if (!isCancellation(resumeData) && toolForValidation.resumeSchema) { + const parseResult = await parseWithSchema(toolForValidation.resumeSchema, data); + if (!parseResult.success) { + throw new Error(`Invalid resume payload: ${parseResult.error}`); + } + resumeData = parseResult.data as JSONValue; + } + + try { + // Merge persisted execution options with fresh caller options + const { runId: _rid, toolCallId: _tcid, ...callerExecOptions } = options; + const persisted = state.executionOptions ?? {}; + const persistedMaxIterations = persisted.maxIterations; + const callerMaxIterations = callerExecOptions.maxIterations; + if ( + callerMaxIterations !== undefined && + persistedMaxIterations !== undefined && + callerMaxIterations < persistedMaxIterations + ) { + throw new Error( + `Cannot decrease maxIterations when resuming a run. Expected >= ${persistedMaxIterations}, received ${callerMaxIterations}.`, + ); + } + + const mergedMaxIterations = callerMaxIterations ?? persistedMaxIterations; + const mergedExecOptions: ExecutionOptions & { iterationCount?: number } = { + ...callerExecOptions, + ...(mergedMaxIterations !== undefined ? { maxIterations: mergedMaxIterations } : {}), + ...(state.iterationCount !== undefined ? { iterationCount: state.iterationCount } : {}), + }; + + const tool = this.context + .getCurrentTools(state.persistence, mergedExecOptions.executionCounter) + .find((t) => t.name === toolCall.toolName); + if (!tool) throw new Error(`Tool ${toolCall.toolName} not found`); + + const resumeOptions: RuntimeExecutionOptions = { + persistence: state.persistence, + ...mergedExecOptions, + }; + + abortScope = this.eventBus.createAbortScope(resumeOptions.abortSignal); + const activeAbortScope = abortScope; + + const pendingResume: PendingResume = { + pendingToolCalls: state.pendingToolCalls, + resumeToolCallId: options.toolCallId, + resumeData, + }; + + await this.ensureModelCost(); + + await this.memory.setListObservationLogMemory(list, state.persistence); + + if (method === 'generate') { + const sink = new GenerateSink(this.createRunServices()); + const rawResult = await this.telemetry.withRootSpan( + 'generate', + resumeOptions, + this.runId, + async () => + await this.runAgentLoop<GenerateResult>( + { + list, + options: resumeOptions, + abortScope: activeAbortScope, + pendingResume, + }, + sink, + ), + ); + try { + return this.finalizeGenerate(rawResult, list); + } finally { + abortScope.dispose(); + } + } + + return { + runId: this.runId, + stream: this.startStream({ + list, + options: resumeOptions, + abortScope: activeAbortScope, + pendingResume, + }), + getState: () => this.getState(), + }; + } catch (error) { + const isAbort = abortScope?.isAborted ?? false; + abortScope?.dispose(); + this.updateState({ status: isAbort ? 'cancelled' : 'failed' }); + if (!isAbort) { + this.eventBus.emit({ type: AgentEvent.Error, message: String(error), error }); + } + if (method === 'generate') { + return { + runId: this.runId, + messages: [], + finishReason: 'error' as const, + error, + getState: () => this.getState(), + }; + } + return { runId: this.runId, stream: makeErrorStream(error), getState: () => this.getState() }; + } + } + + // --- Private --- + + /** + * Build an AgentMessageList for the current turn: + * - Loads memory history (if configured) and adds as historySet + * - Adds raw input (custom messages preserved) as inputSet + * + * The system prompt is NOT stored in the list; list.forLlm(instructions) + * prepends it at every LLM call site. + */ + private async buildMessageList( + input: AgentMessage[], + options?: RunOptions & ExecutionOptions, + ): Promise<AgentMessageList> { + const list = new AgentMessageList(); + await this.memory.loadInto(list, options); + list.addInput(input); + return list; + } + + /** + * Common setup for generate() and stream(): reset abort state, transition to running, + * emit AgentStart, fetch model cost, normalize input, and build the message list. + * Throws if buildMessageList fails; callers catch and handle the error. + */ + private async initRun( + input: AgentMessage[] | string, + options?: RunOptions & ExecutionOptions, + ): Promise<AgentMessageList> { + this.updateState({ + status: 'running', + persistence: options?.persistence, + }); + this.eventBus.emit({ type: AgentEvent.AgentStart }); + await this.ensureModelCost(); + const normalizedInput = normalizeInput(input); + incrementMessageCount(options?.executionCounter); + return await this.buildMessageList(normalizedInput, options); + } + + /** + * Post-loop finalization for generate: apply cost, set model id, roll up sub-agent usage, + * transition to success, and emit AgentEnd. Returns the finalized result. + */ + private finalizeGenerate(result: GenerateResult, list: AgentMessageList): GenerateResult { + result.runId = this.runId; + result.usage = this.applyCost(result.usage); + result.model = this.modelIdString; + this.updateState({ status: 'success', messageList: list.serialize() }); + this.eventBus.emit({ type: AgentEvent.AgentEnd, messages: result.messages }); + return { ...result, getState: () => this.getState() }; + } + + private buildAiSdkOptions( + toolMap: Map<string, BuiltTool>, + options?: ExecutionOptions, + ): { + experimental_telemetry?: TelemetrySettings; + experimental_repairToolCall?: ToolCallRepairFunction<NoInfer<ToolSet>>; + experimental_onStepStart?: ExecutionOptions['onStepStart']; + onStepFinish?: ExecutionOptions['onStepFinish']; + } { + return { + ...this.telemetry.buildTelemetryOptions(options), + ...(options?.onStepStart ? { experimental_onStepStart: options.onStepStart } : {}), + ...(options?.onStepFinish ? { onStepFinish: options.onStepFinish } : {}), + experimental_repairToolCall: async (options) => { + return await fixToolCall( + { + toolCall: options.toolCall, + error: options.error, + }, + toolMap, + ); + }, + }; + } + + /** Throw (and mark the run cancelled) if the abort scope has fired. */ + private assertNotAborted(abortScope: AgentAbortScope): void { + if (abortScope.isAborted) { + this.updateState({ status: 'cancelled' }); + throw new Error('Agent run was aborted'); + } + } + + /** Build the shared services the output sinks call into for terminal concerns. */ + private createRunServices(): RunServices { + return { + runId: this.runId, + modelId: this.modelIdString, + applyCost: (usage) => this.applyCost(usage), + saveToMemory: async (list, options) => await this.memory.saveToMemory(list, options), + maybeGenerateTitle: async (list, options) => await this.maybeGenerateTitle(list, options), + flushTelemetry: async (options) => await this.telemetry.flush(options), + cleanupRun: async () => await this.cleanupRun(), + updateState: (patch) => this.updateState(patch), + emitAgentEnd: (messages) => this.eventBus.emit({ type: AgentEvent.AgentEnd, messages }), + getState: () => this.getState(), + }; + } + + /** Fire-and-forget (or sync, if configured) thread-title generation at end of turn. */ + private async maybeGenerateTitle( + list: AgentMessageList, + options: (RunOptions & ExecutionOptions) | undefined, + ): Promise<void> { + if (!this.config.titleGeneration || !options?.persistence?.threadId || !this.config.memory) { + return; + } + const titlePromise = generateThreadTitle({ + memory: this.config.memory, + threadId: options.persistence.threadId, + resourceId: options.persistence.resourceId, + titleConfig: this.config.titleGeneration, + agentModel: this.config.model, + turnDelta: list.turnDelta(), + executionCounter: options.executionCounter, + }); + this.backgroundTasks.track(titlePromise); + if (this.config.titleGeneration.sync) { + await titlePromise; + } + } + + /** + * Single agentic loop shared by generate and stream. The `sink` adapts the + * loop to its output channel: running the LLM call, emitting tool-batch + * results, and producing the terminal result for suspension / completion. + * + * Aborts throw `Agent run was aborted` (checked at the loop top, after the + * model call, and after each tool batch); model and tool-batch errors + * propagate. Callers (generate's try/catch, the stream session) translate + * those throws into their terminal contract. + */ + private async runAgentLoop<T>(ctx: LoopContext, sink: RunOutputSink<T>): Promise<T> { + const { list, options, abortScope, pendingResume } = ctx; + this.context.hydrateDeferredToolsFromList(list); + + let totalUsage: TokenUsage | undefined; + let lastFinishReason: FinishReason = 'stop'; + let structuredOutput: unknown; + const runTelemetry = this.telemetry.resolve(options); + const staticLoopContext = this.context.buildStaticLoopContext({ + ...options, + persistence: options?.persistence, + }); + const maxIterations = options?.maxIterations ?? MAX_LOOP_ITERATIONS; + let iterationCount = options?.iterationCount ?? 0; + let reachedStopCondition = false; + + const buildToolBatchContext = (toolMap: Map<string, BuiltTool>): ToolBatchContext => ({ + toolMap, + list, + runId: this.runId, + persistence: options?.persistence, + telemetry: runTelemetry, + executionCounter: options?.executionCounter, + abortSignal: abortScope.signal, + isAborted: () => abortScope.isAborted, + }); + + if (pendingResume) { + const pendingLoopContext = this.context.buildToolLoopContext( + staticLoopContext.aiProviderTools, + options?.persistence, + options?.executionCounter, + ); + const batch = await this.toolExecutor.iteratePendingToolCallsConcurrent({ + ...buildToolBatchContext(pendingLoopContext.toolMap), + pendingResume, + }); + await sink.emitToolBatch(batch); + + if (Object.keys(batch.pending).length > 0) { + const suspendRunId = await this.persistSuspension( + batch.pending, + options, + list, + totalUsage, + maxIterations, + iterationCount, + ); + return await sink.finishSuspended({ + suspendRunId, + list, + usage: totalUsage, + suspensions: batch.suspensions, + }); + } + } + + for (; iterationCount < maxIterations; iterationCount++) { + this.assertNotAborted(abortScope); + + this.eventBus.emit({ type: AgentEvent.TurnStart }); + + const { toolMap, aiTools, hasTools, effectiveInstructions } = + this.context.buildToolLoopContext( + staticLoopContext.aiProviderTools, + options?.persistence, + options?.executionCounter, + ); + const { system, messages } = list.forLlm( + effectiveInstructions, + this.config.instructionProviderOptions, + ); + + const turn = await sink.callModel({ + model: staticLoopContext.model, + system, + messages, + abortSignal: abortScope.signal, + hasTools, + aiTools, + providerOptions: staticLoopContext.providerOptions, + outputSpec: staticLoopContext.outputSpec, + aiSdkOptions: this.buildAiSdkOptions(toolMap, options), + }); + + this.assertNotAborted(abortScope); + + lastFinishReason = turn.finishReason; + totalUsage = accumulateUsage(totalUsage, turn.usage); + incrementTokenCountFromUsage(options?.executionCounter, turn.usage); + list.addResponse(turn.newMessages); + + if (turn.aiFinishReason !== 'tool-calls') { + structuredOutput = turn.structuredOutput; + this.emitTurnEnd(turn.newMessages, extractSettledToolCalls(turn.newMessages)); + reachedStopCondition = true; + break; + } + + const batch = await this.toolExecutor.iterateToolCallsConcurrent({ + ...buildToolBatchContext(toolMap), + toolCalls: turn.toolCalls, + }); + + this.assertNotAborted(abortScope); + + await sink.emitToolBatch(batch); + + if (Object.keys(batch.pending).length > 0) { + const suspendRunId = await this.persistSuspension( + batch.pending, + options, + list, + totalUsage, + maxIterations, + iterationCount + 1, + ); + return await sink.finishSuspended({ + suspendRunId, + list, + usage: totalUsage, + suspensions: batch.suspensions, + }); + } + + // Emit TurnEnd after all tool calls in this iteration are processed + this.emitTurnEnd(turn.newMessages, extractSettledToolCalls(list.responseDelta())); + } + + if (!reachedStopCondition && iterationCount >= maxIterations) { + lastFinishReason = 'max-iterations'; + } + + return await sink.finishComplete({ + list, + options, + finishReason: lastFinishReason, + usage: totalUsage, + structuredOutput, + }); + } + + /** + * Wire up a ReadableStream and start the stream loop in the background via the + * StreamSession, which owns the single shutdown / cleanup path. + */ + private startStream(ctx: LoopContext): ReadableStream<StreamChunk> { + return startStreamSession({ + eventBus: this.eventBus, + abortScope: ctx.abortScope, + runId: this.runId, + options: ctx.options, + withRootSpan: async (operation, options, runId, fn) => + await this.telemetry.withRootSpan(operation, options, runId, fn), + runLoop: async (guard) => { + const sink = new StreamSink(guard, this.createRunServices(), ctx.options); + await this.runAgentLoop(ctx, sink); + }, + flushTelemetry: async (options) => await this.telemetry.flush(options), + cleanupRun: async () => await this.cleanupRun(), + updateState: (status) => this.updateState({ status }), + emitError: (error) => + this.eventBus.emit({ type: AgentEvent.Error, message: String(error), error }), + }); + } + + /** + * Persist a suspended run state and update the current state snapshot. + * Returns the runtime's runId. + */ + private async persistSuspension( + pendingToolCalls: Record<string, PendingToolCall>, + options: RuntimeExecutionOptions | undefined, + list: AgentMessageList, + totalUsage: TokenUsage | undefined, + maxIterations?: number, + iterationCount?: number, + ): Promise<string> { + // Persist loop controls only. providerOptions are intentionally excluded + // because they may contain sensitive data (API keys, auth headers). + const resolvedMaxIterations = maxIterations ?? options?.maxIterations; + const resolvedIterationCount = iterationCount ?? options?.iterationCount; + const executionOptions: PersistedExecutionOptions | undefined = + resolvedMaxIterations !== undefined ? { maxIterations: resolvedMaxIterations } : undefined; + + const state: SerializableAgentState = { + persistence: options?.persistence, + status: 'suspended', + messageList: list.serialize(), + pendingToolCalls, + usage: totalUsage, + executionOptions, + ...(resolvedIterationCount !== undefined ? { iterationCount: resolvedIterationCount } : {}), + }; + await this.runState.suspend(this.runId, state); + this.updateState({ status: 'suspended', pendingToolCalls, messageList: list.serialize() }); + return this.runId; + } + + /** Clean up stored state for a run when it finishes without re-suspending. */ + private async cleanupRun(): Promise<void> { + await this.runState.complete(this.runId); + } + + /** Emit a TurnEnd event when an assistant message is present in `newMessages`. */ + private emitTurnEnd(newMessages: AgentMessage[], toolResults: ContentToolCall[]): void { + const assistantMsg = newMessages.find((m) => 'role' in m && m.role === 'assistant'); + if (assistantMsg) { + this.eventBus.emit({ type: AgentEvent.TurnEnd, message: assistantMsg, toolResults }); + } + } + + /** Patch the current state with partial updates. */ + private updateState(patch: Partial<SerializableAgentState>): void { + this.currentState = { ...this.currentState, ...patch }; + } + + /** Get the model ID string. */ + private get modelIdString(): string { + return getModelIdString(this.config.model); + } + + /** Fetch model cost from catalog. Retries on subsequent calls if the catalog was unavailable. */ + private async ensureModelCost(): Promise<ModelCost | undefined> { + if (this.modelCost) return this.modelCost; + try { + this.modelCost = await getModelCost(this.modelIdString); + } catch { + // Catalog unavailable — proceed without cost data, will retry next call + } + return this.modelCost; + } + + /** Apply cost to a TokenUsage object using catalog pricing. */ + private applyCost(usage: TokenUsage | undefined): TokenUsage | undefined { + if (!usage || !this.modelCost) return usage; + return { ...usage, cost: computeCost(usage, this.modelCost) }; + } + + /** + * Configured telemetry handle (build-time). Run-time inheritance via + * `ExecutionOptions.telemetry` only applies inside an active + * agentic loop; out-of-band callers like `agent.reflect()` see the + * builder-time value. + */ + getConfiguredTelemetry(): BuiltTelemetry | undefined { + return this.config.telemetry; + } +} diff --git a/packages/@n8n/agents/src/runtime/loop/execution-counter.ts b/packages/@n8n/agents/src/runtime/loop/execution-counter.ts new file mode 100644 index 00000000000..4c1103626b7 --- /dev/null +++ b/packages/@n8n/agents/src/runtime/loop/execution-counter.ts @@ -0,0 +1,46 @@ +import type { AgentExecutionCounter } from '../../types/sdk/agent'; + +interface TokenUsageLike { + totalTokens?: number; + inputTokens?: number; + outputTokens?: number; + tokens?: number; +} + +/** + * Run a counter mutation, swallowing any error. Aggregate execution counters are + * best-effort instrumentation and must never affect agent execution. + */ +export function recordExecutionCounter(fn: () => void): void { + try { + fn(); + } catch { + // Aggregate counters are best-effort and must never affect agent execution. + } +} + +export function incrementMessageCount(counter: AgentExecutionCounter | undefined): void { + if (!counter) return; + recordExecutionCounter(() => counter.incrementMessageCount()); +} + +export function incrementToolCallCount(counter: AgentExecutionCounter | undefined): void { + if (!counter) return; + recordExecutionCounter(() => counter.incrementToolCallCount()); +} + +export function incrementTokenCountFromUsage( + counter: AgentExecutionCounter | undefined, + usage: TokenUsageLike | undefined, +): void { + if (!counter || !usage) return; + const tokenCount = + usage.totalTokens ?? usage.tokens ?? (usage.inputTokens ?? 0) + (usage.outputTokens ?? 0); + if (tokenCount <= 0) return; + + try { + counter.incrementTokenCount(tokenCount); + } catch { + // Aggregate counters are best-effort and must never affect agent execution. + } +} diff --git a/packages/@n8n/agents/src/runtime/loop/generate-sink.ts b/packages/@n8n/agents/src/runtime/loop/generate-sink.ts new file mode 100644 index 00000000000..f025e1b92df --- /dev/null +++ b/packages/@n8n/agents/src/runtime/loop/generate-sink.ts @@ -0,0 +1,94 @@ +import type { + CompleteEmission, + ModelCallContext, + ModelTurnResult, + RunOutputSink, + RunServices, + SuspendEmission, +} from './run-output-sink'; +import type { GenerateResult } from '../../types'; +import type { ToolResultEntry } from '../../types/sdk/agent'; +import { loadAi } from '../model/lazy-ai'; +import { fromAiFinishReason, fromAiMessages } from '../model/messages'; +import type { ToolCallBatchResult } from '../tools/tool-call-executor'; + +/** + * Non-streaming output sink: drives the loop with `generateText`, accumulates a + * tool-call summary, and assembles the final `GenerateResult` (including the + * `pendingSuspend` shape on suspension). + */ +export class GenerateSink implements RunOutputSink<GenerateResult> { + private readonly toolCallSummary: ToolResultEntry[] = []; + + constructor(private readonly services: RunServices) {} + + async callModel(ctx: ModelCallContext): Promise<ModelTurnResult> { + const { generateText } = loadAi(); + const result = await generateText({ + model: ctx.model, + system: ctx.system, + messages: ctx.messages, + abortSignal: ctx.abortSignal, + ...(ctx.hasTools ? { tools: ctx.aiTools } : {}), + ...(ctx.providerOptions ? { providerOptions: ctx.providerOptions } : {}), + ...(ctx.outputSpec ? { output: ctx.outputSpec } : {}), + ...ctx.aiSdkOptions, + }); + + const aiFinishReason = result.finishReason; + return { + aiFinishReason, + finishReason: fromAiFinishReason(aiFinishReason), + usage: result.usage, + newMessages: fromAiMessages(result.response.messages), + toolCalls: result.toolCalls, + structuredOutput: + ctx.outputSpec && aiFinishReason !== 'tool-calls' ? result.output : undefined, + }; + } + + // eslint-disable-next-line @typescript-eslint/require-await -- sync work behind an async interface + async emitToolBatch(batch: ToolCallBatchResult): Promise<void> { + for (const r of batch.results) { + this.toolCallSummary.push(r.toolEntry); + } + } + + // eslint-disable-next-line @typescript-eslint/require-await -- sync work behind an async interface + async finishSuspended(emission: SuspendEmission): Promise<GenerateResult> { + const { suspendRunId, list, usage, suspensions } = emission; + return { + runId: suspendRunId, + messages: list.responseDelta(), + finishReason: 'tool-calls', + usage, + pendingSuspend: suspensions.map((s) => ({ + runId: suspendRunId, + toolCallId: s.toolCallId, + toolName: s.toolName, + input: s.input, + suspendPayload: s.payload, + resumeSchema: s.resumeSchema, + })), + getState: () => this.services.getState(), + }; + } + + async finishComplete(emission: CompleteEmission): Promise<GenerateResult> { + const { list, options, finishReason, usage, structuredOutput } = emission; + await this.services.saveToMemory(list, options); + await this.services.maybeGenerateTitle(list, options); + await this.services.cleanupRun(); + await this.services.flushTelemetry(options); + + return { + runId: this.services.runId, + messages: list.responseDelta(), + finishReason, + usage, + ...(structuredOutput !== undefined && { structuredOutput }), + ...(this.toolCallSummary.length > 0 && { toolCalls: this.toolCallSummary }), + getState: () => this.services.getState(), + }; + } +} diff --git a/packages/@n8n/agents/src/runtime/loop/run-output-sink.ts b/packages/@n8n/agents/src/runtime/loop/run-output-sink.ts new file mode 100644 index 00000000000..2de2eee538b --- /dev/null +++ b/packages/@n8n/agents/src/runtime/loop/run-output-sink.ts @@ -0,0 +1,103 @@ +import type { + LanguageModel, + LanguageModelUsage, + ModelMessage, + Output, + SystemModelMessage, + TelemetrySettings, + ToolCallRepairFunction, + ToolSet, +} from 'ai'; + +import type { FinishReason, SerializableAgentState, TokenUsage } from '../../types'; +import type { ExecutionOptions, RunOptions } from '../../types/sdk/agent'; +import type { AgentMessage } from '../../types/sdk/message'; +import type { JSONObject } from '../../types/utils/json'; +import type { AgentMessageList } from '../model/message-list'; +import type { ToolCallBatchResult, ToolCallSuspension } from '../tools/tool-call-executor'; + +type RunCallOptions = (RunOptions & ExecutionOptions) | undefined; + +/** Normalized result of a single LLM turn, independent of generate vs stream. */ +export interface ModelTurnResult { + /** Raw AI SDK finish reason (used to detect the `tool-calls` continuation). */ + aiFinishReason: string; + finishReason: FinishReason; + usage: LanguageModelUsage | undefined; + newMessages: AgentMessage[]; + toolCalls: Array<{ + toolCallId: string; + toolName: string; + input: unknown; + providerExecuted?: boolean; + }>; + /** Resolved structured output, only when an output spec is set and the turn finished. */ + structuredOutput: unknown; +} + +/** Per-iteration inputs for the LLM call, assembled by the shared loop. */ +export interface ModelCallContext { + model: LanguageModel; + system: SystemModelMessage; + messages: ModelMessage[]; + abortSignal: AbortSignal; + hasTools: boolean; + aiTools: ToolSet; + providerOptions?: Record<string, JSONObject>; + outputSpec?: ReturnType<typeof Output.object>; + aiSdkOptions: { + experimental_telemetry?: TelemetrySettings; + experimental_repairToolCall?: ToolCallRepairFunction<NoInfer<ToolSet>>; + }; +} + +/** Data needed to emit a terminal suspension result. */ +export interface SuspendEmission { + suspendRunId: string; + list: AgentMessageList; + usage: TokenUsage | undefined; + suspensions: ToolCallSuspension[]; +} + +/** Data needed to emit a terminal completion result. */ +export interface CompleteEmission { + list: AgentMessageList; + options: RunCallOptions; + finishReason: FinishReason; + usage: TokenUsage | undefined; + structuredOutput: unknown; +} + +/** + * Runtime services the sinks call into for shared terminal concerns (cost, + * memory persistence, title generation, telemetry flush, state). Implemented by + * `AgentRuntime` and passed to each sink. + */ +export interface RunServices { + readonly runId: string; + readonly modelId: string; + applyCost(usage: TokenUsage | undefined): TokenUsage | undefined; + saveToMemory(list: AgentMessageList, options: RunCallOptions): Promise<void>; + maybeGenerateTitle(list: AgentMessageList, options: RunCallOptions): Promise<void>; + flushTelemetry(options: RunCallOptions): Promise<void>; + cleanupRun(): Promise<void>; + updateState(patch: Partial<SerializableAgentState>): void; + emitAgentEnd(messages: AgentMessage[]): void; + getState(): SerializableAgentState; +} + +/** + * Strategy that adapts the shared agentic loop to a concrete output channel: + * `GenerateSink` accumulates a `GenerateResult`; `StreamSink` writes + * `StreamChunk`s through the stream writer guard. + */ +export interface RunOutputSink<TResult> { + /** Run one LLM turn. Streaming implementations also emit text/tool chunks here. */ + callModel(ctx: ModelCallContext): Promise<ModelTurnResult>; + /** Emit the results/errors of a completed tool-call batch. */ + emitToolBatch(batch: ToolCallBatchResult): Promise<void>; + /** Produce the terminal result when the run suspends for HITL / suspend-resume. */ + finishSuspended(emission: SuspendEmission): Promise<TResult>; + /** Produce the terminal result when the run completes normally. */ + finishComplete(emission: CompleteEmission): Promise<TResult>; +} diff --git a/packages/@n8n/agents/src/runtime/loop/runtime-context.ts b/packages/@n8n/agents/src/runtime/loop/runtime-context.ts new file mode 100644 index 00000000000..edda2859a0a --- /dev/null +++ b/packages/@n8n/agents/src/runtime/loop/runtime-context.ts @@ -0,0 +1,277 @@ +import type { ProviderOptions } from '@ai-sdk/provider-utils'; +import type { LanguageModel, Output } from 'ai'; + +import type { AgentRuntimeConfig } from './agent-runtime'; +import type { + AgentExecutionCounter, + AnthropicThinkingConfig, + BuiltTool, + GoogleThinkingConfig, + JSONObject, + OpenAIThinkingConfig, + XaiThinkingConfig, +} from '../../types'; +import type { AgentPersistenceOptions, ExecutionOptions, ModelConfig } from '../../types/sdk/agent'; +import { lockAdditionalProperties } from '../../utils/json-schema'; +import { isZodSchema } from '../../utils/zod'; +import { + createRecallMemoryTool, + getEpisodicMemoryScope, + hasEpisodicMemoryStore, + isEpisodicMemoryEnabled, + RECALL_MEMORY_TOOL_NAME, +} from '../memory/episodic-memory'; +import { loadAi } from '../model/lazy-ai'; +import type { AgentMessageList } from '../model/message-list'; +import { createModel } from '../model/model-factory'; +import type { DeferredToolManager } from '../tools/deferred-tool-manager'; +import { buildToolMap, toAiSdkProviderTools, toAiSdkTools } from '../tools/tool-adapter'; + +/** Resolve a model config to its canonical `provider/model` id string. */ +export function getModelIdString(model: ModelConfig): string { + if (typeof model === 'string') return model; + if ('id' in model && typeof model.id === 'string') return model.id; + if ('modelId' in model && typeof model.modelId === 'string') { + const provider = 'provider' in model ? String(model.provider) : 'unknown'; + return `${provider}/${model.modelId}`; + } + return 'unknown'; +} + +export interface StaticLoopContext { + model: LanguageModel; + aiProviderTools: ReturnType<typeof toAiSdkProviderTools>; + providerOptions?: Record<string, JSONObject>; + outputSpec?: ReturnType<typeof Output.object>; +} + +/** + * Builds the per-run and per-iteration dependencies the agentic loop hands to + * the LLM call: the model instance, provider/thinking options, structured + * output spec, and the effective tool surface (base + deferred + recall tools, + * mapped to AI SDK shapes). Keeps tool/model assembly out of the loop body. + */ +export class RuntimeContextBuilder { + constructor( + private readonly config: AgentRuntimeConfig, + private readonly deferredToolManager: DeferredToolManager | undefined, + ) {} + + get modelId(): string { + return getModelIdString(this.config.model); + } + + /** Build run-stable LLM call dependencies shared by all iterations. */ + buildStaticLoopContext( + execOptions?: ExecutionOptions & { persistence?: AgentPersistenceOptions }, + ): StaticLoopContext { + const { Output, jsonSchema } = loadAi(); + const aiProviderTools = toAiSdkProviderTools(this.config.providerTools); + const model = createModel(this.config.model); + const outputSchema = this.config.structuredOutput; + const isRawJsonSchemaOutput = outputSchema !== undefined && !isZodSchema(outputSchema); + const providerOptions = this.relaxStrictJsonSchemaIfNeeded( + this.buildCallProviderOptions(execOptions?.providerOptions), + isRawJsonSchemaOutput, + ); + + const outputSpec = outputSchema + ? Output.object({ + // Zod schemas pass through directly; a raw JSON Schema gets + // `additionalProperties: false` locked onto every object (required by Anthropic) + // and wrapped with the AI SDK's `jsonSchema()` helper. + schema: isZodSchema(outputSchema) + ? outputSchema + : jsonSchema(lockAdditionalProperties(outputSchema)), + }) + : undefined; + + return { + model, + aiProviderTools, + providerOptions: providerOptions as Record<string, JSONObject> | undefined, + outputSpec, + }; + } + + /** Build the current local tool view; deferred loads can change this between iterations. */ + buildToolLoopContext( + aiProviderTools: ReturnType<typeof toAiSdkProviderTools>, + persistence?: AgentPersistenceOptions, + executionCounter?: AgentExecutionCounter, + ) { + const allUserTools = this.getCurrentTools(persistence, executionCounter); + const aiTools = toAiSdkTools(allUserTools); + const allTools = { ...aiTools, ...aiProviderTools }; + const aiToolCount = Object.keys(allTools).length; + const toolMap = buildToolMap(allUserTools); + const effectiveInstructions = this.composeEffectiveInstructions(allUserTools); + + return { + toolMap, + aiTools: allTools, + hasTools: aiToolCount > 0, + effectiveInstructions, + }; + } + + getCurrentTools( + persistence?: AgentPersistenceOptions, + executionCounter?: AgentExecutionCounter, + ): BuiltTool[] { + const baseTools = this.config.tools ?? []; + const tools = [ + ...baseTools, + ...(this.deferredToolManager?.hasTools + ? [ + ...this.deferredToolManager.getControllerTools(), + ...this.deferredToolManager.getLoadedTools(), + ] + : []), + ]; + + const recallTool = this.createRecallMemoryToolForRun(persistence, tools, executionCounter); + return recallTool ? [...tools, recallTool] : tools; + } + + hydrateDeferredToolsFromList(list: AgentMessageList): void { + if (!this.deferredToolManager?.hasTools) return; + this.deferredToolManager.hydrateLoadedToolsFromMessages(list.serialize().messages); + } + + /** + * When structured output is driven by a raw JSON Schema (e.g. one a user + * typed into a workflow node), opt out of strict JSON Schema validation for + * the providers that default to it (OpenAI, Groq). Their strict mode rejects + * schemas whose objects don't list every property in `required` or that use + * keywords it doesn't allow — common in hand-written schemas. With strict off + * the provider still steers generation toward the schema, and the runtime + * validates the model's output against it afterwards. + * + * Zod-defined output keeps strict mode (zod-to-json-schema already produces a + * strict-compliant schema). Providers that hardcode strict (e.g. xAI) or use + * a different namespace (e.g. Azure) are unaffected and remain strict. + */ + private relaxStrictJsonSchemaIfNeeded( + providerOptions: Record<string, Record<string, unknown>> | undefined, + isRawJsonSchemaOutput: boolean, + ): Record<string, Record<string, unknown>> | undefined { + if (!isRawJsonSchemaOutput) return providerOptions; + + const result: Record<string, Record<string, unknown>> = { ...providerOptions }; + for (const provider of ['openai', 'groq']) { + // Keep any caller-provided value (spread last so it wins). + result[provider] = { strictJsonSchema: false, ...result[provider] }; + } + return result; + } + + private createRecallMemoryToolForRun( + persistence: AgentPersistenceOptions | undefined, + existingTools: BuiltTool[], + executionCounter?: AgentExecutionCounter, + ): BuiltTool | undefined { + const { memory, episodicMemory } = this.config; + if ( + !memory || + !episodicMemory || + !isEpisodicMemoryEnabled(episodicMemory) || + !hasEpisodicMemoryStore(memory) + ) { + return undefined; + } + const scope = getEpisodicMemoryScope(persistence); + if (!scope) return undefined; + if (existingTools.some((tool) => tool.name === RECALL_MEMORY_TOOL_NAME)) { + throw new Error( + `Tool name "${RECALL_MEMORY_TOOL_NAME}" is reserved while episodic memory is enabled.`, + ); + } + return createRecallMemoryTool({ memory, config: episodicMemory, scope, executionCounter }); + } + + /** + * Merge tool-attached `systemInstruction` fragments into the agent's + * configured instructions. Fragments are wrapped in a single + * `<built_in_rules>` block, prepended above the user's instructions so + * the user's text remains the dominant tail of the prompt and can still + * override defaults if needed. + */ + private composeEffectiveInstructions(tools: BuiltTool[]): string { + const fragments = tools + .map((t) => t.systemInstruction) + .filter((s): s is string => typeof s === 'string' && s.trim().length > 0); + + const userInstructions = this.config.instructions; + if (fragments.length === 0) return userInstructions; + + const block = `<built_in_rules>\n${fragments.map((f) => `- ${f}`).join('\n')}\n</built_in_rules>`; + return userInstructions ? `${block}\n\n${userInstructions}` : block; + } + + /** Build the providerOptions object for thinking/reasoning config. */ + private buildThinkingProviderOptions(): Record<string, Record<string, unknown>> | undefined { + if (!this.config.thinking) return undefined; + + const provider = this.modelId.split('/')[0]; + const thinking = this.config.thinking; + + switch (provider) { + case 'anthropic': { + const cfg = thinking as AnthropicThinkingConfig; + if (cfg.mode === 'adaptive') { + return { anthropic: { thinking: { type: 'adaptive' } } }; + } + return { + anthropic: { + thinking: { type: 'enabled', budgetTokens: cfg.budgetTokens ?? 10000 }, + }, + }; + } + case 'openai': { + const cfg = thinking as OpenAIThinkingConfig; + return { openai: { reasoningEffort: cfg.reasoningEffort ?? 'medium' } }; + } + case 'google': { + const cfg = thinking as GoogleThinkingConfig; + return { + google: { + thinkingConfig: { + ...(cfg.thinkingBudget !== undefined && { thinkingBudget: cfg.thinkingBudget }), + ...(cfg.thinkingLevel !== undefined && { thinkingLevel: cfg.thinkingLevel }), + }, + }, + }; + } + case 'xai': { + const cfg = thinking as XaiThinkingConfig; + return { xai: { reasoningEffort: cfg.reasoningEffort ?? 'high' } }; + } + default: + return undefined; + } + } + + /** + * Deep-merge thinking providerOptions with caller-supplied providerOptions. + * Per-provider keys are merged shallowly so `.thinking()` + cache control coexist. + */ + private buildCallProviderOptions( + runProviderOptions?: ProviderOptions, + ): Record<string, Record<string, unknown>> | undefined { + const thinkingOpts = this.buildThinkingProviderOptions(); + if (!thinkingOpts && !runProviderOptions) return undefined; + if (!thinkingOpts) return runProviderOptions as Record<string, Record<string, unknown>>; + if (!runProviderOptions) return thinkingOpts; + + const merged: Record<string, Record<string, unknown>> = { ...thinkingOpts }; + for (const [provider, opts] of Object.entries(runProviderOptions)) { + if (provider in merged) { + merged[provider] = { ...merged[provider], ...(opts as Record<string, unknown>) }; + } else { + merged[provider] = opts as Record<string, unknown>; + } + } + return merged; + } +} diff --git a/packages/@n8n/agents/src/runtime/runtime-helpers.ts b/packages/@n8n/agents/src/runtime/loop/runtime-helpers.ts similarity index 94% rename from packages/@n8n/agents/src/runtime/runtime-helpers.ts rename to packages/@n8n/agents/src/runtime/loop/runtime-helpers.ts index 52c6d209e05..68c39b537e6 100644 --- a/packages/@n8n/agents/src/runtime/runtime-helpers.ts +++ b/packages/@n8n/agents/src/runtime/loop/runtime-helpers.ts @@ -2,9 +2,9 @@ * Pure utility functions used by AgentRuntime that require no class context. * These are extracted here to keep agent-runtime.ts focused on orchestration logic. */ -import type { StreamChunk, TokenUsage } from '../types'; -import { toTokenUsage } from './stream'; -import type { AgentMessage, ContentToolCall } from '../types/sdk/message'; +import type { StreamChunk, TokenUsage } from '../../types'; +import type { AgentMessage, ContentToolCall } from '../../types/sdk/message'; +import { toTokenUsage } from '../streaming/stream'; /** * Normalize caller input to `AgentMessage[]` for the runtime. String input becomes a diff --git a/packages/@n8n/agents/src/runtime/loop/stream-sink.ts b/packages/@n8n/agents/src/runtime/loop/stream-sink.ts new file mode 100644 index 00000000000..6a0d5b4bc82 --- /dev/null +++ b/packages/@n8n/agents/src/runtime/loop/stream-sink.ts @@ -0,0 +1,164 @@ +import type { + CompleteEmission, + ModelCallContext, + ModelTurnResult, + RunOutputSink, + RunServices, + SuspendEmission, +} from './run-output-sink'; +import type { ExecutionOptions } from '../../types/sdk/agent'; +import { loadAi } from '../model/lazy-ai'; +import { fromAiFinishReason, fromAiMessages } from '../model/messages'; +import { convertChunk } from '../streaming/stream'; +import type { StreamWriterGuard } from '../streaming/stream-writer-guard'; +import type { ToolCallBatchResult } from '../tools/tool-call-executor'; + +/** + * Streaming output sink: drives the loop with `streamText`, forwards text / + * reasoning / tool chunks (and provider-executed tool timing) through the + * `StreamWriterGuard`, and writes the terminal `finish` / `tool-call-suspended` + * chunks. Owns the smooth-stream transform option. + */ +export class StreamSink implements RunOutputSink<void> { + constructor( + private readonly guard: StreamWriterGuard, + private readonly services: RunServices, + private readonly options: ExecutionOptions | undefined, + ) {} + + private buildSmoothStreamTransformOptions(): { + experimental_transform?: ReturnType<ReturnType<typeof loadAi>['smoothStream']>; + } { + if (this.options?.smoothStream === false) return {}; + const { smoothStream } = loadAi(); + return { experimental_transform: smoothStream(this.options?.smoothStream ?? {}) }; + } + + async callModel(ctx: ModelCallContext): Promise<ModelTurnResult> { + const { streamText } = loadAi(); + const result = streamText({ + model: ctx.model, + system: ctx.system, + messages: ctx.messages, + abortSignal: ctx.abortSignal, + ...(ctx.hasTools ? { tools: ctx.aiTools } : {}), + ...(ctx.providerOptions ? { providerOptions: ctx.providerOptions } : {}), + ...(ctx.outputSpec ? { output: ctx.outputSpec } : {}), + ...ctx.aiSdkOptions, + ...this.buildSmoothStreamTransformOptions(), + }); + + // Consume the stream. When the AbortSignal fires mid-stream the AI SDK + // cancels the underlying fetch and the async iterator throws; the error + // propagates to the StreamSession which closes the consumer stream. + for await (const chunk of result.fullStream) { + // Filter only the SDK's terminal `finish` chunk — the runtime emits its + // own consolidated `finish` after the loop completes. `start-step` / + // `finish-step` are passed through as LLM-iteration boundaries. + if (chunk.type === 'finish') continue; + + // Provider-executed tools (e.g. native web search) skip the local + // execution loop that emits tool-execution lifecycle events via the + // event bus. Stamp them here at chunk-arrival time so live chat and the + // persisted timeline both show a duration. A failed call arrives as a + // `tool-error` part (never a `tool-result`), so close its timing there. + if ((chunk.type === 'tool-result' || chunk.type === 'tool-error') && chunk.providerExecuted) { + await this.guard.write({ + type: 'tool-execution-end', + toolCallId: chunk.toolCallId, + toolName: chunk.toolName ?? '', + isError: chunk.type === 'tool-error', + endTime: Date.now(), + }); + } + + const converted = convertChunk(chunk); + if (converted) await this.guard.write(converted); + + if (chunk.type === 'tool-call' && chunk.providerExecuted) { + await this.guard.write({ + type: 'tool-execution-start', + toolCallId: chunk.toolCallId, + toolName: chunk.toolName ?? '', + startTime: Date.now(), + }); + } + } + + const aiFinishReason = await result.finishReason; + const usage = await result.usage; + const response = await result.response; + + return { + aiFinishReason, + finishReason: fromAiFinishReason(aiFinishReason), + usage, + newMessages: fromAiMessages(response.messages), + toolCalls: await result.toolCalls, + structuredOutput: + ctx.outputSpec && aiFinishReason !== 'tool-calls' ? await result.output : undefined, + }; + } + + async emitToolBatch(batch: ToolCallBatchResult): Promise<void> { + for (const r of batch.results) { + await this.guard.write({ + type: 'tool-result', + toolCallId: r.toolCallId, + toolName: r.toolName, + output: r.modelOutput, + ...(r.toolEntry.canceled ? { canceled: true } : {}), + }); + if (r.customMessage) { + await this.guard.write({ type: 'message', message: r.customMessage }); + } + } + + for (const e of batch.errors) { + await this.guard.write({ + type: 'tool-result', + toolCallId: e.toolCallId, + toolName: e.toolName, + output: e.error, + isError: true, + }); + } + } + + async finishSuspended(emission: SuspendEmission): Promise<void> { + for (const s of emission.suspensions) { + await this.guard.write({ + type: 'tool-call-suspended', + runId: emission.suspendRunId, + toolCallId: s.toolCallId, + toolName: s.toolName, + input: s.input, + suspendPayload: s.payload, + resumeSchema: s.resumeSchema, + }); + } + await this.guard.write({ type: 'finish', finishReason: 'tool-calls' }); + await this.guard.close(); + } + + async finishComplete(emission: CompleteEmission): Promise<void> { + const { list, options, finishReason, usage, structuredOutput } = emission; + const costUsage = this.services.applyCost(usage); + + await this.services.saveToMemory(list, options); + await this.services.maybeGenerateTitle(list, options); + await this.services.cleanupRun(); + await this.services.flushTelemetry(options); + + await this.guard.write({ + type: 'finish', + finishReason, + ...(costUsage && { usage: costUsage }), + model: this.services.modelId, + ...(structuredOutput !== undefined && { structuredOutput }), + }); + this.services.updateState({ status: 'success', messageList: list.serialize() }); + this.services.emitAgentEnd(list.responseDelta()); + await this.guard.close(); + } +} diff --git a/packages/@n8n/agents/src/runtime/mcp-connection.ts b/packages/@n8n/agents/src/runtime/mcp/mcp-connection.ts similarity index 88% rename from packages/@n8n/agents/src/runtime/mcp-connection.ts rename to packages/@n8n/agents/src/runtime/mcp/mcp-connection.ts index 341ef85314d..e53dabdf460 100644 --- a/packages/@n8n/agents/src/runtime/mcp-connection.ts +++ b/packages/@n8n/agents/src/runtime/mcp/mcp-connection.ts @@ -7,9 +7,9 @@ import type { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/cl import type { CallToolResult } from '@modelcontextprotocol/sdk/types.js'; import { McpToolResolver } from './mcp-tool-resolver'; -import { wrapToolForApproval } from '../sdk/tool'; -import type { McpServerConfig } from '../types/sdk/mcp'; -import type { BuiltTool } from '../types/sdk/tool'; +import { wrapToolForApproval } from '../../sdk/tool'; +import type { McpServerConfig } from '../../types/sdk/mcp'; +import type { BuiltTool } from '../../types/sdk/tool'; /** The raw result returned by an MCP tool call. */ export type McpCallToolResult = CallToolResult; @@ -54,21 +54,37 @@ async function loadMcpSdk(): Promise<McpSdkModule> { return await mcpSdkPromise; } +function applyToolFilter<T extends { name: string }>( + tools: T[], + toolFilter: McpServerConfig['toolFilter'], +): T[] { + if (!toolFilter?.mode || !toolFilter?.tools) { + return tools; + } + + const filterSet = new Set(toolFilter.tools); + if (toolFilter.mode === 'allow') { + return tools.filter((tool) => filterSet.has(tool.name)); + } else if (toolFilter.mode === 'exclude') { + return tools.filter((tool) => !filterSet.has(tool.name)); + } + + // Return tools as-is if `mode` is not `'allow' | 'exclude'` for some reason + return tools; +} + /** Wraps a single MCP SDK Client instance for one server. Not publicly exported. */ export class McpConnection { private client: Client | undefined; private config: McpServerConfig; - private readonly shouldRequireToolApproval: boolean; - private connectionPromise: Promise<void> | undefined = undefined; private disconnectPromise: Promise<void> | undefined = undefined; private closed = false; - constructor(config: McpServerConfig, requireToolApproval = false) { + constructor(config: McpServerConfig) { this.config = config; - this.shouldRequireToolApproval = requireToolApproval; } async connect(): Promise<void> { @@ -128,9 +144,10 @@ export class McpConnection { if (!this.client) throw new Error('MCP client not initialized; connect() must be called first'); const result = await this.client.listTools(); const resolver = new McpToolResolver(); - const tools = resolver.resolve(this, result.tools); + const filteredRawTools = applyToolFilter(result.tools, this.config.toolFilter); + const tools = resolver.resolve(this, filteredRawTools); return tools.map((t) => - t.suspendSchema || !this.needsApproval(t) + t.suspendSchema || !this.shouldRequireToolApproval(t) ? t : wrapToolForApproval(t, { requireApproval: true }), ); @@ -140,13 +157,10 @@ export class McpConnection { * Returns true when a resolved tool should be wrapped with an approval gate. * * A tool needs approval when either: - * - the global `shouldRequireToolApproval` flag (set via Agent.requireToolApproval()) is true, OR * - `config.requireApproval` is `true` (all tools on this server), OR * - `config.requireApproval` is a string array that includes the tool's original (un-prefixed) name. */ - private needsApproval(tool: BuiltTool): boolean { - if (this.shouldRequireToolApproval) return true; - + private shouldRequireToolApproval(tool: BuiltTool): boolean { const { requireApproval } = this.config; if (requireApproval === true) return true; diff --git a/packages/@n8n/agents/src/runtime/mcp-tool-resolver.ts b/packages/@n8n/agents/src/runtime/mcp/mcp-tool-resolver.ts similarity index 98% rename from packages/@n8n/agents/src/runtime/mcp-tool-resolver.ts rename to packages/@n8n/agents/src/runtime/mcp/mcp-tool-resolver.ts index c0b8ce699ba..7f92a28e75e 100644 --- a/packages/@n8n/agents/src/runtime/mcp-tool-resolver.ts +++ b/packages/@n8n/agents/src/runtime/mcp/mcp-tool-resolver.ts @@ -2,8 +2,8 @@ import type { Tool } from '@modelcontextprotocol/sdk/types.js'; import type { JSONSchema7 } from 'json-schema'; import type { McpCallToolResult, McpConnection } from './mcp-connection'; -import type { AgentMessage, ContentFile, ContentText } from '../types/sdk/message'; -import type { BuiltTool, InterruptibleToolContext, ToolContext } from '../types/sdk/tool'; +import type { AgentMessage, ContentFile, ContentText } from '../../types/sdk/message'; +import type { BuiltTool, InterruptibleToolContext, ToolContext } from '../../types/sdk/tool'; type McpContentBlock = McpCallToolResult['content'][number]; diff --git a/packages/@n8n/agents/src/runtime/episodic-memory-defaults.ts b/packages/@n8n/agents/src/runtime/memory/episodic-memory-defaults.ts similarity index 99% rename from packages/@n8n/agents/src/runtime/episodic-memory-defaults.ts rename to packages/@n8n/agents/src/runtime/memory/episodic-memory-defaults.ts index f80fd88f4a1..b25929dc540 100644 --- a/packages/@n8n/agents/src/runtime/episodic-memory-defaults.ts +++ b/packages/@n8n/agents/src/runtime/memory/episodic-memory-defaults.ts @@ -1,7 +1,5 @@ import { z } from 'zod'; -import { incrementTokenCountFromUsage } from './execution-counter'; -import { createModel } from './model-factory'; import type { EpisodicMemoryExtraction, EpisodicMemoryExtractorInput, @@ -13,7 +11,9 @@ import type { ModelConfig, ObservationLogEntry, RetrievedEpisodicMemoryEntry, -} from '../types'; +} from '../../types'; +import { incrementTokenCountFromUsage } from '../loop/execution-counter'; +import { createModel } from '../model/model-factory'; export const DEFAULT_EPISODIC_MEMORY_EMBEDDING_MODEL = 'openai/text-embedding-3-small'; export const DEFAULT_EPISODIC_MEMORY_TOP_K = 5; diff --git a/packages/@n8n/agents/src/runtime/episodic-memory.ts b/packages/@n8n/agents/src/runtime/memory/episodic-memory.ts similarity index 98% rename from packages/@n8n/agents/src/runtime/episodic-memory.ts rename to packages/@n8n/agents/src/runtime/memory/episodic-memory.ts index 0a06d06b709..a0791c05223 100644 --- a/packages/@n8n/agents/src/runtime/episodic-memory.ts +++ b/packages/@n8n/agents/src/runtime/memory/episodic-memory.ts @@ -6,10 +6,9 @@ import { DEFAULT_EPISODIC_MEMORY_RECALL_TOOL_INSTRUCTION, DEFAULT_EPISODIC_MEMORY_TOP_K, } from './episodic-memory-defaults'; -import { incrementTokenCountFromUsage } from './execution-counter'; import { normalizeFlatReflectionActions } from './memory-lifecycle'; import { renderObservationLog } from './observation-log-renderer'; -import { Tool } from '../sdk/tool'; +import { Tool } from '../../sdk/tool'; import type { BuiltEpisodicMemoryStore, BuiltMemory, @@ -21,9 +20,10 @@ import type { EpisodicMemoryScope, EpisodicMemorySearchOptions, RetrievedEpisodicMemoryEntry, -} from '../types'; -import type { AgentExecutionCounter, AgentPersistenceOptions } from '../types/sdk/agent'; -import type { ObservationLogEntry, ObservationLogScope } from '../types/sdk/observation-log'; +} from '../../types'; +import type { AgentExecutionCounter, AgentPersistenceOptions } from '../../types/sdk/agent'; +import type { ObservationLogEntry, ObservationLogScope } from '../../types/sdk/observation-log'; +import { incrementTokenCountFromUsage } from '../loop/execution-counter'; export const RECALL_MEMORY_TOOL_NAME = 'recall_memory'; diff --git a/packages/@n8n/agents/src/runtime/memory-lifecycle.ts b/packages/@n8n/agents/src/runtime/memory/memory-lifecycle.ts similarity index 100% rename from packages/@n8n/agents/src/runtime/memory-lifecycle.ts rename to packages/@n8n/agents/src/runtime/memory/memory-lifecycle.ts diff --git a/packages/@n8n/agents/src/runtime/memory/memory-orchestrator.ts b/packages/@n8n/agents/src/runtime/memory/memory-orchestrator.ts new file mode 100644 index 00000000000..a3181f41f32 --- /dev/null +++ b/packages/@n8n/agents/src/runtime/memory/memory-orchestrator.ts @@ -0,0 +1,352 @@ +import { + getEpisodicMemoryScope, + hasEpisodicMemoryStore, + isEpisodicMemoryEnabled, + runEpisodicMemoryIndexer, +} from './episodic-memory'; +import { createFilteredLogger } from '../logger'; +import { saveMessagesToThread } from './memory-store'; +import { + runObservationLogObserver, + type ObservationLogObserverMemory, +} from './observation-log-observer'; +import { runObservationLogReflector } from './observation-log-reflector'; +import { renderObservationLog } from './observation-log-renderer'; +import { hasObservationLogStore, hasObservationLogTaskLockStore } from './observation-log-store'; +import { ScopedMemoryTaskRunner } from './scoped-memory-task-runner'; +import { stripOrphanedToolMessages } from './strip-orphaned-tool-messages'; +import type { + AgentExecutionCounter, + BuiltMemory, + EpisodicMemoryTaskLockHandle, + EpisodicMemoryTaskLockMethods, +} from '../../types'; +import { AgentEvent } from '../../types/runtime/event'; +import type { AgentPersistenceOptions, ExecutionOptions, RunOptions } from '../../types/sdk/agent'; +import type { AgentDbMessage } from '../../types/sdk/message'; +import type { ObservationLogScope, ObservationLogTaskKind } from '../../types/sdk/observation-log'; +import type { AgentRuntimeConfig } from '../loop/agent-runtime'; +import type { AgentMessageList } from '../model/message-list'; +import type { BackgroundTaskTracker } from '../state/background-task-tracker'; +import type { AgentEventBus } from '../state/event-bus'; + +const DEFAULT_MEMORY_TASK_LOCK_TTL_MS = 30_000; +const logger = createFilteredLogger(); + +function hasFunctionProperty<K extends PropertyKey>( + value: object, + property: K, +): value is Record<K, (...args: never[]) => unknown> { + return property in value && typeof Reflect.get(value, property) === 'function'; +} + +function hasObservationLogObserverMemory( + memory: BuiltMemory, +): memory is ObservationLogObserverMemory { + return ( + hasObservationLogStore(memory) && + hasFunctionProperty(memory, 'getMessagesForObservationScope') && + hasFunctionProperty(memory, 'getCursor') && + hasFunctionProperty(memory, 'setCursor') + ); +} + +/** + * Owns all memory-store side effects for a single agent runtime: loading thread + * history, seeding the live message list with the active observation log, + * persisting the turn delta, and scheduling background observation-log and + * episodic-memory indexing jobs. + * + */ +export class MemoryOrchestrator { + private memoryTasks: ScopedMemoryTaskRunner | undefined; + + private episodicMemoryTasksByResource = new Map<string, Promise<unknown>>(); + + constructor( + private readonly config: AgentRuntimeConfig, + private readonly backgroundTasks: BackgroundTaskTracker, + private readonly eventBus: AgentEventBus, + ) {} + + async loadHistoryMessages(persistence: AgentPersistenceOptions): Promise<AgentDbMessage[]> { + const memory = this.config.memory; + + if (!memory) return []; + + const { threadId, resourceId } = persistence; + + if (this.config.observationalMemory && hasObservationLogObserverMemory(memory)) { + const cursor = await memory.getCursor(threadId); + + if (cursor) { + return await memory.getMessagesForObservationScope(threadId, { + since: { + sinceCreatedAt: cursor.lastObservedAt, + sinceMessageId: cursor.lastObservedMessageId, + }, + }); + } + } + + return await memory.getMessages(threadId, { + resourceId, + }); + } + + /** + * Load thread history (if memory + threadId are configured) into the list as + * the history set, stripping orphaned tool pairs, then seed the active + * observation log into the list's working memory. + */ + async loadInto( + list: AgentMessageList, + options: (RunOptions & ExecutionOptions) | undefined, + ): Promise<void> { + if (this.config.memory && options?.persistence?.threadId) { + const memMessages = await this.loadHistoryMessages(options.persistence); + + if (memMessages.length > 0) { + list.addHistory(stripOrphanedToolMessages(memMessages)); + } + } + + await this.setListObservationLogMemory(list, options?.persistence); + } + + async setListObservationLogMemory( + list: AgentMessageList, + options: AgentPersistenceOptions | undefined, + ): Promise<void> { + const memory = this.config.memory; + if (!memory || !options?.threadId || !hasObservationLogStore(memory)) return; + const scope = this.getObservationLogScope(options); + const observations = await memory.getActiveObservationLog({ + ...scope, + order: 'asc', + }); + list.observationLogMemory = + renderObservationLog(observations, { + renderTokenBudget: this.config.observationLog?.renderTokenBudget, + }) ?? undefined; + // Observations are stamped at observer run time, after the messages they + // observed are persisted, so the latest observation's createdAt is a safe + // upper bound on those messages' createdAt. Seeding the list's clock here + // keeps new live messages ordered after the observer cursor's + // lastObservedAt even when resource-filtered history did not surface them + // (e.g. resources sharing a thread on fast back-to-back runs). + if (observations.length > 0) { + list.seedLastCreatedAt(observations[observations.length - 1].createdAt.getTime()); + } + } + + /** Persist the current-turn delta to memory and schedule background indexing. */ + async saveToMemory( + list: AgentMessageList, + options: (RunOptions & ExecutionOptions) | undefined, + ): Promise<void> { + if (!this.config.memory || !options?.persistence) return; + const delta = list.turnDelta(); + if (delta.length === 0) return; + await saveMessagesToThread( + this.config.memory, + options.persistence.threadId, + options.persistence.resourceId, + delta, + ); + + // Memory jobs receive the execution counter so their LLM and embedding + // usage contributes to token_count. + + const observationTasks = this.scheduleObservationLogJobs( + options.persistence, + options.executionCounter, + ); + this.scheduleEpisodicMemoryJob(options.persistence, observationTasks, options.executionCounter); + } + + private scheduleObservationLogJobs( + persistence: AgentPersistenceOptions, + executionCounter?: AgentExecutionCounter, + ): Array<Promise<unknown>> { + const { memory, observationalMemory } = this.config; + if (!memory || !observationalMemory || !hasObservationLogStore(memory)) return []; + + const scope = this.getObservationLogScope(persistence); + const runner = this.getMemoryTaskRunner(memory, observationalMemory.lockTtlMs); + const observe = observationalMemory.observe; + const observerThresholdTokens = observationalMemory.observerThresholdTokens; + const tasks: Array<Promise<unknown>> = []; + + if ( + observe && + observerThresholdTokens !== undefined && + hasObservationLogObserverMemory(memory) + ) { + tasks.push( + this.scheduleMemoryTask( + runner, + scope, + 'observer', + async () => + await runObservationLogObserver({ + memory, + ...scope, + observerThresholdTokens, + observationLogTailLimit: observationalMemory.observationLogTailLimit ?? 0, + observe, + executionCounter, + }), + ), + ); + } + + const reflect = observationalMemory.reflect; + const reflectorThresholdTokens = observationalMemory.reflectorThresholdTokens; + if (reflect && reflectorThresholdTokens !== undefined) { + tasks.push( + this.scheduleMemoryTask( + runner, + scope, + 'reflector', + async () => + await runObservationLogReflector({ + memory, + ...scope, + reflectorThresholdTokens, + reflect, + executionCounter, + }), + ), + ); + } + + return tasks; + } + + private scheduleEpisodicMemoryJob( + persistence: AgentPersistenceOptions, + observationTasks: Array<Promise<unknown>>, + executionCounter?: AgentExecutionCounter, + ): void { + const { memory, episodicMemory } = this.config; + if ( + !memory || + !episodicMemory || + !isEpisodicMemoryEnabled(episodicMemory) || + !hasEpisodicMemoryStore(memory) || + !hasObservationLogStore(memory) || + !episodicMemory.extract + ) { + return; + } + const scope = getEpisodicMemoryScope(persistence); + if (!scope) return; + + const observationScope = this.getObservationLogScope(persistence); + this.scheduleEpisodicMemoryTask(memory, scope.resourceId, async () => { + await Promise.allSettled(observationTasks); + await runEpisodicMemoryIndexer({ + memory, + config: episodicMemory, + scope, + observationScope, + threadId: persistence.threadId, + executionCounter, + }); + }); + } + + private scheduleEpisodicMemoryTask( + memory: BuiltMemory, + resourceId: string, + task: () => Promise<void>, + ): void { + const id = crypto.randomUUID(); + const previous = this.episodicMemoryTasksByResource.get(resourceId) ?? Promise.resolve(); + const done = previous + .catch(() => undefined) + .then(async () => await this.runEpisodicMemoryTask(memory, resourceId, id, task)); + const queued = done.finally(() => { + if (this.episodicMemoryTasksByResource.get(resourceId) === queued) { + this.episodicMemoryTasksByResource.delete(resourceId); + } + }); + this.episodicMemoryTasksByResource.set(resourceId, queued); + this.backgroundTasks.track(queued); + } + + private async runEpisodicMemoryTask( + memory: BuiltMemory, + resourceId: string, + holderId: string, + task: () => Promise<void>, + ): Promise<void> { + const taskLock = memory.episodic?.taskLock; + let lock: EpisodicMemoryTaskLockHandle | null = null; + try { + if (taskLock) { + lock = await taskLock.acquire(resourceId, { + holderId, + ttlMs: this.config.observationalMemory?.lockTtlMs ?? DEFAULT_MEMORY_TASK_LOCK_TTL_MS, + }); + if (!lock) return; + } + await task(); + } catch (error) { + const message = 'Episodic memory indexing task failed'; + logger.warn(message, { error, resourceId }); + this.eventBus.emit({ type: AgentEvent.Error, message, error, source: 'episodic-memory' }); + } finally { + if (lock) { + await this.releaseEpisodicMemoryTaskLock(taskLock, lock, resourceId); + } + } + } + + private async releaseEpisodicMemoryTaskLock( + taskLock: EpisodicMemoryTaskLockMethods | undefined, + lock: EpisodicMemoryTaskLockHandle, + resourceId: string, + ): Promise<void> { + try { + await taskLock?.release(lock); + } catch (error) { + logger.warn('Episodic memory indexing lock release failed', { error, resourceId }); + } + } + + private async scheduleMemoryTask<T>( + runner: ScopedMemoryTaskRunner, + scope: ObservationLogScope, + taskKind: ObservationLogTaskKind, + task: () => Promise<T>, + ): Promise<unknown> { + return await runner.schedule({ ...scope, taskKind }, task).done; + } + + private getMemoryTaskRunner(memory: BuiltMemory, lockTtlMs?: number): ScopedMemoryTaskRunner { + this.memoryTasks ??= new ScopedMemoryTaskRunner({ + tracker: this.backgroundTasks, + lockStore: hasObservationLogTaskLockStore(memory) ? memory : undefined, + lockTtlMs, + onEvent: (event) => { + if (event.type !== 'failed') return; + const source = event.task.taskKind; + const message = `Observation log ${source} task failed`; + logger.warn(message, { + error: event.error, + observationScopeId: event.task.observationScopeId, + }); + this.eventBus.emit({ type: AgentEvent.Error, message, error: event.error, source }); + }, + }); + return this.memoryTasks; + } + + private getObservationLogScope(persistence: AgentPersistenceOptions): ObservationLogScope { + return { + observationScopeId: persistence.threadId, + }; + } +} diff --git a/packages/@n8n/agents/src/runtime/memory-store.ts b/packages/@n8n/agents/src/runtime/memory/memory-store.ts similarity index 98% rename from packages/@n8n/agents/src/runtime/memory-store.ts rename to packages/@n8n/agents/src/runtime/memory/memory-store.ts index f7a0e2318e2..44ead5d46bd 100644 --- a/packages/@n8n/agents/src/runtime/memory-store.ts +++ b/packages/@n8n/agents/src/runtime/memory/memory-store.ts @@ -27,10 +27,10 @@ import type { NewEpisodicMemoryEntrySourceForEntry, RetrievedEpisodicMemoryEntry, Thread, -} from '../types'; -import type { AgentDbMessage } from '../types/sdk/message'; -import type { ObservationCursor } from '../types/sdk/observation'; -import { estimateObservationTokens } from '../types/sdk/observation-log'; +} from '../../types'; +import type { AgentDbMessage } from '../../types/sdk/message'; +import type { ObservationCursor } from '../../types/sdk/observation'; +import { estimateObservationTokens } from '../../types/sdk/observation-log'; import type { BuiltObservationLogStore, BuiltObservationLogTaskLockStore, @@ -42,7 +42,7 @@ import type { ObservationLogScope, ObservationLogTaskKind, ObservationLogTaskLockHandle, -} from '../types/sdk/observation-log'; +} from '../../types/sdk/observation-log'; interface StoredMessage { message: AgentDbMessage; diff --git a/packages/@n8n/agents/src/runtime/observation-log-defaults.ts b/packages/@n8n/agents/src/runtime/memory/observation-log-defaults.ts similarity index 97% rename from packages/@n8n/agents/src/runtime/observation-log-defaults.ts rename to packages/@n8n/agents/src/runtime/memory/observation-log-defaults.ts index 63a4335e466..d5377d9d6d3 100644 --- a/packages/@n8n/agents/src/runtime/observation-log-defaults.ts +++ b/packages/@n8n/agents/src/runtime/memory/observation-log-defaults.ts @@ -1,6 +1,3 @@ -import { incrementTokenCountFromUsage } from './execution-counter'; -import { loadAi } from './lazy-ai'; -import { createModel } from './model-factory'; import type { ObservationLogObserveFn, ObservationLogObserverInput, @@ -9,7 +6,10 @@ import type { ObservationLogReflectFn, ObservationLogReflectorInput, } from './observation-log-reflector'; -import type { ModelConfig } from '../types/sdk/agent'; +import type { ModelConfig } from '../../types/sdk/agent'; +import { incrementTokenCountFromUsage } from '../loop/execution-counter'; +import { loadAi } from '../model/lazy-ai'; +import { createModel } from '../model/model-factory'; // Keep this low while runtime history is a floating message window: short but durable facts // should become observations before older messages are likely to fall out of prompt context. @@ -332,7 +332,7 @@ EXAMPLES Example 1: Log under budget. Return empty arrays. Input: -[obs_001] CRITICAL (14:30) User is migrating @n8n/agents from Mastra to internal SDK +[obs_001] CRITICAL (14:30) User is migrating the backend from REST to gRPC [obs_002] IMPORTANT (14:35) User adopted two-stage compression model (Observer + Reflector) Budget: 5000 tokens. Current: 600 tokens. @@ -421,13 +421,13 @@ BAD: Merging across topics. Input: [obs_001] CRITICAL User works at Acme -[obs_002] CRITICAL User is migrating @n8n/agents from Mastra +[obs_002] CRITICAL User is migrating the backend to gRPC Wrong merge: { "supersedes": ["obs_001", "obs_002"], "marker": "CRITICAL", - "text": "User works at Acme and is migrating @n8n/agents from Mastra" + "text": "User works at Acme and is migrating the backend to gRPC" } These are about different topics. Do NOT merge them. Leave both as separate observations. diff --git a/packages/@n8n/agents/src/runtime/observation-log-observer.ts b/packages/@n8n/agents/src/runtime/memory/observation-log-observer.ts similarity index 96% rename from packages/@n8n/agents/src/runtime/observation-log-observer.ts rename to packages/@n8n/agents/src/runtime/memory/observation-log-observer.ts index 9fe7746be38..92fedcb2256 100644 --- a/packages/@n8n/agents/src/runtime/observation-log-observer.ts +++ b/packages/@n8n/agents/src/runtime/memory/observation-log-observer.ts @@ -1,8 +1,8 @@ import { renderObservationLog } from './observation-log-renderer'; -import type { AgentExecutionCounter } from '../types/sdk/agent'; -import type { BuiltMemory } from '../types/sdk/memory'; -import type { AgentDbMessage, ContentToolCall, Message } from '../types/sdk/message'; -import type { ObservationCursor } from '../types/sdk/observation'; +import type { AgentExecutionCounter } from '../../types/sdk/agent'; +import type { BuiltMemory } from '../../types/sdk/memory'; +import type { AgentDbMessage, ContentToolCall, Message } from '../../types/sdk/message'; +import type { ObservationCursor } from '../../types/sdk/observation'; import type { BuiltObservationLogStore, ObservationLogEntry, @@ -10,8 +10,8 @@ import type { ObservationLogObserveFn, ObservationLogObserverInput, TokenCounter, -} from '../types/sdk/observation-log'; -import { estimateObservationTokens } from '../types/sdk/observation-log'; +} from '../../types/sdk/observation-log'; +import { estimateObservationTokens } from '../../types/sdk/observation-log'; export type { ObservationLogObserveFn, ObservationLogObserverInput }; diff --git a/packages/@n8n/agents/src/runtime/observation-log-reflector.ts b/packages/@n8n/agents/src/runtime/memory/observation-log-reflector.ts similarity index 98% rename from packages/@n8n/agents/src/runtime/observation-log-reflector.ts rename to packages/@n8n/agents/src/runtime/memory/observation-log-reflector.ts index abb64a9a514..fb418400017 100644 --- a/packages/@n8n/agents/src/runtime/observation-log-reflector.ts +++ b/packages/@n8n/agents/src/runtime/memory/observation-log-reflector.ts @@ -1,5 +1,5 @@ import { uniqueStrings } from './memory-lifecycle'; -import type { AgentExecutionCounter } from '../types/sdk/agent'; +import type { AgentExecutionCounter } from '../../types/sdk/agent'; import type { BuiltObservationLogStore, ObservationLogEntry, @@ -10,8 +10,8 @@ import type { ObservationLogReflection, ObservationLogReflectionResult, TokenCounter, -} from '../types/sdk/observation-log'; -import { estimateObservationTokens } from '../types/sdk/observation-log'; +} from '../../types/sdk/observation-log'; +import { estimateObservationTokens } from '../../types/sdk/observation-log'; export type { ObservationLogReflectFn, ObservationLogReflectorInput }; diff --git a/packages/@n8n/agents/src/runtime/observation-log-renderer.ts b/packages/@n8n/agents/src/runtime/memory/observation-log-renderer.ts similarity index 96% rename from packages/@n8n/agents/src/runtime/observation-log-renderer.ts rename to packages/@n8n/agents/src/runtime/memory/observation-log-renderer.ts index df8d2a94106..b36e1f0a8b8 100644 --- a/packages/@n8n/agents/src/runtime/observation-log-renderer.ts +++ b/packages/@n8n/agents/src/runtime/memory/observation-log-renderer.ts @@ -2,8 +2,8 @@ import type { ObservationLogEntry, ObservationLogMarker, TokenCounter, -} from '../types/sdk/observation-log'; -import { estimateObservationTokens } from '../types/sdk/observation-log'; +} from '../../types/sdk/observation-log'; +import { estimateObservationTokens } from '../../types/sdk/observation-log'; const MARKER_LABELS: Record<ObservationLogMarker, string> = { critical: 'CRITICAL', diff --git a/packages/@n8n/agents/src/runtime/observation-log-store.ts b/packages/@n8n/agents/src/runtime/memory/observation-log-store.ts similarity index 98% rename from packages/@n8n/agents/src/runtime/observation-log-store.ts rename to packages/@n8n/agents/src/runtime/memory/observation-log-store.ts index fcb9eceab2d..4743fa9e626 100644 --- a/packages/@n8n/agents/src/runtime/observation-log-store.ts +++ b/packages/@n8n/agents/src/runtime/memory/observation-log-store.ts @@ -2,7 +2,7 @@ import type { BuiltMemory, BuiltObservationLogStore, BuiltObservationLogTaskLockStore, -} from '../types'; +} from '../../types'; const OBSERVATION_LOG_STORE_METHODS = [ 'appendObservationLogEntries', diff --git a/packages/@n8n/agents/src/runtime/scoped-memory-task-runner.ts b/packages/@n8n/agents/src/runtime/memory/scoped-memory-task-runner.ts similarity index 98% rename from packages/@n8n/agents/src/runtime/scoped-memory-task-runner.ts rename to packages/@n8n/agents/src/runtime/memory/scoped-memory-task-runner.ts index 040eb7572ee..f69faa83fb1 100644 --- a/packages/@n8n/agents/src/runtime/scoped-memory-task-runner.ts +++ b/packages/@n8n/agents/src/runtime/memory/scoped-memory-task-runner.ts @@ -1,9 +1,9 @@ -import { BackgroundTaskTracker } from './background-task-tracker'; import type { BuiltObservationLogTaskLockStore, ObservationLogTaskKind, ObservationLogTaskLockHandle, -} from '../types/sdk/observation-log'; +} from '../../types/sdk/observation-log'; +import { BackgroundTaskTracker } from '../state/background-task-tracker'; const DEFAULT_LOCK_TTL_MS = 30_000; const DEFAULT_MAX_CAPTURED_ERRORS = 50; diff --git a/packages/@n8n/agents/src/runtime/strip-orphaned-tool-messages.ts b/packages/@n8n/agents/src/runtime/memory/strip-orphaned-tool-messages.ts similarity index 87% rename from packages/@n8n/agents/src/runtime/strip-orphaned-tool-messages.ts rename to packages/@n8n/agents/src/runtime/memory/strip-orphaned-tool-messages.ts index 9a115f442fe..36bbade0f33 100644 --- a/packages/@n8n/agents/src/runtime/strip-orphaned-tool-messages.ts +++ b/packages/@n8n/agents/src/runtime/memory/strip-orphaned-tool-messages.ts @@ -1,5 +1,5 @@ -import { isLlmMessage } from '../sdk/message'; -import type { AgentMessage, MessageContent } from '../types/sdk/message'; +import { isLlmMessage } from '../../sdk/message'; +import type { AgentMessage, MessageContent } from '../../types/sdk/message'; /** * Strip pending tool-call blocks from a message list before sending to the LLM. diff --git a/packages/@n8n/agents/src/runtime/title-generation.ts b/packages/@n8n/agents/src/runtime/memory/title-generation.ts similarity index 93% rename from packages/@n8n/agents/src/runtime/title-generation.ts rename to packages/@n8n/agents/src/runtime/memory/title-generation.ts index ca22780854d..9b03f0b9d9a 100644 --- a/packages/@n8n/agents/src/runtime/title-generation.ts +++ b/packages/@n8n/agents/src/runtime/memory/title-generation.ts @@ -1,12 +1,12 @@ import type { LanguageModel } from 'ai'; -import { incrementTokenCountFromUsage } from './execution-counter'; -import { loadAi } from './lazy-ai'; -import type { BuiltMemory, BuiltTelemetry, TitleGenerationConfig } from '../types'; -import { createFilteredLogger } from './logger'; -import { createModel } from './model-factory'; -import type { AgentExecutionCounter, ModelConfig } from '../types/sdk/agent'; -import type { AgentDbMessage } from '../types/sdk/message'; +import type { BuiltMemory, BuiltTelemetry, TitleGenerationConfig } from '../../types'; +import type { AgentExecutionCounter, ModelConfig } from '../../types/sdk/agent'; +import type { AgentDbMessage } from '../../types/sdk/message'; +import { createFilteredLogger } from '../logger'; +import { incrementTokenCountFromUsage } from '../loop/execution-counter'; +import { loadAi } from '../model/lazy-ai'; +import { createModel } from '../model/model-factory'; const logger = createFilteredLogger(); @@ -134,8 +134,8 @@ export async function generateTitleFromMessage( const result = await loadAi().generateText({ model, + system: opts?.instructions ?? DEFAULT_TITLE_INSTRUCTIONS, messages: [ - { role: 'system', content: opts?.instructions ?? DEFAULT_TITLE_INSTRUCTIONS }, { role: 'user', content: `Generate a title for the following first message of a conversation. Do not answer the message — only produce the title.\n\n<message>\n${trimmed}\n</message>`, @@ -173,12 +173,16 @@ export async function generateTitleAndEmojiFromMessage( return null; } + const wrappedMessage = ` +Here's the conversation: +<conversation> +${trimmed} +</conversation>`; + const result = await loadAi().generateText({ model, - messages: [ - { role: 'system', content: opts?.instructions ?? DEFAULT_TITLE_AND_EMOJI_INSTRUCTIONS }, - { role: 'user', content: trimmed }, - ], + system: opts?.instructions ?? DEFAULT_TITLE_AND_EMOJI_INSTRUCTIONS, + messages: [{ role: 'user', content: wrappedMessage }], }); incrementTokenCountFromUsage(opts?.executionCounter, result.usage); diff --git a/packages/@n8n/agents/src/runtime/lazy-ai.ts b/packages/@n8n/agents/src/runtime/model/lazy-ai.ts similarity index 100% rename from packages/@n8n/agents/src/runtime/lazy-ai.ts rename to packages/@n8n/agents/src/runtime/model/lazy-ai.ts diff --git a/packages/@n8n/agents/src/runtime/message-list.ts b/packages/@n8n/agents/src/runtime/model/message-list.ts similarity index 90% rename from packages/@n8n/agents/src/runtime/message-list.ts rename to packages/@n8n/agents/src/runtime/model/message-list.ts index d379815cf2c..e1a0a7dd02c 100644 --- a/packages/@n8n/agents/src/runtime/message-list.ts +++ b/packages/@n8n/agents/src/runtime/model/message-list.ts @@ -1,16 +1,21 @@ import type { ProviderOptions } from '@ai-sdk/provider-utils'; -import type { ModelMessage } from 'ai'; +import type { ModelMessage, SystemModelMessage } from 'ai'; import { toAiMessages } from './messages'; -import { stringifyError } from './runtime-helpers'; -import { stripOrphanedToolMessages } from './strip-orphaned-tool-messages'; -import { filterLlmMessages, getCreatedAt } from '../sdk/message'; -import type { SerializedMessageList } from '../types/runtime/message-list'; -import type { AgentDbMessage, AgentMessage, ContentToolCall } from '../types/sdk/message'; -import type { JSONValue } from '../types/utils/json'; +import { filterLlmMessages, getCreatedAt } from '../../sdk/message'; +import type { SerializedMessageList } from '../../types/runtime/message-list'; +import type { AgentDbMessage, AgentMessage, ContentToolCall } from '../../types/sdk/message'; +import type { JSONValue } from '../../types/utils/json'; +import { stringifyError } from '../loop/runtime-helpers'; +import { stripOrphanedToolMessages } from '../memory/strip-orphaned-tool-messages'; export type { SerializedMessageList }; +export type LlmContext = { + system: SystemModelMessage; + messages: ModelMessage[]; +}; + type MessageSource = 'history' | 'input' | 'response'; /** @@ -220,10 +225,10 @@ export class AgentMessageList { /** * Full LLM context for a generateText / streamText call. - * Prepends the system prompt (with observation-log memory appended if configured), - * strips custom messages via filterLlmMessages. + * Returns the system prompt separately (with observation-log memory appended if configured) + * and conversation messages stripped via filterLlmMessages. */ - forLlm(baseInstructions: string, instructionProviderOptions?: ProviderOptions): ModelMessage[] { + forLlm(baseInstructions: string, instructionProviderOptions?: ProviderOptions): LlmContext { let systemPrompt = baseInstructions; const observationLogMemory = this.observationLogMemory?.trim(); @@ -231,10 +236,16 @@ export class AgentMessageList { systemPrompt += `\n\n${observationLogMemory}`; } - const systemMessage: ModelMessage = instructionProviderOptions - ? { role: 'system', content: systemPrompt, providerOptions: instructionProviderOptions } - : { role: 'system', content: systemPrompt }; - return [systemMessage, ...toAiMessages(filterLlmMessages(stripOrphanedToolMessages(this.all)))]; + const system: SystemModelMessage = { + role: 'system', + content: systemPrompt, + ...(instructionProviderOptions ? { providerOptions: instructionProviderOptions } : {}), + }; + + return { + system, + messages: toAiMessages(filterLlmMessages(stripOrphanedToolMessages(this.all))), + }; } /** diff --git a/packages/@n8n/agents/src/runtime/messages.ts b/packages/@n8n/agents/src/runtime/model/messages.ts similarity index 87% rename from packages/@n8n/agents/src/runtime/messages.ts rename to packages/@n8n/agents/src/runtime/model/messages.ts index 289e1508845..8d4f4dd8e1a 100644 --- a/packages/@n8n/agents/src/runtime/messages.ts +++ b/packages/@n8n/agents/src/runtime/model/messages.ts @@ -10,7 +10,7 @@ import type { FinishReason as AiFinishReason, } from 'ai'; -import type { FinishReason } from '../types'; +import type { FinishReason } from '../../types'; import type { AgentMessage, ContentFile, @@ -19,8 +19,8 @@ import type { ContentToolCall, Message, MessageContent, -} from '../types/sdk/message'; -import type { JSONValue } from '../types/utils/json'; +} from '../../types/sdk/message'; +import type { JSONObject, JSONValue } from '../../types/utils/json'; /** Reasoning content part — mirrors @ai-sdk/provider-utils ReasoningPart (not re-exported by 'ai'). */ type ReasoningPart = { type: 'reasoning'; text: string }; @@ -53,25 +53,57 @@ function isToolCall(block: MessageContent): block is ContentToolCall { return block.type === 'tool-call'; } -/** - * Parse a JSONValue that may be a stringified JSON object back into - * its parsed form. Non-string values pass through unchanged. - */ -function parseJsonValue(value: JSONValue): unknown { +type ToolInputNormalizationResult = + | { ok: true; input: JSONObject } + | { ok: false; input: JSONObject; error: string }; + +function describeValue(value: unknown): string { + if (Array.isArray(value)) return 'array'; + if (value === null) return 'null'; + return typeof value; +} + +export function normalizeToolInputForModel(value: unknown): ToolInputNormalizationResult { if (typeof value === 'string') { try { - return JSON.parse(value); + const parsed: unknown = JSON.parse(value); + if (isJsonObject(parsed)) return { ok: true, input: parsed }; + return { + ok: false, + input: {}, + error: `Tool input must be a JSON object, got ${describeValue(parsed)}.`, + }; } catch { - return value; + return { + ok: false, + input: {}, + error: 'Tool input must be a valid JSON object string.', + }; } } - return value; + + if (isJsonObject(value)) return { ok: true, input: value }; + if (value === null || value === undefined) return { ok: true, input: {} }; + + return { + ok: false, + input: {}, + error: `Tool input must be a JSON object, got ${describeValue(value)}.`, + }; +} + +function toToolInputObject(value: JSONValue): JSONObject { + return normalizeToolInputForModel(value).input; } function isRecord(value: unknown): value is Record<string, unknown> { return typeof value === 'object' && value !== null && !Array.isArray(value); } +function isJsonObject(value: unknown): value is JSONObject { + return isRecord(value); +} + function getRecord(value: unknown): Record<string, unknown> | undefined { return isRecord(value) ? value : undefined; } @@ -98,7 +130,7 @@ function toAiContent(block: MessageContent): AiContentPart | undefined { type: 'tool-call', toolCallId: block.toolCallId ?? '', toolName: block.toolName, - input: parseJsonValue(block.input), + input: toToolInputObject(block.input), providerExecuted: block.providerExecuted, }; } else if (isReasoning(block)) { @@ -177,16 +209,20 @@ function fromAiContent(part: AiContentPart): MessageContent | undefined { case 'reasoning': base = { type: 'reasoning', text: part.text }; break; - case 'tool-call': + case 'tool-call': { + const normalizedInput = normalizeToolInputForModel(part.input); base = { type: 'tool-call', toolCallId: part.toolCallId, toolName: part.toolName, - input: part.input as JSONValue, + input: normalizedInput.input, providerExecuted: part.providerExecuted, - state: 'pending', + ...(normalizedInput.ok + ? { state: 'pending' as const } + : { state: 'rejected' as const, error: normalizedInput.error }), }; break; + } case 'tool-result': return undefined; // Ignore these types, because HITL is handled by our runtime @@ -253,7 +289,7 @@ function toAiMessageList(msg: Message): ModelMessage[] { type: 'tool-call', toolCallId: block.toolCallId, toolName: block.toolName, - input: parseJsonValue(block.input), + input: toToolInputObject(block.input), providerExecuted: block.providerExecuted, }; // Replayed settled tool calls still need their original provider diff --git a/packages/@n8n/agents/src/runtime/model-factory.ts b/packages/@n8n/agents/src/runtime/model/model-factory.ts similarity index 99% rename from packages/@n8n/agents/src/runtime/model-factory.ts rename to packages/@n8n/agents/src/runtime/model/model-factory.ts index b6d8fa5e492..1fb7e61c650 100644 --- a/packages/@n8n/agents/src/runtime/model-factory.ts +++ b/packages/@n8n/agents/src/runtime/model/model-factory.ts @@ -8,7 +8,7 @@ import { type ProviderId, type ProviderCredentials, } from './provider-credentials'; -import type { ModelConfig } from '../types/sdk/agent'; +import type { ModelConfig } from '../../types/sdk/agent'; type FetchFn = typeof globalThis.fetch; type EmbeddingProviderOptions = { diff --git a/packages/@n8n/agents/src/runtime/provider-credentials.ts b/packages/@n8n/agents/src/runtime/model/provider-credentials.ts similarity index 100% rename from packages/@n8n/agents/src/runtime/provider-credentials.ts rename to packages/@n8n/agents/src/runtime/model/provider-credentials.ts diff --git a/packages/@n8n/agents/src/runtime/background-task-tracker.ts b/packages/@n8n/agents/src/runtime/state/background-task-tracker.ts similarity index 100% rename from packages/@n8n/agents/src/runtime/background-task-tracker.ts rename to packages/@n8n/agents/src/runtime/state/background-task-tracker.ts diff --git a/packages/@n8n/agents/src/runtime/event-bus.ts b/packages/@n8n/agents/src/runtime/state/event-bus.ts similarity index 54% rename from packages/@n8n/agents/src/runtime/event-bus.ts rename to packages/@n8n/agents/src/runtime/state/event-bus.ts index c44d002339e..ca71f16dbbb 100644 --- a/packages/@n8n/agents/src/runtime/event-bus.ts +++ b/packages/@n8n/agents/src/runtime/state/event-bus.ts @@ -1,5 +1,56 @@ -import { AgentEvent } from '../types/runtime/event'; -import type { AgentEventData, AgentEventHandler } from '../types/runtime/event'; +import { AgentEvent } from '../../types/runtime/event'; +import type { AgentEventData, AgentEventHandler } from '../../types/runtime/event'; + +export interface AgentAbortScope { + readonly signal: AbortSignal; + readonly isAborted: boolean; + abort(): void; + dispose(): void; +} + +class EventBusAbortScope implements AgentAbortScope { + private readonly controller = new AbortController(); + + private externalCleanup?: () => void; + + private disposed = false; + + constructor( + externalSignal: AbortSignal | undefined, + private readonly onDispose: (scope: EventBusAbortScope) => void, + ) { + if (!externalSignal) return; + + if (externalSignal.aborted) { + this.controller.abort(externalSignal.reason); + return; + } + + const onAbort = () => this.controller.abort(externalSignal.reason); + externalSignal.addEventListener('abort', onAbort, { once: true }); + this.externalCleanup = () => externalSignal.removeEventListener('abort', onAbort); + } + + get signal(): AbortSignal { + return this.controller.signal; + } + + get isAborted(): boolean { + return this.controller.signal.aborted; + } + + abort(): void { + this.controller.abort(); + } + + dispose(): void { + if (this.disposed) return; + this.disposed = true; + this.externalCleanup?.(); + this.externalCleanup = undefined; + this.onDispose(this); + } +} /** * Internal event bus for agent lifecycle events. @@ -13,8 +64,8 @@ import type { AgentEventData, AgentEventHandler } from '../types/runtime/event'; * in-flight HTTP requests are cancelled immediately when `abort()` is called, * rather than waiting for the current LLM call to finish. * - * A new controller is created for each run via `resetAbort()` so the same - * agent instance can be reused after cancellation. + * A new run-scoped controller is created for each run via `createAbortScope()` + * so overlapping runs do not replace each other's cancellation signal. */ export class AgentEventBus { private handlers = new Map<AgentEvent, Set<AgentEventHandler>>(); @@ -23,6 +74,8 @@ export class AgentEventBus { private externalCleanup?: () => void; + private abortScopes = new Set<EventBusAbortScope>(); + on(event: AgentEvent, handler: AgentEventHandler): void { let set = this.handlers.get(event); if (!set) { @@ -46,6 +99,17 @@ export class AgentEventBus { abort(): void { this.controller.abort(); + for (const scope of this.abortScopes) { + scope.abort(); + } + } + + createAbortScope(externalSignal?: AbortSignal): AgentAbortScope { + const scope = new EventBusAbortScope(externalSignal, (disposed) => { + this.abortScopes.delete(disposed); + }); + this.abortScopes.add(scope); + return scope; } /** @@ -83,13 +147,16 @@ export class AgentEventBus { } /** - * Remove the external AbortSignal listener registered by resetAbort(). - * Must be called when a per-run bus is retired so the listener does not - * accumulate on long-lived signals when runs complete without aborting. + * Remove external AbortSignal listeners registered by resetAbort() or active + * run scopes so listeners do not accumulate when runs complete without aborting. */ dispose(): void { this.externalCleanup?.(); this.externalCleanup = undefined; + for (const scope of [...this.abortScopes]) { + scope.dispose(); + } + this.abortScopes.clear(); } } diff --git a/packages/@n8n/agents/src/runtime/run-state.ts b/packages/@n8n/agents/src/runtime/state/run-state.ts similarity index 99% rename from packages/@n8n/agents/src/runtime/run-state.ts rename to packages/@n8n/agents/src/runtime/state/run-state.ts index 2ebbd1fcc30..5fc63b683cb 100644 --- a/packages/@n8n/agents/src/runtime/run-state.ts +++ b/packages/@n8n/agents/src/runtime/state/run-state.ts @@ -1,4 +1,4 @@ -import type { CheckpointStore, SerializableAgentState } from '../types'; +import type { CheckpointStore, SerializableAgentState } from '../../types'; /** * Default in-memory CheckpointStore implementation. diff --git a/packages/@n8n/agents/src/runtime/streaming/stream-session.ts b/packages/@n8n/agents/src/runtime/streaming/stream-session.ts new file mode 100644 index 00000000000..513c1aead75 --- /dev/null +++ b/packages/@n8n/agents/src/runtime/streaming/stream-session.ts @@ -0,0 +1,99 @@ +import { StreamWriterGuard } from './stream-writer-guard'; +import type { StreamChunk } from '../../types'; +import { AgentEvent } from '../../types/runtime/event'; +import type { AgentEventData } from '../../types/runtime/event'; +import type { ExecutionOptions, RunOptions } from '../../types/sdk/agent'; +import type { AgentAbortScope, AgentEventBus } from '../state/event-bus'; + +export interface StreamSessionDeps { + eventBus: AgentEventBus; + abortScope: AgentAbortScope; + runId: string; + options: (RunOptions & ExecutionOptions) | undefined; + /** Wrap the loop in the telemetry root span (bound `RuntimeTelemetry.withRootSpan`). */ + withRootSpan: <T>( + operation: 'generate' | 'stream', + options: ExecutionOptions | undefined, + runId: string, + fn: () => Promise<T>, + ) => Promise<T>; + /** Run the stream loop, writing chunks through the provided guard. */ + runLoop: (guard: StreamWriterGuard) => Promise<void>; + flushTelemetry: (options: ExecutionOptions | undefined) => Promise<void>; + cleanupRun: () => Promise<void>; + updateState: (status: 'failed' | 'cancelled') => void; + emitError: (error: unknown) => void; +} + +/** + * Owns the streaming run lifecycle: creates the `TransformStream`, bridges + * event-bus lifecycle events to chunks, runs the loop inside the telemetry root + * span, and guarantees a single shutdown (error/abort translation, listener + * cleanup, abort-scope disposal). Returns the readable side immediately while + * the loop runs in the background. + */ +export function startStreamSession(deps: StreamSessionDeps): ReadableStream<StreamChunk> { + const { readable, writable } = new TransformStream<StreamChunk, StreamChunk>(); + const guard = new StreamWriterGuard(writable.getWriter()); + + // Bridge tool-execution / sub-agent lifecycle events into the stream so + // consumers can show mid-flight indicators. Writes go through the guard, so + // they are safely dropped once the stream is closed. + const onToolExecutionStart = (data: AgentEventData): void => { + if (data.type !== AgentEvent.ToolExecutionStart) return; + void guard.write({ + type: 'tool-execution-start', + toolCallId: data.toolCallId, + toolName: data.toolName, + startTime: Date.now(), + }); + }; + const onToolExecutionEnd = (data: AgentEventData): void => { + if (data.type !== AgentEvent.ToolExecutionEnd) return; + void guard.write({ + type: 'tool-execution-end', + toolCallId: data.toolCallId, + toolName: data.toolName, + isError: data.isError, + endTime: Date.now(), + }); + }; + const onSubAgentStarted = (data: AgentEventData): void => { + if (data.type !== AgentEvent.SubAgentStarted) return; + const { type: _type, ...payload } = data; + void guard.write({ type: 'subagent-started', ...payload }); + }; + const onSubAgentCompleted = (data: AgentEventData): void => { + if (data.type !== AgentEvent.SubAgentCompleted) return; + const { type: _type, ...payload } = data; + void guard.write({ type: 'subagent-completed', ...payload }); + }; + + deps.eventBus.on(AgentEvent.ToolExecutionStart, onToolExecutionStart); + deps.eventBus.on(AgentEvent.ToolExecutionEnd, onToolExecutionEnd); + deps.eventBus.on(AgentEvent.SubAgentStarted, onSubAgentStarted); + deps.eventBus.on(AgentEvent.SubAgentCompleted, onSubAgentCompleted); + + deps + .withRootSpan('stream', deps.options, deps.runId, async () => await deps.runLoop(guard)) + .catch(async (error: unknown) => { + const isAbort = deps.abortScope.isAborted; + deps.updateState(isAbort ? 'cancelled' : 'failed'); + if (!isAbort) { + deps.emitError(error); + } + await deps.cleanupRun(); + await deps.flushTelemetry(deps.options); + await guard.fail(isAbort ? new Error('Agent run was aborted') : error); + }) + .finally(() => { + deps.eventBus.off(AgentEvent.ToolExecutionStart, onToolExecutionStart); + deps.eventBus.off(AgentEvent.ToolExecutionEnd, onToolExecutionEnd); + deps.eventBus.off(AgentEvent.SubAgentStarted, onSubAgentStarted); + deps.eventBus.off(AgentEvent.SubAgentCompleted, onSubAgentCompleted); + void guard.close(); + deps.abortScope.dispose(); + }); + + return readable; +} diff --git a/packages/@n8n/agents/src/runtime/streaming/stream-writer-guard.ts b/packages/@n8n/agents/src/runtime/streaming/stream-writer-guard.ts new file mode 100644 index 00000000000..66212492b81 --- /dev/null +++ b/packages/@n8n/agents/src/runtime/streaming/stream-writer-guard.ts @@ -0,0 +1,57 @@ +import type { FinishReason, StreamChunk } from '../../types'; + +/** + * Wraps a stream writer so the runtime has a single, idempotent shutdown path. + * + * - `write()` becomes a no-op once the stream is closed and never rejects, so a + * late chunk from an aborted/errored run cannot crash the loop. + * - `close()` and `fail()` are idempotent, removing the double-close / write- + * after-close hazards that came from the previous multiple close sites. + */ +export class StreamWriterGuard { + private closed = false; + + constructor(private readonly writer: WritableStreamDefaultWriter<StreamChunk>) { + writer.closed + .then(() => { + this.closed = true; + }) + .catch(() => {}); + } + + get isClosed(): boolean { + return this.closed; + } + + /** Write a chunk unless the stream is already closed. Never throws. */ + async write(chunk: StreamChunk): Promise<void> { + if (this.closed) return; + try { + await this.writer.write(chunk); + } catch { + // Downstream consumer is gone (cancelled/errored). Nothing useful to do. + } + } + + /** Close the stream exactly once. Never throws. */ + async close(): Promise<void> { + if (this.closed) return; + this.closed = true; + try { + await this.writer.close(); + } catch { + // Already errored/closed by the downstream side. + } + } + + /** + * Terminate the stream with an error: emit an `error` chunk and a terminal + * `finish` chunk, then close. Idempotent — a no-op if already closed. + */ + async fail(error: unknown, finishReason: FinishReason = 'error'): Promise<void> { + if (this.closed) return; + await this.write({ type: 'error', error }); + await this.write({ type: 'finish', finishReason }); + await this.close(); + } +} diff --git a/packages/@n8n/agents/src/runtime/stream.ts b/packages/@n8n/agents/src/runtime/streaming/stream.ts similarity index 96% rename from packages/@n8n/agents/src/runtime/stream.ts rename to packages/@n8n/agents/src/runtime/streaming/stream.ts index 35b9695c32c..e93a0d51c11 100644 --- a/packages/@n8n/agents/src/runtime/stream.ts +++ b/packages/@n8n/agents/src/runtime/streaming/stream.ts @@ -1,7 +1,7 @@ import type { TextStreamPart, ToolSet } from 'ai'; -import type { FinishReason, StreamChunk, TokenUsage } from '../types'; -import type { JSONValue } from '../types/utils/json'; +import type { FinishReason, StreamChunk, TokenUsage } from '../../types'; +import type { JSONValue } from '../../types/utils/json'; /** Map AI SDK v6 LanguageModelUsage to our TokenUsage type. */ export function toTokenUsage( diff --git a/packages/@n8n/agents/src/runtime/telemetry/runtime-telemetry.ts b/packages/@n8n/agents/src/runtime/telemetry/runtime-telemetry.ts new file mode 100644 index 00000000000..7dfb7120737 --- /dev/null +++ b/packages/@n8n/agents/src/runtime/telemetry/runtime-telemetry.ts @@ -0,0 +1,251 @@ +import type { TelemetrySettings } from 'ai'; +import { zodToJsonSchema } from 'zod-to-json-schema'; + +import { Telemetry } from '../../sdk/telemetry'; +import type { AttributeValue, BuiltProviderTool, BuiltTelemetry, BuiltTool } from '../../types'; +import type { ExecutionOptions } from '../../types/sdk/agent'; +import type { JSONValue } from '../../types/utils/json'; +import { isZodSchema } from '../../utils/zod'; +import type { AgentRuntimeConfig } from '../loop/agent-runtime'; + +interface TelemetrySpan { + end(): void; + recordException?(error: unknown): void; + setAttributes?(attributes: Record<string, AttributeValue>): void; + setStatus?(status: { code: number; message?: string }): void; +} + +interface ActiveSpanTracer { + startActiveSpan<T>( + name: string, + options: { attributes?: Record<string, AttributeValue> }, + fn: (span: TelemetrySpan) => T, + ): T; +} + +function isActiveSpanTracer(value: unknown): value is ActiveSpanTracer { + return ( + value !== null && + typeof value === 'object' && + typeof Reflect.get(value, 'startActiveSpan') === 'function' + ); +} + +function stringifyTelemetryValue(value: unknown): string | undefined { + try { + return JSON.stringify(value); + } catch { + return undefined; + } +} + +function getToolInputSchema(tool: BuiltTool | BuiltProviderTool): unknown { + if (!tool.inputSchema) { + return undefined; + } + + return isZodSchema(tool.inputSchema) ? zodToJsonSchema(tool.inputSchema) : tool.inputSchema; +} + +function summarizeToolForTelemetry(tool: BuiltTool): Record<string, unknown> { + return { + name: tool.name, + description: tool.description, + type: tool.mcpTool ? 'mcp' : 'local', + ...(tool.mcpServerName ? { mcp_server: tool.mcpServerName } : {}), + ...(tool.suspendSchema || tool.resumeSchema || tool.approval ? { approval: true } : {}), + ...(tool.inputSchema ? { input_schema: getToolInputSchema(tool) } : {}), + }; +} + +function summarizeProviderToolForTelemetry(tool: BuiltProviderTool): Record<string, unknown> { + const [provider] = tool.name.split('.'); + return { + name: tool.name, + provider, + type: 'provider', + args: tool.args, + ...(tool.inputSchema ? { input_schema: getToolInputSchema(tool) } : {}), + }; +} + +function buildAgentRootInputAttributes(config: AgentRuntimeConfig): Record<string, AttributeValue> { + const localTools = (config.tools ?? []).map(summarizeToolForTelemetry); + const providerTools = (config.providerTools ?? []).map(summarizeProviderToolForTelemetry); + const tools = [...localTools, ...providerTools]; + const toolNames = tools + .map((tool) => (typeof tool.name === 'string' ? tool.name : undefined)) + .filter((name): name is string => name !== undefined); + + const serialized = stringifyTelemetryValue({ + agent: config.name, + tool_count: tools.length, + tools, + }); + + return { + ...(toolNames.length > 0 ? { 'langsmith.metadata.available_tools': toolNames } : {}), + ...(serialized ? { 'gen_ai.prompt': serialized } : {}), + }; +} + +/** + * Owns all telemetry concerns for a single agent runtime: resolving the + * effective telemetry config, mapping it to the AI SDK's + * `experimental_telemetry` shape, building LangSmith/AI-SDK span attributes, + * and wrapping the generate/stream loops and tool calls in active spans. + * + * Keeps provider-specific attribute formatting out of the core loop. Holds a + * live reference to the runtime config so `setTelemetry()` mutations are seen. + */ +export class RuntimeTelemetry { + constructor(private readonly config: AgentRuntimeConfig) {} + + /** Resolve telemetry: own config wins, then inherited from options, then nothing. */ + resolve(options?: ExecutionOptions): BuiltTelemetry | undefined { + if (this.config.telemetry) return this.config.telemetry; + const inherited = options?.telemetry; + if (!inherited) return undefined; + return { ...inherited, functionId: this.config.name }; + } + + /** Best-effort flush of telemetry provider. Never throws. */ + async flush(options?: ExecutionOptions): Promise<void> { + await Telemetry.forceFlush(this.resolve(options)); + } + + /** Map resolved telemetry to AI SDK's experimental_telemetry shape. */ + buildTelemetryOptions(options?: ExecutionOptions): { + experimental_telemetry?: TelemetrySettings; + } { + const t = this.resolve(options); + if (!t?.enabled) return {}; + + return { + experimental_telemetry: { + isEnabled: true, + functionId: t.functionId ?? this.config.name, + metadata: t.metadata, + recordInputs: t.recordInputs, + recordOutputs: t.recordOutputs, + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-explicit-any + tracer: t.tracer as any, + integrations: t.integrations.length > 0 ? t.integrations : undefined, + }, + }; + } + + async withRootSpan<T>( + operation: 'generate' | 'stream', + options: ExecutionOptions | undefined, + runId: string, + fn: () => Promise<T>, + ): Promise<T> { + const t = this.resolve(options); + if (!t?.enabled || t.runtimeRootSpanEnabled === false || !isActiveSpanTracer(t.tracer)) { + return await fn(); + } + + const spanName = `${t.functionId ?? this.config.name}.${operation}`; + return await t.tracer.startActiveSpan( + spanName, + { attributes: this.buildTelemetryRootAttributes(t, spanName, runId) }, + async (span) => { + try { + return await fn(); + } catch (error) { + span.recordException?.(error); + span.setStatus?.({ code: 2, message: String(error) }); + throw error; + } finally { + span.end(); + } + }, + ); + } + + async withToolSpan<T>( + toolCallId: string, + toolName: string, + input: JSONValue, + t: BuiltTelemetry | undefined, + fn: () => Promise<T>, + ): Promise<T> { + if (!t?.enabled || !isActiveSpanTracer(t.tracer)) { + return await fn(); + } + + const shouldRecordInputs = t.recordInputs ?? true; + const inputValue = shouldRecordInputs ? stringifyTelemetryValue(input) : undefined; + + return await t.tracer.startActiveSpan( + 'ai.toolCall', + { + attributes: { + ...this.buildAiSdkOperationAttributes('ai.toolCall', t), + 'ai.toolCall.name': toolName, + 'ai.toolCall.id': toolCallId, + ...(inputValue !== undefined ? { 'ai.toolCall.args': inputValue } : {}), + }, + }, + async (span) => { + try { + const result = await fn(); + const shouldRecordOutputs = t.recordOutputs ?? true; + const outputValue = shouldRecordOutputs ? stringifyTelemetryValue(result) : undefined; + if (outputValue !== undefined) { + span.setAttributes?.({ 'ai.toolCall.result': outputValue }); + } + return result; + } catch (error) { + span.recordException?.(error); + span.setStatus?.({ code: 2, message: String(error) }); + throw error; + } finally { + span.end(); + } + }, + ); + } + + private buildTelemetryRootAttributes( + t: BuiltTelemetry, + spanName: string, + runId: string, + ): Record<string, AttributeValue> { + const metadataAttributes = this.buildTelemetryMetadataAttributes(t, 'langsmith.metadata'); + + return { + 'langsmith.traceable': 'true', + 'langsmith.trace.name': spanName, + 'langsmith.span.kind': 'chain', + 'langsmith.metadata.agent_name': this.config.name, + 'langsmith.metadata.agent_run_id': runId, + ...metadataAttributes, + ...buildAgentRootInputAttributes(this.config), + }; + } + + private buildTelemetryMetadataAttributes( + t: BuiltTelemetry, + prefix: string, + ): Record<string, AttributeValue> { + return Object.fromEntries( + Object.entries(t.metadata ?? {}).map(([key, value]) => [`${prefix}.${key}`, value]), + ); + } + + private buildAiSdkOperationAttributes( + operationId: string, + t: BuiltTelemetry, + ): Record<string, AttributeValue> { + const functionId = t.functionId ?? this.config.name; + return { + 'operation.name': `${operationId} ${functionId}`, + 'resource.name': functionId, + 'ai.operationId': operationId, + 'ai.telemetry.functionId': functionId, + ...this.buildTelemetryMetadataAttributes(t, 'ai.telemetry.metadata'), + }; + } +} diff --git a/packages/@n8n/agents/src/runtime/deferred-tool-manager.ts b/packages/@n8n/agents/src/runtime/tools/deferred-tool-manager.ts similarity index 98% rename from packages/@n8n/agents/src/runtime/deferred-tool-manager.ts rename to packages/@n8n/agents/src/runtime/tools/deferred-tool-manager.ts index 2f76c41bfac..8977f19d615 100644 --- a/packages/@n8n/agents/src/runtime/deferred-tool-manager.ts +++ b/packages/@n8n/agents/src/runtime/tools/deferred-tool-manager.ts @@ -1,7 +1,7 @@ import { z } from 'zod'; -import type { AgentDbMessage, ContentToolCall } from '../types/sdk/message'; -import type { BuiltTool } from '../types/sdk/tool'; +import type { AgentDbMessage, ContentToolCall } from '../../types/sdk/message'; +import type { BuiltTool } from '../../types/sdk/tool'; export const SEARCH_TOOLS_TOOL_NAME = 'search_tools'; export const LOAD_TOOL_TOOL_NAME = 'load_tool'; diff --git a/packages/@n8n/agents/src/runtime/delegate-sub-agent-tool.ts b/packages/@n8n/agents/src/runtime/tools/delegate-sub-agent-tool.ts similarity index 73% rename from packages/@n8n/agents/src/runtime/delegate-sub-agent-tool.ts rename to packages/@n8n/agents/src/runtime/tools/delegate-sub-agent-tool.ts index 73cd679326f..40695209403 100644 --- a/packages/@n8n/agents/src/runtime/delegate-sub-agent-tool.ts +++ b/packages/@n8n/agents/src/runtime/tools/delegate-sub-agent-tool.ts @@ -2,17 +2,23 @@ import { z } from 'zod'; import { withSdkOwnedBuiltInMetadata } from './sdk-owned-tool'; import { - assertSubAgentPolicyAllowsChildCount, createChildSubAgentTaskPath, + DEFAULT_SUB_AGENT_MAX_CHILDREN, type SubAgentTaskPath, type SubAgentTaskPathPolicy, } from './sub-agent-task-path'; -import { filterLlmMessages } from '../sdk/message'; -import { Tool } from '../sdk/tool'; -import { AgentEvent } from '../types/runtime/event'; -import type { FinishReason, GenerateResult, TokenUsage } from '../types/sdk/agent'; -import type { AgentMessage } from '../types/sdk/message'; -import type { BuiltTool, ToolContext } from '../types/sdk/tool'; +import { filterLlmMessages } from '../../sdk/message'; +import { Tool } from '../../sdk/tool'; +import { AgentEvent } from '../../types/runtime/event'; +import type { + AgentExecutionCounter, + FinishReason, + GenerateResult, + ModelConfig, + TokenUsage, +} from '../../types/sdk/agent'; +import type { AgentMessage } from '../../types/sdk/message'; +import type { BuiltProviderTool, BuiltTool, ToolContext } from '../../types/sdk/tool'; export const DELEGATE_SUB_AGENT_TOOL_NAME = 'delegate_subagent'; export const INLINE_SUB_AGENT_ID = 'inline'; @@ -21,6 +27,10 @@ export const DELEGATED_CHILD_SUSPEND_UNSUPPORTED_MESSAGE = 'agents.chat.delegate.childSuspendUnsupported'; export const INLINE_DELEGATE_SUB_AGENT_TOOL_METADATA_KEY = 'inlineDelegateSubAgent'; +export const SUB_AGENT_TASK_DIFFICULTIES = ['low', 'medium', 'high'] as const; +const SubAgentTaskDifficultySchema = z.enum(SUB_AGENT_TASK_DIFFICULTIES); +export type SubAgentTaskDifficulty = z.infer<typeof SubAgentTaskDifficultySchema>; + // Model-facing input: the arguments the LLM fills in when it calls the tool. // The `.describe(...)` text is what the model reads, so keep it task-oriented. const delegateSubAgentInputSchema = z.object({ @@ -42,6 +52,9 @@ const delegateSubAgentInputSchema = z.object({ 'All details the child needs, since it sees nothing else: constraints, paths, data, prior decisions, acceptance criteria, and what you have already tried or ruled out.', ), expectedOutput: z.string().optional().describe('The expected shape or contents of the answer.'), + difficulty: SubAgentTaskDifficultySchema.optional().describe( + 'Optional difficulty estimate for this delegated task. Use low for simple bounded work, medium for moderate analysis or implementation, and high for complex research, architecture, or multi-step reasoning.', + ), }); // Documents the tool result shape for typing/introspection. Note: the handler's @@ -52,6 +65,7 @@ const delegateSubAgentOutputSchema = z.object({ taskPath: z.string().optional(), runId: z.string().optional(), threadId: z.string().optional(), + model: z.string().optional(), answer: z.string(), structuredOutput: z.unknown().optional(), usage: z @@ -113,6 +127,8 @@ export interface DelegateSubAgentRequest extends DelegateSubAgentInput { * cancelling the parent run also cancels the delegated work. */ parentAbortSignal?: AbortSignal; + /** Parent aggregate execution counter (`ctx.executionCounter`) for inline child accounting. */ + parentExecutionCounter?: AgentExecutionCounter; /** How many siblings the parent already spawned before this one (0-based). */ childCount: number; /** Effective policy for this delegation. */ @@ -132,6 +148,8 @@ export interface DelegateSubAgentToolOutput { * re-supply it to continue the same thread on a later delegation. */ threadId?: string; + /** Effective child model id used for this delegation (e.g. `anthropic/claude-haiku-4-5`). */ + model?: string; /** The child's answer — the main payload the parent acts on. */ answer: string; structuredOutput?: unknown; @@ -149,7 +167,7 @@ export interface DelegateSubAgentToolOutput { * * You supply `runSubAgent` — the host callback that actually runs the child for * a delegation and returns its result. Everything else (input/output schema, - * system prompt, task-path bookkeeping, policy enforcement, and the + * system prompt, task-path bookkeeping, parallelism policy, and the * `subagent-started` / `-completed` lifecycle events) is owned by * the tool. */ @@ -158,10 +176,14 @@ export interface DelegateSubAgentToolOutput { * `subAgentId: "inline"` while reusing the SDK inline child runner implementation. */ export interface DelegateSubAgentRunnerHelpers { - /** Run a one-off inline child using the parent agent's inherited tool set. */ + /** Run a one-off inline child using the parent agent's inherited local/deferred tool set. */ runInlineSubAgent: (request: DelegateSubAgentRequest) => Promise<DelegateSubAgentToolOutput>; } +export type InlineSubAgentProviderToolsResolver = ( + modelConfig: ModelConfig, +) => BuiltProviderTool[] | Promise<BuiltProviderTool[]>; + export type DelegateSubAgentRunner = ( request: DelegateSubAgentRequest, helpers: DelegateSubAgentRunnerHelpers, @@ -173,10 +195,20 @@ export interface CreateDelegateSubAgentToolOptions { * model selects one by passing its id as `subAgentId`. */ availableSubAgents?: Array<{ id: string; name: string; description?: string }>; - /** Fan-out limits and spawn switch enforced before each delegation. */ + /** Parallelism limit for delegated child runs (also used as delegate_subagent batch size). */ policy?: DelegateSubAgentPolicy; /** Additional local/deferred tool names the host removes from inline children. */ inlineSubAgentBlockedTools?: string[]; + /** + * Resolved inline sub-agent models by task difficulty. Hosts map persisted config + * to runtime {@link ModelConfig} values before registering the delegate tool. + */ + inlineSubAgentModelsByDifficulty?: Partial<Record<SubAgentTaskDifficulty, ModelConfig>>; + /** + * Resolve provider-defined tools for an inline child after its model has been chosen. + * Inline children do not inherit parent provider tools. + */ + resolveInlineSubAgentProviderTools?: InlineSubAgentProviderToolsResolver; /** * Run the child for this delegation and return its result. When provided, the * host receives every `subAgentId` (including `"inline"`) and may call @@ -193,7 +225,7 @@ export type DelegateSubAgentToolMetadata = CreateDelegateSubAgentToolOptions; * * The tool owns the cross-cutting concerns: the model-facing input/output * schema, the description + system instruction that teach the LLM when/how to - * delegate, task-path bookkeeping, fan-out policy enforcement, and the + * delegate, task-path bookkeeping, parallelism policy, and the * `subagent-started` / `-completed` * lifecycle events. You only supply HOW to run the child, via `runSubAgent`. * @@ -201,12 +233,41 @@ export type DelegateSubAgentToolMetadata = CreateDelegateSubAgentToolOptions; * agent.tool(createDelegateSubAgentTool({ * runSubAgent: (request) => runner.run(request), * availableSubAgents, - * policy: { maxChildren: 5 }, + * policy: { maxChildren: 10 }, * })); */ +function resolveDelegateSubAgentPolicy( + policy: DelegateSubAgentPolicy | undefined, +): DelegateSubAgentPolicy { + const resolvedPolicy = { + ...policy, + maxChildren: policy?.maxChildren ?? DEFAULT_SUB_AGENT_MAX_CHILDREN, + }; + + if ( + !Number.isFinite(resolvedPolicy.maxChildren) || + !Number.isInteger(resolvedPolicy.maxChildren) + ) { + throw new Error('delegate_subagent policy.maxChildren must be a finite positive integer'); + } + + if (resolvedPolicy.maxChildren < 1) { + throw new Error('delegate_subagent policy.maxChildren must be at least 1'); + } + + return resolvedPolicy; +} + export function createDelegateSubAgentTool(options: CreateDelegateSubAgentToolOptions = {}) { - // Per-parent fan-out counter keyed by run/thread/task — drives maxChildren. - const childCounts = new Map<string, number>(); + // Per-parent child path index for stable task paths (/root/name_0, /root/name_1, ...). + const childPathIndexes = new Map<string, number>(); + const resolvedOptions: CreateDelegateSubAgentToolOptions = { + ...options, + policy: resolveDelegateSubAgentPolicy(options.policy), + }; + const inlineProviderToolInstruction = resolvedOptions.resolveInlineSubAgentProviderTools + ? "Provider-defined tools are loaded for the inline child's selected model provider." + : 'Inline children do not inherit provider-defined tools.'; const tool = new Tool(DELEGATE_SUB_AGENT_TOOL_NAME) .description( @@ -216,17 +277,21 @@ export function createDelegateSubAgentTool(options: CreateDelegateSubAgentToolOp ) .systemInstruction( [ - 'delegate_subagent runs a focused child agent in a fresh, isolated context and returns only its final answer. Always set subAgentId. Use subAgentId: "inline" to run a one-off inline child that inherits your available tools after safety filtering. The child cannot see this conversation or your memory, so everything it needs must be in the call.', + `delegate_subagent runs a focused child agent in a fresh, isolated context and returns only its final answer. Always set subAgentId. Use subAgentId: "inline" to run a one-off inline child that inherits your local and deferred tools after safety filtering. ${inlineProviderToolInstruction} The child cannot see this conversation or your memory, so everything it needs must be in the call.`, 'Use a configured subagent ID only when one is listed and its name/description fits the subtask better than a generic inline child.', - ...formatAvailableSubAgents(options.availableSubAgents), + ...formatAvailableSubAgents(resolvedOptions.availableSubAgents), + ...formatDelegationPolicyInstructions(resolvedOptions.policy), 'WHEN TO USE delegate_subagent:\n- The request decomposes into 2+ independent workstreams that can be handled separately.\n- A workstream needs substantial research, review, comparison, or analysis.\n- Doing the work inline would flood your context with intermediate findings.\n- A fresh isolated perspective would materially improve a bounded subtask.', 'WHEN NOT TO USE delegate_subagent:\n- Single-step mechanical work: do it directly.\n- Trivial tasks or one/two tool calls: do them yourself.\n- Tasks that need user interaction or hidden conversation context.\n- Your core synthesis, final judgment, or recommendation.\n- The entire user request as one delegated task; that is pass-through with no value added.', - 'HOW TO DELEGATE:\n- Delegate bounded workstreams, not the final answer.\n- Pass all required context, constraints, language/tone, and expected output.\n- If multiple independent workstreams exist, delegate them separately.\n- Inline children inherit your available tools after safety filtering; you cannot change their tool set per delegation.\n- Inspect results and synthesize the final response yourself.\n- Verify side-effect claims before presenting them as done.', + `HOW TO DELEGATE:\n- Delegate bounded workstreams, not the final answer.\n- Pass all required context, constraints, language/tone, and expected output.\n- Set difficulty (low, medium, or high) when you can estimate task complexity; omit it to keep the default inline model.\n- If multiple independent workstreams exist, delegate them separately.\n- Inline children inherit your local and deferred tools after safety filtering. ${inlineProviderToolInstruction}\n- Inspect results and synthesize the final response yourself.\n- Verify side-effect claims before presenting them as done.`, ].join('\n'), ) .input(delegateSubAgentInputSchema) .output(delegateSubAgentOutputSchema) - .handler(async (input, ctx) => await handleDelegateSubAgent(input, ctx, options, childCounts)) + .handler( + async (input, ctx) => + await handleDelegateSubAgent(input, ctx, resolvedOptions, childPathIndexes), + ) .build(); return withSdkOwnedBuiltInMetadata({ @@ -234,14 +299,27 @@ export function createDelegateSubAgentTool(options: CreateDelegateSubAgentToolOp metadata: { ...tool.metadata, [INLINE_DELEGATE_SUB_AGENT_TOOL_METADATA_KEY]: { - ...(options.availableSubAgents !== undefined - ? { availableSubAgents: options.availableSubAgents } + ...(resolvedOptions.availableSubAgents !== undefined + ? { availableSubAgents: resolvedOptions.availableSubAgents } : {}), - ...(options.policy !== undefined ? { policy: options.policy } : {}), - ...(options.inlineSubAgentBlockedTools !== undefined - ? { inlineSubAgentBlockedTools: options.inlineSubAgentBlockedTools } + policy: resolvedOptions.policy, + ...(resolvedOptions.inlineSubAgentBlockedTools !== undefined + ? { inlineSubAgentBlockedTools: resolvedOptions.inlineSubAgentBlockedTools } + : {}), + ...(resolvedOptions.inlineSubAgentModelsByDifficulty !== undefined + ? { + inlineSubAgentModelsByDifficulty: resolvedOptions.inlineSubAgentModelsByDifficulty, + } + : {}), + ...(resolvedOptions.resolveInlineSubAgentProviderTools !== undefined + ? { + resolveInlineSubAgentProviderTools: + resolvedOptions.resolveInlineSubAgentProviderTools, + } + : {}), + ...(resolvedOptions.runSubAgent !== undefined + ? { runSubAgent: resolvedOptions.runSubAgent } : {}), - ...(options.runSubAgent !== undefined ? { runSubAgent: options.runSubAgent } : {}), } satisfies DelegateSubAgentToolMetadata, }, }); @@ -269,8 +347,22 @@ function formatAvailableSubAgents( ]; } +function formatDelegationPolicyInstructions(policy: DelegateSubAgentPolicy | undefined): string[] { + if (policy?.maxChildren === undefined) return []; + + const runLabel = policy.maxChildren === 1 ? 'run' : 'runs'; + return [ + [ + 'DELEGATION PARALLELISM:', + `- Up to ${policy.maxChildren} child sub-agent ${runLabel} can execute at the same time.`, + '- This limits parallelism, not the total number of delegated tasks.', + '- If more independent workstreams are useful, you may issue more delegate_subagent calls; the runtime will run them in batches.', + ].join('\n'), + ]; +} + /** - * Tool handler: enforce policy (fan-out), assign the child's task path, + * Tool handler: assign the child's task path, * assemble the {@link DelegateSubAgentRequest} from the model input plus the * parent tool context, then run the child via the host `runSubAgent` callback * while emitting started/progress/completed lifecycle events. Any error is @@ -281,23 +373,22 @@ async function handleDelegateSubAgent( input: DelegateSubAgentInput, ctx: ToolContext, options: CreateDelegateSubAgentToolOptions, - childCounts: Map<string, number>, + childPathIndexes: Map<string, number>, ): Promise<DelegateSubAgentToolOutput> { let taskPath: SubAgentTaskPath | undefined; let request: DelegateSubAgentRequest | undefined; let startedAt: number | undefined; try { - const childCountKey = getChildCountKey(ctx); - const childCount = childCounts.get(childCountKey) ?? 0; - assertSubAgentPolicyAllowsChildCount(childCount, options.policy); + const childPathIndexKey = getChildPathIndexKey(ctx); + const childPathIndex = childPathIndexes.get(childPathIndexKey) ?? 0; - taskPath = createChildSubAgentTaskPath(input.taskName, childCount); - childCounts.set(childCountKey, childCount + 1); + taskPath = createChildSubAgentTaskPath(input.taskName, childPathIndex); + childPathIndexes.set(childPathIndexKey, childPathIndex + 1); request = { ...input, taskPath, - childCount, + childCount: childPathIndex, ...(ctx.runId !== undefined ? { parentRunId: ctx.runId } : {}), ...(ctx.persistence?.threadId !== undefined ? { parentThreadId: ctx.persistence.threadId } @@ -307,6 +398,9 @@ async function handleDelegateSubAgent( : {}), ...(ctx.abortSignal !== undefined ? { parentAbortSignal: ctx.abortSignal } : {}), ...(ctx.toolCallId !== undefined ? { parentToolCallId: ctx.toolCallId } : {}), + ...(ctx.executionCounter !== undefined + ? { parentExecutionCounter: ctx.executionCounter } + : {}), ...(options.policy !== undefined ? { policy: options.policy } : {}), }; @@ -328,17 +422,14 @@ async function handleDelegateSubAgent( return output; } catch (error) { if (request !== undefined && startedAt !== undefined) { - emitSubAgentCompleted( - ctx, - request, - { - status: 'failed', - ...(taskPath !== undefined ? { taskPath } : {}), - answer: '', - error: stringifyUnknown(error), - }, - startedAt, - ); + const failedOutput: DelegateSubAgentToolOutput = { + status: 'failed', + ...(taskPath !== undefined ? { taskPath } : {}), + answer: '', + error: stringifyUnknown(error), + }; + emitSubAgentCompleted(ctx, request, failedOutput, startedAt); + return failedOutput; } return { status: 'failed', @@ -379,6 +470,7 @@ function emitSubAgentCompleted( ...(output.threadId !== undefined ? { threadId: output.threadId } : {}), ...(output.usage !== undefined ? { usage: output.usage } : {}), ...(output.finishReason !== undefined ? { finishReason: output.finishReason } : {}), + ...(output.model !== undefined ? { model: output.model } : {}), ...(output.error !== undefined ? { error: output.error } : {}), }); } @@ -395,7 +487,7 @@ function subAgentLifecycleBase(request: DelegateSubAgentRequest) { }; } -function getChildCountKey(ctx: ToolContext): string { +function getChildPathIndexKey(ctx: ToolContext): string { return ctx.runId ?? ctx.persistence?.threadId ?? ctx.persistence?.resourceId ?? 'adhoc'; } @@ -472,12 +564,14 @@ function resolveDelegateSubAgentStatus( /** Failed delegate output when a child run suspends for user input (not yet resumable). */ export function failedDelegatedChildSuspendOutput( taskPath: SubAgentTaskPath, + model?: string, ): DelegateSubAgentToolOutput { return { status: 'failed', taskPath, answer: '', error: DELEGATED_CHILD_SUSPEND_UNSUPPORTED_MESSAGE, + ...(model !== undefined ? { model } : {}), }; } @@ -493,6 +587,7 @@ export function generateResultToDelegateSubAgentOutput( taskPath, runId: result.runId, ...(threadId !== undefined ? { threadId } : {}), + ...(result.model !== undefined ? { model: result.model } : {}), answer: lastText(result.messages), ...(result.structuredOutput !== undefined ? { structuredOutput: result.structuredOutput } : {}), ...(result.usage !== undefined diff --git a/packages/@n8n/agents/src/runtime/fix-tool-call.ts b/packages/@n8n/agents/src/runtime/tools/fix-tool-call.ts similarity index 94% rename from packages/@n8n/agents/src/runtime/fix-tool-call.ts rename to packages/@n8n/agents/src/runtime/tools/fix-tool-call.ts index e861a8922ae..61aa701624a 100644 --- a/packages/@n8n/agents/src/runtime/fix-tool-call.ts +++ b/packages/@n8n/agents/src/runtime/tools/fix-tool-call.ts @@ -1,8 +1,8 @@ import type { ToolCall } from '@ai-sdk/provider-utils'; import type { InvalidToolInputError, NoSuchToolError, ToolCallRepairFunction, ToolSet } from 'ai'; -import type { BuiltTool } from '../types'; -import { isZodSchema } from '../utils/zod'; +import type { BuiltTool } from '../../types'; +import { isZodSchema } from '../../utils/zod'; const isZodEmptyObject = (schema: unknown) => { if (!isZodSchema(schema)) return false; diff --git a/packages/@n8n/agents/src/runtime/sdk-owned-tool.ts b/packages/@n8n/agents/src/runtime/tools/sdk-owned-tool.ts similarity index 88% rename from packages/@n8n/agents/src/runtime/sdk-owned-tool.ts rename to packages/@n8n/agents/src/runtime/tools/sdk-owned-tool.ts index b44f80dd3d3..424f51e774d 100644 --- a/packages/@n8n/agents/src/runtime/sdk-owned-tool.ts +++ b/packages/@n8n/agents/src/runtime/tools/sdk-owned-tool.ts @@ -1,4 +1,4 @@ -import type { BuiltTool } from '../types/sdk/tool'; +import type { BuiltTool } from '../../types/sdk/tool'; export const SDK_OWNED_BUILTIN_TOOL_METADATA_KEY = 'sdkOwnedBuiltinTool'; diff --git a/packages/@n8n/agents/src/runtime/sub-agent-task-path.ts b/packages/@n8n/agents/src/runtime/tools/sub-agent-task-path.ts similarity index 75% rename from packages/@n8n/agents/src/runtime/sub-agent-task-path.ts rename to packages/@n8n/agents/src/runtime/tools/sub-agent-task-path.ts index 925f8764fbe..c18b8332454 100644 --- a/packages/@n8n/agents/src/runtime/sub-agent-task-path.ts +++ b/packages/@n8n/agents/src/runtime/tools/sub-agent-task-path.ts @@ -14,9 +14,6 @@ * - Identity: each delegated unit of work gets a unique, traceable name we can * log and surface in the timeline — without the parent having to invent ids. * (Memory/session ids are independent — a run gets its own thread id.) - * - Policy enforcement: together with {@link SubAgentTaskPathPolicy}, the path - * lets us cap per-parent fan-out so a misbehaving agent can't spawn hundreds - * of parallel children, which would blow up cost, latency, and resources. * * Everything in this file is pure (no I/O, no n8n-specific concepts), which is * why it lives in the runtime SDK: it is shared verbatim by both the generic @@ -31,14 +28,17 @@ export type SubAgentTaskPath = '/root' | `/root/${string}`; /** - * Guardrails applied when a parent tries to spawn a child sub-agent. Every limit - * is optional; an undefined field means "no limit for that dimension". + * Policy fields related to sub-agent task paths and delegation parallelism. + * Every limit is optional at the call site; undefined fields use runtime defaults. */ export interface SubAgentTaskPathPolicy { - /** Maximum number of children a single parent may spawn. Bounds fan-out width. */ + /** Maximum number of child sub-agent runs that may execute in parallel. Defaults to {@link DEFAULT_SUB_AGENT_MAX_CHILDREN}. */ maxChildren?: number; } +/** Default parallel delegate batch width when none is configured. */ +export const DEFAULT_SUB_AGENT_MAX_CHILDREN = 10; + /** Path of the initiating (orchestrating) agent. */ export const ROOT_SUB_AGENT_TASK_PATH = '/root' satisfies SubAgentTaskPath; @@ -108,25 +108,3 @@ export function createChildSubAgentTaskPath( return childPath; } - -/** - * Fan-out-dimension gate, checked BEFORE a child is spawned. - * - * `childCount` is how many children the parent has ALREADY spawned. If that has - * reached `maxChildren`, spawning one more (the `+ 1` in the message is the - * would-be new total) exceeds the limit, so we reject. This stops a single agent - * from fanning out to an unbounded number of parallel sub-agents. When - * `maxChildren` is undefined, fan-out is unbounded. - */ -export function assertSubAgentPolicyAllowsChildCount( - childCount: number, - policy: SubAgentTaskPathPolicy | undefined, -): void { - if (policy?.maxChildren === undefined) return; - - if (childCount >= policy.maxChildren) { - throw new Error( - `Sub-agent child count ${childCount + 1} exceeds maxChildren ${policy.maxChildren}`, - ); - } -} diff --git a/packages/@n8n/agents/src/runtime/tool-adapter.ts b/packages/@n8n/agents/src/runtime/tools/tool-adapter.ts similarity index 89% rename from packages/@n8n/agents/src/runtime/tool-adapter.ts rename to packages/@n8n/agents/src/runtime/tools/tool-adapter.ts index 4f8adcfe3b8..68e869e2eb7 100644 --- a/packages/@n8n/agents/src/runtime/tool-adapter.ts +++ b/packages/@n8n/agents/src/runtime/tools/tool-adapter.ts @@ -1,9 +1,7 @@ import type { Tool as AiSdkTool } from 'ai'; -import type { JSONSchema7 } from 'json-schema'; import { z } from 'zod'; -import { loadAi } from './lazy-ai'; -import { isCancellation } from '../sdk/cancellation'; +import { isCancellation } from '../../sdk/cancellation'; import { type BuiltProviderTool, type BuiltTool, @@ -11,8 +9,10 @@ import { type InterruptibleToolContext, type ToolExecutionContext, type ToolContext, -} from '../types'; -import { isZodSchema } from '../utils/zod'; +} from '../../types'; +import { fixSchema } from '../../utils/json-schema'; +import { isZodSchema } from '../../utils/zod'; +import { loadAi } from '../model/lazy-ai'; type AiSdkProviderTool = AiSdkTool & { type: 'provider'; @@ -59,19 +59,6 @@ export function toAiSdkProviderTools(tools?: BuiltProviderTool[]): Record<string return result; } -const fixSchema = (schema: JSONSchema7): JSONSchema7 => { - // Ensure 'type: object' is present when properties are present (required by some providers): - if ( - typeof schema === 'object' && - schema !== null && - 'properties' in schema && - !('type' in schema) - ) { - return { ...schema, type: 'object' as const }; - } - return schema; -}; - /** * Convert an array of BuiltTools into a Record of AI SDK tool definitions. * Tools are created WITHOUT execute — the agent loop handles execution manually. @@ -133,6 +120,7 @@ export async function executeTool( persistence: executionContext.persistence, emitEvent: executionContext.emitEvent, abortSignal: executionContext.abortSignal, + executionCounter: executionContext.executionCounter, }; return await builtTool.handler(args, ctx); } @@ -144,6 +132,7 @@ export async function executeTool( persistence: executionContext.persistence, emitEvent: executionContext.emitEvent, abortSignal: executionContext.abortSignal, + executionCounter: executionContext.executionCounter, }; return await builtTool.handler(args, ctx); } diff --git a/packages/@n8n/agents/src/runtime/tools/tool-call-executor.ts b/packages/@n8n/agents/src/runtime/tools/tool-call-executor.ts new file mode 100644 index 00000000000..ca48ea6810d --- /dev/null +++ b/packages/@n8n/agents/src/runtime/tools/tool-call-executor.ts @@ -0,0 +1,819 @@ +import { zodToJsonSchema, type JsonSchema7Type } from 'zod-to-json-schema'; + +import { + DELEGATE_SUB_AGENT_TOOL_NAME, + getInlineDelegateSubAgentToolOptions, +} from './delegate-sub-agent-tool'; +import { toJsonValue } from '../json-value'; +import { DEFAULT_SUB_AGENT_MAX_CHILDREN } from './sub-agent-task-path'; +import { executeTool, isSuspendedToolResult, type SuspendedToolResult } from './tool-adapter'; +import { isCancellation } from '../../sdk/cancellation'; +import { isLlmMessage } from '../../sdk/message'; +import type { + AgentExecutionCounter, + BuiltTelemetry, + BuiltTool, + PendingToolCall, +} from '../../types'; +import { AgentEvent } from '../../types/runtime/event'; +import type { AgentPersistenceOptions, ToolResultEntry } from '../../types/sdk/agent'; +import type { AgentMessage, ContentToolCall, Message } from '../../types/sdk/message'; +import type { JSONObject, JSONValue } from '../../types/utils/json'; +import { parseWithSchema } from '../../utils/parse'; +import { isZodSchema } from '../../utils/zod'; +import { incrementToolCallCount } from '../loop/execution-counter'; +import type { AgentMessageList } from '../model/message-list'; +import { normalizeToolInputForModel } from '../model/messages'; +import type { AgentEventBus } from '../state/event-bus'; +import type { RuntimeTelemetry } from '../telemetry/runtime-telemetry'; + +/** Pending tool calls from a suspended run, passed into the loop to execute before the first LLM call. */ +export interface PendingResume { + pendingToolCalls: Record<string, PendingToolCall>; + /** The tool call being resumed with new data. */ + resumeToolCallId: string; + resumeData: unknown; +} + +type ToolCallOutcome = + | { + outcome: 'success'; + toolEntry: ToolResultEntry; + /** + * Output as the LLM sees it (after `toModelOutput`). Same as + * `toolEntry.output` when no `toModelOutput` transform is configured. + * Surfaced on the `tool-result` wire chunk so consumers see what the + * LLM saw (rather than the larger raw output). + */ + modelOutput: unknown; + customMessage?: AgentMessage; + } + | { + outcome: 'suspended'; + payload: unknown; + resumeSchema: JsonSchema7Type; + } + | { + outcome: 'cancelled'; + toolEntry: ToolResultEntry; + modelOutput: string; + userMessage: string; + canceled: true; + } + | { outcome: 'error'; error: unknown } + | { outcome: 'noop' }; // tool call shouldn't be saved or logged anywhere, usually means that if was executed by AI SDK + +/** A tool call that completed successfully. */ +export interface ToolCallSuccess { + toolCallId: string; + toolName: string; + input: JSONValue; + toolEntry: ToolResultEntry; + modelOutput: unknown; + customMessage?: AgentMessage; +} + +/** Info about a tool call that suspended (before persistence — no runId yet). */ +export interface ToolCallSuspension { + toolCallId: string; + toolName: string; + input: JSONValue; + payload: unknown; + /** JSON Schema describing the shape of resume data, derived from the tool's resumeSchema. */ + resumeSchema: JsonSchema7Type; +} + +/** Info about a tool call that failed — carries enough data for stream chunks. */ +export interface ToolCallError { + toolCallId: string; + toolName: string; + input: JSONValue; + error: unknown; +} + +/** Result of executing a batch of tool calls (before persistence). */ +export interface ToolCallBatchResult { + results: ToolCallSuccess[]; + suspensions: ToolCallSuspension[]; + errors: ToolCallError[]; + /** All items to persist: suspended tools (with suspendPayload) + unexecuted tools (without). */ + pending: Record<string, PendingToolCall>; +} + +interface RuntimeToolCall { + toolCallId: string; + toolName: string; + input: JSONObject; + providerExecuted?: boolean; +} + +/** Shared input for the tool-call batch iterators. */ +export interface ToolBatchContext { + toolMap: Map<string, BuiltTool>; + list: AgentMessageList; + runId: string; + persistence?: AgentPersistenceOptions; + telemetry?: BuiltTelemetry; + executionCounter?: AgentExecutionCounter; + abortSignal: AbortSignal; + isAborted: () => boolean; +} + +/** A tool-call content block that has already been settled by the AI SDK. */ +type SettledToolCall = ContentToolCall & { state: 'resolved' | 'rejected' }; + +/** Inputs for executing a single tool call. */ +interface ProcessToolCallParams { + toolCallId: string; + toolName: string; + input: JSONValue; + toolMap: Map<string, BuiltTool>; + list: AgentMessageList; + runId: string; + persistence?: AgentPersistenceOptions; + resumeData?: unknown; + resolvedTelemetry?: BuiltTelemetry; + executionCounter?: AgentExecutionCounter; + abortSignal?: AbortSignal; + /** Whether this counts as a new tool-call invocation. Default `true`; `false` on resume. */ + countToolCall?: boolean; +} + +function isDeniedApprovalResumeData(value: unknown): boolean { + return value !== null && typeof value === 'object' && Reflect.get(value, 'approved') === false; +} + +function shouldEmitToolExecutionStart(tool: BuiltTool, resumeData: unknown): boolean { + if (!tool.approval) return true; + if (!tool.approval.required && tool.approval.conditional !== true) return true; + if (resumeData === undefined) return false; + return !isDeniedApprovalResumeData(resumeData); +} + +function getToolResumeJsonSchema(tool: BuiltTool): JsonSchema7Type | undefined { + if (!tool.resumeSchema) return undefined; + return isZodSchema(tool.resumeSchema) ? zodToJsonSchema(tool.resumeSchema) : tool.resumeSchema; +} + +export interface ToolCallExecutorDeps { + telemetry: RuntimeTelemetry; + eventBus: AgentEventBus; + /** Effective tool-call concurrency (default 1 = sequential). */ + concurrency: number; + /** Invoked when a run is aborted mid-batch so the runtime can set cancelled state. */ + onCancelled: () => void; +} + +/** + * Executes a turn's tool calls: batches them by concurrency (with delegated + * sub-agent fan-out), runs each via the tool adapter, records results/errors on + * the message list, emits lifecycle events, and surfaces suspensions for the + * suspend/resume flow. Pure orchestration — persistence and stream/chunk + * emission are owned by the caller. + */ +export class ToolCallExecutor { + constructor(private readonly deps: ToolCallExecutorDeps) {} + + private get telemetry(): RuntimeTelemetry { + return this.deps.telemetry; + } + + private get eventBus(): AgentEventBus { + return this.deps.eventBus; + } + + private get concurrency(): number { + return this.deps.concurrency; + } + + private isDelegateSubAgentCall(toolName: string): boolean { + return toolName === DELEGATE_SUB_AGENT_TOOL_NAME; + } + + private getToolCallBatchSize(toolName: string, toolMap: Map<string, BuiltTool>): number { + if (!this.isDelegateSubAgentCall(toolName)) return this.concurrency; + + const tool = toolMap.get(toolName); + const delegateOptions = tool ? getInlineDelegateSubAgentToolOptions(tool) : undefined; + return delegateOptions?.policy?.maxChildren ?? DEFAULT_SUB_AGENT_MAX_CHILDREN; + } + + private takeNextToolCallBatch<T extends { toolName: string }>( + calls: T[], + start: number, + toolMap: Map<string, BuiltTool>, + ): T[] { + const first = calls[start]; + if (!first) { + throw new Error('Unable to build tool-call batch'); + } + + const isDelegateBatch = this.isDelegateSubAgentCall(first.toolName); + const batchSize = this.getToolCallBatchSize(first.toolName, toolMap); + if ( + batchSize < 1 || + Number.isNaN(batchSize) || + (isDelegateBatch && !Number.isFinite(batchSize)) + ) { + throw new Error(`Invalid tool-call batch size for ${first.toolName}: ${batchSize}`); + } + const batch: T[] = []; + + for (let i = start; i < calls.length && batch.length < batchSize; i++) { + const candidate = calls[i]; + if (this.isDelegateSubAgentCall(candidate.toolName) !== isDelegateBatch) break; + batch.push(candidate); + } + + return batch; + } + + /** + * Execute tool calls concurrently in batches. + * + * Regular tools use `toolCallConcurrency`. Consecutive `delegate_subagent` + * calls use the effective `maxChildren` policy from the built delegate tool. + * Provider-executed calls are skipped. + * + * Returns successes, suspension info, and a pending map (for persistence). + * The caller is responsible for persisting the pending map if non-empty. + * + * When any tool in a batch suspends, processing stops — unexecuted tools + * from later batches are added to the pending map without a `suspendPayload`. + * A Set of IDs tracks which tools have not yet been executed. + * + * Error handling: Promise.allSettled waits for all in-flight tools to finish + * even if one throws, then re-throws the first error. + */ + async iterateToolCallsConcurrent( + ctx: ToolBatchContext & { + toolCalls: Array<{ + toolCallId: string; + toolName: string; + input: unknown; + providerExecuted?: boolean; + }>; + }, + ): Promise<ToolCallBatchResult> { + const { + toolCalls, + toolMap, + list, + runId, + telemetry: resolvedTelemetry, + executionCounter, + abortSignal, + } = ctx; + const errors: ToolCallError[] = []; + const runtimeToolCalls: RuntimeToolCall[] = []; + + for (const toolCall of toolCalls) { + const normalizedInput = normalizeToolInputForModel(toolCall.input); + if (!normalizedInput.ok) { + const error = new Error(normalizedInput.error); + incrementToolCallCount(executionCounter); + list.setToolCallError(toolCall.toolCallId, error); + errors.push({ + toolCallId: toolCall.toolCallId, + toolName: toolCall.toolName, + input: normalizedInput.input, + error, + }); + continue; + } + + runtimeToolCalls.push({ ...toolCall, input: normalizedInput.input }); + } + + const executableCalls = runtimeToolCalls.filter((tc) => !tc.providerExecuted); + const providerExecutedCount = runtimeToolCalls.length - executableCalls.length; + for (let i = 0; i < providerExecutedCount; i++) { + incrementToolCallCount(executionCounter); + } + const executableCallsById = new Map(executableCalls.map((tc) => [tc.toolCallId, tc])); + const unexecutedIds = new Set(executableCalls.map((tc) => tc.toolCallId)); + const results: ToolCallSuccess[] = []; + const suspensions: ToolCallSuspension[] = []; + const pending: Record<string, PendingToolCall> = {}; + + for (let batchStart = 0; batchStart < executableCalls.length; ) { + if (ctx.isAborted()) { + this.deps.onCancelled(); + throw new Error('Agent run was aborted'); + } + + const batch = this.takeNextToolCallBatch(executableCalls, batchStart, toolMap); + batchStart += batch.length; + + const settledResults = await Promise.allSettled( + batch.map( + async (tc) => + await this.processToolCall({ + toolCallId: tc.toolCallId, + toolName: tc.toolName, + input: tc.input, + toolMap, + list, + runId, + persistence: ctx.persistence, + resolvedTelemetry, + executionCounter, + abortSignal, + countToolCall: true, + }), + ), + ); + + for (const tc of batch) { + unexecutedIds.delete(tc.toolCallId); + } + + let hasSuspension = false; + + for (let i = 0; i < settledResults.length; i++) { + const result = settledResults[i]; + const tc = batch[i]; + const toolInput = tc.input; + + if (result.status === 'rejected') { + list.setToolCallError(tc.toolCallId, result.reason); + errors.push({ + toolCallId: tc.toolCallId, + toolName: tc.toolName, + input: toolInput, + error: result.reason, + }); + } else if (result.value.outcome === 'suspended') { + hasSuspension = true; + suspensions.push({ + toolCallId: tc.toolCallId, + toolName: tc.toolName, + input: toolInput, + payload: result.value.payload, + resumeSchema: result.value.resumeSchema, + }); + pending[tc.toolCallId] = { + suspended: true, + toolCallId: tc.toolCallId, + toolName: tc.toolName, + input: toolInput, + suspendPayload: result.value.payload, + resumeSchema: result.value.resumeSchema, + runId, + }; + } else if (result.value.outcome === 'success') { + results.push({ + toolCallId: tc.toolCallId, + toolName: tc.toolName, + input: toolInput, + toolEntry: result.value.toolEntry, + modelOutput: result.value.modelOutput, + customMessage: result.value.customMessage, + }); + } else if (result.value.outcome === 'error') { + errors.push({ + toolCallId: tc.toolCallId, + toolName: tc.toolName, + input: toolInput, + error: result.value.error, + }); + } else if (result.value.outcome === 'noop') { + // noop + } + } + + if (hasSuspension) { + for (const id of unexecutedIds) { + const tc = executableCallsById.get(id)!; + pending[tc.toolCallId] = { + suspended: false, + toolCallId: tc.toolCallId, + toolName: tc.toolName, + input: tc.input, + }; + } + break; + } + } + + return { results, suspensions, errors, pending }; + } + + /** + * Resume flow: re-execute the targeted tool call, then process remaining items. + * + * 1. Execute the resumed tool (with `resumeData`). If it re-suspends, add to pending. + * 2. For remaining items: + * - Already suspended (has `suspendPayload`) → carry forward into pending. + * - Unexecuted (no `suspendPayload`) → execute via `iterateToolCallsConcurrent`. + * + * Returns a `ToolCallBatchResult` — the caller handles persistence. + */ + async iteratePendingToolCallsConcurrent( + ctx: ToolBatchContext & { pendingResume: PendingResume }, + ): Promise<ToolCallBatchResult> { + const { + pendingResume, + toolMap, + list, + runId, + persistence, + telemetry: resolvedTelemetry, + executionCounter, + abortSignal, + } = ctx; + const resumedId = pendingResume.resumeToolCallId; + const resumedEntry = pendingResume.pendingToolCalls[resumedId]; + if (!resumedEntry) { + throw new Error(`No pending tool call found for toolCallId: ${resumedId}`); + } + + const resumedToolName = resumedEntry.toolName; + const results: ToolCallSuccess[] = []; + const suspensions: ToolCallSuspension[] = []; + const errors: ToolCallError[] = []; + const pending: Record<string, PendingToolCall> = {}; + + // 1. Execute the resumed tool + const processResult = await this.processToolCall({ + toolCallId: resumedEntry.toolCallId, + toolName: resumedToolName, + input: resumedEntry.input, + toolMap, + list, + runId, + persistence, + resumeData: pendingResume.resumeData, + resolvedTelemetry, + executionCounter, + abortSignal, + countToolCall: false, + }); + + if (processResult.outcome === 'suspended') { + pending[resumedId] = { + ...resumedEntry, + suspended: true, + suspendPayload: processResult.payload, + resumeSchema: processResult.resumeSchema, + runId, + }; + suspensions.push({ + toolCallId: resumedId, + toolName: resumedToolName, + input: resumedEntry.input, + payload: processResult.payload, + resumeSchema: processResult.resumeSchema, + }); + } else if (processResult.outcome === 'success') { + results.push({ + toolCallId: resumedEntry.toolCallId, + toolName: resumedToolName, + input: resumedEntry.input, + toolEntry: processResult.toolEntry, + modelOutput: processResult.modelOutput, + customMessage: processResult.customMessage, + }); + } else if (processResult.outcome === 'cancelled') { + results.push({ + toolCallId: resumedEntry.toolCallId, + toolName: resumedToolName, + input: resumedEntry.input, + toolEntry: processResult.toolEntry, + modelOutput: processResult.modelOutput, + }); + list.addInput([ + { role: 'user', content: [{ type: 'text', text: processResult.userMessage }] }, + ]); + + for (const id of Object.keys(pendingResume.pendingToolCalls)) { + if (id !== resumedId) { + const siblingEntry = pendingResume.pendingToolCalls[id]; + const modelOutput = '[Skipped: a sibling tool call was cancelled]'; + list.setToolCallResult(id, modelOutput, { + canceled: true, + }); + results.push({ + toolCallId: siblingEntry.toolCallId, + toolName: siblingEntry.toolName, + input: siblingEntry.input, + toolEntry: { + tool: siblingEntry.toolName, + input: siblingEntry.input, + output: modelOutput, + transformed: false, + canceled: true, + }, + modelOutput, + }); + } + } + + return { results, suspensions, errors, pending }; + } else if (processResult.outcome === 'error') { + errors.push({ + toolCallId: resumedEntry.toolCallId, + toolName: resumedToolName, + input: resumedEntry.input, + error: processResult.error, + }); + } else if (processResult.outcome === 'noop') { + // noop + } + + // 2. Process remaining items + const unexecuted: Array<{ toolCallId: string; toolName: string; input: unknown }> = []; + + for (const [id, entry] of Object.entries(pendingResume.pendingToolCalls)) { + if (id === resumedId) continue; + + const entryToolName = entry.toolName; + + if (entry.suspended) { + // Already suspended — carry forward + pending[id] = entry; + suspensions.push({ + toolCallId: id, + toolName: entryToolName, + input: entry.input, + payload: entry.suspendPayload, + resumeSchema: entry.resumeSchema, + }); + } else { + // Unexecuted — collect for batch execution + unexecuted.push({ + toolCallId: id, + toolName: entryToolName, + input: entry.input, + }); + } + } + + // Execute unexecuted tools via iterateToolCallsConcurrent + if (unexecuted.length > 0) { + const batch = await this.iterateToolCallsConcurrent({ + toolCalls: unexecuted, + toolMap, + list, + runId, + persistence, + telemetry: resolvedTelemetry, + executionCounter, + abortSignal, + isAborted: ctx.isAborted, + }); + results.push(...batch.results); + suspensions.push(...batch.suspensions); + errors.push(...batch.errors); + Object.assign(pending, batch.pending); + } + + return { results, suspensions, errors, pending }; + } + + /** + * Execute a single tool call, emit lifecycle events, record the result in the + * message list, and return the outcome. The caller is responsible for writing + * any stream chunks and for handling suspension (building pendingToolCalls and + * persisting state). + * + * On tool execution errors, emits ToolExecutionEnd with isError=true, adds an + * error tool-result message to the list so the LLM can self-correct, and returns + * `{ outcome: 'error' }` — never re-throws. + */ + private async processToolCall(params: ProcessToolCallParams): Promise<ToolCallOutcome> { + const { toolName, toolMap, list, toolCallId, resumeData } = params; + const builtTool = toolMap.get(toolName); + + if (!builtTool) { + return this.toolError(params, new Error(`Tool ${toolName} not found`)); + } + + // Already settled by the AI SDK (e.g. provider-executed tools): emit the + // lifecycle end and skip re-execution. + const settledBlock = this.findSettledToolCall(list, toolCallId); + if (settledBlock) { + return this.completeSettledToolCall(params, settledBlock); + } + + if (isCancellation(resumeData) && !builtTool.handleCancellation) { + return this.buildCancelledOutcome(params, resumeData.message); + } + + if (params.countToolCall ?? true) { + incrementToolCallCount(params.executionCounter); + } + + const validation = await this.validateToolInput(params, builtTool); + if (!validation.ok) return validation.outcome; + const input = validation.input; + + if (shouldEmitToolExecutionStart(builtTool, resumeData)) { + this.eventBus.emit({ + type: AgentEvent.ToolExecutionStart, + toolCallId, + toolName, + args: input, + }); + } + + let toolResult: unknown; + try { + toolResult = await this.runToolHandler(params, builtTool, input); + } catch (error) { + return this.toolError(params, error as Error); + } + + if (isSuspendedToolResult(toolResult)) { + return await this.buildSuspendedOutcome(params, builtTool, toolResult); + } + + return this.buildSuccessOutcome(params, builtTool, input, toolResult); + } + + /** Emit a failed ToolExecutionEnd, record the error on the list, return an error outcome. */ + private toolError(params: ProcessToolCallParams, error: unknown): ToolCallOutcome { + this.eventBus.emit({ + type: AgentEvent.ToolExecutionEnd, + toolCallId: params.toolCallId, + toolName: params.toolName, + result: error, + isError: true, + }); + params.list.setToolCallError(params.toolCallId, error); + return { outcome: 'error', error }; + } + + /** Find an already-settled (resolved/rejected) tool-call block for this id, if any. */ + private findSettledToolCall( + list: AgentMessageList, + toolCallId: string, + ): SettledToolCall | undefined { + return list + .responseDelta() + .flatMap((m) => (isLlmMessage(m) && 'content' in m ? (m as Message).content : [])) + .find( + (c): c is SettledToolCall => + c.type === 'tool-call' && c.toolCallId === toolCallId && c.state !== 'pending', + ); + } + + /** Emit ToolExecutionEnd for a block the AI SDK already settled; the result was written earlier. */ + private completeSettledToolCall( + params: ProcessToolCallParams, + settledBlock: SettledToolCall, + ): ToolCallOutcome { + const settledResult = + settledBlock.state === 'resolved' ? settledBlock.output : settledBlock.error; + this.eventBus.emit({ + type: AgentEvent.ToolExecutionEnd, + toolCallId: params.toolCallId, + toolName: params.toolName, + result: settledResult, + isError: settledBlock.state === 'rejected', + }); + return { outcome: 'noop' }; + } + + /** Record a cancelled tool call (user declined / cancelled) and build its outcome. */ + private buildCancelledOutcome( + params: ProcessToolCallParams, + userMessage: string, + ): ToolCallOutcome { + const { toolCallId, toolName, input, list } = params; + const modelOutput = `[Tool call cancelled. User said: "${userMessage}"]`; + this.eventBus.emit({ + type: AgentEvent.ToolExecutionEnd, + toolCallId, + toolName, + result: modelOutput, + isError: false, + }); + list.setToolCallResult(toolCallId, modelOutput, { canceled: true }); + return { + outcome: 'cancelled', + toolEntry: { tool: toolName, input, output: modelOutput, transformed: false, canceled: true }, + modelOutput, + userMessage, + canceled: true, + }; + } + + /** Validate input against the tool's input schema (if any). */ + private async validateToolInput( + params: ProcessToolCallParams, + builtTool: BuiltTool, + ): Promise<{ ok: true; input: JSONValue } | { ok: false; outcome: ToolCallOutcome }> { + if (!builtTool.inputSchema) return { ok: true, input: params.input }; + const result = await parseWithSchema(builtTool.inputSchema, params.input); + if (!result.success) { + return { + ok: false, + outcome: this.toolError(params, new Error(`Invalid tool input: ${result.error}`)), + }; + } + return { ok: true, input: result.data as JSONValue }; + } + + /** Execute the tool handler inside a telemetry span. Throws on handler failure. */ + private async runToolHandler( + params: ProcessToolCallParams, + builtTool: BuiltTool, + input: JSONValue, + ): Promise<unknown> { + const { + toolCallId, + toolName, + runId, + persistence, + resumeData, + resolvedTelemetry, + executionCounter, + abortSignal, + } = params; + return await this.telemetry.withToolSpan( + toolCallId, + toolName, + input, + resolvedTelemetry, + async () => + await executeTool(input, builtTool, resumeData, resolvedTelemetry, toolCallId, { + runId, + persistence, + emitEvent: (event) => this.eventBus.emit(event), + abortSignal, + executionCounter, + }), + ); + } + + /** Validate a suspend payload + resume schema and build the suspended outcome. */ + private async buildSuspendedOutcome( + params: ProcessToolCallParams, + builtTool: BuiltTool, + toolResult: SuspendedToolResult, + ): Promise<ToolCallOutcome> { + if (builtTool.suspendSchema) { + const parseResult = await parseWithSchema(builtTool.suspendSchema, toolResult.payload); + if (!parseResult.success) { + return this.toolError(params, new Error(`Invalid suspend payload: ${parseResult.error}`)); + } + toolResult.payload = parseResult.data as JSONValue; + } + if (!builtTool.resumeSchema) { + return this.toolError(params, new Error(`Tool ${params.toolName} has no resume schema`)); + } + const resumeSchema = getToolResumeJsonSchema(builtTool); + if (!resumeSchema) { + return this.toolError(params, new Error('Invalid resume schema')); + } + return { outcome: 'suspended', payload: toolResult.payload, resumeSchema }; + } + + /** Apply toModelOutput, emit ToolExecutionEnd, build the success outcome. */ + private buildSuccessOutcome( + params: ProcessToolCallParams, + builtTool: BuiltTool, + input: JSONValue, + toolResult: unknown, + ): ToolCallOutcome { + const { toolCallId, toolName, list } = params; + + // Apply toModelOutput transform before emitting the success event. + // If the transform throws, treat it as a tool error so processToolCall + // never re-throws (preserving the "never re-throws" contract). + let modelResult: unknown; + try { + modelResult = builtTool.toModelOutput ? builtTool.toModelOutput(toolResult) : toolResult; + } catch (error) { + return this.toolError(params, error); + } + + this.eventBus.emit({ + type: AgentEvent.ToolExecutionEnd, + toolCallId, + toolName, + result: toolResult, + isError: false, + }); + + list.setToolCallResult(toolCallId, toJsonValue(modelResult)); + + const customMessage = builtTool.toMessage?.(toolResult); + if (customMessage) { + list.addResponse([customMessage]); + } + + return { + outcome: 'success', + toolEntry: { + tool: toolName, + input, + output: toolResult, + transformed: !!builtTool.toModelOutput, + }, + modelOutput: modelResult, + customMessage, + }; + } +} diff --git a/packages/@n8n/agents/src/runtime/write-todos-tool.ts b/packages/@n8n/agents/src/runtime/tools/write-todos-tool.ts similarity index 85% rename from packages/@n8n/agents/src/runtime/write-todos-tool.ts rename to packages/@n8n/agents/src/runtime/tools/write-todos-tool.ts index 7fad09b0c25..f6438232771 100644 --- a/packages/@n8n/agents/src/runtime/write-todos-tool.ts +++ b/packages/@n8n/agents/src/runtime/tools/write-todos-tool.ts @@ -1,13 +1,16 @@ import { z } from 'zod'; +import { SUB_AGENT_TASK_DIFFICULTIES } from './delegate-sub-agent-tool'; import { withSdkOwnedBuiltInMetadata } from './sdk-owned-tool'; -import { Tool } from '../sdk/tool'; -import type { BuiltTool } from '../types/sdk/tool'; +import { Tool } from '../../sdk/tool'; +import type { BuiltTool } from '../../types/sdk/tool'; export const WRITE_TODOS_TOOL_NAME = 'write_todos'; const todoStatusSchema = z.enum(['pending', 'in_progress', 'completed', 'blocked', 'cancelled']); +const todoDifficultySchema = z.enum(SUB_AGENT_TASK_DIFFICULTIES); + const todoDelegateHintSchema = z .object({ subAgentId: z @@ -27,6 +30,9 @@ const todoItemSchema = z.object({ id: z.string().min(1).describe('Stable identifier for this task within the current plan.'), content: z.string().min(1).describe('Concrete, self-contained task description.'), status: todoStatusSchema, + difficulty: todoDifficultySchema.describe( + 'Task difficulty: "low", "medium", or "high". Use the same value when delegating this task with delegate_subagent.', + ), delegateHint: todoDelegateHintSchema, }); @@ -72,8 +78,9 @@ const WRITE_TODOS_SYSTEM_INSTRUCTION = [ "- You would only create a todo list to restate the user's request.", 'HOW TO USE write_todos:', '- Write concrete, self-contained tasks, not vague phases.', + '- Assign difficulty to every task: low for simple mechanical or localized work, medium for normal implementation or review requiring judgment, high for complex, broad, ambiguous, or high-risk work.', '- Mark the first active task, or independent active tasks, as in_progress immediately.', - '- For sub-agent-worthy work, create one todo per bounded workstream, then call delegate_subagent separately for that task.', + '- For sub-agent-worthy work, create one todo per bounded workstream, then call delegate_subagent separately for that task; pass the same difficulty on the delegate call.', '- Do not delegate the entire user request as one task.', '- Update task status as soon as work completes; do not batch completions at the end.', '- Revise the list when new information changes the plan.', diff --git a/packages/@n8n/agents/src/sdk/__tests__/agent-isolated-runtime.test.ts b/packages/@n8n/agents/src/sdk/__tests__/agent-isolated-runtime.test.ts index d6fc1c06f44..2b8535f6d75 100644 --- a/packages/@n8n/agents/src/sdk/__tests__/agent-isolated-runtime.test.ts +++ b/packages/@n8n/agents/src/sdk/__tests__/agent-isolated-runtime.test.ts @@ -1,9 +1,9 @@ import * as aiModule from 'ai'; import type { Mock } from 'vitest'; -import type { AgentRuntimeConfig } from '../../runtime/agent-runtime'; -import type { AgentEventBus } from '../../runtime/event-bus'; -import { AgentEvent } from '../../runtime/event-bus'; +import type { AgentRuntimeConfig } from '../../runtime/loop/agent-runtime'; +import type { AgentEventBus } from '../../runtime/state/event-bus'; +import { AgentEvent } from '../../runtime/state/event-bus'; import type { StreamChunk } from '../../types'; import { Agent } from '../agent'; diff --git a/packages/@n8n/agents/src/sdk/__tests__/catalog.test.ts b/packages/@n8n/agents/src/sdk/__tests__/catalog.test.ts index 24dc26777b8..63e809edd28 100644 --- a/packages/@n8n/agents/src/sdk/__tests__/catalog.test.ts +++ b/packages/@n8n/agents/src/sdk/__tests__/catalog.test.ts @@ -70,4 +70,58 @@ describe('fetchProviderCatalog', () => { expect(catalog.azure).toBeUndefined(); expect(catalog['azure-cognitive-services']).toBeUndefined(); }); + + it('strips the "(latest)" suffix from model names and drops duplicate pinned snapshots', async () => { + const fetchMock = vi.fn().mockResolvedValue({ + ok: true, + json: async () => + await Promise.resolve({ + anthropic: { + id: 'anthropic', + name: 'Anthropic', + models: { + 'claude-opus-4-5': { + id: 'claude-opus-4-5', + name: 'Claude Opus 4.5 (latest)', + }, + 'claude-opus-4-5-20251101': { + id: 'claude-opus-4-5-20251101', + name: 'Claude Opus 4.5', + }, + 'claude-opus-4-8': { + id: 'claude-opus-4-8', + name: 'Claude Opus 4.8', + }, + 'claude-3-5-haiku-latest': { + id: 'claude-3-5-haiku-latest', + name: 'Claude Haiku 3.5 (latest)', + }, + }, + }, + google: { + id: 'google', + name: 'Google', + models: { + 'gemini-flash-latest': { + id: 'gemini-flash-latest', + name: 'Gemini Flash Latest', + }, + }, + }, + }), + }); + global.fetch = fetchMock as typeof fetch; + + const catalog = await fetchProviderCatalog(); + + // Alias keeps its id but loses the "(latest)" tag + expect(catalog.anthropic.models['claude-opus-4-5'].name).toBe('Claude Opus 4.5'); + expect(catalog.anthropic.models['claude-3-5-haiku-latest'].name).toBe('Claude Haiku 3.5'); + // Pinned snapshot with the same name as an alias is dropped + expect(catalog.anthropic.models['claude-opus-4-5-20251101']).toBeUndefined(); + // Models without a same-named alias are untouched + expect(catalog.anthropic.models['claude-opus-4-8'].name).toBe('Claude Opus 4.8'); + // Only the parenthesized suffix is stripped, not other "latest" naming + expect(catalog.google.models['gemini-flash-latest'].name).toBe('Gemini Flash Latest'); + }); }); diff --git a/packages/@n8n/agents/src/sdk/__tests__/delegate-sub-agent-routing.test.ts b/packages/@n8n/agents/src/sdk/__tests__/delegate-sub-agent-routing.test.ts index 54e9908ac9a..a0cea52afaf 100644 --- a/packages/@n8n/agents/src/sdk/__tests__/delegate-sub-agent-routing.test.ts +++ b/packages/@n8n/agents/src/sdk/__tests__/delegate-sub-agent-routing.test.ts @@ -1,6 +1,6 @@ import { z } from 'zod'; -import type * as AgentRuntimeModule from '../../runtime/agent-runtime'; +import type * as AgentRuntimeModule from '../../runtime/loop/agent-runtime'; import { DELEGATED_CHILD_SUSPEND_UNSUPPORTED_MESSAGE, DELEGATE_SUB_AGENT_TOOL_NAME, @@ -9,11 +9,18 @@ import { getInlineDelegateSubAgentToolOptions, type DelegateSubAgentRunner, type DelegateSubAgentRunnerHelpers, -} from '../../runtime/delegate-sub-agent-tool'; -import type { BuiltTool, GenerateResult, SerializableAgentState } from '../../types'; +} from '../../runtime/tools/delegate-sub-agent-tool'; +import type { + BuiltTool, + GenerateResult, + InterruptibleToolContext, + SerializableAgentState, +} from '../../types'; import { Agent } from '../agent'; +import { wrapToolForApproval } from '../tool'; const runtimeConfigs: Array<Record<string, unknown>> = []; +const runtimeGenerateOptions: Array<Record<string, unknown> | undefined> = []; let inlineChildGenerateResult: GenerateResult | undefined; const mockState = (): SerializableAgentState => ({ @@ -22,7 +29,7 @@ const mockState = (): SerializableAgentState => ({ pendingToolCalls: {}, }); -vi.mock('../../runtime/agent-runtime', async (importOriginal) => { +vi.mock('../../runtime/loop/agent-runtime', async (importOriginal) => { const actual = await importOriginal<typeof AgentRuntimeModule>(); return { ...actual, @@ -31,7 +38,8 @@ vi.mock('../../runtime/agent-runtime', async (importOriginal) => { runtimeConfigs.push(config); } - async generate() { + async generate(_input: unknown, options?: Record<string, unknown>) { + runtimeGenerateOptions.push(options); if (inlineChildGenerateResult !== undefined) { return await Promise.resolve(inlineChildGenerateResult); } @@ -81,6 +89,7 @@ async function buildAgentConfig(agent: Agent): Promise<AgentRuntimeModule.AgentR describe('delegate sub-agent routing', () => { beforeEach(() => { runtimeConfigs.length = 0; + runtimeGenerateOptions.length = 0; inlineChildGenerateResult = undefined; }); @@ -145,6 +154,122 @@ describe('delegate sub-agent routing', () => { expect(runtimeConfigs).toHaveLength(1); }); + it('uses a mapped inline model when difficulty is configured', async () => { + const agent = new Agent('parent') + .model('openai', 'gpt-4o-mini') + .instructions('Delegate when needed.') + .tool( + createDelegateSubAgentTool({ + inlineSubAgentModelsByDifficulty: { + high: 'anthropic/claude-sonnet-4-5', + }, + }), + ) + .tool(makeTool('lookup')); + + const runtimeConfig = await buildAgentConfig(agent); + const delegateTool = runtimeConfig.tools?.find( + (tool) => tool.name === DELEGATE_SUB_AGENT_TOOL_NAME, + ); + expect(delegateTool).toBeDefined(); + + await delegateTool?.handler?.( + { ...delegateInput, difficulty: 'high' }, + { runId: 'parent-run-1' }, + ); + + expect(runtimeConfigs).toHaveLength(1); + expect(runtimeConfigs[0]?.model).toBe('anthropic/claude-sonnet-4-5'); + }); + + it('falls back to the parent model when difficulty is omitted or unmapped', async () => { + const agent = new Agent('parent') + .model('openai', 'gpt-4o-mini') + .instructions('Delegate when needed.') + .tool( + createDelegateSubAgentTool({ + inlineSubAgentModelsByDifficulty: { + high: 'anthropic/claude-sonnet-4-5', + }, + }), + ) + .tool(makeTool('lookup')); + + const runtimeConfig = await buildAgentConfig(agent); + const delegateTool = runtimeConfig.tools?.find( + (tool) => tool.name === DELEGATE_SUB_AGENT_TOOL_NAME, + ); + expect(delegateTool).toBeDefined(); + + await delegateTool?.handler?.(delegateInput, { runId: 'parent-run-1' }); + expect(runtimeConfigs[0]?.model).toBe('openai/gpt-4o-mini'); + + runtimeConfigs.length = 0; + await delegateTool?.handler?.( + { ...delegateInput, difficulty: 'low' }, + { runId: 'parent-run-1' }, + ); + expect(runtimeConfigs[0]?.model).toBe('openai/gpt-4o-mini'); + }); + + it('passes the parent execution counter to inline child generate options', async () => { + const executionCounter = { + incrementMessageCount: vi.fn(), + incrementToolCallCount: vi.fn(), + incrementTokenCount: vi.fn(), + }; + const agent = new Agent('parent') + .model('openai', 'gpt-4o-mini') + .instructions('Delegate when needed.') + .tool(createDelegateSubAgentTool()) + .tool(makeTool('lookup')); + + const runtimeConfig = await buildAgentConfig(agent); + const delegateTool = runtimeConfig.tools?.find( + (tool) => tool.name === DELEGATE_SUB_AGENT_TOOL_NAME, + ); + expect(delegateTool).toBeDefined(); + + await delegateTool?.handler?.(delegateInput, { + runId: 'parent-run-1', + executionCounter, + }); + + expect(runtimeGenerateOptions[0]).toEqual(expect.objectContaining({ executionCounter })); + }); + + it('preserves required approval when completing inline delegate tools', async () => { + const agent = new Agent('parent') + .model('openai', 'gpt-4o-mini') + .instructions('Delegate when needed.') + .checkpoint('memory') + .tool(wrapToolForApproval(createDelegateSubAgentTool(), { requireApproval: true })) + .tool(makeTool('lookup')); + + const runtimeConfig = await buildAgentConfig(agent); + + expect(runtimeConfigs).toHaveLength(0); + const builtTools = runtimeConfig.tools; + const delegateTool = builtTools?.find((tool) => tool.name === DELEGATE_SUB_AGENT_TOOL_NAME); + expect(delegateTool?.approval?.required).toBe(true); + + const suspend = vi.fn(async (payload: unknown) => { + return await Promise.resolve({ suspended: payload }); + }); + await delegateTool?.handler?.(delegateInput, { + suspend: suspend as unknown as InterruptibleToolContext['suspend'], + resumeData: undefined, + runId: 'parent-run-1', + }); + + expect(suspend).toHaveBeenCalledWith({ + type: 'approval', + toolName: DELEGATE_SUB_AGENT_TOOL_NAME, + args: delegateInput, + }); + expect(runtimeConfigs).toHaveLength(0); + }); + it('lets a host-style runner delegate inline through helpers from tool metadata', async () => { const runInlineSubAgent = vi .fn<DelegateSubAgentRunnerHelpers['runInlineSubAgent']>() diff --git a/packages/@n8n/agents/src/sdk/__tests__/guardrails.test.ts b/packages/@n8n/agents/src/sdk/__tests__/guardrails.test.ts new file mode 100644 index 00000000000..241b7859777 --- /dev/null +++ b/packages/@n8n/agents/src/sdk/__tests__/guardrails.test.ts @@ -0,0 +1,236 @@ +import { Guardrail } from '../guardrail'; +import { passesLuhn } from '../guardrails/patterns'; +import { redactText, redactionOptionsFromGuardrail } from '../guardrails/redactor'; +import { StreamingRedactor } from '../guardrails/streaming-redactor'; + +// A Luhn-valid test card number (Visa test PAN). +const VALID_CARD = '4111111111111111'; +// Same length, not Luhn-valid. +const INVALID_CARD = '4111111111111112'; + +describe('redactText', () => { + describe('secrets', () => { + it('redacts an Anthropic-style key', () => { + const { text, matches } = redactText('use sk-ant-api03-aaaaaaaaaaaaaaaa now'); + expect(text).toBe('use [REDACTED] now'); + expect(matches).toEqual([{ category: 'secret' }]); + }); + + it('redacts a bearer token', () => { + const { text } = redactText('Authorization: Bearer abc.def-ghi_jkl/mno='); + expect(text).toContain('[REDACTED]'); + expect(text).not.toContain('abc.def'); + }); + + it('leaves non-sensitive prose untouched', () => { + const input = 'The workflow ran successfully and produced 42 items.'; + const { text, matches } = redactText(input); + expect(text).toBe(input); + expect(matches).toEqual([]); + }); + + it('is idempotent', () => { + const once = redactText('key sk-ant-api03-aaaaaaaaaaaaaaaa').text; + const twice = redactText(once).text; + expect(twice).toBe(once); + }); + + it('can be disabled', () => { + const input = 'key sk-ant-api03-aaaaaaaaaaaaaaaa'; + const { text } = redactText(input, { secrets: false }); + expect(text).toBe(input); + }); + + it('uses a custom placeholder', () => { + const { text } = redactText('key sk-ant-api03-aaaaaaaaaaaaaaaa', { placeholder: '###' }); + expect(text).toBe('key ###'); + }); + }); + + describe('PII', () => { + it('does not scan PII unless requested', () => { + const input = 'reach me at jane@example.com'; + expect(redactText(input).text).toBe(input); + }); + + it('redacts an email when detect includes email', () => { + const { text, matches } = redactText('reach me at jane@example.com', { + detect: ['email'], + }); + expect(text).toBe('reach me at [REDACTED]'); + expect(matches).toEqual([{ category: 'email' }]); + }); + + it('redacts a Luhn-valid credit card', () => { + const { text, matches } = redactText(`card ${VALID_CARD}`, { detect: ['credit-card'] }); + expect(text).toBe('card [REDACTED]'); + expect(matches).toEqual([{ category: 'credit-card' }]); + }); + + it('does not redact a Luhn-invalid number', () => { + const input = `card ${INVALID_CARD}`; + const { text, matches } = redactText(input, { detect: ['credit-card'] }); + expect(text).toBe(input); + expect(matches).toEqual([]); + }); + + it('redacts a US SSN', () => { + const { text } = redactText('ssn 123-45-6789', { detect: ['ssn-us'] }); + expect(text).toBe('ssn [REDACTED]'); + }); + + it('redacts E.164 phone numbers, compact and formatted', () => { + const { text, matches } = redactText('intl +15551234567', { detect: ['phone'] }); + expect(text).toBe('intl [REDACTED]'); + expect(matches).toEqual([{ category: 'phone' }]); + expect(redactText('call +1 (555) 123-4567', { detect: ['phone'] }).text).toBe( + 'call [REDACTED]', + ); + }); + + it('does not redact non-E.164 numbers (no leading +) or dates/IDs', () => { + // NANP without a leading + is intentionally not E.164. + const input = 'call 555-123-4567 on 2024-01-15 ticket 12345'; + expect(redactText(input, { detect: ['phone'] }).text).toBe(input); + }); + + it('redacts a checksum-valid IBAN (spaced or compact) but not an invalid one', () => { + expect(redactText('pay GB82 WEST 1234 5698 7654 32 today', { detect: ['iban'] }).text).toBe( + 'pay [REDACTED] today', + ); + // Lower/mixed-case compact IBANs must still be located and redacted. + expect(redactText('pay gb82west12345698765432 today', { detect: ['iban'] }).text).toBe( + 'pay [REDACTED] today', + ); + expect(redactText('pay Gb82WEST12345698765432 today', { detect: ['iban'] }).text).toBe( + 'pay [REDACTED] today', + ); + const invalid = 'iban GB99WEST12345698765432'; + expect(redactText(invalid, { detect: ['iban'] }).text).toBe(invalid); + }); + + it('redacts crypto wallet addresses (ETH, BTC bech32, BTC base58)', () => { + expect( + redactText('to 0x52908400098527886E0F7030069857D2E4169EE7', { + detect: ['crypto-wallet'], + }).text, + ).toBe('to [REDACTED]'); + expect( + redactText('to bc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf5mdq', { detect: ['crypto-wallet'] }) + .text, + ).toBe('to [REDACTED]'); + expect( + redactText('to 1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa', { detect: ['crypto-wallet'] }).text, + ).toBe('to [REDACTED]'); + }); + + it('does not redact a base58 string with a broken checksum', () => { + const input = 'addr 1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNb'; + expect(redactText(input, { detect: ['crypto-wallet'] }).text).toBe(input); + }); + + it('redacts IPv4 and IPv6 addresses but not out-of-range octets', () => { + expect(redactText('host 192.168.0.1 and 2001:db8::1', { detect: ['ip'] }).text).toBe( + 'host [REDACTED] and [REDACTED]', + ); + const invalid = 'ver 999.888.777.666'; + expect(redactText(invalid, { detect: ['ip'] }).text).toBe(invalid); + }); + + it('redacts a MAC address', () => { + const { text, matches } = redactText('mac 01:23:45:67:89:AB', { detect: ['mac'] }); + expect(text).toBe('mac [REDACTED]'); + expect(matches).toEqual([{ category: 'mac' }]); + }); + + it('redacts a full URL', () => { + expect( + redactText('see https://internal.example.com/admin?token=abc123 ok', { detect: ['url'] }) + .text, + ).toBe('see [REDACTED] ok'); + }); + }); + + describe('redactionOptionsFromGuardrail', () => { + it('maps a pii guardrail to detect types without secrets', () => { + const guardrail = new Guardrail('pii') + .type('pii') + .strategy('redact') + .detect(['email', 'ssn-us']) + .build(); + expect(redactionOptionsFromGuardrail(guardrail)).toEqual({ + secrets: false, + detect: ['email', 'ssn-us'], + }); + }); + }); +}); + +describe('passesLuhn', () => { + it('accepts a valid card with separators', () => { + expect(passesLuhn('4111 1111 1111 1111')).toBe(true); + }); + + it('rejects too-short input', () => { + expect(passesLuhn('411111')).toBe(false); + }); +}); + +describe('StreamingRedactor', () => { + // Small holdback keeps the tests readable while exercising the same logic. + const HOLDBACK = 8; + + it('redacts a secret split across two deltas', () => { + const redactor = new StreamingRedactor({}, HOLDBACK); + let out = ''; + out += redactor.push('here is sk-ant-').text; + out += redactor.push('api03-aaaaaaaaaaaaaaaa done now').text; + out += redactor.flush().text; + expect(out).toBe('here is [REDACTED] done now'); + expect(out).not.toContain('sk-ant-'); + }); + + it('redacts an email split across deltas', () => { + const redactor = new StreamingRedactor({ detect: ['email'] }, HOLDBACK); + let out = ''; + out += redactor.push('mail jane@').text; + out += redactor.push('example.com bye').text; + out += redactor.flush().text; + expect(out).toBe('mail [REDACTED] bye'); + }); + + it('redacts a spaced credit card that straddles the holdback boundary', () => { + const redactor = new StreamingRedactor({ detect: ['credit-card'] }, HOLDBACK); + let out = ''; + out += redactor.push('card 4111 1111 ').text; + out += redactor.push('1111 1111 done here').text; + out += redactor.flush().text; + expect(out).toBe('card [REDACTED] done here'); + expect(out).not.toContain('4111'); + }); + + it('passes through non-sensitive streamed prose intact', () => { + const redactor = new StreamingRedactor({}, HOLDBACK); + const parts = ['Hello ', 'there, ', 'this is ', 'all fine.']; + let out = ''; + for (const part of parts) out += redactor.push(part).text; + out += redactor.flush().text; + expect(out).toBe('Hello there, this is all fine.'); + }); + + it('emits nothing before the holdback fills and flushes the remainder', () => { + const redactor = new StreamingRedactor({}, HOLDBACK); + expect(redactor.push('short').text).toBe(''); + expect(redactor.flush().text).toBe('short'); + }); + + it('reports one match for a secret across the whole stream', () => { + const redactor = new StreamingRedactor({}, HOLDBACK); + const matches = [ + ...redactor.push('token sk-ant-').matches, + ...redactor.push('api03-aaaaaaaaaaaaaaaa end').matches, + ...redactor.flush().matches, + ]; + expect(matches).toEqual([{ category: 'secret' }]); + }); +}); diff --git a/packages/@n8n/agents/src/sdk/__tests__/inline-sub-agent-tools.test.ts b/packages/@n8n/agents/src/sdk/__tests__/inline-sub-agent-tools.test.ts index 40acad44aa9..15f83dfd912 100644 --- a/packages/@n8n/agents/src/sdk/__tests__/inline-sub-agent-tools.test.ts +++ b/packages/@n8n/agents/src/sdk/__tests__/inline-sub-agent-tools.test.ts @@ -1,19 +1,39 @@ import { z } from 'zod'; -import type * as AgentRuntimeModule from '../../runtime/agent-runtime'; -import type { DelegateSubAgentRequest } from '../../runtime/delegate-sub-agent-tool'; +import type * as AgentRuntimeModule from '../../runtime/loop/agent-runtime'; +import { RECALL_MEMORY_TOOL_NAME } from '../../runtime/memory/episodic-memory'; +import type { + DelegateSubAgentRequest, + InlineSubAgentProviderToolsResolver, +} from '../../runtime/tools/delegate-sub-agent-tool'; import { DELEGATE_SUB_AGENT_TOOL_NAME, INLINE_SUB_AGENT_ID, -} from '../../runtime/delegate-sub-agent-tool'; -import { RECALL_MEMORY_TOOL_NAME } from '../../runtime/episodic-memory'; -import { WRITE_TODOS_TOOL_NAME } from '../../runtime/write-todos-tool'; + createDelegateSubAgentTool, +} from '../../runtime/tools/delegate-sub-agent-tool'; +import { WRITE_TODOS_TOOL_NAME } from '../../runtime/tools/write-todos-tool'; import type { BuiltProviderTool, BuiltTool } from '../../types'; import { Agent, filterInlineSubAgentTools } from '../agent'; const runtimeConfigs: Array<Record<string, unknown>> = []; +const runtimeGenerateResults: Array<Record<string, unknown>> = []; -vi.mock('../../runtime/agent-runtime', async (importOriginal) => { +function makeGenerateSuccess(): Record<string, unknown> { + return { + runId: 'child-run', + finishReason: 'stop', + messages: [ + { + role: 'assistant', + type: 'llm', + content: [{ type: 'text', text: 'done' }], + }, + ], + usage: {}, + }; +} + +vi.mock('../../runtime/loop/agent-runtime', async (importOriginal) => { const actual = await importOriginal<typeof AgentRuntimeModule>(); return { ...actual, @@ -23,18 +43,7 @@ vi.mock('../../runtime/agent-runtime', async (importOriginal) => { } async generate() { - return await Promise.resolve({ - runId: 'child-run', - finishReason: 'stop', - messages: [ - { - role: 'assistant', - type: 'llm', - content: [{ type: 'text', text: 'done' }], - }, - ], - usage: {}, - }); + return await Promise.resolve(runtimeGenerateResults.shift() ?? makeGenerateSuccess()); } async dispose() { @@ -67,30 +76,41 @@ type AgentWithInlineRunner = { createInlineSubAgentRunner: (options: { deferredTools: BuiltTool[]; modelConfig: string; - providerTools: BuiltProviderTool[]; tools: BuiltTool[]; inlineSubAgentBlockedTools?: string[]; + inlineSubAgentModelsByDifficulty?: Partial<Record<'low' | 'medium' | 'high', string>>; + resolveInlineSubAgentProviderTools?: InlineSubAgentProviderToolsResolver; }) => (request: DelegateSubAgentRequest) => Promise<unknown>; }; function createInlineRunner(options: { - providerTools: BuiltProviderTool[]; tools?: BuiltTool[]; inlineSubAgentBlockedTools?: string[]; + inlineSubAgentModelsByDifficulty?: Partial<Record<'low' | 'medium' | 'high', string>>; + resolveInlineSubAgentProviderTools?: InlineSubAgentProviderToolsResolver; }) { const agent = new Agent('parent'); return (agent as unknown as AgentWithInlineRunner).createInlineSubAgentRunner({ deferredTools: [], modelConfig: 'openai/gpt-4o-mini', tools: options.tools ?? [makeTool('lookup')], - providerTools: options.providerTools, inlineSubAgentBlockedTools: options.inlineSubAgentBlockedTools, + inlineSubAgentModelsByDifficulty: options.inlineSubAgentModelsByDifficulty, + resolveInlineSubAgentProviderTools: options.resolveInlineSubAgentProviderTools, }); } +function providerToolNames(runtimeConfig: Record<string, unknown> | undefined): string[] { + return ( + (runtimeConfig?.providerTools as BuiltProviderTool[] | undefined)?.map((tool) => tool.name) ?? + [] + ); +} + describe('inline sub-agent tool filtering', () => { beforeEach(() => { runtimeConfigs.length = 0; + runtimeGenerateResults.length = 0; }); it.each([ @@ -118,17 +138,16 @@ describe('inline sub-agent tool filtering', () => { ); }); - it('inherits all provider tools when not blocked', () => { - expect( - filterInlineSubAgentTools([openaiWebSearchProviderTool, anthropicWebSearchProviderTool]).map( - (tool) => tool.name, - ), - ).toEqual(['openai.web_search_preview', 'anthropic.web_search_20250305']); - }); + it('does not pass parent provider tools to inline child runtimes without a resolver', async () => { + const agent = new Agent('parent') + .model('openai', 'gpt-4o-mini') + .providerTool(openaiWebSearchProviderTool) + .tool(makeTool('lookup')); - it('passes all provider tools to inline child runtimes by default', async () => { - const runner = createInlineRunner({ - providerTools: [openaiWebSearchProviderTool, anthropicWebSearchProviderTool], + const runner = (agent as unknown as AgentWithInlineRunner).createInlineSubAgentRunner({ + deferredTools: [], + modelConfig: 'openai/gpt-4o-mini', + tools: [makeTool('lookup')], }); await runner({ @@ -140,13 +159,189 @@ describe('inline sub-agent tool filtering', () => { }); expect(runtimeConfigs).toHaveLength(1); - expect( - (runtimeConfigs[0]?.providerTools as BuiltProviderTool[] | undefined)?.map( - (tool) => tool.name, - ), - ).toEqual(['openai.web_search_preview', 'anthropic.web_search_20250305']); + expect(runtimeConfigs[0]?.providerTools).toBeUndefined(); + }); + + it('loads provider tools from the inline provider-tool resolver', async () => { + const runner = createInlineRunner({ + resolveInlineSubAgentProviderTools: () => [openaiWebSearchProviderTool], + }); + + await runner({ + subAgentId: INLINE_SUB_AGENT_ID, + taskName: 'research', + goal: 'Find the answer', + taskPath: '/root/research', + childCount: 0, + }); + + expect(runtimeConfigs).toHaveLength(1); + expect(providerToolNames(runtimeConfigs[0])).toEqual(['openai.web_search_preview']); expect((runtimeConfigs[0]?.tools as BuiltTool[] | undefined)?.map((tool) => tool.name)).toEqual( ['lookup'], ); }); + + it('loads provider tools after difficulty changes the inline child model', async () => { + const resolveInlineSubAgentProviderTools = vi + .fn<InlineSubAgentProviderToolsResolver>() + .mockImplementation((modelConfig) => { + if (typeof modelConfig === 'string' && modelConfig.startsWith('anthropic/')) { + return [anthropicWebSearchProviderTool]; + } + return [openaiWebSearchProviderTool]; + }); + + const runner = createInlineRunner({ + inlineSubAgentModelsByDifficulty: { medium: 'anthropic/claude-sonnet-4-6' }, + resolveInlineSubAgentProviderTools, + }); + + await runner({ + subAgentId: INLINE_SUB_AGENT_ID, + taskName: 'research', + goal: 'Find the answer', + taskPath: '/root/research', + childCount: 0, + difficulty: 'medium', + }); + + expect(runtimeConfigs).toHaveLength(1); + expect(runtimeConfigs[0]?.model).toBe('anthropic/claude-sonnet-4-6'); + expect(providerToolNames(runtimeConfigs[0])).toEqual(['anthropic.web_search_20250305']); + expect(resolveInlineSubAgentProviderTools).toHaveBeenCalledWith('anthropic/claude-sonnet-4-6'); + }); + + it('omits resolver provider tools when the matching provider tool is blocked', async () => { + const runner = createInlineRunner({ + inlineSubAgentBlockedTools: ['anthropic.web_search_20250305'], + inlineSubAgentModelsByDifficulty: { high: 'anthropic/claude-sonnet-4-5' }, + resolveInlineSubAgentProviderTools: () => [anthropicWebSearchProviderTool], + }); + + await runner({ + subAgentId: INLINE_SUB_AGENT_ID, + taskName: 'research', + goal: 'Find the answer', + taskPath: '/root/research', + childCount: 0, + difficulty: 'high', + }); + + expect(runtimeConfigs).toHaveLength(1); + expect(runtimeConfigs[0]?.providerTools).toBeUndefined(); + }); + + it('does not inherit parent thinking when difficulty selects a different provider', async () => { + const agent = new Agent('parent').model('openai', 'gpt-4o-mini').thinking('openai', { + reasoningEffort: 'high', + }); + const runner = (agent as unknown as AgentWithInlineRunner).createInlineSubAgentRunner({ + deferredTools: [], + modelConfig: 'openai/gpt-4o-mini', + tools: [makeTool('lookup')], + inlineSubAgentModelsByDifficulty: { high: 'anthropic/claude-sonnet-4-5' }, + }); + + await runner({ + subAgentId: INLINE_SUB_AGENT_ID, + taskName: 'research', + goal: 'Find the answer', + taskPath: '/root/research', + childCount: 0, + difficulty: 'high', + }); + + expect(runtimeConfigs).toHaveLength(1); + expect(runtimeConfigs[0]?.model).toBe('anthropic/claude-sonnet-4-5'); + expect(runtimeConfigs[0]?.thinking).toBeUndefined(); + }); + + it('keeps parent thinking when difficulty keeps the same provider', async () => { + const thinking = { reasoningEffort: 'high' as const }; + const agent = new Agent('parent').model('openai', 'gpt-4o-mini').thinking('openai', thinking); + const runner = (agent as unknown as AgentWithInlineRunner).createInlineSubAgentRunner({ + deferredTools: [], + modelConfig: 'openai/gpt-4o-mini', + tools: [makeTool('lookup')], + inlineSubAgentModelsByDifficulty: { high: 'openai/o3-mini' }, + }); + + await runner({ + subAgentId: INLINE_SUB_AGENT_ID, + taskName: 'research', + goal: 'Find the answer', + taskPath: '/root/research', + childCount: 0, + difficulty: 'high', + }); + + expect(runtimeConfigs).toHaveLength(1); + expect(runtimeConfigs[0]?.model).toBe('openai/o3-mini'); + expect(runtimeConfigs[0]?.thinking).toEqual(thinking); + }); + + it('includes selected child model in failed inline child output when runtime result omits it', async () => { + runtimeGenerateResults.push({ + runId: 'child-run', + finishReason: 'error', + error: 'model failed', + messages: [], + usage: {}, + }); + const runner = createInlineRunner({ + inlineSubAgentModelsByDifficulty: { high: 'anthropic/claude-sonnet-4-5' }, + }); + + const output = await runner({ + subAgentId: INLINE_SUB_AGENT_ID, + taskName: 'research', + goal: 'Find the answer', + taskPath: '/root/research', + childCount: 0, + difficulty: 'high', + }); + + expect(output).toMatchObject({ + status: 'failed', + model: 'anthropic/claude-sonnet-4-5', + error: 'model failed', + }); + }); + + it('wires provider-tool resolver through the public Agent delegate tool path', async () => { + const resolveInlineSubAgentProviderTools = vi + .fn<InlineSubAgentProviderToolsResolver>() + .mockResolvedValue([anthropicWebSearchProviderTool]); + const agent = new Agent('parent') + .model('openai', 'gpt-4o-mini') + .instructions('Help') + .tool( + createDelegateSubAgentTool({ + inlineSubAgentModelsByDifficulty: { high: 'anthropic/claude-sonnet-4-5' }, + resolveInlineSubAgentProviderTools, + }), + ); + + await agent.generate('delegate something'); + const parentRuntimeConfig = runtimeConfigs[0]; + const delegateTool = (parentRuntimeConfig?.tools as BuiltTool[] | undefined)?.find( + (tool) => tool.name === DELEGATE_SUB_AGENT_TOOL_NAME, + ); + expect(delegateTool).toBeDefined(); + + await delegateTool?.handler?.( + { + subAgentId: INLINE_SUB_AGENT_ID, + taskName: 'research', + goal: 'Find the answer', + difficulty: 'high', + }, + { runId: 'parent-run' }, + ); + + expect(runtimeConfigs).toHaveLength(2); + expect(resolveInlineSubAgentProviderTools).toHaveBeenCalledWith('anthropic/claude-sonnet-4-5'); + expect(providerToolNames(runtimeConfigs[1])).toEqual(['anthropic.web_search_20250305']); + }); }); diff --git a/packages/@n8n/agents/src/sdk/__tests__/memory-builder-episodic.test.ts b/packages/@n8n/agents/src/sdk/__tests__/memory-builder-episodic.test.ts index bf89ea51a20..d683e25320e 100644 --- a/packages/@n8n/agents/src/sdk/__tests__/memory-builder-episodic.test.ts +++ b/packages/@n8n/agents/src/sdk/__tests__/memory-builder-episodic.test.ts @@ -1,10 +1,10 @@ -import type { AgentRuntimeConfig } from '../../runtime/agent-runtime'; +import type { AgentRuntimeConfig } from '../../runtime/loop/agent-runtime'; import { DEFAULT_EPISODIC_MEMORY_EMBEDDING_MODEL, DEFAULT_EPISODIC_MEMORY_MAX_ENTRIES_PER_RUN, DEFAULT_EPISODIC_MEMORY_TOP_K, -} from '../../runtime/episodic-memory-defaults'; -import { InMemoryMemory } from '../../runtime/memory-store'; +} from '../../runtime/memory/episodic-memory-defaults'; +import { InMemoryMemory } from '../../runtime/memory/memory-store'; import type { BuiltMemory, EpisodicMemoryConfig } from '../../types'; import { Agent } from '../agent'; import { diff --git a/packages/@n8n/agents/src/sdk/__tests__/memory-builder-observational.test.ts b/packages/@n8n/agents/src/sdk/__tests__/memory-builder-observational.test.ts index 448bef1356c..361d54584b2 100644 --- a/packages/@n8n/agents/src/sdk/__tests__/memory-builder-observational.test.ts +++ b/packages/@n8n/agents/src/sdk/__tests__/memory-builder-observational.test.ts @@ -1,5 +1,5 @@ -import type { AgentRuntimeConfig } from '../../runtime/agent-runtime'; -import { InMemoryMemory } from '../../runtime/memory-store'; +import type { AgentRuntimeConfig } from '../../runtime/loop/agent-runtime'; +import { InMemoryMemory } from '../../runtime/memory/memory-store'; import type { BuiltMemory, MemoryConfig } from '../../types'; import { Agent } from '../agent'; import { diff --git a/packages/@n8n/agents/src/sdk/__tests__/tool-name-collisions.test.ts b/packages/@n8n/agents/src/sdk/__tests__/tool-name-collisions.test.ts index 64f395961c5..61be4f36ee0 100644 --- a/packages/@n8n/agents/src/sdk/__tests__/tool-name-collisions.test.ts +++ b/packages/@n8n/agents/src/sdk/__tests__/tool-name-collisions.test.ts @@ -3,9 +3,9 @@ import { z } from 'zod'; import { createDelegateSubAgentTool, DELEGATE_SUB_AGENT_TOOL_NAME, -} from '../../runtime/delegate-sub-agent-tool'; -import { isSdkOwnedBuiltInTool } from '../../runtime/sdk-owned-tool'; -import { createWriteTodosTool, WRITE_TODOS_TOOL_NAME } from '../../runtime/write-todos-tool'; +} from '../../runtime/tools/delegate-sub-agent-tool'; +import { isSdkOwnedBuiltInTool } from '../../runtime/tools/sdk-owned-tool'; +import { createWriteTodosTool, WRITE_TODOS_TOOL_NAME } from '../../runtime/tools/write-todos-tool'; import { Agent } from '../agent'; import { Tool } from '../tool'; diff --git a/packages/@n8n/agents/src/sdk/__tests__/tool.test.ts b/packages/@n8n/agents/src/sdk/__tests__/tool.test.ts index 496716d2fbf..b06e74305d8 100644 --- a/packages/@n8n/agents/src/sdk/__tests__/tool.test.ts +++ b/packages/@n8n/agents/src/sdk/__tests__/tool.test.ts @@ -48,6 +48,7 @@ describe('Tool builder — .requireApproval()', () => { expect(tool.suspendSchema).toBeDefined(); expect(tool.resumeSchema).toBeDefined(); + expect(tool.approval?.required).toBe(true); }); it('build() throws when .requireApproval() is combined with .suspend()/.resume()', () => { @@ -85,6 +86,7 @@ describe('Tool builder — .needsApprovalFn()', () => { expect(tool.suspendSchema).toBeDefined(); expect(tool.resumeSchema).toBeDefined(); + expect(tool.approval?.required).toBe(false); }); it('build() throws when .needsApprovalFn() is combined with .suspend()/.resume()', () => { @@ -174,6 +176,24 @@ describe('wrapToolForApproval — requireApproval: true', () => { }); }); + it('includes display metadata from the wrapped tool object when suspending', async () => { + const baseTool = makeBuiltTool(); + const wrapped = { + ...wrapToolForApproval(baseTool, { requireApproval: true }), + metadata: { displayName: 'Display test tool' }, + }; + const { ctx, suspendMock } = makeCtx(); + + await wrapped.handler!({ id: '1' }, ctx); + + expect(suspendMock).toHaveBeenCalledWith({ + type: 'approval', + toolName: 'testTool', + displayName: 'Display test tool', + args: { id: '1' }, + }); + }); + it('executes original handler when approved on resume', async () => { const baseTool = makeBuiltTool(); const wrapped = wrapToolForApproval(baseTool, { requireApproval: true }); @@ -247,13 +267,44 @@ describe('wrapToolForApproval — needsApprovalFn', () => { expect(suspendMock).not.toHaveBeenCalled(); expect(result).toEqual({ result: 'public' }); }); + + it('emits tool execution start with the original structured args when approval is not needed', async () => { + const baseTool = makeBuiltTool({ + inputSchema: z.object({ + id: z.string(), + password: z.string(), + nested: z.object({ apiKey: z.string() }), + }), + }); + const wrapped = wrapToolForApproval(baseTool, { + needsApprovalFn: async () => await Promise.resolve(false), + }); + const { ctx } = makeCtx(); + const emitEvent = vi.fn(); + ctx.toolCallId = 'tool-call-1'; + ctx.emitEvent = emitEvent; + const input = { + id: 'public', + password: 'plain-secret-password', + nested: { apiKey: 'secret-api-key' }, + }; + + await wrapped.handler!(input, ctx); + + expect(emitEvent).toHaveBeenCalledWith({ + type: 'tool_execution_start', + toolCallId: 'tool-call-1', + toolName: 'testTool', + args: input, + }); + }); }); // --------------------------------------------------------------------------- -// wrapToolForApproval — config: { requireApproval: true } (agent-level wrapping) +// wrapToolForApproval — config: { requireApproval: true } // --------------------------------------------------------------------------- -describe('wrapToolForApproval — config: { requireApproval: true } (agent-level wrapping)', () => { +describe('wrapToolForApproval — config: { requireApproval: true }', () => { it('always suspends regardless of original tool settings', async () => { const baseTool = makeBuiltTool(); const wrapped = wrapToolForApproval(baseTool, { requireApproval: true }); diff --git a/packages/@n8n/agents/src/sdk/agent.ts b/packages/@n8n/agents/src/sdk/agent.ts index 3cb2ab6992c..27d886470f9 100644 --- a/packages/@n8n/agents/src/sdk/agent.ts +++ b/packages/@n8n/agents/src/sdk/agent.ts @@ -1,4 +1,5 @@ import type { ProviderOptions } from '@ai-sdk/provider-utils'; +import type { JSONSchema7 } from 'json-schema'; import type { z } from 'zod'; import { getModelCost } from './catalog'; @@ -7,8 +8,14 @@ import type { McpClient } from './mcp-client'; import { Memory, normalizeMemoryConfig, resolveMemoryConfigDefaults } from './memory'; import { Telemetry } from './telemetry'; import { wrapToolForApproval } from './tool'; -import { AgentRuntime, type AgentRuntimeConfig } from '../runtime/agent-runtime'; -import { LOAD_TOOL_TOOL_NAME, SEARCH_TOOLS_TOOL_NAME } from '../runtime/deferred-tool-manager'; +import { AgentRuntime, type AgentRuntimeConfig } from '../runtime/loop/agent-runtime'; +import { RECALL_MEMORY_TOOL_NAME } from '../runtime/memory/episodic-memory'; +import { AgentEventBus } from '../runtime/state/event-bus'; +import { RunStateManager } from '../runtime/state/run-state'; +import { + LOAD_TOOL_TOOL_NAME, + SEARCH_TOOLS_TOOL_NAME, +} from '../runtime/tools/deferred-tool-manager'; import { DELEGATE_SUB_AGENT_TOOL_NAME, INLINE_SUB_AGENT_ID, @@ -19,12 +26,11 @@ import { renderDelegateSubAgentPrompt, type DelegateSubAgentRequest, type DelegateSubAgentToolOutput, -} from '../runtime/delegate-sub-agent-tool'; -import { RECALL_MEMORY_TOOL_NAME } from '../runtime/episodic-memory'; -import { AgentEventBus } from '../runtime/event-bus'; -import { RunStateManager } from '../runtime/run-state'; -import { isSdkOwnedBuiltInTool } from '../runtime/sdk-owned-tool'; -import { WRITE_TODOS_TOOL_NAME } from '../runtime/write-todos-tool'; + type InlineSubAgentProviderToolsResolver, + type SubAgentTaskDifficulty, +} from '../runtime/tools/delegate-sub-agent-tool'; +import { isSdkOwnedBuiltInTool } from '../runtime/tools/sdk-owned-tool'; +import { WRITE_TODOS_TOOL_NAME } from '../runtime/tools/write-todos-tool'; import { appendSkillCatalogToInstructions, createRuntimeSkillSource, @@ -107,8 +113,6 @@ export interface AgentSnapshot { thinking: ThinkingConfig | null; /** Tool-call concurrency limit if set, otherwise null. */ toolCallConcurrency: number | null; - /** Whether `.requireToolApproval()` was called. */ - requireToolApproval: boolean; } /** @@ -156,7 +160,7 @@ export class Agent implements BuiltAgent, AgentBuilder { private agentEvals: BuiltEval[] = []; - private outputSchema?: z.ZodType; + private outputSchema?: z.ZodType | JSONSchema7; private checkpointStore?: 'memory' | CheckpointStore; @@ -170,8 +174,6 @@ export class Agent implements BuiltAgent, AgentBuilder { private middlewares: AgentMiddleware[] = []; - private requireToolApprovalValue = false; - private mcpClients: McpClient[] = []; private defaultExecutionOptions?: ExecutionOptions; @@ -361,6 +363,10 @@ export class Agent implements BuiltAgent, AgentBuilder { * Set a structured output schema. When set, the agent's response will be * parsed into a typed object matching the schema, available as `result.output`. * + * Accepts either a Zod schema or a raw JSON Schema. JSON Schema is useful + * when the schema is supplied dynamically (e.g. entered in a workflow node) + * and there is no Zod type to compile against. + * * @example * ```typescript * const agent = new Agent('extractor') @@ -375,7 +381,7 @@ export class Agent implements BuiltAgent, AgentBuilder { * console.log(result.structuredOutput); // { code: '...', explanation: '...' } * ``` */ - structuredOutput(schema: z.ZodType): this { + structuredOutput(schema: z.ZodType | JSONSchema7): this { this.outputSchema = schema; return this; } @@ -435,16 +441,6 @@ export class Agent implements BuiltAgent, AgentBuilder { return this; } - /** - * Require human approval before any tool executes. - * Tools that already have .suspend()/.resume() (suspendSchema) are skipped. - * Requires .checkpoint() to be set. - */ - requireToolApproval(): this { - this.requireToolApprovalValue = true; - return this; - } - /** * Attach a workspace to this agent. Workspace tools and instructions * are injected at build time. @@ -575,7 +571,6 @@ export class Agent implements BuiltAgent, AgentBuilder { hasEpisodicMemory: this.memoryConfig?.episodicMemory !== undefined, thinking: this.thinkingConfig ?? null, toolCallConcurrency: this.concurrencyValue ?? null, - requireToolApproval: this.requireToolApprovalValue, }; } @@ -809,27 +804,15 @@ export class Agent implements BuiltAgent, AgentBuilder { finalTools.push(...wsTools); } - let finalStaticTools = finalTools; - let finalDeferredTools = configuredDeferredTools; - if (this.requireToolApprovalValue) { - finalStaticTools = finalTools.map((t) => - RUNTIME_SKILL_TOOL_NAMES.has(t.name) || t.suspendSchema - ? t - : wrapToolForApproval(t, { requireApproval: true }), - ); - finalDeferredTools = configuredDeferredTools.map((t) => - t.suspendSchema ? t : wrapToolForApproval(t, { requireApproval: true }), - ); - } + const finalStaticTools = finalTools; + const finalDeferredTools = configuredDeferredTools; // Validate checkpoint requirement from static tools and known MCP approval config // before attempting any network connections (allows fast failure). const staticNeedsCheckpoint = finalStaticTools.some((t) => t.suspendSchema) || finalDeferredTools.some((t) => t.suspendSchema); - const mcpNeedsCheckpoint = - (this.requireToolApprovalValue && this.mcpClients.length > 0) || - this.mcpClients.some((c) => c.declaresApproval()); + const mcpNeedsCheckpoint = this.mcpClients.some((c) => c.declaresApproval()); if ((staticNeedsCheckpoint || mcpNeedsCheckpoint) && !this.checkpointStore) { throw new Error( `Agent "${this.name}" has tools requiring approval or suspend/resume but no checkpoint storage. ` + @@ -840,15 +823,7 @@ export class Agent implements BuiltAgent, AgentBuilder { // Resolve tools from all MCP clients. const mcpToolLists = await Promise.all(this.mcpClients.map(async (c) => await c.listTools())); - let mcpTools = mcpToolLists.flat(); - - // Apply global requireToolApproval to MCP tools (per-server approval is already - // handled inside McpClient/McpConnection.listTools()). - if (this.requireToolApprovalValue) { - mcpTools = mcpTools.map((t) => - t.suspendSchema ? t : wrapToolForApproval(t, { requireApproval: true }), - ); - } + const mcpTools = mcpToolLists.flat(); // Detect collisions between direct, deferred, and MCP tools. const staticCollisions = findDuplicateToolNames(finalStaticTools); @@ -930,7 +905,6 @@ export class Agent implements BuiltAgent, AgentBuilder { allTools = this.completeInlineDelegateTools(allTools, { deferredTools: finalDeferredTools, modelConfig, - providerTools: this.providerTools, ...(telemetry !== undefined ? { telemetry } : {}), ...(this.concurrencyValue !== undefined ? { toolCallConcurrency: this.concurrencyValue } @@ -982,7 +956,6 @@ export class Agent implements BuiltAgent, AgentBuilder { options: { deferredTools: BuiltTool[]; modelConfig: ModelConfig; - providerTools: BuiltProviderTool[]; telemetry?: BuiltTelemetry; toolCallConcurrency?: number; toolSearch?: { topK?: number }; @@ -996,6 +969,8 @@ export class Agent implements BuiltAgent, AgentBuilder { ...options, tools, inlineSubAgentBlockedTools: delegateOptions.inlineSubAgentBlockedTools, + inlineSubAgentModelsByDifficulty: delegateOptions.inlineSubAgentModelsByDifficulty, + resolveInlineSubAgentProviderTools: delegateOptions.resolveInlineSubAgentProviderTools, }); const hostRunner = delegateOptions.runSubAgent; const completedTool = createDelegateSubAgentTool({ @@ -1017,7 +992,7 @@ export class Agent implements BuiltAgent, AgentBuilder { }, }); - if (tool.withDefaultApproval) { + if (tool.approval?.required === true) { return wrapToolForApproval(completedTool, { requireApproval: true }); } return completedTool; @@ -1027,12 +1002,13 @@ export class Agent implements BuiltAgent, AgentBuilder { private createInlineSubAgentRunner(options: { deferredTools: BuiltTool[]; modelConfig: ModelConfig; - providerTools: BuiltProviderTool[]; telemetry?: BuiltTelemetry; toolCallConcurrency?: number; toolSearch?: { topK?: number }; tools: BuiltTool[]; inlineSubAgentBlockedTools?: string[]; + inlineSubAgentModelsByDifficulty?: Partial<Record<SubAgentTaskDifficulty, ModelConfig>>; + resolveInlineSubAgentProviderTools?: InlineSubAgentProviderToolsResolver; }): (request: DelegateSubAgentRequest) => Promise<DelegateSubAgentToolOutput> { return async (request) => { const tools = filterInlineSubAgentTools(options.tools, options.inlineSubAgentBlockedTools); @@ -1040,13 +1016,20 @@ export class Agent implements BuiltAgent, AgentBuilder { options.deferredTools, options.inlineSubAgentBlockedTools, ); - const providerTools = filterInlineSubAgentTools( - options.providerTools, - options.inlineSubAgentBlockedTools, - ); + const childModelConfig = resolveInlineSubAgentModelConfig(request, options); + const providerTools = options.resolveInlineSubAgentProviderTools + ? filterInlineSubAgentTools( + await options.resolveInlineSubAgentProviderTools(childModelConfig), + options.inlineSubAgentBlockedTools, + ) + : []; + const childModelId = modelConfigToId(childModelConfig); + const childThinkingConfig = shouldInheritThinking(options.modelConfig, childModelConfig) + ? this.thinkingConfig + : undefined; const childRuntime = new AgentRuntime({ name: `${this.name}:${request.taskName}`, - model: options.modelConfig, + model: childModelConfig, instructions: 'You are a focused subagent working on a specific delegated task. Complete the delegated task independently and return a concise, self-contained summary to your parent agent.', tools: tools.length > 0 ? tools : undefined, @@ -1055,7 +1038,7 @@ export class Agent implements BuiltAgent, AgentBuilder { providerTools: providerTools.length > 0 ? providerTools : undefined, instructionProviderOptions: this.instructionProviderOpts, checkpointStorage: this.checkpointStore, - thinking: this.thinkingConfig, + ...(childThinkingConfig !== undefined ? { thinking: childThinkingConfig } : {}), ...(options.telemetry !== undefined ? { telemetry: options.telemetry } : {}), ...(options.toolCallConcurrency !== undefined ? { toolCallConcurrency: options.toolCallConcurrency } @@ -1068,11 +1051,18 @@ export class Agent implements BuiltAgent, AgentBuilder { ? { abortSignal: request.parentAbortSignal } : {}), ...(options.telemetry !== undefined ? { telemetry: options.telemetry } : {}), + ...(request.parentExecutionCounter !== undefined + ? { executionCounter: request.parentExecutionCounter } + : {}), }); if (result.pendingSuspend !== undefined && result.pendingSuspend.length > 0) { - return failedDelegatedChildSuspendOutput(request.taskPath); + return failedDelegatedChildSuspendOutput(request.taskPath, result.model ?? childModelId); } - return generateResultToDelegateSubAgentOutput(request.taskPath, result); + const resultWithModel = + result.model === undefined && childModelId !== undefined + ? { ...result, model: childModelId } + : result; + return generateResultToDelegateSubAgentOutput(request.taskPath, resultWithModel); } finally { await childRuntime.dispose(); } @@ -1105,6 +1095,55 @@ export class Agent implements BuiltAgent, AgentBuilder { } } +function resolveInlineSubAgentModelConfig( + request: DelegateSubAgentRequest, + options: { + modelConfig: ModelConfig; + inlineSubAgentModelsByDifficulty?: Partial<Record<SubAgentTaskDifficulty, ModelConfig>>; + }, +): ModelConfig { + if (request.difficulty === undefined) { + return options.modelConfig; + } + + const mappedModel = options.inlineSubAgentModelsByDifficulty?.[request.difficulty]; + return mappedModel ?? options.modelConfig; +} + +function modelConfigToId(modelConfig: ModelConfig): string | undefined { + if (typeof modelConfig === 'string') return modelConfig; + if (typeof modelConfig === 'object' && modelConfig !== null && 'id' in modelConfig) { + return typeof modelConfig.id === 'string' ? modelConfig.id : undefined; + } + if ( + typeof modelConfig === 'object' && + modelConfig !== null && + 'provider' in modelConfig && + 'modelId' in modelConfig + ) { + const provider = typeof modelConfig.provider === 'string' ? modelConfig.provider : undefined; + const modelId = typeof modelConfig.modelId === 'string' ? modelConfig.modelId : undefined; + return provider && modelId ? `${provider}/${modelId}` : undefined; + } + return undefined; +} + +function modelConfigProvider(modelConfig: ModelConfig): string | undefined { + const modelId = modelConfigToId(modelConfig); + if (!modelId) return undefined; + const slashIndex = modelId.indexOf('/'); + return slashIndex > 0 ? modelId.slice(0, slashIndex) : undefined; +} + +function shouldInheritThinking( + parentModelConfig: ModelConfig, + childModelConfig: ModelConfig, +): boolean { + const parentProvider = modelConfigProvider(parentModelConfig); + const childProvider = modelConfigProvider(childModelConfig); + return parentProvider !== undefined && parentProvider === childProvider; +} + export function buildInlineSubAgentBlockedToolNames(hostBlockedTools?: string[]): Set<string> { return new Set([...SDK_INLINE_SUB_AGENT_BLOCKED_TOOL_NAMES, ...(hostBlockedTools ?? [])]); } diff --git a/packages/@n8n/agents/src/sdk/catalog.ts b/packages/@n8n/agents/src/sdk/catalog.ts index 6cc165c563f..70fa17c8f4a 100644 --- a/packages/@n8n/agents/src/sdk/catalog.ts +++ b/packages/@n8n/agents/src/sdk/catalog.ts @@ -82,6 +82,33 @@ function toAgentProviderId(modelsDevProviderId: string): string { return MODELS_DEV_PROVIDER_ALIASES[modelsDevProviderId] ?? modelsDevProviderId; } +const LATEST_NAME_SUFFIX = /\s*\(latest\)$/i; + +/** + * models.dev names versionless alias models with a " (latest)" suffix + * (e.g. `claude-opus-4-5` → "Claude Opus 4.5 (latest)"), which quickly goes + * stale as newer models ship. Strip the suffix from every model name, and when + * a pinned snapshot shares the resulting name with an alias (e.g. + * `claude-opus-4-5-20251101` "Claude Opus 4.5"), drop the snapshot so the + * alias is the single entry for that model. + */ +function normalizeLatestModelNames(models: Record<string, ModelInfo>): void { + const aliasNames = new Set<string>(); + for (const model of Object.values(models)) { + if (LATEST_NAME_SUFFIX.test(model.name)) { + aliasNames.add(model.name.replace(LATEST_NAME_SUFFIX, '')); + } + } + + for (const [modelId, model] of Object.entries(models)) { + if (LATEST_NAME_SUFFIX.test(model.name)) { + model.name = model.name.replace(LATEST_NAME_SUFFIX, ''); + } else if (aliasNames.has(model.name)) { + delete models[modelId]; + } + } +} + /** * Fetch the provider/model catalog from models.dev. * @@ -146,6 +173,10 @@ export async function fetchProviderCatalog(): Promise<ProviderCatalog> { }; } + for (const provider of Object.values(catalog)) { + normalizeLatestModelNames(provider.models); + } + return catalog; } diff --git a/packages/@n8n/agents/src/sdk/eval.ts b/packages/@n8n/agents/src/sdk/eval.ts index e6760f541bb..ad091ffd79b 100644 --- a/packages/@n8n/agents/src/sdk/eval.ts +++ b/packages/@n8n/agents/src/sdk/eval.ts @@ -1,5 +1,5 @@ import { filterLlmMessages } from './message'; -import { AgentRuntime } from '../runtime/agent-runtime'; +import { AgentRuntime } from '../runtime/loop/agent-runtime'; import type { BuiltEval, CheckFn, EvalInput, EvalScore, JudgeFn, JudgeHandlerFn } from '../types'; import type { ModelConfig } from '../types/sdk/agent'; import type { AgentMessage } from '../types/sdk/message'; diff --git a/packages/@n8n/agents/src/sdk/guardrails/index.ts b/packages/@n8n/agents/src/sdk/guardrails/index.ts new file mode 100644 index 00000000000..d3561d54dce --- /dev/null +++ b/packages/@n8n/agents/src/sdk/guardrails/index.ts @@ -0,0 +1,10 @@ +export { + redactText, + redactDeep, + redactionOptionsFromGuardrail, + DEFAULT_PLACEHOLDER, +} from './redactor'; +export type { RedactionOptions, RedactionResult, DeepRedactionResult } from './redactor'; +export { StreamingRedactor } from './streaming-redactor'; +export { resolvePatterns, passesLuhn, SUPPORTED_PII_CATEGORIES } from './patterns'; +export type { RedactionCategory, RedactionPattern } from './patterns'; diff --git a/packages/@n8n/agents/src/sdk/guardrails/patterns.ts b/packages/@n8n/agents/src/sdk/guardrails/patterns.ts new file mode 100644 index 00000000000..0110c96e7c0 --- /dev/null +++ b/packages/@n8n/agents/src/sdk/guardrails/patterns.ts @@ -0,0 +1,247 @@ +import { SECRET_VALUE_PATTERNS } from '@n8n/utils'; +import { createHash } from 'node:crypto'; +import { z, type ZodType } from 'zod'; + +import type { PiiDetectionType } from '../../types'; + +/** + * A category attached to every redaction match so callers can log *what kind* + * of sensitive content was removed without ever handling the value itself. + * `'secret'` covers credential/token patterns; the rest mirror the SDK's + * {@link PiiDetectionType} vocabulary. + */ +export type RedactionCategory = 'secret' | PiiDetectionType; + +export interface RedactionPattern { + readonly category: RedactionCategory; + /** + * Precompiled regex matching the sensitive value. Always global — the + * redactor relies on `g` both for replace-all and for the `exec` scan loop. + * Compiled once at module load; callers reset `lastIndex` before reuse. + */ + readonly regex: RegExp; + /** + * Optional gate: a candidate match is only redacted when this returns + * `true`. Used to suppress false positives (e.g. Luhn check for cards). + */ + readonly validate?: (match: string) => boolean; +} + +/** Compile a global regex once, adding the `g` flag if the source omits it. */ +function globalRegex(source: string, flags = ''): RegExp { + return new RegExp(source, flags.includes('g') ? flags : `${flags}g`); +} + +/** + * Secret/credential patterns, sourced from `@n8n/utils` so there is a single + * place that defines what a credential looks like across the codebase. + */ +const SECRET_PATTERNS: readonly RedactionPattern[] = SECRET_VALUE_PATTERNS.map((re) => ({ + category: 'secret', + regex: globalRegex(re.source, re.flags), +})); + +/** Luhn checksum — used to keep credit-card redaction from firing on any long digit run. */ +export function passesLuhn(candidate: string): boolean { + const digits = candidate.replace(/\D/g, ''); + if (digits.length < 13 || digits.length > 19) return false; + + let sum = 0; + let double = false; + for (let i = digits.length - 1; i >= 0; i--) { + let digit = digits.charCodeAt(i) - 48; + if (double) { + digit *= 2; + if (digit > 9) digit -= 9; + } + sum += digit; + double = !double; + } + return sum % 10 === 0; +} + +/** + * Adapt a Zod schema into a {@link RedactionPattern} `validate` gate: the + * pattern's regex *locates* a candidate substring in free-form text (Zod cannot + * scan prose), then the schema *confirms* it before redaction. Lets a rule + * express its confidence check declaratively — including a `z.string().regex(…)` + * — instead of as ad-hoc code (cf. {@link passesLuhn}). An optional `normalize` + * step runs on the located substring before validation (e.g. stripping the + * separators a regex tolerated so the schema sees a canonical value). + */ +export function zodGuard( + schema: ZodType, + normalize?: (match: string) => string, +): (match: string) => boolean { + return (match) => schema.safeParse(normalize ? normalize(match) : match).success; +} + +/** + * Confidence gate for phone candidates, encoding the **E.164** standard: a + * leading `+`, a non-zero country code, and 7–15 digits total. This mirrors + * Zod 4's `z.e164()`; expressed here as a classic-Zod regex because the repo is + * on Zod 3.25, where `e164()` isn't exposed on the default `zod` import. + * Validation runs on the digit/`+`-only normalized form (separators stripped). + */ +const PHONE_SCHEMA = z.string().regex(/^\+[1-9]\d{6,14}$/); + +/** + * IBAN mod-97 checksum (ISO 13616): drop spaces, move the first 4 chars to the + * end, map letters A–Z → 10–35, and confirm the big-integer value mod 97 === 1. + */ +export function passesIbanChecksum(candidate: string): boolean { + const compact = candidate.replace(/\s/g, '').toUpperCase(); + if (!/^[A-Z]{2}\d{2}[A-Z0-9]{11,30}$/.test(compact)) return false; + + const rearranged = compact.slice(4) + compact.slice(0, 4); + let remainder = 0; + for (let i = 0; i < rearranged.length; i++) { + const code = rearranged.charCodeAt(i); + const value = code >= 65 ? code - 55 : code - 48; // 'A'→10 … 'Z'→35, '0'→0 … '9'→9 + remainder = value > 9 ? (remainder * 100 + value) % 97 : (remainder * 10 + value) % 97; + } + return remainder === 1; +} + +const BASE58_ALPHABET = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'; + +function base58Decode(input: string): Uint8Array | undefined { + const bytes: number[] = []; + for (let i = 0; i < input.length; i++) { + let carry = BASE58_ALPHABET.indexOf(input[i]); + if (carry === -1) return undefined; + for (let j = 0; j < bytes.length; j++) { + carry += bytes[j] * 58; + bytes[j] = carry & 0xff; + carry >>= 8; + } + while (carry > 0) { + bytes.push(carry & 0xff); + carry >>= 8; + } + } + for (let i = 0; i < input.length && input[i] === '1'; i++) bytes.push(0); + return Uint8Array.from(bytes.reverse()); +} + +/** Bitcoin Base58Check: the trailing 4 bytes are the SHA-256d checksum of the payload. */ +function passesBase58Check(candidate: string): boolean { + const decoded = base58Decode(candidate); + if (!decoded || decoded.length < 5) return false; + const payload = decoded.subarray(0, decoded.length - 4); + const checksum = decoded.subarray(decoded.length - 4); + const hash = createHash('sha256').update(createHash('sha256').update(payload).digest()).digest(); + for (let i = 0; i < 4; i++) if (hash[i] !== checksum[i]) return false; + return true; +} + +/** Ethereum (`0x`+40 hex), Bitcoin bech32 (`bc1`/`tb1`), or Bitcoin Base58Check address. */ +function isCryptoWallet(match: string): boolean { + if (/^0x[0-9a-fA-F]{40}$/.test(match)) return true; // ETH — `0x`+40 hex is distinctive + if (/^(?:bc1|tb1)[023456789acdefghjklmnpqrstuvwxyz]{11,71}$/.test(match)) return true; // bech32 + return passesBase58Check(match); // legacy P2PKH/P2SH — checksum-gated +} + +/** IPv4 with octets ≤ 255, or a colon-delimited IPv6 (shape already constrained by the regex). */ +function isIpAddress(match: string): boolean { + if (match.includes(':')) return true; + const octets = match.split('.'); + return octets.length === 4 && octets.every((o) => /^\d{1,3}$/.test(o) && Number(o) <= 255); +} + +/** + * Conservative, high-confidence PII patterns. Phone detection is best-effort: + * only well-structured (E.164) formats are matched. New {@link PiiDetectionType} + * categories slot in here; a category may map to `undefined` to declare it + * before a pattern exists, in which case it is excluded from detection. + */ +const PII_PATTERNS: Readonly<Record<PiiDetectionType, RedactionPattern | undefined>> = { + email: { + category: 'email', + regex: /[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}/g, + }, + 'credit-card': { + category: 'credit-card', + // 13-19 digits, optionally grouped by single spaces or dashes. + regex: /\b\d(?:[ -]?\d){12,18}\b/g, + validate: passesLuhn, + }, + 'ssn-us': { + category: 'ssn-us', + // US Social Security Number, dashed form only (123-45-6789). Bare 9-digit + // runs are intentionally not matched (too false-positive-prone). Per-country + // national IDs each get their own `ssn-<cc>` category (e.g. a future `ssn-uk`). + regex: /\b\d{3}-\d{2}-\d{4}\b/g, + }, + phone: { + category: 'phone', + // Best-effort, E.164 only: a leading `+` then 7–15 digits, tolerating + // the spaces/parens/dots/dashes people write between groups + // (e.g. `+1 (555) 123-4567`). Requiring the `+` keeps false positives + // low — bare digit runs (IDs, dates, NANP without `+`) are not matched. + // `zodGuard` normalizes to the digit/`+`-only form, then validates E.164. + regex: /\+\d(?:[\s().-]*\d){6,14}\b/g, + validate: zodGuard(PHONE_SCHEMA, (match) => match.replace(/[^\d+]/g, '')), + }, + iban: { + category: 'iban', + // Two forms: the compact (un-spaced) IBAN is matched case-insensitively so + // lower/mixed-case IBANs are caught — with no internal spaces it can't bleed + // into a following word. The spaced, group-of-4 form is matched upper-case + // only: spaced IBANs are written upper-case by convention, and that keeps the + // greedy body from swallowing following lower-case prose (which would fail the + // checksum and suppress redaction, since the engine doesn't retry sub-matches). + // `passesIbanChecksum` upper-cases, strips spaces, and verifies mod-97. + regex: /\b[A-Za-z]{2}\d{2}[A-Za-z0-9]{11,30}\b|\b[A-Z]{2}\d{2}(?: [A-Z0-9]{1,4}){2,8}\b/g, + validate: passesIbanChecksum, + }, + 'crypto-wallet': { + category: 'crypto-wallet', + // Ethereum `0x…40hex`, Bitcoin bech32 `bc1…`/`tb1…`, or Bitcoin Base58Check. + regex: + /\b(?:0x[0-9a-fA-F]{40}|(?:bc1|tb1)[023456789acdefghjklmnpqrstuvwxyz]{11,71}|[13][1-9A-HJ-NP-Za-km-z]{25,34})\b/g, + validate: isCryptoWallet, + }, + // `mac` is declared before `ip`: a MAC is colon-delimited hex and would also + // match the IPv6 branch, so matching it as `mac` first keeps the category right. + mac: { + category: 'mac', + regex: /\b(?:[0-9A-Fa-f]{2}[:-]){5}[0-9A-Fa-f]{2}\b/g, + }, + ip: { + category: 'ip', + // IPv4 (octets validated) or IPv6 (full and `::`-compressed forms). + regex: + /\b(?:\d{1,3}\.){3}\d{1,3}\b|\b(?:[A-Fa-f0-9]{1,4}:){2,7}[A-Fa-f0-9]{1,4}\b|\b(?:[A-Fa-f0-9]{1,4}:){1,7}:(?:[A-Fa-f0-9]{1,4})?\b/g, + validate: isIpAddress, + }, + url: { + category: 'url', + // Whole http(s) URL. Stops at whitespace and common trailing delimiters. + regex: /\bhttps?:\/\/[^\s<>"')\]}]+/g, + }, +}; + +/** + * PII categories that actually have a detection pattern today — the source of + * truth for what redaction can detect. Any {@link PiiDetectionType} mapped to + * `undefined` in {@link PII_PATTERNS} (declared but not yet implemented) is + * excluded here. + */ +export const SUPPORTED_PII_CATEGORIES: PiiDetectionType[] = ( + Object.keys(PII_PATTERNS) as PiiDetectionType[] +).filter((type) => PII_PATTERNS[type] !== undefined); + +/** Resolve the active pattern set for the given options. */ +export function resolvePatterns(opts: { + secrets: boolean; + detect: readonly PiiDetectionType[]; +}): RedactionPattern[] { + const patterns: RedactionPattern[] = []; + if (opts.secrets) patterns.push(...SECRET_PATTERNS); + for (const type of opts.detect) { + const pattern = PII_PATTERNS[type]; + if (pattern) patterns.push(pattern); + } + return patterns; +} diff --git a/packages/@n8n/agents/src/sdk/guardrails/redactor.ts b/packages/@n8n/agents/src/sdk/guardrails/redactor.ts new file mode 100644 index 00000000000..6207210203b --- /dev/null +++ b/packages/@n8n/agents/src/sdk/guardrails/redactor.ts @@ -0,0 +1,142 @@ +import type { RedactionCategory } from './patterns'; +import { resolvePatterns } from './patterns'; +import type { BuiltGuardrail, PiiDetectionType } from '../../types'; + +export const DEFAULT_PLACEHOLDER = '[REDACTED]'; + +export interface RedactionOptions { + /** Scan for credential/secret patterns. Defaults to `true`. */ + secrets?: boolean; + /** PII categories to scan for. Defaults to none. */ + detect?: readonly PiiDetectionType[]; + /** Replacement text for a match. Defaults to `[REDACTED]`. */ + placeholder?: string; +} + +export interface RedactionResult { + /** The input with every detected match replaced by the placeholder. */ + text: string; + /** One entry per replaced match (category only — never the value). */ + matches: Array<{ category: RedactionCategory }>; +} + +/** + * Map an `@n8n/agents` {@link BuiltGuardrail} to redaction options, so a future + * `.outputGuardrail()` runtime enforcement can drive this engine directly. + */ +export function redactionOptionsFromGuardrail(guardrail: BuiltGuardrail): RedactionOptions { + const detect = guardrail._config.detectionTypes; + return { + secrets: guardrail.guardType === 'pii' ? false : true, + detect: Array.isArray(detect) ? (detect as PiiDetectionType[]) : [], + }; +} + +/** + * Redact secret/PII patterns from a complete string. Pure and idempotent — + * already-redacted placeholders are left untouched by the underlying patterns. + */ +export function redactText(input: string, opts: RedactionOptions = {}): RedactionResult { + const placeholder = opts.placeholder ?? DEFAULT_PLACEHOLDER; + const patterns = resolvePatterns({ + secrets: opts.secrets ?? true, + detect: opts.detect ?? [], + }); + + const matches: Array<{ category: RedactionCategory }> = []; + let text = input; + + for (const pattern of patterns) { + // `replace` with a global regex scans from 0 and resets lastIndex, so the + // shared precompiled regex is safe to reuse across calls. + text = text.replace(pattern.regex, (match) => { + if (pattern.validate && !pattern.validate(match)) return match; + matches.push({ category: pattern.category }); + return placeholder; + }); + } + + return { text, matches }; +} + +/** + * Find the `[start, end)` ranges of every (validated) match in `input`. Used by + * the streaming redactor to avoid emitting through the middle of a complete + * match that contains internal whitespace (e.g. a spaced credit-card number). + */ +export function findMatchRanges( + input: string, + opts: RedactionOptions = {}, +): Array<[number, number]> { + const patterns = resolvePatterns({ + secrets: opts.secrets ?? true, + detect: opts.detect ?? [], + }); + + const ranges: Array<[number, number]> = []; + for (const pattern of patterns) { + const { regex } = pattern; + // Reset before the scan loop; reusing the shared global regex is safe + // because usage is synchronous and the loop always runs to completion. + regex.lastIndex = 0; + let match: RegExpExecArray | null; + while ((match = regex.exec(input)) !== null) { + if (match[0].length === 0) { + regex.lastIndex++; + continue; + } + if (pattern.validate && !pattern.validate(match[0])) continue; + ranges.push([match.index, match.index + match[0].length]); + } + } + return ranges; +} + +const MAX_DEEP_DEPTH = 8; + +export interface DeepRedactionResult { + value: unknown; + matches: Array<{ category: RedactionCategory }>; +} + +/** + * Recursively redact string values inside an arbitrary JSON-like value + * (tool results, structured payloads). Object keys are left intact; only + * string values are scanned. Recursion is depth-bounded as a cheap guard + * against pathological/cyclic structures. + */ +export function redactDeep( + value: unknown, + opts: RedactionOptions = {}, + depth = 0, +): DeepRedactionResult { + if (typeof value === 'string') { + const { text, matches } = redactText(value, opts); + return { value: text, matches }; + } + + if (depth >= MAX_DEEP_DEPTH) return { value, matches: [] }; + + if (Array.isArray(value)) { + const matches: Array<{ category: RedactionCategory }> = []; + const next = value.map((item) => { + const result = redactDeep(item, opts, depth + 1); + matches.push(...result.matches); + return result.value; + }); + return { value: next, matches }; + } + + if (value !== null && typeof value === 'object') { + const matches: Array<{ category: RedactionCategory }> = []; + const next: Record<string, unknown> = {}; + for (const [key, item] of Object.entries(value)) { + const result = redactDeep(item, opts, depth + 1); + matches.push(...result.matches); + next[key] = result.value; + } + return { value: next, matches }; + } + + return { value, matches: [] }; +} diff --git a/packages/@n8n/agents/src/sdk/guardrails/streaming-redactor.ts b/packages/@n8n/agents/src/sdk/guardrails/streaming-redactor.ts new file mode 100644 index 00000000000..637e10f7aca --- /dev/null +++ b/packages/@n8n/agents/src/sdk/guardrails/streaming-redactor.ts @@ -0,0 +1,85 @@ +import type { RedactionOptions, RedactionResult } from './redactor'; +import { findMatchRanges, redactText } from './redactor'; + +/** + * How many trailing characters to hold back before emitting. + * + * The cut-at-whitespace rule below already guarantees no *contiguous* token is + * ever split across a chunk boundary (a segment always ends after whitespace, + * so every word lands wholly on one side). That alone catches the dominant + * leak — an echoed API key/JWT/token — at any holdback value. + * + * The holdback only adds margin for *multi-word* patterns (`Bearer <token>`, + * `key = value`): it keeps the trailing context buffered long enough for such + * a pattern to complete before it is emitted. Kept small so streaming output + * stays responsive; a multi-word secret longer than this that lands exactly on + * the emit boundary may not be caught (its contiguous value still is, via the + * standalone secret patterns). Configurable via the constructor. + */ +const DEFAULT_HOLDBACK = 32; + +const WHITESPACE = /\s/; + +/** + * Redacts secret/PII patterns from a *streamed* text channel where the text + * arrives in arbitrary fragments. Per-channel state: construct one per logical + * stream (e.g. one for `text-delta`, one for `reasoning-delta`). + * + * Guarantees no partial token is emitted across a chunk boundary: text is only + * released up to the last whitespace at or before `length - holdback`, so any + * contiguous token (or short multi-word pattern) stays buffered until it is + * fully present. Call {@link flush} at end-of-stream to release the remainder. + */ +export class StreamingRedactor { + private buffer = ''; + + private readonly holdback: number; + + constructor( + private readonly options: RedactionOptions = {}, + holdback: number = DEFAULT_HOLDBACK, + ) { + this.holdback = Math.max(0, holdback); + } + + /** Feed the next fragment; returns the redacted text safe to emit now. */ + push(delta: string): RedactionResult { + this.buffer += delta; + + if (this.buffer.length <= this.holdback) { + return { text: '', matches: [] }; + } + + // Cut at the last whitespace at or before the holdback boundary so a + // token straddling the boundary stays whole in the buffer. + const target = this.buffer.length - this.holdback; + let cut = target; + while (cut > 0 && !WHITESPACE.test(this.buffer[cut - 1])) { + cut -= 1; + } + + // Never emit through the middle of a complete match. A match with internal + // whitespace (e.g. a spaced credit-card number) can straddle the cut; pull + // the boundary back to its start so it stays buffered and is redacted whole. + for (const [start, end] of findMatchRanges(this.buffer, this.options)) { + if (start < cut && end > cut) cut = start; + } + + if (cut === 0) { + // No safe boundary yet — keep everything buffered. + return { text: '', matches: [] }; + } + + const segment = this.buffer.slice(0, cut); + this.buffer = this.buffer.slice(cut); + return redactText(segment, this.options); + } + + /** Release and redact any buffered remainder. Call once at end-of-stream. */ + flush(): RedactionResult { + const remainder = this.buffer; + this.buffer = ''; + if (!remainder) return { text: '', matches: [] }; + return redactText(remainder, this.options); + } +} diff --git a/packages/@n8n/agents/src/sdk/mcp-client.ts b/packages/@n8n/agents/src/sdk/mcp-client.ts index 44412913a6e..916bfae0da1 100644 --- a/packages/@n8n/agents/src/sdk/mcp-client.ts +++ b/packages/@n8n/agents/src/sdk/mcp-client.ts @@ -1,4 +1,4 @@ -import { McpConnection } from '../runtime/mcp-connection'; +import { McpConnection } from '../runtime/mcp/mcp-connection'; import type { McpServerConfig, McpVerifyResult } from '../types/sdk/mcp'; import type { BuiltTool } from '../types/sdk/tool'; @@ -39,10 +39,8 @@ export class McpClient { /** * @param configs - Server configurations. Each must have either `url` or `command`. * Duplicate names within the list are rejected. - * @param requireToolApproval - When true, every tool from every server is wrapped - * with a human-approval gate (requires `.checkpoint()` on the Agent). */ - constructor(configs: McpServerConfig[], requireToolApproval = false) { + constructor(configs: McpServerConfig[]) { for (const cfg of configs) { if (!cfg.url && !cfg.command) { throw new Error( @@ -63,7 +61,7 @@ export class McpClient { } this.configs = configs; - this.connections = configs.map((cfg) => new McpConnection(cfg, requireToolApproval)); + this.connections = configs.map((cfg) => new McpConnection(cfg)); } /** diff --git a/packages/@n8n/agents/src/sdk/memory.ts b/packages/@n8n/agents/src/sdk/memory.ts index 9478d0ab275..0a3fde554c5 100644 --- a/packages/@n8n/agents/src/sdk/memory.ts +++ b/packages/@n8n/agents/src/sdk/memory.ts @@ -1,13 +1,12 @@ -import { hasEpisodicMemoryStore, isEpisodicMemoryEnabled } from '../runtime/episodic-memory'; +import { hasEpisodicMemoryStore, isEpisodicMemoryEnabled } from '../runtime/memory/episodic-memory'; import { DEFAULT_EPISODIC_MEMORY_EMBEDDING_MODEL, DEFAULT_EPISODIC_MEMORY_MAX_ENTRIES_PER_RUN, DEFAULT_EPISODIC_MEMORY_TOP_K, createEpisodicMemoryExtractFn, createEpisodicMemoryReflectFn, -} from '../runtime/episodic-memory-defaults'; -import { InMemoryMemory } from '../runtime/memory-store'; -import { createEmbeddingModel } from '../runtime/model-factory'; +} from '../runtime/memory/episodic-memory-defaults'; +import { InMemoryMemory } from '../runtime/memory/memory-store'; import { createObservationLogObserveFn, createObservationLogReflectFn, @@ -16,8 +15,9 @@ import { DEFAULT_OBSERVATION_LOG_REFLECTOR_THRESHOLD_TOKENS, DEFAULT_OBSERVATION_LOG_RENDER_TOKEN_BUDGET, DEFAULT_OBSERVATION_LOG_TAIL_LIMIT, -} from '../runtime/observation-log-defaults'; -import { hasObservationLogStore } from '../runtime/observation-log-store'; +} from '../runtime/memory/observation-log-defaults'; +import { hasObservationLogStore } from '../runtime/memory/observation-log-store'; +import { createEmbeddingModel } from '../runtime/model/model-factory'; import type { BuiltMemory, EpisodicMemoryConfig, diff --git a/packages/@n8n/agents/src/sdk/tool.ts b/packages/@n8n/agents/src/sdk/tool.ts index 93c7b56c27b..c7e5b23f2bc 100644 --- a/packages/@n8n/agents/src/sdk/tool.ts +++ b/packages/@n8n/agents/src/sdk/tool.ts @@ -2,6 +2,7 @@ import type { JSONSchema7 } from 'json-schema'; import { z } from 'zod'; import type { BuiltTool, InterruptibleToolContext, ToolContext } from '../types'; +import { AgentEvent } from '../types/runtime/event'; import type { AgentMessage } from '../types/sdk/message'; import type { ToolDescriptor } from '../types/sdk/tool-descriptor'; import type { JSONObject } from '../types/utils/json'; @@ -10,6 +11,7 @@ import { isZodSchema, zodToJsonSchema } from '../utils/zod'; const APPROVAL_SUSPEND_SCHEMA = z.object({ type: z.literal('approval'), toolName: z.string(), + displayName: z.string().optional(), args: z.unknown(), }); @@ -26,10 +28,30 @@ export interface ApprovalConfig { needsApprovalFn?: (args: unknown) => Promise<boolean> | boolean; } +function emitToolExecutionStart( + tool: BuiltTool, + input: unknown, + ctx: InterruptibleToolContext, +): void { + if (!ctx.toolCallId) return; + ctx.emitEvent?.({ + type: AgentEvent.ToolExecutionStart, + toolCallId: ctx.toolCallId, + toolName: tool.name, + args: input, + }); +} + +export function getToolApprovalDisplayName(tool: BuiltTool): string | undefined { + const metadata = tool.metadata; + const displayName = metadata?.displayName ?? metadata?.workflowName; + return typeof displayName === 'string' && displayName.length > 0 ? displayName : undefined; +} + /** * Wrap a BuiltTool with an approval gate that suspends before execution and * waits for human confirmation. Used by Tool.build() (when .requireApproval() - * or .needsApprovalFn() is set) and by Agent.build() (for global approval). + * or .needsApprovalFn() is set) and per-tool JSON config reconstruction. * * The wrapped tool has suspendSchema/resumeSchema set, making it an * interruptible tool that uses the existing suspend/resume mechanism. @@ -38,13 +60,18 @@ export interface ApprovalConfig { export function wrapToolForApproval(tool: BuiltTool, config: ApprovalConfig): BuiltTool { const originalHandler = tool.handler!; + const hasConditionalApproval = config.needsApprovalFn !== undefined; return { ...tool, - withDefaultApproval: true, + approval: { + required: config.requireApproval === true, + ...(hasConditionalApproval ? { conditional: true } : {}), + }, suspendSchema: APPROVAL_SUSPEND_SCHEMA, resumeSchema: APPROVAL_RESUME_SCHEMA, - handler: async (input, ctx) => { + async handler(this: BuiltTool | undefined, input, ctx) { + const currentTool = this ?? tool; // This handler is always called with InterruptibleToolContext because // wrapToolForApproval adds suspendSchema/resumeSchema. const interruptCtx = ctx as InterruptibleToolContext; @@ -54,14 +81,23 @@ export function wrapToolForApproval(tool: BuiltTool, config: ApprovalConfig): Bu needs = await config.needsApprovalFn(input); } if (needs) { - return await interruptCtx.suspend({ type: 'approval', toolName: tool.name, args: input }); + const displayName = getToolApprovalDisplayName(currentTool); + return await interruptCtx.suspend({ + type: 'approval', + toolName: currentTool.name, + ...(displayName ? { displayName } : {}), + args: input, + }); + } + if (hasConditionalApproval) { + emitToolExecutionStart(currentTool, input, interruptCtx); } return await originalHandler(input, interruptCtx as ToolContext); } const { approved } = interruptCtx.resumeData as z.infer<typeof APPROVAL_RESUME_SCHEMA>; if (!approved) { - return { declined: true, message: `Tool "${tool.name}" was not approved` }; + return { declined: true, message: `Tool "${currentTool.name}" was not approved` }; } return await originalHandler(input, interruptCtx as ToolContext); }, diff --git a/packages/@n8n/agents/src/skills/__tests__/runtime-skills.test.ts b/packages/@n8n/agents/src/skills/__tests__/runtime-skills.test.ts index df326568e8a..f9469ca0c42 100644 --- a/packages/@n8n/agents/src/skills/__tests__/runtime-skills.test.ts +++ b/packages/@n8n/agents/src/skills/__tests__/runtime-skills.test.ts @@ -13,7 +13,7 @@ import { parseRuntimeSkillMarkdown, renderSkillCatalogPrompt, } from '..'; -import type { AgentRuntimeConfig } from '../../runtime/agent-runtime'; +import type { AgentRuntimeConfig } from '../../runtime/loop/agent-runtime'; import { Agent } from '../../sdk/agent'; import { isZodSchema } from '../../utils/zod'; diff --git a/packages/@n8n/agents/src/types/runtime/event.ts b/packages/@n8n/agents/src/types/runtime/event.ts index 9620c7c7fe3..1e651e29f71 100644 --- a/packages/@n8n/agents/src/types/runtime/event.ts +++ b/packages/@n8n/agents/src/types/runtime/event.ts @@ -26,6 +26,8 @@ export interface SubAgentCompletedPayload extends SubAgentLifecycleBase { runId?: string; /** The child run's memory thread id (`persistence.threadId`), so consumers can correlate or continue it. */ threadId?: string; + /** Effective child model id used for this delegation. */ + model?: string; usage?: SubAgentLifecycleUsage; finishReason?: FinishReason; error?: string; diff --git a/packages/@n8n/agents/src/types/sdk/agent-builder.ts b/packages/@n8n/agents/src/types/sdk/agent-builder.ts index 983d2569fe9..3a6814c37ec 100644 --- a/packages/@n8n/agents/src/types/sdk/agent-builder.ts +++ b/packages/@n8n/agents/src/types/sdk/agent-builder.ts @@ -23,7 +23,6 @@ export interface AgentBuilder { providerTool(t: BuiltProviderTool): this; thinking(provider: string, config?: Record<string, unknown>): this; toolCallConcurrency(n: number): this; - requireToolApproval(): this; memory(m: unknown): this; checkpoint(storage: 'memory' | CheckpointStore): this; inputGuardrail(g: BuiltGuardrail): this; diff --git a/packages/@n8n/agents/src/types/sdk/agent.ts b/packages/@n8n/agents/src/types/sdk/agent.ts index cfe14bc035c..d48f08315bc 100644 --- a/packages/@n8n/agents/src/types/sdk/agent.ts +++ b/packages/@n8n/agents/src/types/sdk/agent.ts @@ -1,9 +1,9 @@ import type { ProviderOptions } from '@ai-sdk/provider-utils'; -import type { LanguageModel, smoothStream } from 'ai'; +import type { LanguageModel, OnStepFinishEvent, OnStepStartEvent, smoothStream } from 'ai'; import type { JsonSchema7Type } from 'zod-to-json-schema'; import type { AgentMessage, ContentMetadata } from './message'; -import type { ProviderId, ProviderCredentials } from '../../runtime/provider-credentials'; +import type { ProviderId, ProviderCredentials } from '../../runtime/model/provider-credentials'; import type { AgentEvent, AgentEventHandler, @@ -165,6 +165,8 @@ export interface ExecutionOptions { telemetry?: BuiltTelemetry; /** Inherited execution counter from the host runtime. Used for aggregate heartbeat telemetry. */ executionCounter?: AgentExecutionCounter; + onStepStart?: (event: OnStepStartEvent) => void | Promise<void>; + onStepFinish?: (event: OnStepFinishEvent) => void | Promise<void>; } export interface PersistedExecutionOptions { @@ -272,11 +274,11 @@ export interface BuiltAgent { options: ResumeOptions & ExecutionOptions, ): Promise<StreamResult>; - /** Approve a tool that uses requiresApproval or needsApprovalFn */ + /** Approve a tool that uses requireApproval or needsApprovalFn */ approve(method: 'generate', options: ResumeOptions & ExecutionOptions): Promise<GenerateResult>; approve(method: 'stream', options: ResumeOptions & ExecutionOptions): Promise<StreamResult>; - /** Deny a tool that uses requiresApproval or needsApprovalFn */ + /** Deny a tool that uses requireApproval or needsApprovalFn */ deny(method: 'generate', options: ResumeOptions & ExecutionOptions): Promise<GenerateResult>; deny(method: 'stream', options: ResumeOptions & ExecutionOptions): Promise<StreamResult>; } diff --git a/packages/@n8n/agents/src/types/sdk/guardrail.ts b/packages/@n8n/agents/src/types/sdk/guardrail.ts index 8ee1a1baf2b..99b8e326ecd 100644 --- a/packages/@n8n/agents/src/types/sdk/guardrail.ts +++ b/packages/@n8n/agents/src/types/sdk/guardrail.ts @@ -1,6 +1,15 @@ export type GuardrailType = 'pii' | 'prompt-injection' | 'moderation' | 'custom'; export type GuardrailStrategy = 'block' | 'redact' | 'warn'; -export type PiiDetectionType = 'email' | 'phone' | 'credit-card' | 'ssn' | 'address'; +export type PiiDetectionType = + | 'email' + | 'phone' + | 'credit-card' + | 'ssn-us' + | 'iban' + | 'crypto-wallet' + | 'ip' + | 'mac' + | 'url'; export interface BuiltGuardrail { readonly name: string; diff --git a/packages/@n8n/agents/src/types/sdk/mcp.ts b/packages/@n8n/agents/src/types/sdk/mcp.ts index 278513663e6..049b0c1d1db 100644 --- a/packages/@n8n/agents/src/types/sdk/mcp.ts +++ b/packages/@n8n/agents/src/types/sdk/mcp.ts @@ -34,8 +34,7 @@ export interface McpServerConfig { * - `true` — every tool from this server requires approval before execution. * - `string[]` — only the listed tools (by their original, un-prefixed names) * require approval; all other tools from the server run without interruption. - * - `false` / omitted — no per-server approval requirement (the global - * `.requireToolApproval()` flag on the Agent still applies). + * - `false` / omitted — no approval requirement. */ requireApproval?: string[] | boolean; diff --git a/packages/@n8n/agents/src/types/sdk/tool.ts b/packages/@n8n/agents/src/types/sdk/tool.ts index f28e63a2592..632d5a6001c 100644 --- a/packages/@n8n/agents/src/types/sdk/tool.ts +++ b/packages/@n8n/agents/src/types/sdk/tool.ts @@ -1,6 +1,7 @@ import type { JSONSchema7 } from 'json-schema'; import type { ZodType } from 'zod'; +import type { AgentExecutionCounter } from './agent'; import type { AgentMessage } from './message'; import type { AgentEventData } from '../runtime/event'; import type { BuiltTelemetry } from '../telemetry'; @@ -27,6 +28,8 @@ export interface ToolExecutionContext { * the work they started. */ abortSignal?: AbortSignal; + /** Aggregate execution counter for usage telemetry inherited from the current agent run. */ + executionCounter?: AgentExecutionCounter; } export interface ToolContext { @@ -42,6 +45,8 @@ export interface ToolContext { emitEvent?: ToolExecutionContext['emitEvent']; /** The current run's abort signal, for tools that start cancellable work. */ abortSignal?: ToolExecutionContext['abortSignal']; + /** Aggregate execution counter for usage telemetry inherited from the current agent run. */ + executionCounter?: ToolExecutionContext['executionCounter']; } export interface InterruptibleToolContext<S = unknown, R = unknown> { @@ -67,6 +72,8 @@ export interface InterruptibleToolContext<S = unknown, R = unknown> { emitEvent?: ToolExecutionContext['emitEvent']; /** The current run's abort signal, for tools that start cancellable work. */ abortSignal?: ToolExecutionContext['abortSignal']; + /** Aggregate execution counter for usage telemetry inherited from the current agent run. */ + executionCounter?: ToolExecutionContext['executionCounter']; } export interface BuiltTool { @@ -82,9 +89,12 @@ export interface BuiltTool { readonly systemInstruction?: string; readonly suspendSchema?: ZodType | JSONSchema7; readonly resumeSchema?: ZodType | JSONSchema7; + readonly approval?: { + readonly required: boolean; + readonly conditional?: boolean; + }; /** When `true`, the handler is called on cancellation with `ctx.cancellation` set instead of being bypassed. */ readonly handleCancellation?: boolean; - readonly withDefaultApproval?: boolean; readonly toMessage?: (output: unknown) => AgentMessage | undefined; /** * Transform the handler output before sending it to the LLM as a tool result. diff --git a/packages/@n8n/agents/src/utils/__tests__/json-schema.test.ts b/packages/@n8n/agents/src/utils/__tests__/json-schema.test.ts new file mode 100644 index 00000000000..13633759670 --- /dev/null +++ b/packages/@n8n/agents/src/utils/__tests__/json-schema.test.ts @@ -0,0 +1,124 @@ +import type { JSONSchema7 } from 'json-schema'; + +import { fixSchema, lockAdditionalProperties } from '../json-schema'; + +describe('fixSchema', () => { + it('adds type "object" when properties is present but type is absent', () => { + expect(fixSchema({ properties: { name: { type: 'string' } } })).toEqual({ + type: 'object', + properties: { name: { type: 'string' } }, + }); + }); + + it('leaves the type untouched when it is already set', () => { + const schema: JSONSchema7 = { type: 'object', properties: { a: { type: 'number' } } }; + expect(fixSchema(schema)).toEqual(schema); + }); + + it('does not add a type when there are no properties', () => { + expect(fixSchema({ description: 'no properties' })).toEqual({ description: 'no properties' }); + }); + + it('does not mutate the input schema', () => { + const input: JSONSchema7 = { properties: { x: { type: 'string' } } }; + fixSchema(input); + expect(input).not.toHaveProperty('type'); + }); +}); + +describe('lockAdditionalProperties', () => { + it('sets additionalProperties:false on a root object that omits it', () => { + const result = lockAdditionalProperties({ + type: 'object', + properties: { name: { type: 'string' } }, + required: ['name'], + }); + + expect(result).toEqual({ + type: 'object', + properties: { name: { type: 'string' } }, + required: ['name'], + additionalProperties: false, + }); + }); + + it('normalises an object that declares properties without a type', () => { + const result = lockAdditionalProperties({ + properties: { id: { type: 'string' } }, + } as JSONSchema7); + + expect(result).toMatchObject({ type: 'object', additionalProperties: false }); + }); + + it('applies additionalProperties:false recursively to nested objects', () => { + const result = lockAdditionalProperties({ + type: 'object', + properties: { + address: { + type: 'object', + properties: { city: { type: 'string' } }, + }, + tags: { + type: 'array', + items: { type: 'object', properties: { label: { type: 'string' } } }, + }, + }, + }); + + const props = (result.properties ?? {}) as Record<string, JSONSchema7>; + expect(props.address.additionalProperties).toBe(false); + const items = props.tags.items as JSONSchema7; + expect(items.additionalProperties).toBe(false); + }); + + it('recurses into $defs and anyOf branches', () => { + const result = lockAdditionalProperties({ + type: 'object', + properties: { ref: { $ref: '#/$defs/Inner' } }, + anyOf: [{ type: 'object', properties: { a: { type: 'string' } } }], + $defs: { + Inner: { type: 'object', properties: { b: { type: 'number' } } }, + }, + }); + + const defs = (result.$defs ?? {}) as Record<string, JSONSchema7>; + expect(defs.Inner.additionalProperties).toBe(false); + const anyOf = (result.anyOf ?? []) as JSONSchema7[]; + expect(anyOf[0].additionalProperties).toBe(false); + }); + + it('does not override an explicit additionalProperties value', () => { + const result = lockAdditionalProperties({ + type: 'object', + properties: { name: { type: 'string' } }, + additionalProperties: true, + }); + + expect(result.additionalProperties).toBe(true); + }); + + it('does not mutate the input schema', () => { + const input: JSONSchema7 = { type: 'object', properties: { name: { type: 'string' } } }; + lockAdditionalProperties(input); + expect(input.additionalProperties).toBeUndefined(); + }); + + it('handles a property literally named __proto__ as an own property without mutating the prototype chain', () => { + // Build an object with a real own `__proto__` property (a plain object + // literal would instead set the prototype) to exercise the safe re-mapping. + const properties: Record<string, JSONSchema7> = {}; + Object.defineProperty(properties, '__proto__', { + value: { type: 'string' }, + enumerable: true, + writable: true, + configurable: true, + }); + const result = lockAdditionalProperties({ type: 'object', properties }); + + const resultProps = result.properties as Record<string, JSONSchema7>; + // The dangerous key is kept as a real own property, and the rebuilt object's + // prototype is left untouched (Object.defineProperty, not bracket assignment). + expect(Object.getPrototypeOf(resultProps)).toBe(Object.prototype); + expect(Object.prototype.hasOwnProperty.call(resultProps, '__proto__')).toBe(true); + }); +}); diff --git a/packages/@n8n/agents/src/utils/json-schema.ts b/packages/@n8n/agents/src/utils/json-schema.ts new file mode 100644 index 00000000000..efd2b2ab4d9 --- /dev/null +++ b/packages/@n8n/agents/src/utils/json-schema.ts @@ -0,0 +1,110 @@ +import type { JSONSchema7, JSONSchema7Definition } from 'json-schema'; + +/** + * Pure JSON Schema transforms used when handing a raw JSON Schema to a model + * provider (tool input schemas and structured-output schemas). + */ + +/** + * Ensure `type: "object"` is present when an object lists `properties` but omits + * the type — some providers require the explicit type. + */ +export const fixSchema = (schema: JSONSchema7): JSONSchema7 => { + if ( + typeof schema === 'object' && + schema !== null && + 'properties' in schema && + !('type' in schema) + ) { + return { ...schema, type: 'object' as const }; + } + return schema; +}; + +/** + * Recursively set `additionalProperties: false` on every object in a JSON + * Schema so it can be used as a *structured output* schema. + * + * This only applies the JSON Schema keyword — it closes objects to undeclared + * keys. It is NOT a provider "strict mode": it does not require every property + * to be in `required`, so declared-optional fields stay optional. + * + * Anthropic's structured output rejects any object that omits + * `additionalProperties: false`. Zod schemas get this during conversion, but a + * raw JSON Schema (e.g. typed into a workflow node) usually omits it. + * + * Returns a deep copy — the input schema is never mutated. + */ +export function lockAdditionalProperties(schema: JSONSchema7): JSONSchema7 { + const result = lockDefinition(schema); + return typeof result === 'object' ? result : schema; +} + +function lockDefinition(schema: JSONSchema7Definition): JSONSchema7Definition { + if (typeof schema !== 'object' || schema === null) return schema; + + const result: JSONSchema7 = { ...schema }; + + // Normalise objects that list properties but omit the type (mirrors fixSchema). + if (result.properties !== undefined && result.type === undefined) { + result.type = 'object'; + } + + const isObjectSchema = + result.type === 'object' || + (Array.isArray(result.type) && result.type.includes('object')) || + result.properties !== undefined; + + if (isObjectSchema && result.additionalProperties === undefined) { + result.additionalProperties = false; + } + + if (result.properties) { + result.properties = mapDefinitions(result.properties); + } + if (result.$defs) { + result.$defs = mapDefinitions(result.$defs); + } + if (result.definitions) { + result.definitions = mapDefinitions(result.definitions); + } + if (result.items !== undefined) { + result.items = Array.isArray(result.items) + ? result.items.map(lockDefinition) + : lockDefinition(result.items); + } + if (typeof result.additionalProperties === 'object' && result.additionalProperties !== null) { + result.additionalProperties = lockDefinition(result.additionalProperties); + } + for (const key of ['allOf', 'anyOf', 'oneOf'] as const) { + const branch = result[key]; + if (Array.isArray(branch)) { + result[key] = branch.map(lockDefinition); + } + } + if (result.not !== undefined) { + result.not = lockDefinition(result.not); + } + + return result; +} + +/** + * Re-map a record of sub-schemas, locking each value. Uses + * `Object.defineProperty` so a user-supplied property name like `__proto__` + * becomes a normal own property instead of mutating the prototype chain. + */ +function mapDefinitions( + record: Record<string, JSONSchema7Definition>, +): Record<string, JSONSchema7Definition> { + const out: Record<string, JSONSchema7Definition> = {}; + for (const [key, value] of Object.entries(record)) { + Object.defineProperty(out, key, { + value: lockDefinition(value), + enumerable: true, + writable: true, + configurable: true, + }); + } + return out; +} diff --git a/packages/@n8n/agents/src/workspace/filesystem/daytona-filesystem.ts b/packages/@n8n/agents/src/workspace/filesystem/daytona-filesystem.ts new file mode 100644 index 00000000000..3b1b6e99d06 --- /dev/null +++ b/packages/@n8n/agents/src/workspace/filesystem/daytona-filesystem.ts @@ -0,0 +1,178 @@ +/** + * Daytona Filesystem Adapter + * + * Implements a native agents filesystem backed by the Daytona SDK's FileSystem API. + * This gives Daytona workspaces all built-in workspace tools: + * read_file, write_file, edit_file, list_files, grep, ast_edit, etc. + * + * Without this adapter, Daytona workspaces only get sandbox tools (execute_command). + */ +import type { + CopyOptions, + FileContent, + FileEntry, + FileStat, + ListOptions, + ProviderStatus, + ReadOptions, + RemoveOptions, + WriteOptions, +} from '../types'; +import { BaseFilesystem } from './base-filesystem'; +import type { DaytonaSandbox } from '../sandbox/daytona-sandbox'; + +type DaytonaFsHandle = Parameters<Parameters<DaytonaSandbox['withFilesystem']>[0]>[0]; + +/** + * A native agents filesystem implementation that delegates to the Daytona SDK's + * sandbox.instance.fs API for all file operations. + */ +export class DaytonaFilesystem extends BaseFilesystem { + readonly id: string; + readonly name = 'DaytonaFilesystem'; + readonly provider = 'daytona'; + status: ProviderStatus = 'pending'; + + constructor(private readonly sandbox: DaytonaSandbox) { + super(); + this.id = `daytona-fs-${sandbox.id}`; + } + + /** + * Run a filesystem op against the live Daytona handle. `withFilesystem()` ensures the + * sandbox is running with fresh auth and recovers once if the remote was stopped or + * deleted while idle, so callers never touch a stale `fs` handle directly. + */ + private async withFs<T>(op: (fs: DaytonaFsHandle) => Promise<T>): Promise<T> { + await this.ensureReady(); + return await this.sandbox.withFilesystem(op); + } + + async readFile(path: string, options?: ReadOptions): Promise<string | Buffer> { + return await this.withFs(async (fs) => { + const buffer = await fs.downloadFile(path); + if (options?.encoding) { + return buffer.toString(options.encoding); + } + return buffer; + }); + } + + async writeFile(path: string, content: FileContent, options?: WriteOptions): Promise<void> { + await this.withFs(async (fs) => { + if (options?.recursive) { + const dir = path.substring(0, path.lastIndexOf('/')); + if (dir) { + await fs.createFolder(dir, '755'); + } + } + const buffer = + typeof content === 'string' ? Buffer.from(content, 'utf-8') : Buffer.from(content); + await fs.uploadFile(buffer, path); + }); + } + + async appendFile(path: string, content: FileContent): Promise<void> { + await this.withFs(async (fs) => { + let existing: Buffer; + try { + existing = await fs.downloadFile(path); + } catch (error) { + // Only a genuinely missing file means "start empty". Sandbox/provider errors + // (e.g. a stopped sandbox) must bubble up so withFilesystem() can recover. + if (!isDaytona404(error)) throw error; + existing = Buffer.alloc(0); + } + const append = + typeof content === 'string' ? Buffer.from(content, 'utf-8') : Buffer.from(content); + await fs.uploadFile(Buffer.concat([existing, append]), path); + }); + } + + async deleteFile(path: string, options?: RemoveOptions): Promise<void> { + await this.withFs(async (fs) => await fs.deleteFile(path, options?.recursive)); + } + + async copyFile(src: string, dest: string, _options?: CopyOptions): Promise<void> { + await this.withFs(async (fs) => { + const content = await fs.downloadFile(src); + await fs.uploadFile(content, dest); + }); + } + + async moveFile(src: string, dest: string, _options?: CopyOptions): Promise<void> { + await this.withFs(async (fs) => await fs.moveFiles(src, dest)); + } + + async mkdir(path: string, _options?: { recursive?: boolean }): Promise<void> { + // createFolder with mode '755' creates intermediate dirs + await this.withFs(async (fs) => await fs.createFolder(path, '755')); + } + + async rmdir(path: string, options?: RemoveOptions): Promise<void> { + await this.withFs(async (fs) => await fs.deleteFile(path, options?.recursive ?? false)); + } + + async readdir(path: string, _options?: ListOptions): Promise<FileEntry[]> { + return await this.withFs(async (fs) => { + const files = await fs.listFiles(path); + return files.map((f) => ({ + name: f.name ?? '', + type: f.isDir ? ('directory' as const) : ('file' as const), + size: f.size, + })); + }); + } + + async exists(path: string): Promise<boolean> { + return await this.withFs(async (fs) => { + try { + await fs.getFileDetails(path); + return true; + } catch (error) { + // A genuine 404 means the file is absent. Sandbox/provider errors (e.g. a + // stopped sandbox) must bubble up so withFilesystem() can recover instead of + // silently reporting the file as missing. + if (isDaytona404(error)) return false; + throw error; + } + }); + } + + async stat(path: string): Promise<FileStat> { + return await this.withFs(async (fs) => { + let info; + try { + info = await fs.getFileDetails(path); + } catch (error: unknown) { + if (isDaytona404(error)) { + throw new DaytonaFileNotFoundError(path); + } + throw error; + } + return { + name: info.name ?? path.split('/').pop() ?? '', + path, + type: info.isDir ? 'directory' : 'file', + size: info.size ?? 0, + createdAt: new Date(info.modTime ?? 0), + modifiedAt: new Date(info.modTime ?? 0), + }; + }); + } +} + +class DaytonaFileNotFoundError extends Error { + constructor(path: string) { + super(`File not found: ${path}`); + this.name = 'DaytonaFileNotFoundError'; + } +} + +function isDaytona404(error: unknown): boolean { + return ( + error instanceof Error && + 'statusCode' in error && + (error as { statusCode: unknown }).statusCode === 404 + ); +} diff --git a/packages/@n8n/instance-ai/src/workspace/n8n-sandbox-filesystem.ts b/packages/@n8n/agents/src/workspace/filesystem/n8n-sandbox-filesystem.ts similarity index 96% rename from packages/@n8n/instance-ai/src/workspace/n8n-sandbox-filesystem.ts rename to packages/@n8n/agents/src/workspace/filesystem/n8n-sandbox-filesystem.ts index 19e46883d70..8fc412e2e1f 100644 --- a/packages/@n8n/instance-ai/src/workspace/n8n-sandbox-filesystem.ts +++ b/packages/@n8n/agents/src/workspace/filesystem/n8n-sandbox-filesystem.ts @@ -1,3 +1,6 @@ +import { SandboxServiceError } from '@n8n/sandbox-client'; +import { dirname } from 'node:path/posix'; + import type { CopyOptions, FileContent, @@ -8,12 +11,9 @@ import type { ReadOptions, RemoveOptions, WriteOptions, -} from '@n8n/agents'; -import { BaseFilesystem } from '@n8n/agents'; -import { SandboxServiceError } from '@n8n/sandbox-client'; -import { dirname } from 'node:path/posix'; - -import type { N8nSandboxServiceSandbox } from './n8n-sandbox-sandbox'; +} from '../types'; +import { BaseFilesystem } from './base-filesystem'; +import type { N8nSandboxServiceSandbox } from '../sandbox/n8n-sandbox-sandbox'; function getParentDirectory(path: string): string | null { const parent = dirname(path); diff --git a/packages/@n8n/agents/src/workspace/sandbox/base-sandbox.ts b/packages/@n8n/agents/src/workspace/sandbox/base-sandbox.ts index 1fb4a37dd5c..e2f6585954a 100644 --- a/packages/@n8n/agents/src/workspace/sandbox/base-sandbox.ts +++ b/packages/@n8n/agents/src/workspace/sandbox/base-sandbox.ts @@ -102,6 +102,22 @@ export abstract class BaseSandbox implements WorkspaceSandbox { } } + /** + * Drop the cached "running" state so the next `ensureRunning()`/`_start()` + * re-runs the provider's `start()`. Used to recover when the remote sandbox + * was stopped/deleted out from under us (the in-memory status is stale). + * No-op once destroyed/destroying — those are terminal. + * + * Intentionally does NOT touch `startPromise`: clearing it would let a + * concurrent caller bypass the single-flight start dedupe in `_start()` and + * launch a second start. A start that is genuinely in flight will be awaited + * (and deduped) by the next `_start()`. + */ + protected markNeedsStart(): void { + if (this.status === 'destroyed' || this.status === 'destroying') return; + this.status = 'pending'; + } + async ensureRunning(): Promise<void> { if (this.status === 'destroyed') { throw new Error(`Sandbox "${this.name}" has been destroyed`); diff --git a/packages/@n8n/agents/src/workspace/sandbox/create-workspace.ts b/packages/@n8n/agents/src/workspace/sandbox/create-workspace.ts new file mode 100644 index 00000000000..662e4e38f94 --- /dev/null +++ b/packages/@n8n/agents/src/workspace/sandbox/create-workspace.ts @@ -0,0 +1,87 @@ +import { DaytonaSandbox } from './daytona-sandbox'; +import { N8nSandboxServiceSandbox } from './n8n-sandbox-sandbox'; +import type { + CreateSandboxOptions, + SandboxConfig, + SandboxFilesystem, + SandboxInstance, +} from './types'; +import { DaytonaFilesystem } from '../filesystem/daytona-filesystem'; +import { N8nSandboxFilesystem } from '../filesystem/n8n-sandbox-filesystem'; + +export async function createSandbox( + config: SandboxConfig, + options: CreateSandboxOptions = {}, +): Promise<SandboxInstance | undefined> { + return await Promise.resolve(buildSandbox(config, options)); +} + +function buildSandbox( + config: SandboxConfig, + options: CreateSandboxOptions = {}, +): SandboxInstance | undefined { + if (!config.enabled) return undefined; + + const provider = config.provider; + + if (provider === 'daytona') { + const mode = config.getAuthToken ? 'proxy' : 'direct'; + const logger = options.logger ?? config.logger; + return new DaytonaSandbox({ + id: config.id, + name: config.name, + apiKey: config.getAuthToken ? undefined : config.daytonaApiKey, + getAuthToken: config.getAuthToken, + refreshSkewMs: config.refreshSkewMs, + logger, + apiUrl: config.daytonaApiUrl, + labels: config.labels, + ...(config.ephemeral !== undefined ? { ephemeral: config.ephemeral } : {}), + ...(config.autoStopInterval !== undefined + ? { autoStopInterval: config.autoStopInterval } + : {}), + ...(config.autoArchiveInterval !== undefined + ? { autoArchiveInterval: config.autoArchiveInterval } + : {}), + ...(config.autoDeleteInterval !== undefined + ? { autoDeleteInterval: config.autoDeleteInterval } + : {}), + ...(config.image ? { image: config.image } : {}), + ...(config.snapshot ? { snapshot: config.snapshot } : {}), + language: 'typescript', + timeout: config.timeout ?? 300_000, + createTimeoutSeconds: config.createTimeoutSeconds ?? 300, + errorReporter: options.errorReporter, + createStrategyMode: mode, + }); + } + + if (provider === 'n8n-sandbox') { + return new N8nSandboxServiceSandbox({ + apiKey: config.apiKey, + serviceUrl: config.serviceUrl, + timeout: config.timeout ?? 300_000, + }); + } + + const exhaustiveProvider: never = provider; + throw new Error(`Unsupported sandbox provider: ${String(exhaustiveProvider)}`); +} + +export function createFilesystem(sandbox: undefined): undefined; +export function createFilesystem(sandbox: SandboxInstance): SandboxFilesystem; +export function createFilesystem( + sandbox: SandboxInstance | undefined, +): SandboxFilesystem | undefined { + if (!sandbox) return undefined; + + if (sandbox instanceof N8nSandboxServiceSandbox) { + return new N8nSandboxFilesystem(sandbox); + } + + if (sandbox instanceof DaytonaSandbox) { + return new DaytonaFilesystem(sandbox); + } + + throw new Error(`Unsupported sandbox instance: ${sandbox.name}`); +} diff --git a/packages/@n8n/instance-ai/src/workspace/daytona-auth-manager.ts b/packages/@n8n/agents/src/workspace/sandbox/daytona-auth-manager.ts similarity index 93% rename from packages/@n8n/instance-ai/src/workspace/daytona-auth-manager.ts rename to packages/@n8n/agents/src/workspace/sandbox/daytona-auth-manager.ts index 72daf953f2d..c2da30e2683 100644 --- a/packages/@n8n/instance-ai/src/workspace/daytona-auth-manager.ts +++ b/packages/@n8n/agents/src/workspace/sandbox/daytona-auth-manager.ts @@ -1,9 +1,8 @@ import type { Daytona, DaytonaConfig } from '@daytonaio/sdk'; import { getJwtExpiry } from '@n8n/utils'; -import { UnexpectedError } from 'n8n-workflow'; import { loadDaytona } from './lazy-daytona'; -import type { Logger } from '../logger'; +import type { Logger } from './logger'; const DEFAULT_REFRESH_SKEW_MS = 5 * 60 * 1000; const DECODE_FALLBACK_TTL_MS = 30 * 60 * 1000; @@ -56,9 +55,7 @@ export class DaytonaAuthManager { const hasStatic = options.staticApiKey !== undefined; const hasCallback = options.getAuthToken !== undefined; if (hasStatic === hasCallback) { - throw new UnexpectedError( - 'DaytonaAuthManager requires exactly one of staticApiKey or getAuthToken', - ); + throw new Error('DaytonaAuthManager requires exactly one of staticApiKey or getAuthToken'); } this.options = options; this.now = options.now ?? Date.now; @@ -77,7 +74,7 @@ export class DaytonaAuthManager { } await this.refresh(); if (!this.client) { - throw new UnexpectedError('DaytonaAuthManager.refresh did not set a client'); + throw new Error('DaytonaAuthManager.refresh did not set a client'); } return this.client; } diff --git a/packages/@n8n/instance-ai/src/workspace/daytona-sandbox.ts b/packages/@n8n/agents/src/workspace/sandbox/daytona-sandbox.ts similarity index 67% rename from packages/@n8n/instance-ai/src/workspace/daytona-sandbox.ts rename to packages/@n8n/agents/src/workspace/sandbox/daytona-sandbox.ts index 875386d733d..8cc4279b5bf 100644 --- a/packages/@n8n/instance-ai/src/workspace/daytona-sandbox.ts +++ b/packages/@n8n/agents/src/workspace/sandbox/daytona-sandbox.ts @@ -8,25 +8,37 @@ import type { SandboxState, VolumeMount, } from '@daytonaio/sdk'; -import { - BaseSandbox, - type CommandResult, - type ExecuteCommandOptions, - type ProviderStatus, - type SandboxInfo, -} from '@n8n/agents'; import { randomUUID } from 'node:crypto'; +import type { CommandResult, ExecuteCommandOptions, ProviderStatus, SandboxInfo } from '../types'; +import { BaseSandbox } from './base-sandbox'; import { DaytonaAuthManager } from './daytona-auth-manager'; import { loadDaytona } from './lazy-daytona'; -import type { ErrorReporter, Logger } from '../logger'; +import type { ErrorReporter, Logger } from './logger'; const SANDBOX_STATE_STARTED = 'started'; +const SANDBOX_STATE_STOPPED = 'stopped'; +const SANDBOX_STATE_ARCHIVED = 'archived'; const SANDBOX_STATE_DESTROYED = 'destroyed'; const SANDBOX_STATE_DESTROYING = 'destroying'; const SANDBOX_STATE_ERROR = 'error'; const SANDBOX_STATE_BUILD_FAILED = 'build_failed'; +/** + * States a failed operation may recover from by resuming the sandbox: an idle sandbox that + * Daytona auto-stopped, or one that was auto-archived. `start()` brings both back to + * 'started'. Deliberately narrow — it excludes: + * - transient states (creating/starting/stopping/resizing/pending_build): a reset+restart + * would race the in-flight transition; + * - failed states (error/build_failed): those can be silently deleted and recreated, which + * we don't want to trigger off an unrelated operation failure. + * Deletion is handled separately as a `DaytonaNotFoundError` fast-path. + */ +const RECOVERABLE_SANDBOX_STATES: ReadonlySet<string> = new Set([ + SANDBOX_STATE_STOPPED, + SANDBOX_STATE_ARCHIVED, +]); + export interface DaytonaSandboxOptions { id?: string; /** Static Daytona API key (direct mode). Mutually exclusive with `getAuthToken`. */ @@ -108,6 +120,7 @@ export class DaytonaSandbox extends BaseSandbox { private lastClientGeneration = -1; private sandbox?: Sandbox; private workingDirectory?: string; + private recoveryPromise?: Promise<void>; constructor(private readonly options: DaytonaSandboxOptions = {}) { super(); @@ -182,28 +195,44 @@ export class DaytonaSandbox extends BaseSandbox { args: string[] = [], options?: ExecuteCommandOptions, ): Promise<CommandResult> { - await this.ensureRunning(); - await this.ensureAuthFresh(); - const startedAt = Date.now(); - const fullCommand = toShellCommand(command, args); - const result = await this.instance.process.executeCommand( - fullCommand, - options?.cwd, - this.compactEnv(options?.env), - Math.ceil((options?.timeout ?? this.timeout) / 1000), - ); - const stdout = result.artifacts?.stdout ?? result.result ?? ''; - if (stdout) options?.onStdout?.(stdout); + return await this.recoverAndRetry(async () => { + await this.ensureRunning(); + await this.ensureAuthFresh(); + const startedAt = Date.now(); + const fullCommand = toShellCommand(command, args); + const result = await this.instance.process.executeCommand( + fullCommand, + options?.cwd, + this.compactEnv(options?.env), + Math.ceil((options?.timeout ?? this.timeout) / 1000), + ); + const stdout = result.artifacts?.stdout ?? result.result ?? ''; + if (stdout) options?.onStdout?.(stdout); - return { - command, - args, - success: result.exitCode === 0, - exitCode: result.exitCode, - stdout, - stderr: '', - executionTimeMs: Date.now() - startedAt, - }; + return { + command, + args, + success: result.exitCode === 0, + exitCode: result.exitCode, + stdout, + stderr: '', + executionTimeMs: Date.now() - startedAt, + }; + }); + } + + /** + * Run a filesystem operation against the live Daytona FileSystem handle, ensuring the + * sandbox is running with fresh auth first, and recovering once if the remote was + * stopped/deleted while idle. Lets `DaytonaFilesystem` reuse the same recovery as + * `executeCommand` without reaching into private state. + */ + async withFilesystem<T>(op: (fs: Sandbox['fs']) => Promise<T>): Promise<T> { + return await this.recoverAndRetry(async () => { + await this.ensureRunning(); + await this.ensureAuthFresh(); + return await op(this.instance.fs); + }); } /** @@ -266,6 +295,81 @@ export class DaytonaSandbox extends BaseSandbox { return client; } + /** + * Drop the in-memory handle so the next `ensureRunning()`/`start()` re-resolves the + * remote (resume if stopped, recreate if gone). The stale `status: 'running'` is the + * reason a resume is otherwise skipped after a long idle. + */ + private resetLocalHandle(): void { + this.sandbox = undefined; + this.lastClientGeneration = -1; + this.workingDirectory = undefined; + this.markNeedsStart(); + } + + /** + * Whether a failed operation can be recovered by re-resolving the remote. + * + * We don't infer "sandbox unusable" from the failed op's error code, because the code + * isn't a reliable signal: a stopped container returns a 400 from the toolbox, a deleted + * one is 404, auth is 401/403, and transport/proxy conditions vary. Instead we consult + * the authoritative state via the management API — which responds even when the container + * is stopped — and recover only when the sandbox is gone, or in an explicitly recoverable + * state ({@link RECOVERABLE_SANDBOX_STATES}: stopped/archived). Any other state (running, + * a transient transition, or a failed build) propagates the original error so we neither + * mask real failures nor recreate a sandbox off an unrelated error. + * + * A genuine auth failure is handled implicitly: the probe's own `get()` fails too (it + * uses the same credentials), so we fall through to `false` and never recreate. + */ + private async isRecoverable(error: unknown): Promise<boolean> { + if (isSandboxGone(error)) return true; + try { + const client = await this.auth.getClient(); + const remote = await client.get(this.sandboxName); + return remote.state !== undefined && RECOVERABLE_SANDBOX_STATES.has(remote.state); + } catch (probeError) { + // Gone entirely → recreate; anything else (incl. auth) → don't mask the original. + return isSandboxGone(probeError); + } + } + + /** + * Run a sandbox operation, recovering once if the remote was stopped/archived/deleted out + * from under us. On a recoverable failure the sandbox is resumed (or recreated if gone) and + * the operation is retried exactly once; a second failure propagates. + * + * Replaying the operation is safe because recovery only triggers when the probe confirms + * the remote was NOT running (stopped/archived/gone — see {@link isRecoverable}). In those + * states the toolbox/exec request never reached a live container, so it could not have + * partially executed. Operations on a running sandbox are never retried — their error + * propagates untouched. + */ + private async recoverAndRetry<T>(op: () => Promise<T>): Promise<T> { + try { + return await op(); + } catch (error) { + if (!(await this.isRecoverable(error))) throw error; + await this.recover(); + return await op(); + } + } + + /** + * Reset the stale handle and bring the sandbox back to 'started'. Serialized via + * {@link recoveryPromise} so concurrent failed operations share a single resume/recreate + * rather than racing multiple start flows. + */ + private async recover(): Promise<void> { + this.recoveryPromise ??= (async () => { + this.resetLocalHandle(); + await this.ensureRunning(); + })().finally(() => { + this.recoveryPromise = undefined; + }); + await this.recoveryPromise; + } + private async findExistingSandbox(client: Daytona): Promise<Sandbox | null> { try { const sandbox = await client.get(this.sandboxName); @@ -321,13 +425,10 @@ export class DaytonaSandbox extends BaseSandbox { }> { const base: CreateSandboxBaseParams = { language: this.language, - labels: { - ...this.options.labels, - 'n8n-instance-ai-sandbox-id': this.id, - }, autoStopInterval: this.options.autoStopInterval ?? 15, name: this.sandboxName, }; + if (this.options.labels !== undefined) base.labels = this.options.labels; if (this.options.ephemeral !== undefined) base.ephemeral = this.options.ephemeral; if (this.options.autoArchiveInterval !== undefined) { base.autoArchiveInterval = this.options.autoArchiveInterval; diff --git a/packages/@n8n/agents/src/workspace/sandbox/index.ts b/packages/@n8n/agents/src/workspace/sandbox/index.ts new file mode 100644 index 00000000000..489f0dc979e --- /dev/null +++ b/packages/@n8n/agents/src/workspace/sandbox/index.ts @@ -0,0 +1,47 @@ +export { + DEFAULT_SANDBOX_PROVIDER, + normalizeSandboxProvider, +} from './provider'; +export { + WORKSPACE_DIR, + DAYTONA_HOME, + DAYTONA_WORKSPACE_ROOT, + N8N_SANDBOX_HOME, + N8N_SANDBOX_WORKSPACE_ROOT, + getPromptWorkspaceRoot, + getWorkspaceRoot, + type SandboxWorkspace, +} from './workspace-root'; +export { runInSandbox, type SandboxCommandTarget } from './run-in-sandbox'; +export { loadDaytona } from './lazy-daytona'; +export { createFilesystem, createSandbox } from './create-workspace'; +export type { + CommandResult, + CopyOptions, + SandboxProvider, + SandboxConfig, + SandboxInstance, + SandboxFilesystem, + CreateSandboxOptions, + DaytonaSandboxConfig, + N8nSandboxConfig, + DisabledSandboxConfig, + ExecuteCommandOptions, + FileContent, + FileEntry, + FileStat, + ListOptions, + MountConfig, + ProcessHandle, + ProcessInfo, + ProviderStatus, + ReadOptions, + RemoveOptions, + SandboxInfo, + SandboxProcessManager, + SpawnProcessOptions, + WorkspaceFilesystem, + WorkspaceSandbox, + WriteOptions, +} from './types'; +export type { Logger, ErrorReporter } from './logger'; diff --git a/packages/@n8n/instance-ai/src/workspace/lazy-daytona.ts b/packages/@n8n/agents/src/workspace/sandbox/lazy-daytona.ts similarity index 100% rename from packages/@n8n/instance-ai/src/workspace/lazy-daytona.ts rename to packages/@n8n/agents/src/workspace/sandbox/lazy-daytona.ts diff --git a/packages/@n8n/agents/src/workspace/sandbox/logger.ts b/packages/@n8n/agents/src/workspace/sandbox/logger.ts new file mode 100644 index 00000000000..09b2fa71be7 --- /dev/null +++ b/packages/@n8n/agents/src/workspace/sandbox/logger.ts @@ -0,0 +1,16 @@ +export interface Logger { + info(message: string, metadata?: Record<string, unknown>): void; + warn(message: string, metadata?: Record<string, unknown>): void; + error(message: string, metadata?: Record<string, unknown>): void; + debug(message: string, metadata?: Record<string, unknown>): void; +} + +export interface ErrorReporter { + error( + error: unknown, + options?: { + tags?: Record<string, string>; + extra?: Record<string, unknown>; + }, + ): void; +} diff --git a/packages/@n8n/instance-ai/src/workspace/n8n-sandbox-sandbox.ts b/packages/@n8n/agents/src/workspace/sandbox/n8n-sandbox-sandbox.ts similarity index 97% rename from packages/@n8n/instance-ai/src/workspace/n8n-sandbox-sandbox.ts rename to packages/@n8n/agents/src/workspace/sandbox/n8n-sandbox-sandbox.ts index a3712c3708a..d40cb1363e9 100644 --- a/packages/@n8n/instance-ai/src/workspace/n8n-sandbox-sandbox.ts +++ b/packages/@n8n/agents/src/workspace/sandbox/n8n-sandbox-sandbox.ts @@ -1,14 +1,10 @@ -import type { - CommandResult, - ExecuteCommandOptions, - ProviderStatus, - SandboxInfo, -} from '@n8n/agents'; -import { BaseSandbox } from '@n8n/agents'; import { SandboxClient, SandboxServiceError, type SandboxRecord } from '@n8n/sandbox-client'; import assert from 'node:assert/strict'; import { randomUUID } from 'node:crypto'; +import { BaseSandbox } from './base-sandbox'; +import type { CommandResult, ExecuteCommandOptions, ProviderStatus, SandboxInfo } from '../types'; + export interface N8nSandboxServiceSandboxOptions { id?: string; apiKey?: string; diff --git a/packages/@n8n/agents/src/workspace/sandbox/provider.ts b/packages/@n8n/agents/src/workspace/sandbox/provider.ts new file mode 100644 index 00000000000..8ec7dd30e82 --- /dev/null +++ b/packages/@n8n/agents/src/workspace/sandbox/provider.ts @@ -0,0 +1,13 @@ +import type { SandboxProvider } from './types'; + +export const DEFAULT_SANDBOX_PROVIDER: SandboxProvider = 'n8n-sandbox'; + +const SANDBOX_PROVIDERS: ReadonlySet<string> = new Set(['daytona', 'n8n-sandbox']); + +export function isSandboxProvider(value: string | undefined): value is SandboxProvider { + return typeof value === 'string' && SANDBOX_PROVIDERS.has(value); +} + +export function normalizeSandboxProvider(value: string | undefined): SandboxProvider { + return isSandboxProvider(value) ? value : DEFAULT_SANDBOX_PROVIDER; +} diff --git a/packages/@n8n/agents/src/workspace/sandbox/run-in-sandbox.ts b/packages/@n8n/agents/src/workspace/sandbox/run-in-sandbox.ts new file mode 100644 index 00000000000..978457a19f3 --- /dev/null +++ b/packages/@n8n/agents/src/workspace/sandbox/run-in-sandbox.ts @@ -0,0 +1,48 @@ +interface SandboxCommandResult { + exitCode: number; + stdout: string; + stderr: string; +} + +export interface SandboxCommandTarget { + sandbox?: { + provider?: string; + executeCommand?: ( + command: string, + args?: string[], + options?: { cwd?: string }, + ) => Promise<SandboxCommandResult>; + processes?: { + spawn: ( + command: string, + options?: { cwd?: string }, + ) => Promise<{ wait: () => Promise<SandboxCommandResult> }>; + }; + }; +} + +/** + * Execute a shell command in the sandbox and wait for completion. + * Tries `executeCommand` first, falls back to `processes.spawn` + wait. + */ +export async function runInSandbox( + workspace: SandboxCommandTarget, + command: string, + cwd?: string, +): Promise<{ exitCode: number; stdout: string; stderr: string }> { + const sandbox = workspace.sandbox; + if (!sandbox) throw new Error('Workspace has no sandbox'); + + if (sandbox.executeCommand) { + const result = await sandbox.executeCommand(command, [], { cwd }); + return { exitCode: result.exitCode, stdout: result.stdout, stderr: result.stderr }; + } + + if (sandbox.processes) { + const handle = await sandbox.processes.spawn(command, { cwd }); + const result = await handle.wait(); + return { exitCode: result.exitCode, stdout: result.stdout, stderr: result.stderr }; + } + + throw new Error('Sandbox has neither executeCommand nor processes available'); +} diff --git a/packages/@n8n/agents/src/workspace/sandbox/types.ts b/packages/@n8n/agents/src/workspace/sandbox/types.ts new file mode 100644 index 00000000000..83d15cb2e0b --- /dev/null +++ b/packages/@n8n/agents/src/workspace/sandbox/types.ts @@ -0,0 +1,105 @@ +import type { CreateSandboxFromImageParams } from '@daytonaio/sdk'; + +import type { BaseFilesystemOptions } from '../filesystem/base-filesystem'; +import type { + BaseSandboxOptions, + CommandOptions, + CommandResult, + CopyOptions, + ExecuteCommandOptions, + FileContent, + FileEntry, + FileStat, + ListOptions, + MountConfig, + ProcessHandle, + ProcessInfo, + ProviderStatus, + ReadOptions, + RemoveOptions, + SandboxInfo, + SandboxProcessManager, + SpawnProcessOptions, + WorkspaceFilesystem, + WorkspaceSandbox, + WriteOptions, +} from '../types'; +import type { ErrorReporter, Logger } from './logger'; + +export type { + BaseFilesystemOptions, + BaseSandboxOptions, + CommandOptions, + CommandResult, + CopyOptions, + ExecuteCommandOptions, + FileContent, + FileEntry, + FileStat, + ListOptions, + MountConfig, + ProcessHandle, + ProcessInfo, + ProviderStatus, + ReadOptions, + RemoveOptions, + SandboxInfo, + SandboxProcessManager, + SpawnProcessOptions, + WorkspaceFilesystem, + WorkspaceSandbox, + WriteOptions, +}; + +export type SandboxProvider = 'daytona' | 'n8n-sandbox'; + +export interface SandboxConfigBase { + provider: SandboxProvider; + timeout?: number; +} + +export interface DisabledSandboxConfig extends SandboxConfigBase { + enabled: false; +} + +export interface DaytonaSandboxConfig extends SandboxConfigBase { + enabled: true; + provider: 'daytona'; + id?: string; + name?: string; + labels?: Record<string, string>; + daytonaApiUrl?: string; + daytonaApiKey?: string; + image?: CreateSandboxFromImageParams['image']; + snapshot?: string; + /** + * When true, Daytona auto-deletes the sandbox when it stops (instead of leaving it + * stopped). Used for throwaway sandboxes (e.g. eval runs) so they don't accumulate. + * Overrides {@link autoDeleteInterval} (Daytona forces it to 0 when ephemeral). + */ + ephemeral?: boolean; + autoStopInterval?: number; + autoArchiveInterval?: number; + autoDeleteInterval?: number; + createTimeoutSeconds?: number; + getAuthToken?: () => Promise<string>; + refreshSkewMs?: number; + logger?: Logger; +} + +export interface N8nSandboxConfig extends SandboxConfigBase { + enabled: true; + provider: 'n8n-sandbox'; + serviceUrl: string; + apiKey?: string; +} + +export type SandboxConfig = DisabledSandboxConfig | DaytonaSandboxConfig | N8nSandboxConfig; + +export type SandboxInstance = WorkspaceSandbox; +export type SandboxFilesystem = WorkspaceFilesystem; + +export interface CreateSandboxOptions { + logger?: Logger; + errorReporter?: ErrorReporter; +} diff --git a/packages/@n8n/agents/src/workspace/sandbox/workspace-root.ts b/packages/@n8n/agents/src/workspace/sandbox/workspace-root.ts new file mode 100644 index 00000000000..1fefdccdc97 --- /dev/null +++ b/packages/@n8n/agents/src/workspace/sandbox/workspace-root.ts @@ -0,0 +1,81 @@ +import { runInSandbox, type SandboxCommandTarget } from './run-in-sandbox'; +import type { SandboxProvider } from './types'; + +export const WORKSPACE_DIR = 'workspace'; +export const DAYTONA_HOME = '/home/daytona'; +export const DAYTONA_WORKSPACE_ROOT = `${DAYTONA_HOME}/${WORKSPACE_DIR}`; +export const N8N_SANDBOX_HOME = '/home/user'; +export const N8N_SANDBOX_WORKSPACE_ROOT = `${N8N_SANDBOX_HOME}/${WORKSPACE_DIR}`; + +export function getPromptWorkspaceRoot(provider: SandboxProvider): string { + switch (provider) { + case 'daytona': + return DAYTONA_WORKSPACE_ROOT; + case 'n8n-sandbox': + return N8N_SANDBOX_WORKSPACE_ROOT; + } +} + +export interface SandboxWorkspace extends SandboxCommandTarget { + filesystem?: { + provider?: string; + basePath?: string; + init?: () => Promise<void>; + }; +} + +const workspaceRootCache = new WeakMap<SandboxWorkspace, string>(); + +function getLocalFilesystemRoot(workspace: SandboxWorkspace): string | null { + const filesystem = workspace.filesystem; + if (!filesystem) return null; + + const provider = filesystem.provider; + if (provider !== 'local' && provider !== 'lazy') return null; + + const basePath = Reflect.get(filesystem, 'basePath'); + return typeof basePath === 'string' && basePath.length > 0 ? basePath : null; +} + +async function initializeLazyFilesystem(workspace: SandboxWorkspace): Promise<void> { + const filesystem = workspace.filesystem; + if (filesystem?.provider !== 'lazy') return; + + await filesystem.init?.(); +} + +function getFallbackHome(workspace: SandboxWorkspace): string { + switch (workspace.sandbox?.provider) { + case 'n8n-sandbox': + return N8N_SANDBOX_HOME; + case 'daytona': + return DAYTONA_HOME; + case undefined: + default: + return DAYTONA_HOME; + } +} + +export async function getWorkspaceRoot(workspace: SandboxWorkspace): Promise<string> { + const cached = workspaceRootCache.get(workspace); + if (cached) return cached; + + const localRoot = getLocalFilesystemRoot(workspace); + if (localRoot) { + workspaceRootCache.set(workspace, localRoot); + return localRoot; + } + + await initializeLazyFilesystem(workspace); + const initializedLocalRoot = getLocalFilesystemRoot(workspace); + if (initializedLocalRoot) { + workspaceRootCache.set(workspace, initializedLocalRoot); + return initializedLocalRoot; + } + + const result = await runInSandbox(workspace, 'echo $HOME'); + const home = result.stdout.trim() || getFallbackHome(workspace); + const root = `${home}/${WORKSPACE_DIR}`; + workspaceRootCache.set(workspace, root); + return root; +} diff --git a/packages/@n8n/agents/src/workspace/tools/batch-str-replace-file.ts b/packages/@n8n/agents/src/workspace/tools/batch-str-replace-file.ts index 59276e4e0ca..92ea2c5dd5b 100644 --- a/packages/@n8n/agents/src/workspace/tools/batch-str-replace-file.ts +++ b/packages/@n8n/agents/src/workspace/tools/batch-str-replace-file.ts @@ -1,4 +1,4 @@ -import { TextEditorDocument, type BatchReplaceResult } from '@n8n/ai-utilities/text-editor'; +import { TextEditorDocument, type BatchReplaceResult } from '@n8n/ai-utilities/generic-text-editor'; import { z } from 'zod'; import { Tool } from '../../sdk/tool'; diff --git a/packages/@n8n/agents/src/workspace/tools/str-replace-file.ts b/packages/@n8n/agents/src/workspace/tools/str-replace-file.ts index f9128d87871..e0b0b251dab 100644 --- a/packages/@n8n/agents/src/workspace/tools/str-replace-file.ts +++ b/packages/@n8n/agents/src/workspace/tools/str-replace-file.ts @@ -1,4 +1,4 @@ -import { TextEditorDocument } from '@n8n/ai-utilities/text-editor'; +import { TextEditorDocument } from '@n8n/ai-utilities/generic-text-editor'; import { z } from 'zod'; import { Tool } from '../../sdk/tool'; diff --git a/packages/@n8n/agents/tsconfig.build.json b/packages/@n8n/agents/tsconfig.build.json index ee0e3e20fda..e08cb937d03 100644 --- a/packages/@n8n/agents/tsconfig.build.json +++ b/packages/@n8n/agents/tsconfig.build.json @@ -3,8 +3,7 @@ "compilerOptions": { "composite": true, "rootDir": "src", - "outDir": "dist", - "tsBuildInfoFile": "dist/build.tsbuildinfo" + "outDir": "dist" }, "include": ["src/**/*.ts"], "exclude": ["src/**/__tests__/**"] diff --git a/packages/@n8n/agents/tsconfig.json b/packages/@n8n/agents/tsconfig.json index f989681db5e..1e07f95211b 100644 --- a/packages/@n8n/agents/tsconfig.json +++ b/packages/@n8n/agents/tsconfig.json @@ -1,8 +1,7 @@ { "extends": "@n8n/typescript-config/tsconfig.common.json", "compilerOptions": { - "types": ["node", "vitest/globals"], - "tsBuildInfoFile": "dist/typecheck.tsbuildinfo" + "types": ["node", "vitest/globals"] }, "include": ["src/**/*.ts"], "exclude": ["dist/**/*", "node_modules/**/*"] diff --git a/packages/@n8n/agents/vite.config.ts b/packages/@n8n/agents/vite.config.ts index 237dc8bb2db..e4acff98476 100644 --- a/packages/@n8n/agents/vite.config.ts +++ b/packages/@n8n/agents/vite.config.ts @@ -16,8 +16,8 @@ import { configDefaults } from 'vitest/config'; * because those tests deliberately exercise the real provider packages. */ const REWRITE_REQUIRE_TARGETS = [ - '/src/runtime/lazy-ai.ts', - '/src/runtime/model-factory.ts', + '/src/runtime/model/lazy-ai.ts', + '/src/runtime/model/model-factory.ts', '/src/utils/parse.ts', ]; diff --git a/packages/@n8n/ai-node-sdk/package.json b/packages/@n8n/ai-node-sdk/package.json index 97383e79542..f89108745b7 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.15.0", + "version": "0.17.0", "description": "SDK for building AI nodes in n8n", "types": "dist/esm/index.d.ts", "module": "dist/esm/index.js", @@ -38,5 +38,6 @@ "@n8n/typescript-config": "workspace:*", "@n8n/vitest-config": "workspace:*", "vitest": "catalog:" - } + }, + "license": "LicenseRef-n8n-sustainable-use" } diff --git a/packages/@n8n/ai-node-sdk/tsconfig.build.cjs.json b/packages/@n8n/ai-node-sdk/tsconfig.build.cjs.json index 37c8ef0936e..7cd314eeb42 100644 --- a/packages/@n8n/ai-node-sdk/tsconfig.build.cjs.json +++ b/packages/@n8n/ai-node-sdk/tsconfig.build.cjs.json @@ -3,7 +3,6 @@ "compilerOptions": { "rootDir": "src", "outDir": "dist/cjs", - "tsBuildInfoFile": "dist/cjs/typecheck.tsbuildinfo", "declaration": true }, "include": ["src/**/*.ts"], diff --git a/packages/@n8n/ai-node-sdk/tsconfig.build.json b/packages/@n8n/ai-node-sdk/tsconfig.build.json index 87d5dd2f856..c134a3ee7ea 100644 --- a/packages/@n8n/ai-node-sdk/tsconfig.build.json +++ b/packages/@n8n/ai-node-sdk/tsconfig.build.json @@ -3,8 +3,7 @@ "compilerOptions": { "composite": true, "rootDir": "src", - "outDir": "dist", - "tsBuildInfoFile": "dist/build.tsbuildinfo" + "outDir": "dist" }, "include": ["src/**/*.ts"], "exclude": ["src/**/__tests__/**", "src/**/*.test.ts"] diff --git a/packages/@n8n/ai-node-sdk/tsconfig.json b/packages/@n8n/ai-node-sdk/tsconfig.json index 2c718f0fd98..8fad32d5999 100644 --- a/packages/@n8n/ai-node-sdk/tsconfig.json +++ b/packages/@n8n/ai-node-sdk/tsconfig.json @@ -4,8 +4,7 @@ "@n8n/typescript-config/tsconfig.backend.json" ], "compilerOptions": { - "types": ["node", "vitest/globals"], - "tsBuildInfoFile": "dist/typecheck.tsbuildinfo" + "types": ["node", "vitest/globals"] }, "include": ["src/**/*.ts"] } diff --git a/packages/@n8n/ai-utilities/package.json b/packages/@n8n/ai-utilities/package.json index 668c0e14cb2..741b0c65d97 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.18.0", + "version": "0.20.0", "description": "Utilities for building AI nodes in n8n", "types": "dist/esm/index.d.ts", "module": "dist/esm/index.js", @@ -8,6 +8,9 @@ "typesVersions": { "*": { "text-editor": [ + "dist/esm/utils/workflow-text-editor.d.ts" + ], + "generic-text-editor": [ "dist/esm/utils/text-editor.d.ts" ], "node-catalog": [ @@ -31,6 +34,11 @@ "require": "./dist/cjs/index.js" }, "./text-editor": { + "types": "./dist/esm/utils/workflow-text-editor.d.ts", + "import": "./dist/esm/utils/workflow-text-editor.js", + "require": "./dist/cjs/utils/workflow-text-editor.js" + }, + "./generic-text-editor": { "types": "./dist/esm/utils/text-editor.d.ts", "import": "./dist/esm/utils/text-editor.js", "require": "./dist/cjs/utils/text-editor.js" @@ -85,7 +93,7 @@ "@types/mime-types": "catalog:", "tsx": "catalog:", "axios": "catalog:", - "n8n-workflow": "workspace:*" + "nock": "catalog:" }, "dependencies": { "zod": "catalog:", @@ -96,18 +104,18 @@ "@langchain/textsplitters": "1.0.1", "@langchain/openai": "catalog:", "langchain": "catalog:", + "lodash": "catalog:", "@n8n/config": "workspace:*", "@n8n/typescript-config": "workspace:*", "@n8n/utils": "workspace:*", + "n8n-workflow": "workspace:*", "tmp-promise": "3.0.3", "js-tiktoken": "catalog:", "https-proxy-agent": "catalog:", "@thednp/dommatrix": "^2.0.12", "pdf-parse": "catalog:", - "proxy-from-env": "^1.1.0", - "undici": "^6.21.0" + "proxy-from-env": "catalog:", + "undici": "catalog:undici-v6" }, - "peerDependencies": { - "n8n-workflow": "*" - } + "license": "LicenseRef-n8n-sustainable-use" } diff --git a/packages/@n8n/ai-utilities/src/__tests__/utils/text-editor.test.ts b/packages/@n8n/ai-utilities/src/__tests__/utils/text-editor.test.ts index c9b9f0c1810..63ef43195a1 100644 --- a/packages/@n8n/ai-utilities/src/__tests__/utils/text-editor.test.ts +++ b/packages/@n8n/ai-utilities/src/__tests__/utils/text-editor.test.ts @@ -1,10 +1,16 @@ +import { describe, expect, it } from 'vitest'; + import { + FileNotFoundError, + InvalidLineNumberError, + InvalidPathError, + InvalidViewRangeError, MultipleMatchesError, NoMatchFoundError, TextEditorDocument, findDivergenceContext, parseStrReplacements, -} from '../../utils/text-editor'; +} from 'src/utils/text-editor'; describe('TextEditorDocument', () => { it('views text with line numbers', () => { @@ -42,6 +48,20 @@ describe('TextEditorDocument', () => { expect(editor.getText()).toBe('const value = "$& $1 $$";'); }); + it('keeps master behavior for empty old_str', () => { + const editor = new TextEditorDocument({ initialText: 'hello\nworld' }); + + const result = editor.execute({ + command: 'str_replace', + path: '/file.ts', + old_str: '', + new_str: 'REPLACED', + }); + + expect(result).toBe('Edit applied successfully.'); + expect(editor.getText()).toBe('helloREPLACEDworld'); + }); + it('rejects missing and non-unique matches', () => { const editor = new TextEditorDocument({ initialText: 'const x = 1;\nconst x = 1;' }); @@ -88,16 +108,21 @@ describe('TextEditorDocument', () => { { old_str: 'const c = 3;', new_str: 'const c = 30;' }, ]); + expect(result).not.toBe('All 3 replacements applied successfully.'); + if (typeof result === 'string') { + throw new Error(`Expected batch result details, got: ${result}`); + } expect(result).toEqual([ { index: 0, old_str: 'const a = 1;', status: 'success' }, { index: 1, old_str: 'const missing = 0;', status: 'failed', - error: expect.stringContaining('No exact match found'), + error: result[1]?.error, }, { index: 2, old_str: 'const c = 3;', status: 'not_attempted' }, ]); + expect(result[1]?.error).toContain('No exact match found'); expect(editor.getText()).toBe(original); }); @@ -110,6 +135,22 @@ describe('TextEditorDocument', () => { }); }); +describe('text editor errors', () => { + it('formats matching and line errors', () => { + expect(new NoMatchFoundError('search string').message).toContain('No exact match found'); + expect(new MultipleMatchesError(3).message).toContain('Found 3 matches'); + expect(new InvalidLineNumberError(10, 5).message).toContain('Invalid line number 10'); + expect(new InvalidViewRangeError(4, 2, 10).message).toContain('end (2)'); + }); + + it('formats path and missing-file errors without workflow-specific defaults', () => { + const pathError = new InvalidPathError('/bad/path.ts', '/file.ts'); + expect(pathError.message).toContain('/bad/path.ts'); + expect(pathError.message).toContain('/file.ts'); + expect(new FileNotFoundError().message).toContain('No file content exists'); + }); +}); + describe('text editor helpers', () => { it('finds useful divergence context', () => { const result = findDivergenceContext('line1\nline2\nline3', 'line1\nline2\nwrong'); @@ -118,6 +159,29 @@ describe('text editor helpers', () => { expect(result).toContain('line3'); }); + it('returns undefined when divergence prefix is too short', () => { + const result = findDivergenceContext('abcdefghij\nklmnop', 'xyz_completely_different'); + + expect(result).toBeUndefined(); + }); + + it('escapes whitespace and includes match percentage', () => { + const result = findDivergenceContext('hello world\nfoo bar\n', 'hello world\nfoo baz\t'); + + expect(result).toContain('\\t'); + expect(result).toMatch(/\d+%/); + }); + + it('shows nearby file lines around the divergence point', () => { + const code = ' function foo() {\n return 1;\n }\n function bar() {\n return 2;\n }'; + const searchStr = + ' function foo() {\n return 1;\n }\n function bar() {\n return WRONG;\n }'; + + const result = findDivergenceContext(code, searchStr); + + expect(result).toContain('return 2;'); + }); + it('parses replacements from arrays and JSON strings', () => { const arrayResult = parseStrReplacements([{ old_str: 'old', new_str: 'new' }]); const stringResult = parseStrReplacements('[{"old_str":"old","new_str":"new"}]'); @@ -125,4 +189,10 @@ describe('text editor helpers', () => { expect(arrayResult).toEqual([{ old_str: 'old', new_str: 'new' }]); expect(stringResult).toEqual([{ old_str: 'old', new_str: 'new' }]); }); + + it('parses empty old_str to preserve master behavior', () => { + expect(parseStrReplacements([{ old_str: '', new_str: 'new' }])).toEqual([ + { old_str: '', new_str: 'new' }, + ]); + }); }); diff --git a/packages/@n8n/ai-utilities/src/__tests__/utils/workflow-text-editor.test.ts b/packages/@n8n/ai-utilities/src/__tests__/utils/workflow-text-editor.test.ts new file mode 100644 index 00000000000..8b3e757d901 --- /dev/null +++ b/packages/@n8n/ai-utilities/src/__tests__/utils/workflow-text-editor.test.ts @@ -0,0 +1,38 @@ +import { + FileNotFoundError, + InvalidPathError, + TextEditorDocument, +} from 'src/utils/workflow-text-editor'; + +describe('text editor compatibility exports', () => { + it('keeps the ai-utilities InvalidPathError default supported path', () => { + const error = new InvalidPathError('/tmp/workflow.js'); + + expect(error.message).toBe('Invalid path "/tmp/workflow.js". Only /workflow.js is supported.'); + }); + + it('keeps the ai-utilities FileNotFoundError default message', () => { + const error = new FileNotFoundError(); + + expect(error.message).toBe('No workflow code exists yet. Use create first.'); + }); + + it('keeps TextEditorDocument missing-file errors workflow-specific', () => { + const editor = new TextEditorDocument(); + + expect(() => editor.execute({ command: 'view', path: '/workflow.js' })).toThrow( + FileNotFoundError, + ); + expect(() => editor.execute({ command: 'view', path: '/workflow.js' })).toThrow( + 'No workflow code exists yet. Use create first.', + ); + }); + + it('keeps TextEditorDocument path errors workflow-specific', () => { + const editor = new TextEditorDocument({ supportedPath: '/workflow.js' }); + + expect(() => editor.execute({ command: 'view', path: '/tmp/workflow.js' })).toThrow( + InvalidPathError, + ); + }); +}); diff --git a/packages/@n8n/ai-utilities/src/index.ts b/packages/@n8n/ai-utilities/src/index.ts index 764b90815b0..f741c40f81b 100644 --- a/packages/@n8n/ai-utilities/src/index.ts +++ b/packages/@n8n/ai-utilities/src/index.ts @@ -26,7 +26,7 @@ export { formatTextWithLineNumbers, findDivergenceContext, parseStrReplacements, -} from './utils/text-editor'; +} from './utils/workflow-text-editor'; export type { ViewCommand, CreateCommand, @@ -40,7 +40,7 @@ export type { StrReplacement, BatchReplaceResult, TextEditorDocumentOptions, -} from './utils/text-editor'; +} from './utils/workflow-text-editor'; export { estimateTokensFromStringList, estimateTokensByCharCount, diff --git a/packages/@n8n/ai-utilities/src/node-catalog/__tests__/search-engine.test.ts b/packages/@n8n/ai-utilities/src/node-catalog/__tests__/search-engine.test.ts index b8a9262ecb7..d5532095059 100644 --- a/packages/@n8n/ai-utilities/src/node-catalog/__tests__/search-engine.test.ts +++ b/packages/@n8n/ai-utilities/src/node-catalog/__tests__/search-engine.test.ts @@ -253,6 +253,114 @@ describe('CodeBuilderNodeSearchEngine', () => { }); }); + describe('searchByName - multi-word queries', () => { + // Nodes representative of the real-world queries that previously returned + // no results (tracked via MCP `queriesWithNoResults` telemetry). Before the + // multi-word split, sublimeSearch matched the whole query as one ordered + // subsequence against a single field, so none of these resolved. + const multiWordNodes = [ + createNodeType({ + name: 'n8n-nodes-base.webhook', + displayName: 'Webhook', + description: 'Starts the workflow on a webhook call', + group: ['trigger'], + }), + createNodeType({ + name: 'n8n-nodes-base.telegram', + displayName: 'Telegram', + description: 'Sends data to Telegram', + }), + createNodeType({ + name: '@n8n/n8n-nodes-langchain.lmChatAnthropic', + displayName: 'Anthropic Chat Model', + description: 'Language model from Anthropic', + outputs: ['ai_languageModel'], + }), + createNodeType({ + name: 'n8n-nodes-base.set', + displayName: 'Edit Fields', + description: 'Modify, add, or remove item fields', + }), + createNodeType({ + name: 'n8n-nodes-base.code', + displayName: 'Code', + description: 'Run custom JavaScript code', + }), + createNodeType({ + name: 'n8n-nodes-base.gmail', + displayName: 'Gmail', + description: 'Consume the Gmail API', + }), + createNodeType({ + name: 'n8n-nodes-base.googleSheets', + displayName: 'Google Sheets', + description: 'Read, update and write data to Google Sheets', + }), + createNodeType({ + name: 'n8n-nodes-base.slack', + displayName: 'Slack', + description: 'Consume the Slack API', + }), + createNodeType({ + name: '@n8n/n8n-nodes-langchain.agent', + displayName: 'AI Agent', + description: 'Generates an action plan and executes it', + }), + createNodeType({ + name: '@n8n/n8n-nodes-langchain.memoryBufferWindow', + displayName: 'Simple Memory', + description: 'Stores the last N messages in a buffer window', + codex: { alias: ['Window Buffer Memory'] }, + outputs: ['ai_memory'], + }), + ]; + + let engine: CodeBuilderNodeSearchEngine; + + beforeEach(() => { + engine = new CodeBuilderNodeSearchEngine(multiWordNodes); + }); + + it.each([ + ['webhook trigger', 'n8n-nodes-base.webhook'], + ['telegram send message', 'n8n-nodes-base.telegram'], + ['anthropic claude', '@n8n/n8n-nodes-langchain.lmChatAnthropic'], + ['set edit fields', 'n8n-nodes-base.set'], + ['code javascript', 'n8n-nodes-base.code'], + ['gmail send email', 'n8n-nodes-base.gmail'], + ['google sheets append', 'n8n-nodes-base.googleSheets'], + ['slack send message', 'n8n-nodes-base.slack'], + ['langchain agent', '@n8n/n8n-nodes-langchain.agent'], + ['ai agent langchain', '@n8n/n8n-nodes-langchain.agent'], + ['memory buffer window', '@n8n/n8n-nodes-langchain.memoryBufferWindow'], + ['window buffer memory', '@n8n/n8n-nodes-langchain.memoryBufferWindow'], + ])('resolves "%s" to %s (previously no results)', (query, expectedNodeName) => { + const results = engine.searchByName(query); + + expect(results.map((r) => r.name)).toContain(expectedNodeName); + }); + + it('splits a multi-word query and merges per-term matches', () => { + // "webhook" matches the trigger, "trigger" alone does not narrow it away + const results = engine.searchByName('webhook trigger'); + + expect(results.map((r) => r.name)).toContain('n8n-nodes-base.webhook'); + }); + + it('matches an alias term within a multi-word query', () => { + // Only the alias "Window Buffer Memory" carries these words in this order + const results = engine.searchByName('window buffer memory'); + + expect(results.map((r) => r.name)).toContain('@n8n/n8n-nodes-langchain.memoryBufferWindow'); + }); + + it('still returns no results for genuinely unknown multi-word queries', () => { + const results = engine.searchByName('nonexistent imaginary integration'); + + expect(results).toEqual([]); + }); + }); + describe('searchByConnectionType', () => { it('should find nodes with exact connection type match', () => { const results = searchEngine.searchByConnectionType(NodeConnectionTypes.AiTool); @@ -662,6 +770,30 @@ describe('CodeBuilderNodeSearchEngine', () => { expect(results[0].builderHintMessage).toBe('Use with output parser for structured output'); }); + it('should filter out null/undefined entries in builderHint.inputs', () => { + const agentNode = createNodeType({ + name: '@n8n/n8n-nodes-langchain.agent', + displayName: 'AI Agent', + builderHint: { + inputs: { + ai_languageModel: { required: true }, + // JSON-sourced data can carry `null`; a Partial config can be `undefined`. + // Both must be skipped instead of throwing on `config.required`. + ai_memory: undefined, + ai_tool: null, + } as unknown as NonNullable<INodeTypeDescription['builderHint']>['inputs'], + }, + }); + const engine = new CodeBuilderNodeSearchEngine([agentNode]); + + const results = engine.searchByName('agent'); + + expect(results).toHaveLength(1); + expect(results[0].subnodeRequirements).toEqual([ + { connectionType: 'ai_languageModel', required: true }, + ]); + }); + it('should not include subnodeRequirements for nodes without builderHint.inputs', () => { const basicNode = createNodeType({ name: 'n8n-nodes-base.httpRequest', diff --git a/packages/@n8n/ai-utilities/src/node-catalog/search-engine.ts b/packages/@n8n/ai-utilities/src/node-catalog/search-engine.ts index ac1b8e50f8d..e2e7b73e121 100644 --- a/packages/@n8n/ai-utilities/src/node-catalog/search-engine.ts +++ b/packages/@n8n/ai-utilities/src/node-catalog/search-engine.ts @@ -41,14 +41,16 @@ const DEFAULT_SUBNODES: Record<string, string[]> = { }; /** - * Search keys configuration for sublimeSearch - * Keys are ordered by importance with corresponding weights + * Search keys for sublimeSearch. + * + * `description` is intentionally excluded: with the per-word splitting in + * `fuzzySearchNodes`, fuzzy-matching short terms against long descriptions is too + * noisy (the `descriptionMatchScore` substring fallback covers it instead). */ const NODE_SEARCH_KEYS = [ { key: 'displayName', weight: 1.5 }, { key: 'name', weight: 1.3 }, { key: 'codex.alias', weight: 1.0 }, - { key: 'description', weight: 0.7 }, ]; /** @@ -61,6 +63,26 @@ function getTypeName(nodeName: string): string { return lastDotIndex >= 0 ? nodeName.substring(lastDotIndex + 1) : nodeName; } +/** + * Count how many query terms appear as substrings of a node's description. + * Used as a fallback for nodes the fuzzy/name passes miss, since `description` + * is no longer a sublimeSearch key (see {@link NODE_SEARCH_KEYS}). + */ +function descriptionMatchScore( + description: string | undefined, + queryLower: string, + queryTerms: string[], +): number { + if (!description) return 0; + const descriptionLower = description.toLowerCase(); + if (queryTerms.length === 0) return descriptionLower.includes(queryLower) ? 1 : 0; + let matches = 0; + for (const term of queryTerms) { + if (descriptionLower.includes(term)) matches += 1; + } + return matches; +} + /** * Scoring weights for connection type matching */ @@ -73,17 +95,19 @@ function getLatestVersion(version: number | number[]): number { return Array.isArray(version) ? Math.max(...version) : version; } -/** - * Extract subnode requirements from builderHint.inputs - */ function extractSubnodeRequirements(inputs?: BuilderHintInputs): SubnodeRequirement[] { if (!inputs) return []; - return Object.entries(inputs).map(([connectionType, config]) => ({ - connectionType, - required: config.required, - ...(config.displayOptions && { displayOptions: config.displayOptions }), - })); + return Object.entries(inputs) + .filter( + (entry): entry is [string, NonNullable<(typeof entry)[1]>] => + entry[1] !== null && entry[1] !== undefined, + ) + .map(([connectionType, config]) => ({ + connectionType, + required: config.required, + ...(config.displayOptions && { displayOptions: config.displayOptions }), + })); } function dedupeNodes(nodes: LeanNodeTypeDescription[]): LeanNodeTypeDescription[] { @@ -123,10 +147,117 @@ export class CodeBuilderNodeSearchEngine { } /** - * Search nodes by name, display name, or description - * Always return the latest version of a node + * Fuzzy-search a list of nodes by query, handling multi-word queries by + * splitting into individual terms and merging results. Falls back to + * description keyword matching and direct type-name / display-name matching + * for nodes the fuzzy search missed. + * + * Ported from the Instance AI `NodeSearchEngine` so code-builder / MCP node + * search resolves natural-language multi-word queries (e.g. "telegram send + * message", "ai agent langchain") instead of returning no results — these + * previously failed because sublimeSearch matched the whole query string as a + * single ordered character subsequence against one field. + */ + private fuzzySearchNodes( + query: string, + candidates: LeanNodeTypeDescription[], + limit?: number, + ): Array<{ item: LeanNodeTypeDescription; score: number }> { + const queryLower = query.toLowerCase().trim(); + const queryTerms = queryLower.split(/\s+/).filter((t) => t.length > 1); + const isMultiWord = queryTerms.length > 1; + + type ScoredNode = { item: LeanNodeTypeDescription; score: number }; + let searchResults: ScoredNode[]; + + // For multi-word queries, search each term individually then merge. + // sublimeSearch breaks down on multi-word queries because it tries to + // fuzzy-match the entire string as one character sequence. + if (isMultiWord) { + const scoreMap = new Map<string, ScoredNode>(); + for (const term of queryTerms) { + const termResults = sublimeSearch<LeanNodeTypeDescription>( + term, + candidates, + NODE_SEARCH_KEYS, + ).slice(0, limit); + for (const r of termResults) { + const existing = scoreMap.get(r.item.name); + if (!existing || r.score > existing.score) { + scoreMap.set(r.item.name, { item: r.item, score: r.score }); + } + } + } + searchResults = [...scoreMap.values()]; + } else { + searchResults = sublimeSearch<LeanNodeTypeDescription>(query, candidates, NODE_SEARCH_KEYS); + } + + const fuzzyResultNames = new Set(searchResults.map((r) => r.item.name)); + + // Description keyword fallback for nodes the fuzzy pass missed + const remainingDescriptionMatches = + limit === undefined ? Number.POSITIVE_INFINITY : Math.max(0, limit - searchResults.length); + if (remainingDescriptionMatches > 0) { + const descriptionResults: ScoredNode[] = []; + for (const item of candidates) { + if (fuzzyResultNames.has(item.name)) continue; + const score = descriptionMatchScore(item.description, queryLower, queryTerms); + if (score === 0) continue; + descriptionResults.push({ item, score }); + fuzzyResultNames.add(item.name); + if (descriptionResults.length >= remainingDescriptionMatches) break; + } + searchResults = [...searchResults, ...descriptionResults]; + } + + // Direct type name / display name match — catches nodes fuzzy search missed. + // `displayName` is guarded against undefined to tolerate malformed node types. + const typeNameMatches = candidates + .filter((node) => { + if (fuzzyResultNames.has(node.name)) return false; + const typeName = getTypeName(node.name).toLowerCase(); + const displayName = (node.displayName ?? '').toLowerCase(); + if (typeName === queryLower || displayName === queryLower) return true; + return queryTerms.some( + (term) => + typeName === term || + typeName.includes(term) || + displayName === term || + displayName.includes(term), + ); + }) + .map((item) => ({ item, score: 0 })); + + // Merge and sort: exact type/display name matches first, then by fuzzy score + const allResults = [...searchResults, ...typeNameMatches]; + allResults.sort((a, b) => { + const typeNameA = getTypeName(a.item.name).toLowerCase(); + const displayNameA = (a.item.displayName ?? '').toLowerCase(); + const typeNameB = getTypeName(b.item.name).toLowerCase(); + const displayNameB = (b.item.displayName ?? '').toLowerCase(); + const exactA = + typeNameA === queryLower || + displayNameA === queryLower || + queryTerms.some((t) => typeNameA === t || displayNameA === t); + const exactB = + typeNameB === queryLower || + displayNameB === queryLower || + queryTerms.some((t) => typeNameB === t || displayNameB === t); + if (exactA && !exactB) return -1; + if (!exactA && exactB) return 1; + return b.score - a.score; + }); + + return allResults; + } + + /** + * Search nodes by name, display name, alias, or description. + * Always return the latest version of a node. * @param query - The search query string * @param limit - Maximum number of results to return + * @param nodeFilter - Optional predicate restricting which node IDs are searched * @returns Array of matching nodes sorted by relevance */ searchByName( @@ -138,36 +269,7 @@ export class CodeBuilderNodeSearchEngine { ? this.nodeTypes.filter((node) => nodeFilter(node.name)) : this.nodeTypes; - // Use sublimeSearch for fuzzy matching - const searchResults = sublimeSearch<LeanNodeTypeDescription>( - query, - nodeTypes, - NODE_SEARCH_KEYS, - ); - - const queryLower = query.toLowerCase().trim(); - const fuzzyResultNames = new Set(searchResults.map((r) => r.item.name)); - - // Direct type name match on all nodeTypes (catches nodes sublimeSearch ranked too low) - const typeNameMatches = nodeTypes - .filter((node) => { - if (fuzzyResultNames.has(node.name)) return false; - return getTypeName(node.name).toLowerCase() === queryLower; - }) - .map((item) => ({ item, score: 0 })); - - // Merge and sort: exact type name matches first, then by fuzzy score - const allResults = [...searchResults, ...typeNameMatches]; - allResults.sort((a, b) => { - const exactA = getTypeName(a.item.name).toLowerCase() === queryLower; - const exactB = getTypeName(b.item.name).toLowerCase() === queryLower; - if (exactA && !exactB) return -1; - if (!exactA && exactB) return 1; - return b.score - a.score; - }); - - // Apply limit and map to result format - return allResults + return this.fuzzySearchNodes(query, nodeTypes, limit) .slice(0, limit) .map( ({ @@ -238,9 +340,9 @@ export class CodeBuilderNodeSearchEngine { }); } - // Apply name filter using sublimeSearch + // Apply name filter using the same multi-word-aware fuzzy search as searchByName const nodeTypesOnly = nodesWithConnectionType.map((result) => result.nodeType); - const nameFilteredResults = sublimeSearch(nameFilter, nodeTypesOnly, NODE_SEARCH_KEYS); + const nameFilteredResults = this.fuzzySearchNodes(nameFilter, nodeTypesOnly, limit); // Combine connection score with name score return nameFilteredResults diff --git a/packages/@n8n/ai-utilities/src/utils/follow-redirects.ts b/packages/@n8n/ai-utilities/src/utils/follow-redirects.ts index a0fda3204b8..2d0b9cfa958 100644 --- a/packages/@n8n/ai-utilities/src/utils/follow-redirects.ts +++ b/packages/@n8n/ai-utilities/src/utils/follow-redirects.ts @@ -1,4 +1,4 @@ -import { ApplicationError } from 'n8n-workflow'; +import { OperationalError } from 'n8n-workflow'; const DEFAULT_MAX_REDIRECTS = 20; @@ -45,7 +45,7 @@ export async function fetchFollowingRedirects( hops += 1; if (hops > maxRedirects) { - throw new ApplicationError(`Too many redirects (max ${maxRedirects})`); + throw new OperationalError(`Too many redirects (max ${maxRedirects})`); } await response.body?.cancel().catch(() => {}); diff --git a/packages/@n8n/ai-utilities/src/utils/text-editor.ts b/packages/@n8n/ai-utilities/src/utils/text-editor.ts index 631b1081d07..4420fbb3eb8 100644 --- a/packages/@n8n/ai-utilities/src/utils/text-editor.ts +++ b/packages/@n8n/ai-utilities/src/utils/text-editor.ts @@ -26,22 +26,8 @@ export interface InsertCommand { insert_text: string; } -export interface BatchStrReplaceCommand { - command: 'batch_str_replace'; - path: string; - replacements: StrReplacement[]; -} - export type TextEditorCommand = ViewCommand | CreateCommand | StrReplaceCommand | InsertCommand; -export type TextEditorCommandWithBatch = TextEditorCommand | BatchStrReplaceCommand; - -export interface TextEditorToolCall { - name: 'str_replace_based_edit_tool'; - args: TextEditorCommand; - id: string; -} - export interface TextEditorResult { content: string; } @@ -80,21 +66,14 @@ export class InvalidViewRangeError extends Error { } export class InvalidPathError extends Error { - constructor(path: string, supportedPath = '/workflow.js', message?: string) { + constructor(path: string, supportedPath: string, message?: string) { super(message ?? `Invalid path "${path}". Only ${supportedPath} is supported.`); this.name = 'InvalidPathError'; } } -export class FileExistsError extends Error { - constructor() { - super('File already exists. Use text editor tools to modify existing content.'); - this.name = 'FileExistsError'; - } -} - export class FileNotFoundError extends Error { - constructor(message = 'No workflow code exists yet. Use create first.') { + constructor(message = 'No file content exists yet. Use create first.') { super(message); this.name = 'FileNotFoundError'; } @@ -113,26 +92,6 @@ export interface BatchReplaceResult { error?: string; } -export class BatchReplacementError extends Error { - readonly failedIndex: number; - readonly totalCount: number; - override readonly cause: NoMatchFoundError | MultipleMatchesError; - - constructor( - failedIndex: number, - totalCount: number, - cause: NoMatchFoundError | MultipleMatchesError, - ) { - super( - `Batch replacement failed at index ${failedIndex} of ${totalCount}: ${cause.message}. All changes have been rolled back.`, - ); - this.name = 'BatchReplacementError'; - this.failedIndex = failedIndex; - this.totalCount = totalCount; - this.cause = cause; - } -} - export interface TextEditorDocumentOptions { initialText?: string | null; supportedPath?: string; @@ -159,6 +118,10 @@ function isObjectRecord(value: unknown): value is Record<string, unknown> { return typeof value === 'object' && value !== null && !Array.isArray(value); } +function isUnknownArray(value: unknown): value is unknown[] { + return Array.isArray(value); +} + export function formatTextWithLineNumbers(text: string): string { const lines = text.split('\n'); return lines.map((line, i) => `${i + 1}: ${line}`).join('\n'); @@ -210,7 +173,7 @@ export function parseStrReplacements(raw: unknown): StrReplacement[] { if (typeof parsed === 'string') { try { - parsed = JSON.parse(parsed); + parsed = JSON.parse(parsed) as unknown; } catch { throw new Error( 'replacements must be a JSON array of {old_str, new_str} objects, but received an invalid JSON string.', @@ -218,7 +181,7 @@ export function parseStrReplacements(raw: unknown): StrReplacement[] { } } - if (!Array.isArray(parsed)) { + if (!isUnknownArray(parsed)) { throw new Error( 'replacements must be an array of {old_str, new_str} objects. Example: {"replacements": [{"old_str": "foo", "new_str": "bar"}]}', ); @@ -354,7 +317,7 @@ export class TextEditorDocument { return; } - throw new InvalidPathError( + throw this.createInvalidPathError( path, supportedPath, this.options.invalidPathMessage?.(path, supportedPath), @@ -470,7 +433,15 @@ export class TextEditorDocument { } } - private createFileNotFoundError(): FileNotFoundError { + protected createInvalidPathError( + path: string, + supportedPath: string, + message?: string, + ): InvalidPathError { + return new InvalidPathError(path, supportedPath, message); + } + + protected createFileNotFoundError(): FileNotFoundError { return new FileNotFoundError(this.options.fileNotFoundMessage); } diff --git a/packages/@n8n/ai-utilities/src/utils/workflow-text-editor.ts b/packages/@n8n/ai-utilities/src/utils/workflow-text-editor.ts new file mode 100644 index 00000000000..f8841ac1325 --- /dev/null +++ b/packages/@n8n/ai-utilities/src/utils/workflow-text-editor.ts @@ -0,0 +1,116 @@ +import { + findDivergenceContext, + FileNotFoundError as BaseFileNotFoundError, + formatTextWithLineNumbers, + InvalidLineNumberError, + InvalidPathError as BaseInvalidPathError, + InvalidViewRangeError, + MultipleMatchesError, + NoMatchFoundError, + parseStrReplacements, + type StrReplacement, + TextEditorDocument as BaseTextEditorDocument, + type TextEditorCommand, + type TextEditorDocumentOptions, +} from './text-editor'; + +export { + findDivergenceContext, + formatTextWithLineNumbers, + InvalidLineNumberError, + InvalidViewRangeError, + MultipleMatchesError, + NoMatchFoundError, + parseStrReplacements, +}; + +export type { + BatchReplaceResult, + CreateCommand, + InsertCommand, + StrReplaceCommand, + StrReplacement, + TextEditorCommand, + TextEditorDocumentOptions, + TextEditorResult, + ViewCommand, +} from './text-editor'; + +export class InvalidPathError extends BaseInvalidPathError { + constructor(path: string, supportedPath = '/workflow.js', message?: string) { + super(path, supportedPath, message); + } +} + +export class FileNotFoundError extends BaseFileNotFoundError { + constructor(message = 'No workflow code exists yet. Use create first.') { + super(message); + } +} + +export class TextEditorDocument extends BaseTextEditorDocument { + private readonly fileNotFoundMessage: string; + + constructor(options: TextEditorDocumentOptions = {}) { + const fileNotFoundMessage = + options.fileNotFoundMessage ?? 'No workflow code exists yet. Use create first.'; + super({ + ...options, + fileNotFoundMessage, + }); + this.fileNotFoundMessage = fileNotFoundMessage; + } + + protected override createInvalidPathError( + path: string, + supportedPath: string, + message?: string, + ): InvalidPathError { + return new InvalidPathError(path, supportedPath, message); + } + + protected override createFileNotFoundError(): FileNotFoundError { + return new FileNotFoundError(this.fileNotFoundMessage); + } +} + +export interface BatchStrReplaceCommand { + command: 'batch_str_replace'; + path: string; + replacements: StrReplacement[]; +} + +export type TextEditorCommandWithBatch = TextEditorCommand | BatchStrReplaceCommand; + +export interface TextEditorToolCall { + name: 'str_replace_based_edit_tool'; + args: TextEditorCommand; + id: string; +} + +export class FileExistsError extends Error { + constructor() { + super('File already exists. Use text editor tools to modify existing content.'); + this.name = 'FileExistsError'; + } +} + +export class BatchReplacementError extends Error { + readonly failedIndex: number; + readonly totalCount: number; + override readonly cause: NoMatchFoundError | MultipleMatchesError; + + constructor( + failedIndex: number, + totalCount: number, + cause: NoMatchFoundError | MultipleMatchesError, + ) { + super( + `Batch replacement failed at index ${failedIndex} of ${totalCount}: ${cause.message}. All changes have been rolled back.`, + ); + this.name = 'BatchReplacementError'; + this.failedIndex = failedIndex; + this.totalCount = totalCount; + this.cause = cause; + } +} diff --git a/packages/@n8n/ai-utilities/tsconfig.json b/packages/@n8n/ai-utilities/tsconfig.json index b635780098e..2908b03a1e8 100644 --- a/packages/@n8n/ai-utilities/tsconfig.json +++ b/packages/@n8n/ai-utilities/tsconfig.json @@ -8,7 +8,6 @@ "src/*": ["./src/*"], "src": ["./src"] }, - "tsBuildInfoFile": "dist/typecheck.tsbuildinfo", "emitDecoratorMetadata": true, "experimentalDecorators": true, "types": ["node", "vitest/globals"] diff --git a/packages/@n8n/ai-workflow-builder.ee/evaluations/README.md b/packages/@n8n/ai-workflow-builder.ee/evaluations/README.md index 465ebed3f6d..1a93a84e355 100644 --- a/packages/@n8n/ai-workflow-builder.ee/evaluations/README.md +++ b/packages/@n8n/ai-workflow-builder.ee/evaluations/README.md @@ -372,7 +372,6 @@ Notes: --donts <text> # Pairwise: things the workflow should not do --checks <names> # Comma-separated binary check names (binary-checks suite only) --output-dir <dir> # Local mode: write artifacts (one folder per example + summary.json) ---template-examples # Enable template examples feature flag --webhook-url <url> # Send results to webhook URL on completion (HTTPS only) --webhook-secret <s> # HMAC-SHA256 secret for webhook authentication (min 16 chars) ``` diff --git a/packages/@n8n/ai-workflow-builder.ee/evaluations/cli/argument-parser.ts b/packages/@n8n/ai-workflow-builder.ee/evaluations/cli/argument-parser.ts index 5cd27698488..9a93f26230b 100644 --- a/packages/@n8n/ai-workflow-builder.ee/evaluations/cli/argument-parser.ts +++ b/packages/@n8n/ai-workflow-builder.ee/evaluations/cli/argument-parser.ts @@ -73,15 +73,7 @@ export interface EvaluationArgs { } type CliValueKind = 'boolean' | 'string'; -type FlagGroup = - | 'input' - | 'eval' - | 'pairwise' - | 'langsmith' - | 'output' - | 'feature' - | 'model' - | 'advanced'; +type FlagGroup = 'input' | 'eval' | 'pairwise' | 'langsmith' | 'output' | 'model' | 'advanced'; // Model ID validation schema const modelIdSchema = z.enum(AVAILABLE_MODELS as [ModelId, ...ModelId[]]); @@ -125,7 +117,6 @@ const cliSchema = z checks: z.string().min(1).optional(), langsmith: z.boolean().optional(), - templateExamples: z.boolean().default(false), webhookUrl: z.string().url().optional(), webhookSecret: z.string().min(16).optional(), @@ -279,14 +270,6 @@ const FLAG_DEFS: Record<string, FlagDef> = { desc: 'Secret for HMAC-SHA256 signature (min 16 chars)', }, - // Feature flags - '--template-examples': { - key: 'templateExamples', - kind: 'boolean', - group: 'feature', - desc: 'Enable template examples phase', - }, - // Model configuration '--model': { key: 'model', @@ -362,7 +345,6 @@ const GROUP_TITLES: Record<FlagGroup, string> = { pairwise: 'Pairwise Options', langsmith: 'LangSmith Options', output: 'Output', - feature: 'Feature Flags', model: 'Model Configuration', advanced: 'Advanced', }; @@ -381,7 +363,6 @@ function formatHelp(): string { 'pairwise', 'langsmith', 'output', - 'feature', 'model', 'advanced', ]; @@ -469,20 +450,13 @@ function parseCli(argv: string[]): { return { values, seenKeys }; } -function parseFeatureFlags(args: { - templateExamples: boolean; - suite: EvaluationSuite; -}): BuilderFeatureFlags | undefined { - const templateExamplesFromEnv = process.env.EVAL_FEATURE_TEMPLATE_EXAMPLES === 'true'; - const templateExamples = templateExamplesFromEnv || args.templateExamples; - +function parseFeatureFlags(args: { suite: EvaluationSuite }): BuilderFeatureFlags | undefined { // Auto-enable introspection for introspection suite const enableIntrospection = args.suite === 'introspection'; - if (!templateExamples && !enableIntrospection) return undefined; + if (!enableIntrospection) return undefined; return { - templateExamples: templateExamples || undefined, enableIntrospection: enableIntrospection || undefined, }; } @@ -550,7 +524,6 @@ export function parseEvaluationArgs(argv: string[] = process.argv.slice(2)): Eva const parsed = cliSchema.parse(values); const featureFlags = parseFeatureFlags({ - templateExamples: parsed.templateExamples, suite: parsed.suite, }); diff --git a/packages/@n8n/ai-workflow-builder.ee/evaluations/support/constants.ts b/packages/@n8n/ai-workflow-builder.ee/evaluations/support/constants.ts index 7da739dcab3..bb520336bba 100644 --- a/packages/@n8n/ai-workflow-builder.ee/evaluations/support/constants.ts +++ b/packages/@n8n/ai-workflow-builder.ee/evaluations/support/constants.ts @@ -40,7 +40,5 @@ export const DEFAULTS = { /** Per-operation timeout (generation / evaluator) */ TIMEOUT_MS: 20 * 60 * 1000, DATASET_NAME: 'notion-pairwise-workflows', - FEATURE_FLAGS: { - templateExamples: false, - }, + FEATURE_FLAGS: {}, } as const; diff --git a/packages/@n8n/ai-workflow-builder.ee/package.json b/packages/@n8n/ai-workflow-builder.ee/package.json index 2eefc826a4c..b423a22328f 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.25.0", + "version": "1.27.0", "scripts": { "clean": "rimraf dist .turbo", "typecheck": "tsc --noEmit", @@ -60,7 +60,7 @@ "@langchain/core": "catalog:", "@langchain/langgraph": "1.0.2", "@langchain/openai": "catalog:", - "@mozilla/readability": "0.6.0", + "@mozilla/readability": "catalog:", "@n8n/api-types": "workspace:*", "@n8n/ai-utilities": "workspace:*", "@n8n/backend-common": "workspace:*", @@ -77,7 +77,11 @@ "lodash": "catalog:", "n8n-workflow": "workspace:*", "picocolors": "catalog:", - "turndown": "^7.2.2", + "p-limit": "^3.1.0", + "proxy-from-env": "catalog:", + "turndown": "catalog:", + "undici": "catalog:undici-v6", + "uuid": "catalog:", "zod": "catalog:" }, "devDependencies": { @@ -89,8 +93,8 @@ "cli-progress": "^3.12.0", "cli-table3": "^0.6.3", "madge": "^8.0.0", - "p-limit": "^3.1.0", "vitest": "catalog:", "vitest-mock-extended": "catalog:" - } + }, + "license": "LicenseRef-n8n-sustainable-use" } diff --git a/packages/@n8n/ai-workflow-builder.ee/src/code-builder/constants.ts b/packages/@n8n/ai-workflow-builder.ee/src/code-builder/constants.ts index a7b912a9098..7384a0e49e1 100644 --- a/packages/@n8n/ai-workflow-builder.ee/src/code-builder/constants.ts +++ b/packages/@n8n/ai-workflow-builder.ee/src/code-builder/constants.ts @@ -134,6 +134,11 @@ export const MCP_UPDATE_WORKFLOW_TOOL: BuilderToolBase = { displayTitle: 'Updating workflow', }; +export const MCP_EXPLORE_NODE_RESOURCES_TOOL: BuilderToolBase = { + toolName: 'explore_node_resources', + displayTitle: 'Exploring node resources', +}; + export const MCP_GET_WORKFLOW_BEST_PRACTICES_TOOL: BuilderToolBase = { toolName: 'get_workflow_best_practices', displayTitle: 'Getting workflow best practices', diff --git a/packages/@n8n/ai-workflow-builder.ee/src/code-builder/handlers/chat-setup-handler.ts b/packages/@n8n/ai-workflow-builder.ee/src/code-builder/handlers/chat-setup-handler.ts index b8239b24e20..02685113cf0 100644 --- a/packages/@n8n/ai-workflow-builder.ee/src/code-builder/handlers/chat-setup-handler.ts +++ b/packages/@n8n/ai-workflow-builder.ee/src/code-builder/handlers/chat-setup-handler.ts @@ -13,6 +13,7 @@ import type { AIMessage, BaseMessage } from '@langchain/core/messages'; import type { Runnable } from '@langchain/core/runnables'; import type { StructuredToolInterface } from '@langchain/core/tools'; import { formatNodeResult, type NodeTypeParser } from '@n8n/ai-utilities/node-catalog'; +import type { TextEditorCommand } from '@n8n/ai-utilities/text-editor'; import type { Logger } from '@n8n/backend-common'; import { generateWorkflowCode } from '@n8n/workflow-sdk'; import type { WorkflowJSON } from '@n8n/workflow-sdk'; @@ -21,7 +22,6 @@ import { TEXT_EDITOR_TOOL, VALIDATE_TOOL, BATCH_STR_REPLACE_TOOL } from '../cons import { buildCodeBuilderPrompt, type HistoryContext } from '../prompts'; import { TextEditorHandler } from './text-editor-handler'; import { TextEditorToolHandler } from './text-editor-tool-handler'; -import type { TextEditorCommand } from './text-editor.types'; import type { PlanOutput } from '../../types/planning'; import type { ChatPayload } from '../../workflow-builder-agent'; import type { ParseAndValidateResult } from '../types'; diff --git a/packages/@n8n/ai-workflow-builder.ee/src/code-builder/handlers/test/text-editor-handler.test.ts b/packages/@n8n/ai-workflow-builder.ee/src/code-builder/handlers/test/text-editor-handler.test.ts index 90500fcb5f9..bb3d8bee0e7 100644 --- a/packages/@n8n/ai-workflow-builder.ee/src/code-builder/handlers/test/text-editor-handler.test.ts +++ b/packages/@n8n/ai-workflow-builder.ee/src/code-builder/handlers/test/text-editor-handler.test.ts @@ -1,15 +1,14 @@ -import { TextEditorHandler, findDivergenceContext } from '../text-editor-handler'; import { - NoMatchFoundError, - MultipleMatchesError, + FileNotFoundError, + InvalidPathError, InvalidLineNumberError, InvalidViewRangeError, - InvalidPathError, - FileExistsError, - FileNotFoundError, - BatchReplacementError, + MultipleMatchesError, + NoMatchFoundError, type BatchReplaceResult, -} from '../text-editor.types'; +} from '@n8n/ai-utilities/text-editor'; + +import { TextEditorHandler } from '../text-editor-handler'; describe('TextEditorHandler', () => { let handler: TextEditorHandler; @@ -475,65 +474,6 @@ describe('TextEditorHandler', () => { }); }); - describe('error messages', () => { - it('NoMatchFoundError should have descriptive message', () => { - const error = new NoMatchFoundError('search string'); - expect(error.message).toContain('No exact match found'); - expect(error.name).toBe('NoMatchFoundError'); - }); - - it('MultipleMatchesError should include count', () => { - const error = new MultipleMatchesError(3); - expect(error.message).toContain('Found 3 matches'); - expect(error.name).toBe('MultipleMatchesError'); - }); - - it('InvalidLineNumberError should include line info', () => { - const error = new InvalidLineNumberError(10, 5); - expect(error.message).toContain('Invalid line number 10'); - expect(error.message).toContain('5 lines'); - expect(error.name).toBe('InvalidLineNumberError'); - }); - - it('InvalidViewRangeError should include start, end, and maxLine', () => { - const error = new InvalidViewRangeError(4, 2, 10); - expect(error.message).toContain('end (2)'); - expect(error.message).toContain('start (4)'); - expect(error.message).toContain('10 lines'); - expect(error.name).toBe('InvalidViewRangeError'); - }); - - it('InvalidPathError should include path', () => { - const error = new InvalidPathError('/bad/path.ts'); - expect(error.message).toContain('/bad/path.ts'); - expect(error.message).toContain('/workflow.js'); - expect(error.name).toBe('InvalidPathError'); - }); - - it('FileExistsError should have descriptive message', () => { - const error = new FileExistsError(); - expect(error.message).toContain('already exists'); - expect(error.name).toBe('FileExistsError'); - }); - - it('FileNotFoundError should have descriptive message', () => { - const error = new FileNotFoundError(); - expect(error.message).toContain('No workflow code exists'); - expect(error.name).toBe('FileNotFoundError'); - }); - - it('BatchReplacementError should include failedIndex and cause', () => { - const cause = new NoMatchFoundError('search'); - const error = new BatchReplacementError(2, 5, cause); - expect(error.message).toContain('index 2 of 5'); - expect(error.message).toContain('rolled back'); - expect(error.name).toBe('BatchReplacementError'); - expect(error.failedIndex).toBe(2); - expect(error.totalCount).toBe(5); - expect(error.cause).toBe(cause); - }); - }); - describe('executeBatch', () => { it('should apply multiple replacements successfully', () => { handler.setWorkflowCode('const x = 1;\nconst y = 2;\nconst z = 3;'); @@ -680,62 +620,6 @@ describe('TextEditorHandler', () => { }); }); - describe('findDivergenceContext', () => { - it('should show divergence point with file lines when prefix matches', () => { - const code = 'line1\nline2\nline3\nline4\nline5'; - const searchStr = 'line1\nline2\nline3_WRONG'; - - const result = findDivergenceContext(code, searchStr); - - expect(result).toBeDefined(); - expect(result).toContain('line 3'); - // Should show the actual file line - expect(result).toContain('line3'); - }); - - it('should return undefined when prefix match is too short', () => { - const code = 'abcdefghij\nklmnop'; - const searchStr = 'xyz_completely_different'; - - const result = findDivergenceContext(code, searchStr); - - expect(result).toBeUndefined(); - }); - - it('should escape whitespace characters in old_str context', () => { - const code = 'hello world\nfoo bar\n'; - const searchStr = 'hello world\nfoo baz\t'; - - const result = findDivergenceContext(code, searchStr); - - expect(result).toBeDefined(); - // Should show escaped \t in the old_str portion - expect(result).toContain('\\t'); - }); - - it('should include match percentage', () => { - const code = 'abcdefghijklmnopqrstuvwxyz'; - const searchStr = 'abcdefghijklmnopqrstZZZZZ'; - - const result = findDivergenceContext(code, searchStr); - - expect(result).toBeDefined(); - expect(result).toMatch(/\d+%/); - }); - - it('should show full file lines around divergence point', () => { - const code = ' function foo() {\n return 1;\n }\n function bar() {\n return 2;\n }'; - const searchStr = - ' function foo() {\n return 1;\n }\n function bar() {\n return WRONG;\n }'; - - const result = findDivergenceContext(code, searchStr); - - expect(result).toBeDefined(); - // Should contain the full file line with line number - expect(result).toContain('return 2;'); - }); - }); - describe('str_replace divergence diagnostics', () => { it('should include divergence context in NoMatchFoundError when prefix matches', () => { handler.setWorkflowCode('const x = 1;\nconst y = 2;\nconst z = 3;'); diff --git a/packages/@n8n/ai-workflow-builder.ee/src/code-builder/handlers/text-editor-handler.ts b/packages/@n8n/ai-workflow-builder.ee/src/code-builder/handlers/text-editor-handler.ts index 302be71ae2b..906e96ada90 100644 --- a/packages/@n8n/ai-workflow-builder.ee/src/code-builder/handlers/text-editor-handler.ts +++ b/packages/@n8n/ai-workflow-builder.ee/src/code-builder/handlers/text-editor-handler.ts @@ -1,14 +1,7 @@ -import { - TextEditorDocument, - findDivergenceContext, - formatTextWithLineNumbers, -} from '@n8n/ai-utilities/text-editor'; +import { TextEditorDocument } from '@n8n/ai-utilities/text-editor'; const WORKFLOW_FILE_PATH = '/workflow.js'; -export { findDivergenceContext }; -export { formatTextWithLineNumbers as formatCodeWithLineNumbers }; - /** * Manages the virtual workflow code file used by the code builder agent. */ diff --git a/packages/@n8n/ai-workflow-builder.ee/src/code-builder/handlers/text-editor.types.ts b/packages/@n8n/ai-workflow-builder.ee/src/code-builder/handlers/text-editor.types.ts deleted file mode 100644 index db6ab654ff3..00000000000 --- a/packages/@n8n/ai-workflow-builder.ee/src/code-builder/handlers/text-editor.types.ts +++ /dev/null @@ -1,22 +0,0 @@ -export { - NoMatchFoundError, - MultipleMatchesError, - InvalidLineNumberError, - InvalidViewRangeError, - InvalidPathError, - FileExistsError, - FileNotFoundError, - BatchReplacementError, -} from '@n8n/ai-utilities/text-editor'; - -export type { - ViewCommand, - CreateCommand, - StrReplaceCommand, - InsertCommand, - TextEditorCommand, - TextEditorToolCall, - TextEditorResult, - StrReplacement, - BatchReplaceResult, -} from '@n8n/ai-utilities/text-editor'; diff --git a/packages/@n8n/ai-workflow-builder.ee/src/code-builder/handlers/tool-dispatch-handler.ts b/packages/@n8n/ai-workflow-builder.ee/src/code-builder/handlers/tool-dispatch-handler.ts index 3ffed75bb19..b4c0ca38858 100644 --- a/packages/@n8n/ai-workflow-builder.ee/src/code-builder/handlers/tool-dispatch-handler.ts +++ b/packages/@n8n/ai-workflow-builder.ee/src/code-builder/handlers/tool-dispatch-handler.ts @@ -8,12 +8,11 @@ import type { BaseMessage } from '@langchain/core/messages'; import { ToolMessage } from '@langchain/core/messages'; import type { StructuredToolInterface } from '@langchain/core/tools'; -import { parseStrReplacements } from '@n8n/ai-utilities/text-editor'; +import { parseStrReplacements, type StrReplacement } from '@n8n/ai-utilities/text-editor'; import type { WorkflowJSON } from '@n8n/workflow-sdk'; import type { TextEditorHandler } from './text-editor-handler'; import type { TextEditorToolHandler } from './text-editor-tool-handler'; -import type { StrReplacement } from './text-editor.types'; import type { ValidateToolHandler } from './validate-tool-handler'; import type { StreamOutput, ToolProgressChunk } from '../../types/streaming'; import type { WarningTracker } from '../state/warning-tracker'; diff --git a/packages/@n8n/ai-workflow-builder.ee/src/code-builder/index.ts b/packages/@n8n/ai-workflow-builder.ee/src/code-builder/index.ts index 0fa946ac857..62c4a0862a3 100644 --- a/packages/@n8n/ai-workflow-builder.ee/src/code-builder/index.ts +++ b/packages/@n8n/ai-workflow-builder.ee/src/code-builder/index.ts @@ -43,5 +43,6 @@ export { MCP_CREATE_WORKFLOW_FROM_CODE_TOOL, MCP_ARCHIVE_WORKFLOW_TOOL, MCP_UPDATE_WORKFLOW_TOOL, + MCP_EXPLORE_NODE_RESOURCES_TOOL, MCP_GET_WORKFLOW_BEST_PRACTICES_TOOL, } from './constants'; diff --git a/packages/@n8n/ai-workflow-builder.ee/src/code-builder/prompts/index.ts b/packages/@n8n/ai-workflow-builder.ee/src/code-builder/prompts/index.ts index 65b25fb968f..29fd2ae2680 100644 --- a/packages/@n8n/ai-workflow-builder.ee/src/code-builder/prompts/index.ts +++ b/packages/@n8n/ai-workflow-builder.ee/src/code-builder/prompts/index.ts @@ -6,6 +6,7 @@ */ import { ChatPromptTemplate } from '@langchain/core/prompts'; +import { formatTextWithLineNumbers } from '@n8n/ai-utilities/text-editor'; import { generateWorkflowCode } from '@n8n/workflow-sdk'; import type { WorkflowJSON } from '@n8n/workflow-sdk'; import { @@ -18,7 +19,6 @@ import type { IRunExecutionData, NodeExecutionSchema } from 'n8n-workflow'; import type { PlanOutput } from '../../types/planning'; import { formatPlanAsText } from '../../utils/plan-helpers'; import type { ExpressionValue } from '../../workflow-builder-agent'; -import { formatCodeWithLineNumbers } from '../handlers/text-editor-handler'; import { type ConversationEntry, entryToString } from '../utils/code-builder-session'; import { SDK_IMPORT_STATEMENT } from '../utils/extract-code'; @@ -856,7 +856,7 @@ function buildUserMessageParts( // Format as file with line numbers (matches view command output) // Include SDK import so LLM sees the same code that's in the text editor const codeWithImport = `${SDK_IMPORT_STATEMENT}\n\n${workflowCode}`; - const formattedCode = formatCodeWithLineNumbers(codeWithImport); + const formattedCode = formatTextWithLineNumbers(codeWithImport); const escapedCode = escapeCurlyBrackets(formattedCode); parts.push(`<workflow_file path="/workflow.js">\n${escapedCode}\n</workflow_file>`); } else { diff --git a/packages/@n8n/ai-workflow-builder.ee/src/index.ts b/packages/@n8n/ai-workflow-builder.ee/src/index.ts index 0cd9da6e9f3..c6f56fb87a1 100644 --- a/packages/@n8n/ai-workflow-builder.ee/src/index.ts +++ b/packages/@n8n/ai-workflow-builder.ee/src/index.ts @@ -34,6 +34,7 @@ export { MCP_CREATE_WORKFLOW_FROM_CODE_TOOL, MCP_ARCHIVE_WORKFLOW_TOOL, MCP_UPDATE_WORKFLOW_TOOL, + MCP_EXPLORE_NODE_RESOURCES_TOOL, MCP_GET_WORKFLOW_BEST_PRACTICES_TOOL, } from './code-builder'; export type { ParseAndValidateResult, ValidationWarning } from './code-builder'; diff --git a/packages/@n8n/ai-workflow-builder.ee/src/multi-agent-workflow-subgraphs.ts b/packages/@n8n/ai-workflow-builder.ee/src/multi-agent-workflow-subgraphs.ts index 8eedb2ede37..db539f98307 100644 --- a/packages/@n8n/ai-workflow-builder.ee/src/multi-agent-workflow-subgraphs.ts +++ b/packages/@n8n/ai-workflow-builder.ee/src/multi-agent-workflow-subgraphs.ts @@ -369,12 +369,7 @@ export function createMultiAgentWorkflowWithSubgraphs(config: MultiAgentSubgraph // After discovery in plan mode, getNextPhaseFromLog returns 'builder'. // With builder removed, redirect back to discovery to retry planning. - if ( - next === 'builder' && - featureFlags?.planMode === true && - state.mode === 'plan' && - !state.planOutput - ) { + if (next === 'builder' && state.mode === 'plan' && !state.planOutput) { return { nextPhase: 'discovery', planDecision: null }; } @@ -384,16 +379,10 @@ export function createMultiAgentWorkflowWithSubgraphs(config: MultiAgentSubgraph .addNode('check_state', (state) => { const action = determineStateAction(state, autoCompactThresholdTokens); - // In plan mode (without mergeAskBuild), skip the supervisor and - // route directly to discovery (which contains the planner). + // In plan mode (without mergeAskBuild), skip the supervisor and route directly to + // discovery (which contains the planner). // Set nextPhase to 'discovery' so create_workflow_name can route correctly. - if ( - action === 'continue' && - featureFlags?.planMode === true && - state.mode === 'plan' && - !state.planOutput && - !mergeAskBuild - ) { + if (action === 'continue' && state.mode === 'plan' && !state.planOutput && !mergeAskBuild) { return { nextPhase: 'discovery' }; } diff --git a/packages/@n8n/ai-workflow-builder.ee/src/prompts/agents/discovery.prompt.ts b/packages/@n8n/ai-workflow-builder.ee/src/prompts/agents/discovery.prompt.ts index ffcc25e8b25..5bf0544a0e6 100644 --- a/packages/@n8n/ai-workflow-builder.ee/src/prompts/agents/discovery.prompt.ts +++ b/packages/@n8n/ai-workflow-builder.ee/src/prompts/agents/discovery.prompt.ts @@ -39,11 +39,6 @@ export function formatExampleCategorizations(): string { .join('\n'); } -export interface DiscoveryPromptOptions { - includeExamples: boolean; - includeQuestions: boolean; -} - const ROLE = `You are a Discovery Agent for n8n AI Workflow Builder. Identify relevant n8n nodes and their connection-changing parameters for the user's request. When the request is underspecified, ask clarifying questions to ensure the right workflow gets built.`; @@ -52,28 +47,11 @@ const N8N_EXECUTION_MODEL = `n8n executes each node once per input item. When a trigger or node outputs multiple items (e.g., Gmail returns 10 emails), every downstream node runs once for each item. Flow control nodes like Aggregate and Split Out change how items flow through the workflow by combining or expanding them.`; -const PROCESS = `1. Search for nodes matching the user's request using search_nodes tool -2. Identify connection-changing parameters from input/output expressions (look for $parameter.X) -3. Call submit_discovery_results with your nodesFound array`; - const PROCESS_WITH_QUESTIONS = `1. Search for nodes matching the user's request using search_nodes tool 2. Identify connection-changing parameters from input/output expressions (look for $parameter.X) 3. Assess: do you have enough information to build exactly what the user wants, or would you need to make assumptions about their intent? If assumptions are needed, ask clarifying questions using submit_questions (see clarifying_questions section) 4. Call submit_discovery_results with your nodesFound array`; -const PROCESS_WITH_EXAMPLES = `1. Search for nodes matching the user's request using search_nodes tool -2. Identify connection-changing parameters from input/output expressions (look for $parameter.X) -3. Use get_documentation to retrieve best practices for relevant workflow techniques—this provides proven patterns that improve workflow quality -4. Use get_workflow_examples to find real community workflows using mentioned services—these examples show how experienced users structure similar integrations -5. Call submit_discovery_results with your nodesFound array`; - -const PROCESS_WITH_EXAMPLES_AND_QUESTIONS = `1. Search for nodes matching the user's request using search_nodes tool -2. Identify connection-changing parameters from input/output expressions (look for $parameter.X) -3. Use get_documentation to retrieve best practices for relevant workflow techniques—this provides proven patterns that improve workflow quality -4. Use get_workflow_examples to find real community workflows using mentioned services—these examples show how experienced users structure similar integrations -5. Assess: do you have enough information to build exactly what the user wants, or would you need to make assumptions about their intent? If assumptions are needed, ask clarifying questions using submit_questions (see clarifying_questions section) -6. Call submit_discovery_results with your nodesFound array`; - const AI_NODE_SELECTION = `AI node selection guidance: AI Agent: Use for text analysis, summarization, classification, or any AI reasoning tasks. @@ -366,10 +344,8 @@ Guidelines: - Baseline flow control nodes (Aggregate, IF, Switch, Split Out, Merge, Set) are automatically included—no need to search for them - Prioritize native nodes in your searches because they provide better UX and visual debugging than Code node alternatives`; -function generateToolCallRequirement(options: DiscoveryPromptOptions): string { - const toolExamples = ['search_nodes']; - if (options.includeQuestions) toolExamples.push('submit_questions'); - if (options.includeExamples) toolExamples.push('get_documentation', 'get_workflow_examples'); +function generateToolCallRequirement(): string { + const toolExamples = ['search_nodes', 'submit_questions']; return `<output_requirement> Use tools when needed (e.g. ${toolExamples.join(', ')}). @@ -379,43 +355,29 @@ Do not output the results as text or XML. </output_requirement>`; } -function generateAvailableToolsList(options: DiscoveryPromptOptions): string { +function generateAvailableToolsList(): string { const tools = [ '- search_nodes: Find n8n nodes by keyword (returns name, version, inputs, outputs)', + '- submit_questions: Ask clarifying questions when critical details are missing', ]; - if (options.includeQuestions) { - tools.push('- submit_questions: Ask clarifying questions when critical details are missing'); - } - if (options.includeExamples) { - tools.push( - '- get_documentation: Retrieve best practices for workflow techniques to improve quality', - ); - tools.push( - '- get_workflow_examples: Find real community workflows as reference for structuring integrations', - ); - } tools.push('- web_fetch: Fetch content from a URL the user provided (requires approval)'); tools.push('- submit_discovery_results: Submit final results'); return tools.join('\n'); } -function selectProcessSection(options: DiscoveryPromptOptions): string { - if (options.includeExamples && options.includeQuestions) - return PROCESS_WITH_EXAMPLES_AND_QUESTIONS; - if (options.includeExamples) return PROCESS_WITH_EXAMPLES; - if (options.includeQuestions) return PROCESS_WITH_QUESTIONS; - return PROCESS; +function selectProcessSection(): string { + return PROCESS_WITH_QUESTIONS; } -export function buildDiscoveryPrompt(options: DiscoveryPromptOptions): string { - const availableTools = generateAvailableToolsList(options); +export function buildDiscoveryPrompt(): string { + const availableTools = generateAvailableToolsList(); return prompt() .section('role', ROLE) .section('available_tools', availableTools) - .section('process', selectProcessSection(options)) - .section('tool_call_requirement', generateToolCallRequirement(options)) - .sectionIf(options.includeQuestions, 'clarifying_questions', CLARIFYING_QUESTIONS) + .section('process', selectProcessSection()) + .section('tool_call_requirement', generateToolCallRequirement()) + .section('clarifying_questions', CLARIFYING_QUESTIONS) .section('n8n_execution_model', N8N_EXECUTION_MODEL) .section('baseline_flow_control', BASELINE_FLOW_CONTROL) .section('trigger_selection', TRIGGER_SELECTION) diff --git a/packages/@n8n/ai-workflow-builder.ee/src/prompts/agents/index.ts b/packages/@n8n/ai-workflow-builder.ee/src/prompts/agents/index.ts index ecfeebfb967..1fa052e3c6b 100644 --- a/packages/@n8n/ai-workflow-builder.ee/src/prompts/agents/index.ts +++ b/packages/@n8n/ai-workflow-builder.ee/src/prompts/agents/index.ts @@ -11,7 +11,6 @@ export { formatTechniqueList, formatExampleCategorizations, } from './discovery.prompt'; -export type { DiscoveryPromptOptions } from './discovery.prompt'; export { buildResponderPrompt, buildRecursionErrorWithWorkflowGuidance, diff --git a/packages/@n8n/ai-workflow-builder.ee/src/prompts/index.ts b/packages/@n8n/ai-workflow-builder.ee/src/prompts/index.ts index cc162d9c822..a1b9283f823 100644 --- a/packages/@n8n/ai-workflow-builder.ee/src/prompts/index.ts +++ b/packages/@n8n/ai-workflow-builder.ee/src/prompts/index.ts @@ -26,7 +26,6 @@ export { exampleCategorizations, formatTechniqueList, formatExampleCategorizations, - type DiscoveryPromptOptions, } from './agents/discovery.prompt'; export { buildSupervisorPrompt } from './agents/supervisor.prompt'; export { buildPlannerPrompt, buildPlannerContext } from './agents/planner.prompt'; diff --git a/packages/@n8n/ai-workflow-builder.ee/src/subgraphs/discovery.subgraph.ts b/packages/@n8n/ai-workflow-builder.ee/src/subgraphs/discovery.subgraph.ts index fc819832676..f6620a0a8cf 100644 --- a/packages/@n8n/ai-workflow-builder.ee/src/subgraphs/discovery.subgraph.ts +++ b/packages/@n8n/ai-workflow-builder.ee/src/subgraphs/discovery.subgraph.ts @@ -25,7 +25,6 @@ import { LLMServiceError } from '@/errors'; import type { ParentGraphState } from '@/parent-graph-state'; import { buildDiscoveryPrompt } from '@/prompts'; import { createGetDocumentationTool } from '@/tools/get-documentation.tool'; -import { createGetWorkflowExamplesTool } from '@/tools/get-workflow-examples.tool'; import { createIntrospectTool, extractIntrospectionEventsFromMessages, @@ -265,7 +264,6 @@ export class DiscoverySubgraph extends BaseSubgraph< private toolMap!: Map<string, StructuredTool>; private logger?: Logger; private parsedNodeTypes!: INodeTypeDescription[]; - private featureFlags?: BuilderFeatureFlags; /** Mutable state for planner web_fetch hooks, updated before each planner invocation */ private plannerWebFetchState: MutableWebFetchState = { @@ -278,11 +276,8 @@ export class DiscoverySubgraph extends BaseSubgraph< create(config: DiscoverySubgraphConfig) { this.logger = config.logger; this.parsedNodeTypes = config.parsedNodeTypes; - this.featureFlags = config.featureFlags; // Check feature flags - const includeExamples = config.featureFlags?.templateExamples === true; - const includePlanMode = config.featureFlags?.planMode === true; const enableIntrospection = config.featureFlags?.enableIntrospection === true; // Create security manager factories for web_fetch in each context @@ -293,30 +288,18 @@ export class DiscoverySubgraph extends BaseSubgraph< const ssrf = config.ssrf ?? createPassthroughSsrfGuard(); // Create base tools - search_nodes provides all data needed for discovery - const baseTools: StructuredTool[] = includePlanMode - ? [ - createNodeSearchTool(config.parsedNodeTypes).tool, - submitQuestionsTool, - createWebFetchTool(discoverySecurityFactory, ssrf).tool, - ] - : [ - createNodeSearchTool(config.parsedNodeTypes).tool, - createWebFetchTool(discoverySecurityFactory, ssrf).tool, - ]; + const baseTools: StructuredTool[] = [ + createNodeSearchTool(config.parsedNodeTypes).tool, + submitQuestionsTool, + createWebFetchTool(discoverySecurityFactory, ssrf).tool, + ]; // Conditionally add introspect tool if feature flag is enabled if (enableIntrospection) { baseTools.push(createIntrospectTool(config.logger).tool); } - // Conditionally add documentation and workflow examples tools if feature flag is enabled - const tools = includeExamples - ? [ - ...baseTools, - createGetDocumentationTool().tool, - createGetWorkflowExamplesTool(config.logger).tool, - ] - : baseTools; + const tools = baseTools; this.toolMap = new Map(tools.map((toolInstance) => [toolInstance.name, toolInstance])); @@ -327,11 +310,7 @@ export class DiscoverySubgraph extends BaseSubgraph< schema: discoveryOutputSchema, }); - // Generate prompt based on feature flags - const discoveryPrompt = buildDiscoveryPrompt({ - includeExamples, - includeQuestions: includePlanMode, - }); + const discoveryPrompt = buildDiscoveryPrompt(); // Create agent with tools bound (including submit tool) const systemPrompt = ChatPromptTemplate.fromMessages([ @@ -418,7 +397,7 @@ export class DiscoverySubgraph extends BaseSubgraph< state: typeof DiscoverySubgraphState.State, runnableConfig?: RunnableConfig, ) { - if (!this.featureFlags?.planMode || state.mode !== 'plan' || state.planOutput) { + if (state.mode !== 'plan' || state.planOutput) { return {}; } @@ -459,7 +438,6 @@ export class DiscoverySubgraph extends BaseSubgraph< } private shouldPlan(state: typeof DiscoverySubgraphState.State): 'planner' | typeof END { - if (!this.featureFlags?.planMode) return END; if (state.mode !== 'plan') return END; return state.planOutput ? END : 'planner'; } diff --git a/packages/@n8n/ai-workflow-builder.ee/src/subgraphs/test/integration/plan-mode-discovery.integration.test.ts b/packages/@n8n/ai-workflow-builder.ee/src/subgraphs/test/integration/plan-mode-discovery.integration.test.ts index 7ad828470e4..c86be5c8942 100644 --- a/packages/@n8n/ai-workflow-builder.ee/src/subgraphs/test/integration/plan-mode-discovery.integration.test.ts +++ b/packages/@n8n/ai-workflow-builder.ee/src/subgraphs/test/integration/plan-mode-discovery.integration.test.ts @@ -114,7 +114,6 @@ describe('Plan Mode Discovery - Integration Tests', () => { parsedNodeTypes, llm, plannerLLM: llm, - featureFlags: { planMode: true }, checkpointer: new MemorySaver(), }); } @@ -317,7 +316,6 @@ describe('Plan Mode Discovery - Integration Tests', () => { parsedNodeTypes, llm, plannerLLM: llm, - featureFlags: { planMode: true }, }); console.log('Invoking in build mode...'); diff --git a/packages/@n8n/ai-workflow-builder.ee/src/subgraphs/test/integration/question-quality.integration.test.ts b/packages/@n8n/ai-workflow-builder.ee/src/subgraphs/test/integration/question-quality.integration.test.ts index 41d77d21099..1a3d9d5fdc6 100644 --- a/packages/@n8n/ai-workflow-builder.ee/src/subgraphs/test/integration/question-quality.integration.test.ts +++ b/packages/@n8n/ai-workflow-builder.ee/src/subgraphs/test/integration/question-quality.integration.test.ts @@ -356,7 +356,6 @@ describe('Question Quality - Integration Tests', () => { parsedNodeTypes, llm, plannerLLM: llm, - featureFlags: { planMode: true }, checkpointer: new MemorySaver(), }); } diff --git a/packages/@n8n/ai-workflow-builder.ee/src/test/workflow-builder-agent.test.ts b/packages/@n8n/ai-workflow-builder.ee/src/test/workflow-builder-agent.test.ts index 212aa63b9db..0a448bf08ca 100644 --- a/packages/@n8n/ai-workflow-builder.ee/src/test/workflow-builder-agent.test.ts +++ b/packages/@n8n/ai-workflow-builder.ee/src/test/workflow-builder-agent.test.ts @@ -4,7 +4,7 @@ import type { MemorySaver } from '@langchain/langgraph'; import { GraphRecursionError } from '@langchain/langgraph'; import type { Logger } from '@n8n/backend-common'; import type { INodeTypeDescription } from 'n8n-workflow'; -import { ApplicationError, OperationalError } from 'n8n-workflow'; +import { OperationalError, UserError } from 'n8n-workflow'; import type { Mock, MockedClass, MockedFunction } from 'vitest'; import { mock } from 'vitest-mock-extended'; @@ -128,8 +128,6 @@ describe('WorkflowBuilderAgent', () => { mockPayload = { id: '12345', message: 'Create a workflow', - // Test for plan mode as it's the only case when legacy multi-agent implementation is still in use - featureFlags: { planMode: true }, mode: 'plan', workflowContext: { currentWorkflow: { id: 'workflow-123' }, @@ -160,7 +158,6 @@ describe('WorkflowBuilderAgent', () => { const payload: ChatPayload = { id: '12345', message: validMessage, - featureFlags: { planMode: true }, mode: 'plan', }; @@ -203,7 +200,7 @@ describe('WorkflowBuilderAgent', () => { await expect(async () => { const generator = agent.chat(mockPayload); await generator.next(); - }).rejects.toThrow(ApplicationError); + }).rejects.toThrow(UserError); }); it('should handle 401 expired token error from LangChain MODEL_AUTHENTICATION', async () => { @@ -223,11 +220,11 @@ describe('WorkflowBuilderAgent', () => { await expect(async () => { const generator = agent.chat(mockPayload); await generator.next(); - }).rejects.toThrow(ApplicationError); + }).rejects.toThrow(UserError); }); it('should not treat generic 401 errors as expired token errors', async () => { - // A generic 401 without lc_error_code should be rethrown as-is, not converted to ApplicationError + // A generic 401 without lc_error_code should be rethrown as-is, not converted to UserError const generic401Error = Object.assign(new Error('Unauthorized'), { status: 401 }); mockCreateStreamProcessor.mockImplementation(() => { @@ -360,11 +357,10 @@ describe('WorkflowBuilderAgent', () => { ); }); - it('should route to multi-agent for initial plan request when planMode enabled', async () => { + it('should route to multi-agent for initial plan request', async () => { const payload: ChatPayload = { id: '123', message: 'Create a weather alert workflow', - featureFlags: { planMode: true }, mode: 'plan', }; @@ -390,7 +386,6 @@ describe('WorkflowBuilderAgent', () => { const payload: ChatPayload = { id: '123', message: 'Create a weather alert workflow', - featureFlags: { planMode: true }, resumeData: { action: 'approve' }, resumeInterrupt: mockPlanInterrupt, }; @@ -416,7 +411,6 @@ describe('WorkflowBuilderAgent', () => { const payload: ChatPayload = { id: '123', message: 'Create a weather alert workflow', - featureFlags: { planMode: true }, resumeData: { action: 'modify', feedback: 'Add error handling' }, resumeInterrupt: mockPlanInterrupt, }; @@ -442,7 +436,6 @@ describe('WorkflowBuilderAgent', () => { const payload: ChatPayload = { id: '123', message: 'Create a weather alert workflow', - featureFlags: { planMode: true }, resumeData: { action: 'reject' }, resumeInterrupt: mockPlanInterrupt, }; diff --git a/packages/@n8n/ai-workflow-builder.ee/src/tools/builder-tools.ts b/packages/@n8n/ai-workflow-builder.ee/src/tools/builder-tools.ts index ce6393f5f9d..08ea2c88abd 100644 --- a/packages/@n8n/ai-workflow-builder.ee/src/tools/builder-tools.ts +++ b/packages/@n8n/ai-workflow-builder.ee/src/tools/builder-tools.ts @@ -18,7 +18,6 @@ import { GET_EXECUTION_SCHEMA_TOOL } from './get-execution-schema.tool'; import { GET_EXPRESSION_DATA_MAPPING_TOOL } from './get-expression-data-mapping.tool'; import { GET_NODE_CONTEXT_TOOL } from './get-node-context.tool'; import { GET_NODE_PARAMETER_TOOL } from './get-node-parameter.tool'; -import { GET_WORKFLOW_EXAMPLES_TOOL } from './get-workflow-examples.tool'; import { GET_WORKFLOW_OVERVIEW_TOOL } from './get-workflow-overview.tool'; import { INTROSPECT_TOOL } from './introspect.tool'; import { NODE_DETAILS_TOOL } from './node-details.tool'; @@ -43,12 +42,6 @@ export function getBuilderToolsForDisplay({ }): BuilderToolBase[] { const tools: BuilderToolBase[] = [GET_DOCUMENTATION_TOOL]; - // Conditionally add workflow examples tool based on feature flag - // Only enabled when flag is explicitly true - if (featureFlags?.templateExamples === true) { - tools.push(GET_WORKFLOW_EXAMPLES_TOOL); - } - // Add remaining tools tools.push( NODE_SEARCH_TOOL, diff --git a/packages/@n8n/ai-workflow-builder.ee/src/tools/get-workflow-examples.tool.ts b/packages/@n8n/ai-workflow-builder.ee/src/tools/get-workflow-examples.tool.ts deleted file mode 100644 index da8fff5746f..00000000000 --- a/packages/@n8n/ai-workflow-builder.ee/src/tools/get-workflow-examples.tool.ts +++ /dev/null @@ -1,213 +0,0 @@ -import { tool } from '@langchain/core/tools'; -import type { Logger } from '@n8n/backend-common'; -import { z } from 'zod'; - -import type { GetWorkflowExamplesOutput, WorkflowMetadata } from '@/types'; -import type { BuilderToolBase } from '@/utils/stream-processor'; - -import { ValidationError, ToolExecutionError } from '../errors'; -import { - createProgressReporter, - createBatchProgressReporter, - createSuccessResponse, - createErrorResponse, -} from './helpers'; -import { processWorkflowExamples } from './utils/mermaid.utils'; -import { fetchWorkflowsFromTemplates } from './web/templates'; - -/** - * Workflow example query schema - */ -const workflowExampleQuerySchema = z.object({ - search: z.string().optional().describe('Search term to find workflow examples'), -}); - -/** - * Main schema for get workflow examples tool - */ -const getWorkflowExamplesSchema = z.object({ - queries: z - .array(workflowExampleQuerySchema) - .min(1) - .describe('Array of search queries to find workflow examples'), -}); - -/** - * Build a human-readable identifier for a query - */ -function buildQueryIdentifier(query: { - search?: string; -}): string { - const parts: string[] = []; - if (query.search) { - parts.push(`search: ${query.search}`); - } - return parts.join(','); -} - -/** - * Build the response message from search results - */ -function buildResponseMessage(output: GetWorkflowExamplesOutput): string { - if (output.examples.length === 0) { - return 'No workflow examples found'; - } - - const sections: string[] = [`Found ${output.totalResults} workflow example(s):`]; - - for (const example of output.examples) { - sections.push(`\n## ${example.name}`); - if (example.description) { - sections.push(example.description); - } - sections.push(example.workflow); - } - - return sections.join('\n'); -} - -export const GET_WORKFLOW_EXAMPLES_TOOL: BuilderToolBase = { - toolName: 'get_workflow_examples', - displayTitle: 'Retrieving workflow examples', -}; - -/** Tool description */ -const TOOL_DESCRIPTION = `Retrieve workflow examples from n8n's workflow library to use as reference for building workflows. - -This tool searches for existing workflow examples that match specific criteria. -The retrieved workflows serve as reference material to understand common patterns, node usage and connections. -Consider these workflows as ideal solutions. -The workflows will be returned in a token efficient format rather than JSON. - -Usage: -- Provide search criteria to find relevant workflow examples -- Results include workflow metadata, summaries, and full workflow data for reference - -Parameters: -- search: Keywords to search for in workflow names/descriptions based on the user prompt`; - -/** - * Factory function to create the get workflow examples tool - */ -export function createGetWorkflowExamplesTool(logger?: Logger) { - const dynamicTool = tool( - async (input, config) => { - const reporter = createProgressReporter( - config, - GET_WORKFLOW_EXAMPLES_TOOL.toolName, - GET_WORKFLOW_EXAMPLES_TOOL.displayTitle, - ); - - try { - // Validate input using Zod schema - const validatedInput = getWorkflowExamplesSchema.parse(input); - const { queries } = validatedInput; - - // Report tool start - reporter.start(validatedInput); - - let allResults: WorkflowMetadata[] = []; - let allTemplateIds: number[] = []; - - // Create batch reporter for progress tracking - const batchReporter = createBatchProgressReporter(reporter, 'Retrieving workflow examples'); - batchReporter.init(queries.length); - - // Process each query - for (const query of queries) { - const identifier = buildQueryIdentifier(query); - - try { - // Report progress - batchReporter.next(identifier); - - // Fetch workflow examples using shared utility - const result = await fetchWorkflowsFromTemplates({ search: query.search }, { logger }); - - // Add to results - allResults = allResults.concat(result.workflows); - allTemplateIds = allTemplateIds.concat(result.templateIds); - } catch (error) { - logger?.error('Error fetching workflow examples', { error }); - } - } - - // Complete batch reporting - batchReporter.complete(); - - // Deduplicate results based on workflow name - const uniqueWorkflows = new Map<string, WorkflowMetadata>(); - for (const workflow of allResults) { - if (!uniqueWorkflows.has(workflow.name)) { - uniqueWorkflows.set(workflow.name, workflow); - } - } - const deduplicatedResults = Array.from(uniqueWorkflows.values()); - - // Process workflows to get mermaid diagrams - const processedResults = processWorkflowExamples(deduplicatedResults, { - includeNodeParameters: false, - }); - - // Build output with formatted results - const formattedResults = deduplicatedResults.map((workflow, index) => ({ - name: workflow.name, - description: workflow.description, - workflow: processedResults[index].mermaid, - })); - const output: GetWorkflowExamplesOutput = { - examples: formattedResults, - totalResults: deduplicatedResults.length, - }; - - // Build response message and report - const responseMessage = buildResponseMessage(output); - reporter.complete(output); - - // Deduplicate template IDs - const uniqueTemplateIds = [...new Set(allTemplateIds)]; - - // Debug: Log what we're caching - logger?.debug('Caching workflow templates in state', { - templateCount: deduplicatedResults.length, - templateNames: deduplicatedResults.map((w) => w.name), - }); - - // Return success response with templates and template IDs stored in state - return createSuccessResponse(config, responseMessage, { - templateIds: uniqueTemplateIds, - cachedTemplates: deduplicatedResults, - }); - } catch (error) { - // Handle validation or unexpected errors - if (error instanceof z.ZodError) { - const validationError = new ValidationError('Invalid input parameters', { - extra: { errors: error.errors }, - }); - reporter.error(validationError); - return createErrorResponse(config, validationError); - } - - const toolError = new ToolExecutionError( - error instanceof Error ? error.message : 'Unknown error occurred', - { - toolName: GET_WORKFLOW_EXAMPLES_TOOL.toolName, - cause: error instanceof Error ? error : undefined, - }, - ); - reporter.error(toolError); - return createErrorResponse(config, toolError); - } - }, - { - name: GET_WORKFLOW_EXAMPLES_TOOL.toolName, - description: TOOL_DESCRIPTION, - schema: getWorkflowExamplesSchema, - }, - ); - - return { - tool: dynamicTool, - ...GET_WORKFLOW_EXAMPLES_TOOL, - }; -} diff --git a/packages/@n8n/ai-workflow-builder.ee/src/tools/test/builder-tools.test.ts b/packages/@n8n/ai-workflow-builder.ee/src/tools/test/builder-tools.test.ts index 148b1183dcc..67708bb4bfc 100644 --- a/packages/@n8n/ai-workflow-builder.ee/src/tools/test/builder-tools.test.ts +++ b/packages/@n8n/ai-workflow-builder.ee/src/tools/test/builder-tools.test.ts @@ -11,13 +11,6 @@ vi.mock('../get-documentation.tool', () => ({ }, })); -vi.mock('../get-workflow-examples.tool', () => ({ - GET_WORKFLOW_EXAMPLES_TOOL: { - toolName: 'get_workflow_examples', - displayTitle: 'Retrieving workflow examples', - }, -})); - vi.mock('../add-node.tool', () => ({ getAddNodeToolBase: vi.fn().mockReturnValue({ toolName: 'add_node', @@ -182,22 +175,10 @@ describe('builder-tools', () => { }); expect(tools).toHaveLength(BASE_TOOL_COUNT); - expect(tools.map((t) => t.toolName)).not.toContain('get_workflow_examples'); expect(tools.map((t) => t.toolName)).not.toContain('introspect'); expect(getAddNodeToolBase).toHaveBeenCalledWith(parsedNodeTypes); }); - it('should include workflow examples tool when templateExamples flag is enabled', () => { - const tools = getBuilderToolsForDisplay({ - nodeTypes: parsedNodeTypes, - featureFlags: { templateExamples: true }, - }); - - expect(tools).toHaveLength(BASE_TOOL_COUNT + 1); - expect(tools.map((t) => t.toolName)).toContain('get_workflow_examples'); - expect(tools.map((t) => t.toolName)).not.toContain('introspect'); - }); - it('should include introspect tool when enableIntrospection flag is enabled', () => { const tools = getBuilderToolsForDisplay({ nodeTypes: parsedNodeTypes, @@ -206,18 +187,6 @@ describe('builder-tools', () => { expect(tools).toHaveLength(BASE_TOOL_COUNT + 1); expect(tools.map((t) => t.toolName)).toContain('introspect'); - expect(tools.map((t) => t.toolName)).not.toContain('get_workflow_examples'); - }); - - it('should include both conditional tools when both flags are enabled', () => { - const tools = getBuilderToolsForDisplay({ - nodeTypes: parsedNodeTypes, - featureFlags: { templateExamples: true, enableIntrospection: true }, - }); - - expect(tools).toHaveLength(BASE_TOOL_COUNT + 2); - expect(tools.map((t) => t.toolName)).toContain('get_workflow_examples'); - expect(tools.map((t) => t.toolName)).toContain('introspect'); }); it('should work with empty node types array', () => { diff --git a/packages/@n8n/ai-workflow-builder.ee/src/tools/test/get-workflow-examples.tool.test.ts b/packages/@n8n/ai-workflow-builder.ee/src/tools/test/get-workflow-examples.tool.test.ts deleted file mode 100644 index d146aa1257a..00000000000 --- a/packages/@n8n/ai-workflow-builder.ee/src/tools/test/get-workflow-examples.tool.test.ts +++ /dev/null @@ -1,319 +0,0 @@ -import type { INode } from 'n8n-workflow'; -import type { MockedFunction } from 'vitest'; - -import { - parseToolResult, - extractProgressMessages, - findProgressMessage, - createToolConfigWithWriter, - createToolConfig, - expectToolSuccess, - type ParsedToolContent, - createNode, -} from '../../../test/test-utils'; -import type { WorkflowMetadata } from '../../types/tools'; -import { createGetWorkflowExamplesTool } from '../get-workflow-examples.tool'; -import type { FetchWorkflowsResult } from '../web/templates'; -import * as templates from '../web/templates'; - -// Mock LangGraph dependencies -vi.mock('@langchain/langgraph', () => ({ - getCurrentTaskInput: vi.fn(), - // eslint-disable-next-line @typescript-eslint/naming-convention - Command: vi.fn(function (params: Record<string, unknown>) { - return { content: JSON.stringify(params) }; - }), -})); - -// Mock the templates module -vi.mock('../web/templates'); - -describe('GetWorkflowExamplesTool', () => { - let getWorkflowExamplesTool: ReturnType<typeof createGetWorkflowExamplesTool>['tool']; - const mockFetchWorkflowsFromTemplates = templates.fetchWorkflowsFromTemplates as MockedFunction< - typeof templates.fetchWorkflowsFromTemplates - >; - - beforeEach(() => { - vi.clearAllMocks(); - getWorkflowExamplesTool = createGetWorkflowExamplesTool().tool; - }); - - afterEach(() => { - vi.clearAllMocks(); - }); - - // Helper to create mock workflow nodes - const createMockWorkflowNodes = (count: number = 3): INode[] => { - return Array.from({ length: count }, (_, i) => - createNode({ - id: `node-${i}`, - name: `Node ${i}`, - type: 'n8n-nodes-base.httpRequest', - }), - ); - }; - - // Helper to create mock workflow metadata - let mockTemplateIdCounter = 1; - const createMockWorkflowMetadata = ( - name: string, - description: string, - nodeCount: number = 3, - ): WorkflowMetadata => ({ - templateId: mockTemplateIdCounter++, - name, - description, - workflow: { - nodes: createMockWorkflowNodes(nodeCount), - connections: {}, - name, - }, - }); - - // Helper to create mock fetch result - const createMockFetchResult = ( - workflows: WorkflowMetadata[], - templateIds: number[] = workflows.map((_, i) => i + 1), - ): FetchWorkflowsResult => ({ - workflows, - totalFound: workflows.length, - templateIds, - }); - - describe('invoke', () => { - it('should successfully fetch workflow examples with search query', async () => { - const mockConfig = createToolConfigWithWriter('get_workflow_examples', 'test-call-1'); - - // Mock API response - mockFetchWorkflowsFromTemplates.mockResolvedValue( - createMockFetchResult([ - createMockWorkflowMetadata('Email Automation', 'Automate email workflows', 3), - createMockWorkflowMetadata('Slack Notification', 'Send Slack notifications', 4), - ]), - ); - - const result = await getWorkflowExamplesTool.invoke( - { - queries: [{ search: 'email automation' }], - }, - mockConfig, - ); - - const content = parseToolResult<ParsedToolContent>(result); - const message = content.update.messages[0]?.kwargs.content; - - expectToolSuccess(content, 'Found 2 workflow example(s)'); - expect(message).toContain('Email Automation'); - expect(message).toContain('Automate email workflows'); - expect(message).toContain('Slack Notification'); - expect(message).toContain('Send Slack notifications'); - // Verify mermaid diagrams are included - expect(message).toContain('```mermaid'); - expect(message).toContain('flowchart TD'); - - // Verify API call - expect(mockFetchWorkflowsFromTemplates).toHaveBeenCalledWith( - { search: 'email automation' }, - expect.any(Object), - ); - - // Check progress messages - const progressCalls = extractProgressMessages(mockConfig.writer); - expect(progressCalls.length).toBeGreaterThanOrEqual(3); - - const startMessage = findProgressMessage(progressCalls, 'running', 'input'); - expect(startMessage).toBeDefined(); - - const completeMessage = findProgressMessage(progressCalls, 'completed'); - expect(completeMessage).toBeDefined(); - }); - - it('should handle multiple queries and combine results', async () => { - const mockConfig = createToolConfig('get_workflow_examples', 'test-call-3'); - - // Set up mocks for two queries - mockFetchWorkflowsFromTemplates - .mockResolvedValueOnce( - createMockFetchResult([createMockWorkflowMetadata('Workflow 1', 'Description 1', 2)]), - ) - .mockResolvedValueOnce( - createMockFetchResult([createMockWorkflowMetadata('Workflow 2', 'Description 2', 3)]), - ); - - const result = await getWorkflowExamplesTool.invoke( - { - queries: [{ search: 'database' }, { search: 'api' }], - }, - mockConfig, - ); - - const content = parseToolResult<ParsedToolContent>(result); - const message = content.update.messages[0]?.kwargs.content; - - expectToolSuccess(content, 'Found 2 workflow example'); - expect(message).toContain('Workflow 1'); - expect(message).toContain('Workflow 2'); - - expect(mockFetchWorkflowsFromTemplates).toHaveBeenCalledTimes(2); - expect(mockFetchWorkflowsFromTemplates).toHaveBeenNthCalledWith( - 1, - { search: 'database' }, - expect.any(Object), - ); - expect(mockFetchWorkflowsFromTemplates).toHaveBeenNthCalledWith( - 2, - { search: 'api' }, - expect.any(Object), - ); - }); - - it('should return no results message when no workflows found', async () => { - const mockConfig = createToolConfig('get_workflow_examples', 'test-call-4'); - - mockFetchWorkflowsFromTemplates.mockResolvedValue({ - workflows: [], - totalFound: 0, - templateIds: [], - }); - - const result = await getWorkflowExamplesTool.invoke( - { - queries: [{ search: 'nonexistent workflow' }], - }, - mockConfig, - ); - - const content = parseToolResult<ParsedToolContent>(result); - - expectToolSuccess(content, 'No workflow examples found'); - }); - - it('should handle partial failures when fetching individual templates', async () => { - const mockConfig = createToolConfig('get_workflow_examples', 'test-call-5'); - - // Mock returns 2 workflows (simulating one failed internally) - mockFetchWorkflowsFromTemplates.mockResolvedValue( - createMockFetchResult([ - createMockWorkflowMetadata('Workflow 1', 'Description 1', 2), - createMockWorkflowMetadata('Workflow 3', 'Description 3', 3), - ]), - ); - - const result = await getWorkflowExamplesTool.invoke( - { - queries: [{ search: 'test' }], - }, - mockConfig, - ); - - const content = parseToolResult<ParsedToolContent>(result); - const message = content.update.messages[0]?.kwargs.content; - - // Should return 2 successful workflows (ignoring the failed one) - expectToolSuccess(content, 'Found 2 workflow example(s)'); - expect(message).toContain('Workflow 1'); - expect(message).toContain('Workflow 3'); - }); - - it('should handle validation errors for empty queries array', async () => { - const mockConfig = createToolConfig('get_workflow_examples', 'test-call-6'); - - try { - await getWorkflowExamplesTool.invoke( - { - queries: [], - }, - mockConfig, - ); - - expect(true).toBe(false); - } catch (error) { - expect(error).toBeDefined(); - expect(String(error)).toContain('Received tool input did not match expected schema'); - } - }); - - it('should handle network errors when fetching template list', async () => { - const mockConfig = createToolConfig('get_workflow_examples', 'test-call-8'); - - mockFetchWorkflowsFromTemplates.mockRejectedValue(new Error('Network error')); - - const result = await getWorkflowExamplesTool.invoke( - { - queries: [{ search: 'test' }], - }, - mockConfig, - ); - - const content = parseToolResult<ParsedToolContent>(result); - - // Should return no results since the query failed - expectToolSuccess(content, 'No workflow examples found'); - }); - - it('should track batch progress for multiple queries', async () => { - const mockConfig = createToolConfigWithWriter('get_workflow_examples', 'test-call-11'); - - mockFetchWorkflowsFromTemplates - .mockResolvedValueOnce( - createMockFetchResult([createMockWorkflowMetadata('Workflow 1', 'Description 1', 2)]), - ) - .mockResolvedValueOnce( - createMockFetchResult([createMockWorkflowMetadata('Workflow 2', 'Description 2', 3)]), - ); - - await getWorkflowExamplesTool.invoke( - { - queries: [{ search: 'query1' }, { search: 'query2' }], - }, - mockConfig, - ); - - const progressCalls = extractProgressMessages(mockConfig.writer); - - // Should have progress messages for batch processing - const progressMessages = progressCalls.filter( - (msg) => msg.status === 'running' && msg.updates.some((u) => u.type === 'progress'), - ); - expect(progressMessages.length).toBeGreaterThan(0); - - // Check for batch-related progress messages - const batchMessages = progressMessages.filter((msg) => - msg.updates.some( - (u) => - typeof u.data?.message === 'string' && - u.data.message.includes('Retrieving workflow examples'), - ), - ); - expect(batchMessages.length).toBeGreaterThan(0); - }); - - it('should continue processing remaining queries if one fails', async () => { - const mockConfig = createToolConfig('get_workflow_examples', 'test-call-13'); - - // First query fails, second succeeds - mockFetchWorkflowsFromTemplates - .mockRejectedValueOnce(new Error('API error')) - .mockResolvedValueOnce( - createMockFetchResult([ - createMockWorkflowMetadata('Success Workflow', 'Success Description', 2), - ]), - ); - - const result = await getWorkflowExamplesTool.invoke( - { - queries: [{ search: 'failing query' }, { search: 'successful query' }], - }, - mockConfig, - ); - - const content = parseToolResult<ParsedToolContent>(result); - const message = content.update.messages[0]?.kwargs.content; - - // Should return result from successful query - expectToolSuccess(content, 'Found 1 workflow example(s)'); - expect(message).toContain('Success Workflow'); - }); - }); -}); diff --git a/packages/@n8n/ai-workflow-builder.ee/src/tools/web/templates.ts b/packages/@n8n/ai-workflow-builder.ee/src/tools/web/templates.ts index 53fa9cd5230..c239fe48887 100644 --- a/packages/@n8n/ai-workflow-builder.ee/src/tools/web/templates.ts +++ b/packages/@n8n/ai-workflow-builder.ee/src/tools/web/templates.ts @@ -124,7 +124,7 @@ export interface FetchWorkflowsResult { /** * Fetch workflows from templates API and return full workflow data - * Shared utility used by both get-workflow-examples and get-node-examples tools + * Shared utility used by the get-node-examples and node-details tools */ export async function fetchWorkflowsFromTemplates( query: { diff --git a/packages/@n8n/ai-workflow-builder.ee/src/types/tools.ts b/packages/@n8n/ai-workflow-builder.ee/src/types/tools.ts index df828270ff0..73c66fa69a9 100644 --- a/packages/@n8n/ai-workflow-builder.ee/src/types/tools.ts +++ b/packages/@n8n/ai-workflow-builder.ee/src/types/tools.ts @@ -182,18 +182,6 @@ export interface NodeConfigurationEntry { */ export type NodeConfigurationsMap = Record<string, NodeConfigurationEntry[]>; -/** - * Output type for get workflow examples tool - */ -export interface GetWorkflowExamplesOutput { - examples: Array<{ - name: string; - description?: string; - workflow: string; - }>; - totalResults: number; -} - /** * Output type for get node configuration examples tool */ diff --git a/packages/@n8n/ai-workflow-builder.ee/src/workflow-builder-agent.ts b/packages/@n8n/ai-workflow-builder.ee/src/workflow-builder-agent.ts index 10dfd5c87c7..0fe0d8941ce 100644 --- a/packages/@n8n/ai-workflow-builder.ee/src/workflow-builder-agent.ts +++ b/packages/@n8n/ai-workflow-builder.ee/src/workflow-builder-agent.ts @@ -9,8 +9,8 @@ import { Command, GraphRecursionError } from '@langchain/langgraph'; import type { SelectedNodeContext } from '@n8n/api-types'; import type { Logger } from '@n8n/backend-common'; import { - ApplicationError, OperationalError, + UserError, type INodeTypeDescription, type IRunExecutionData, type ITelemetryTrackProperties, @@ -108,10 +108,8 @@ export interface ExpressionValue { } export interface BuilderFeatureFlags { - templateExamples?: boolean; /** Enable pin data generation in code builder (default: true). */ pinData?: boolean; - planMode?: boolean; /** Enable introspection tool for diagnostic data collection. Disabled by default. */ enableIntrospection?: boolean; /** Enable merged ask/build experience with assistant subgraph (default: false). */ @@ -240,8 +238,6 @@ export class WorkflowBuilderAgent { externalCallbacks: Callbacks | undefined, historicalMessages: BaseMessage[] | undefined, ) { - const usePlanMode = payload.featureFlags?.planMode === true; - // web_fetch_approval resumes always go through multi-agent (where the interrupt lives) if (payload.resumeData && payload.resumeInterrupt?.type === 'web_fetch_approval') { this.logger?.debug('web_fetch_approval resume, routing to multi-agent system', { @@ -292,7 +288,7 @@ export class WorkflowBuilderAgent { } // Initial plan request: route to multi-agent for discovery + planning - if (usePlanMode && payload.mode === 'plan') { + if (payload.mode === 'plan') { this.logger?.debug('Plan mode with code builder, routing to multi-agent for planning', { userId, }); @@ -649,12 +645,12 @@ export class WorkflowBuilderAgent { // If it's not an abort error, check for GraphRecursionError if (error instanceof GraphRecursionError) { - throw new ApplicationError(WORKFLOW_TOO_COMPLEX_ERROR); + throw new UserError(WORKFLOW_TOO_COMPLEX_ERROR); } // Check for 401 expired token errors (typically from long-running generations) if (this.isTokenExpiredError(error)) { - throw new ApplicationError(WORKFLOW_TOO_COMPLEX_ERROR); + throw new UserError(WORKFLOW_TOO_COMPLEX_ERROR); } // Re-throw any other errors diff --git a/packages/@n8n/ai-workflow-builder.ee/tsconfig.build.json b/packages/@n8n/ai-workflow-builder.ee/tsconfig.build.json index 3849fc785bd..d73a01a4308 100644 --- a/packages/@n8n/ai-workflow-builder.ee/tsconfig.build.json +++ b/packages/@n8n/ai-workflow-builder.ee/tsconfig.build.json @@ -3,8 +3,7 @@ "compilerOptions": { "composite": true, "rootDir": "src", - "outDir": "dist", - "tsBuildInfoFile": "dist/build.tsbuildinfo" + "outDir": "dist" }, "include": ["src/**/*.ts"], "exclude": ["src/**/__tests__/**", "src/**/test-utils/**", "**/*.test.ts"] diff --git a/packages/@n8n/ai-workflow-builder.ee/tsconfig.json b/packages/@n8n/ai-workflow-builder.ee/tsconfig.json index 8ae09705f48..2ffa784905d 100644 --- a/packages/@n8n/ai-workflow-builder.ee/tsconfig.json +++ b/packages/@n8n/ai-workflow-builder.ee/tsconfig.json @@ -11,7 +11,6 @@ "paths": { "@/*": ["./src/*"] }, - "tsBuildInfoFile": "dist/typecheck.tsbuildinfo", "types": ["node", "vitest/globals"] }, "include": ["src/**/*.ts", "test/**/*.ts", "evaluations/**/*.ts", "scripts/**/*.ts"] diff --git a/packages/@n8n/api-types/package.json b/packages/@n8n/api-types/package.json index e8ed6bf90f3..8a28859b5e2 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.25.0", + "version": "1.27.0", "scripts": { "clean": "rimraf dist .turbo", "dev": "pnpm watch", @@ -29,14 +29,13 @@ "@vitest/coverage-v8": "catalog:", "vitest": "catalog:", "vitest-mock-extended": "catalog:", - "zod": "catalog:" + "minifaker": "1.34.1" }, "dependencies": { "n8n-workflow": "workspace:*", "xss": "catalog:", - "@n8n/permissions": "workspace:*" - }, - "peerDependencies": { + "@n8n/permissions": "workspace:*", "zod": "catalog:" - } + }, + "license": "LicenseRef-n8n-sustainable-use" } diff --git a/packages/@n8n/api-types/src/agent-builder-interactive.ts b/packages/@n8n/api-types/src/agent-builder-interactive.ts index 4f20ffb0a96..0d39f0cb166 100644 --- a/packages/@n8n/api-types/src/agent-builder-interactive.ts +++ b/packages/@n8n/api-types/src/agent-builder-interactive.ts @@ -11,6 +11,13 @@ import { z } from 'zod'; export const ASK_LLM_TOOL_NAME = 'ask_llm' as const; export const ASK_CREDENTIAL_TOOL_NAME = 'ask_credential' as const; export const ASK_QUESTION_TOOL_NAME = 'ask_question' as const; +/** + * Frontend-only discriminator for generic approval cards. + * + * Approval suspensions keep the underlying tool name on the wire, so the FE + * maps them to this value before dispatching to the approval card component. + */ +export const APPROVAL_TOOL_NAME = 'approval' as const; export const interactiveToolNameSchema = z.union([ z.literal(ASK_LLM_TOOL_NAME), diff --git a/packages/@n8n/api-types/src/agent-builder-tool-node-types.ts b/packages/@n8n/api-types/src/agent-builder-tool-node-types.ts new file mode 100644 index 00000000000..d083dc9dab5 --- /dev/null +++ b/packages/@n8n/api-types/src/agent-builder-tool-node-types.ts @@ -0,0 +1,13 @@ +import { AI_VENDOR_NODE_TYPES, CHAT_TOOL_NODE_TYPE } from 'n8n-workflow'; + +export const AGENT_BUILDER_HIDDEN_AVAILABLE_TOOL_NODE_TYPES: readonly string[] = [ + ...AI_VENDOR_NODE_TYPES.map((nodeType) => `${nodeType}Tool`), + CHAT_TOOL_NODE_TYPE, +]; + +export const AGENT_BUILDER_AVAILABLE_AI_UTILITY_TOOL_NODE_TYPES = [ + 'toolCalculator', + 'toolThink', + '@n8n/n8n-nodes-langchain.toolCalculator', + '@n8n/n8n-nodes-langchain.toolThink', +] as const; 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 efe5b7d23fa..efbab115c0d 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 @@ -1,5 +1,6 @@ import { AgentJsonConfigSchema } from '../agent-json-config.schema'; import { sanitizeAgentJsonConfig } from '../sanitize-agent-json-config'; +import { SUB_AGENT_MAX_CHILDREN_MAX, SUB_AGENT_MAX_CHILDREN_MIN } from '../sub-agent.schema'; const baseConfig = { name: 'Test Agent', @@ -24,6 +25,183 @@ describe('sanitizeAgentJsonConfig', () => { expect(sanitizeAgentJsonConfig(config)).toEqual(config); }); + it('does not add omitted optional schema keys', () => { + const sanitized = sanitizeAgentJsonConfig(baseConfig); + + expect(sanitized).toStrictEqual(baseConfig); + expect(Object.keys(sanitized as Record<string, unknown>).sort()).toEqual([ + 'instructions', + 'model', + 'name', + ]); + }); + + it('strips unknown top-level keys before validation', () => { + expect( + sanitizeAgentJsonConfig({ + ...baseConfig, + legacyTopLevelField: 'removed', + }), + ).toEqual(baseConfig); + }); + + it('strips unknown nested object keys before validation', () => { + const sanitized = sanitizeAgentJsonConfig({ + ...baseConfig, + subAgents: { + maxChildren: 3, + agents: [{ agentId: 'agent-2', legacyLabel: 'Research' }], + legacyBudget: 99, + }, + config: { + toolCallConcurrency: 2, + webSearch: { enabled: true, provider: 'native', legacyProviderSetting: true }, + nodeTools: { enabled: true, legacyNodeToolSetting: true }, + legacyRuntimeSetting: true, + }, + }); + + expect(sanitized).toEqual({ + ...baseConfig, + subAgents: { + maxChildren: 3, + agents: [{ agentId: 'agent-2' }], + }, + config: { + toolCallConcurrency: 2, + webSearch: { enabled: true, provider: 'native' }, + nodeTools: { enabled: true }, + }, + }); + expect(AgentJsonConfigSchema.safeParse(sanitized).success).toBe(true); + }); + + it('strips unknown keys from supported typed-array entries', () => { + const sanitized = sanitizeAgentJsonConfig({ + ...baseConfig, + tools: [ + { + type: 'workflow', + workflow: 'wf-1', + name: 'Run workflow', + legacyWorkflowField: true, + }, + { + type: 'node', + name: 'Send message', + description: 'Sends a message', + node: { + nodeType: 'n8n-nodes-base.slack', + nodeTypeVersion: 1, + nodeParameters: { + channel: '#support', + arbitraryRuntimeParameter: true, + }, + credentials: { + slackApi: { + id: 'cred-1', + name: 'Slack', + legacyCredentialField: true, + }, + }, + legacyNodeConfigField: true, + }, + legacyNodeToolField: true, + }, + ], + }); + + expect(sanitized).toEqual({ + ...baseConfig, + tools: [ + { + type: 'workflow', + workflow: 'wf-1', + name: 'Run workflow', + }, + { + type: 'node', + name: 'Send message', + description: 'Sends a message', + node: { + nodeType: 'n8n-nodes-base.slack', + nodeTypeVersion: 1, + nodeParameters: { + channel: '#support', + arbitraryRuntimeParameter: true, + }, + credentials: { + slackApi: { + id: 'cred-1', + name: 'Slack', + }, + }, + }, + }, + ], + }); + expect(AgentJsonConfigSchema.safeParse(sanitized).success).toBe(true); + }); + + it('strips unknown keys from strict nested MCP config schemas', () => { + const sanitized = sanitizeAgentJsonConfig({ + ...baseConfig, + mcpServers: [ + { + name: 'github', + description: 'GitHub tools', + url: 'https://example.com/mcp', + transport: 'streamableHttp', + authentication: 'bearerAuth', + credential: 'cred-github', + metadata: { + nodeTypeName: '@n8n/mcp-registry.github', + legacyMetadataField: true, + }, + toolFilter: { + mode: 'allow', + tools: ['create_issue'], + legacyToolFilterField: true, + }, + approval: { + mode: 'selected', + tools: ['create_issue'], + legacyApprovalField: true, + }, + connectionTimeoutMs: 10_000, + legacyServerField: true, + }, + ], + }); + + expect(sanitized).toEqual({ + ...baseConfig, + mcpServers: [ + { + name: 'github', + description: 'GitHub tools', + url: 'https://example.com/mcp', + transport: 'streamableHttp', + authentication: 'bearerAuth', + credential: 'cred-github', + metadata: { + nodeTypeName: '@n8n/mcp-registry.github', + }, + toolFilter: { + mode: 'allow', + tools: ['create_issue'], + }, + approval: { + mode: 'selected', + tools: ['create_issue'], + }, + connectionTimeoutMs: 10_000, + }, + ], + }); + expect(AgentJsonConfigSchema.safeParse(sanitized).success).toBe(true); + }); + it('strips unsupported integration types such as the removed schedule integration', () => { const config = { ...baseConfig, @@ -105,17 +283,24 @@ describe('sanitizeAgentJsonConfig', () => { const sanitized = sanitizeAgentJsonConfig(legacyConfig); expect(sanitized).toMatchObject({ - ...legacyConfig, + name: legacyConfig.name, + model: legacyConfig.model, + instructions: legacyConfig.instructions, + tools: [], + skills: [], + credential: legacyConfig.credential, + memory: legacyConfig.memory, + providerTools: legacyConfig.providerTools, + config: legacyConfig.config, integrations: [], - legacyTopLevelField: 'should survive until schema parse', }); + expect(sanitized).not.toHaveProperty('legacyTopLevelField'); const parsed = AgentJsonConfigSchema.safeParse(sanitized); expect(parsed.success).toBe(true); if (!parsed.success) return; expect(parsed.data.integrations).toEqual([]); - expect(parsed.data).not.toHaveProperty('legacyTopLevelField'); }); it('strips unsupported entries across integrations, tools, skills, and tasks in one pass', () => { @@ -182,4 +367,190 @@ describe('sanitizeAgentJsonConfig', () => { expect(sanitizeAgentJsonConfig(config)).toEqual(config); }); + + it('preserves schema-known fields such as subAgents.maxChildren', () => { + const sanitized = sanitizeAgentJsonConfig({ + ...baseConfig, + subAgents: { + maxChildren: 3, + agents: [{ agentId: 'agent-2' }], + }, + }); + const parsed = AgentJsonConfigSchema.safeParse(sanitized); + + expect(parsed.success).toBe(true); + if (!parsed.success) return; + expect(parsed.data.subAgents?.maxChildren).toBe(3); + }); + + it.each([SUB_AGENT_MAX_CHILDREN_MIN, SUB_AGENT_MAX_CHILDREN_MAX])( + 'accepts boundary subAgents.maxChildren %s', + (maxChildren) => { + expect( + AgentJsonConfigSchema.safeParse({ + ...baseConfig, + subAgents: { maxChildren }, + }).success, + ).toBe(true); + }, + ); + + it.each([0, -1, 1.5, SUB_AGENT_MAX_CHILDREN_MAX + 1])( + 'rejects invalid subAgents.maxChildren %s', + (maxChildren) => { + expect( + AgentJsonConfigSchema.safeParse({ + ...baseConfig, + subAgents: { maxChildren }, + }).success, + ).toBe(false); + }, + ); + + it('preserves sub-agent model mappings by difficulty', () => { + const config = { + ...baseConfig, + subAgents: { + maxChildren: 3, + agents: [{ agentId: 'agent-2' }], + modelsByDifficulty: { + low: { model: 'openai/gpt-4o-mini', credential: 'cred-openai' }, + medium: { model: 'anthropic/claude-haiku-4-5', credential: 'cred-anthropic' }, + high: { + model: 'openrouter/anthropic/claude-sonnet-4-5', + credential: 'cred-openrouter', + }, + }, + }, + }; + + expect(sanitizeAgentJsonConfig(config)).toEqual(config); + expect(AgentJsonConfigSchema.safeParse(config).success).toBe(true); + }); + + it('strips unknown sub-agent difficulty model keys', () => { + const sanitized = sanitizeAgentJsonConfig({ + ...baseConfig, + subAgents: { + modelsByDifficulty: { + low: { model: 'openai/gpt-4o-mini', credential: 'cred-openai' }, + extreme: { model: 'anthropic/claude-sonnet-4-5', credential: 'cred-anthropic' }, + }, + }, + }); + + expect(sanitized).toEqual({ + ...baseConfig, + subAgents: { + modelsByDifficulty: { + low: { model: 'openai/gpt-4o-mini', credential: 'cred-openai' }, + }, + }, + }); + expect(AgentJsonConfigSchema.safeParse(sanitized).success).toBe(true); + }); + + it('strips unknown fields from sub-agent difficulty model mappings', () => { + const sanitized = sanitizeAgentJsonConfig({ + ...baseConfig, + subAgents: { + modelsByDifficulty: { + low: { + model: 'openai/gpt-4o-mini', + credential: 'cred-openai', + label: 'Cheap model', + provider: 'openai', + }, + }, + }, + }); + + expect(sanitized).toEqual({ + ...baseConfig, + subAgents: { + modelsByDifficulty: { + low: { model: 'openai/gpt-4o-mini', credential: 'cred-openai' }, + }, + }, + }); + expect(AgentJsonConfigSchema.safeParse(sanitized).success).toBe(true); + }); + + it('keeps invalid sub-agent difficulty model values for validation errors', () => { + const sanitized = sanitizeAgentJsonConfig({ + ...baseConfig, + subAgents: { + modelsByDifficulty: { + low: { + model: 'gpt-4o-mini', + credential: 'cred-openai', + }, + }, + }, + }); + + expect(sanitized).toEqual({ + ...baseConfig, + subAgents: { + modelsByDifficulty: { + low: { + model: 'gpt-4o-mini', + credential: 'cred-openai', + }, + }, + }, + }); + + const result = AgentJsonConfigSchema.safeParse(sanitized); + expect(result.success).toBe(false); + if (result.success) return; + expect( + result.error.issues.some( + (issue) => issue.path.join('.') === 'subAgents.modelsByDifficulty.low.model', + ), + ).toBe(true); + }); + + it('allows cleared sub-agent difficulty model credentials in draft config', () => { + const result = AgentJsonConfigSchema.safeParse({ + ...baseConfig, + subAgents: { + modelsByDifficulty: { + low: { + model: 'openai/gpt-4o-mini', + credential: ' ', + }, + }, + }, + }); + + expect(result.success).toBe(true); + if (!result.success) return; + expect(result.data.subAgents?.modelsByDifficulty?.low?.credential).toBe(''); + }); + + it('preserves existing sub-agent refs and maxChildren with model mappings', () => { + const sanitized = sanitizeAgentJsonConfig({ + ...baseConfig, + subAgents: { + maxChildren: 4, + agents: [{ agentId: 'agent-2' }], + modelsByDifficulty: { + high: { model: 'anthropic/claude-sonnet-4-5', credential: 'cred-anthropic' }, + }, + }, + }); + + expect(sanitized).toEqual({ + ...baseConfig, + subAgents: { + maxChildren: 4, + agents: [{ agentId: 'agent-2' }], + modelsByDifficulty: { + high: { model: 'anthropic/claude-sonnet-4-5', credential: 'cred-anthropic' }, + }, + }, + }); + expect(AgentJsonConfigSchema.safeParse(sanitized).success).toBe(true); + }); }); 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 14bed4a5227..0161df0a217 100644 --- a/packages/@n8n/api-types/src/agents/agent-integration.schema.ts +++ b/packages/@n8n/api-types/src/agents/agent-integration.schema.ts @@ -72,10 +72,6 @@ export type AgentTelegramIntegrationSettings = z.infer<typeof AgentTelegramSetti export const AgentIntegrationSettingsSchema = z.union([AgentTelegramSettingsSchema, z.undefined()]); export type AgentIntegrationSettings = z.infer<typeof AgentIntegrationSettingsSchema>; -/** Supported chat integration types; keep in sync with `credentialIntegrations` below. */ -export const SUPPORTED_AGENT_INTEGRATION_TYPES = ['telegram', 'slack', 'linear'] as const; -export type SupportedAgentIntegrationType = (typeof SUPPORTED_AGENT_INTEGRATION_TYPES)[number]; - const credentialIntegrations = [ createCredIntegrationSchema('telegram', AgentTelegramSettingsSchema).extend({ // keep optional for older agents 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 7c9332ef8f0..b41217ba9f5 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,6 +1,11 @@ import { z, type ZodError } from 'zod'; import { AgentIntegrationConfigSchema } from './agent-integration.schema'; +import { + SUB_AGENT_MAX_CHILDREN_DEFAULT, + SUB_AGENT_MAX_CHILDREN_MAX, + SUB_AGENT_MAX_CHILDREN_MIN, +} from './sub-agent.schema'; export const AgentModelSchema = z .string() @@ -68,9 +73,39 @@ const SubAgentConfigSchema = z.object({ agentId: z.string().trim().min(1), }); +export const SUB_AGENT_TASK_DIFFICULTIES = ['low', 'medium', 'high'] as const; +const SubAgentTaskDifficultySchema = z.enum(SUB_AGENT_TASK_DIFFICULTIES); + +const SubAgentDifficultyModelConfigSchema = z + .object({ + model: AgentModelSchema, + credential: z.string().trim(), + }) + .strict(); + const SubAgentsConfigSchema = z .object({ + maxChildren: z + .number() + .int() + .min(SUB_AGENT_MAX_CHILDREN_MIN) + .max(SUB_AGENT_MAX_CHILDREN_MAX) + .optional() + .describe( + `Maximum number of child sub-agent runs this parent agent may run in parallel. Defaults to ${SUB_AGENT_MAX_CHILDREN_DEFAULT} when unset.`, + ), agents: z.array(SubAgentConfigSchema).optional(), + modelsByDifficulty: z + .object({ + low: SubAgentDifficultyModelConfigSchema.optional(), + medium: SubAgentDifficultyModelConfigSchema.optional(), + high: SubAgentDifficultyModelConfigSchema.optional(), + }) + .strict() + .optional() + .describe( + 'Optional inline sub-agent model mappings by task difficulty. Missing mappings fall back to the parent agent model.', + ), }) .strict(); @@ -224,6 +259,7 @@ const AgentJsonToolConfigSchema = z.discriminatedUnion('type', [ type: z.literal('node'), name: z.string().min(1), description: z.string().optional(), + inputSchema: z.never().optional(), node: NodeConfigSchema, requireApproval: z.boolean().optional(), }) @@ -294,6 +330,7 @@ export type AgentJsonMemoryConfig = z.infer<typeof MemoryConfigSchema>; export type NodeToolConfig = z.infer<typeof NodeConfigSchema>; export type AgentJsonMcpServerConfig = z.infer<typeof McpServerConfigSchema>; export type McpAuthenticationSchemaType = z.infer<typeof McpAuthenticationSchemaTypes>; +export type SubAgentTaskDifficulty = z.infer<typeof SubAgentTaskDifficultySchema>; export interface ConfigValidationError { path: string; diff --git a/packages/@n8n/api-types/src/agents/dto.ts b/packages/@n8n/api-types/src/agents/dto.ts index 3d2dc65add5..330d173bdfd 100644 --- a/packages/@n8n/api-types/src/agents/dto.ts +++ b/packages/@n8n/api-types/src/agents/dto.ts @@ -1,8 +1,58 @@ +import { jsonParse } from 'n8n-workflow'; import { z } from 'zod'; import { interactiveResumeDataSchema } from '../agent-builder-interactive'; -import { Z } from '../zod-class'; import { agentTaskSchema } from './agent-task.schema'; +import { paginationSchema } from '../dto/pagination/pagination.dto'; +import { Z } from '../zod-class'; + +export const AGENTS_LIST_SORT_OPTIONS = [ + 'name:asc', + 'name:desc', + 'createdAt:asc', + 'createdAt:desc', + 'updatedAt:asc', + 'updatedAt:desc', +] as const; + +const agentListFilterSchema = z + .object({ + query: z.string().trim().min(1).max(128).optional(), + }) + .strict(); + +const agentListFilterValidator = z + .string() + .optional() + .transform((val, ctx) => { + if (!val) return undefined; + + try { + const result = agentListFilterSchema.safeParse(jsonParse(val)); + if (!result.success) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'Invalid filter fields', + path: ['filter'], + }); + return z.NEVER; + } + return result.data; + } catch { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'Invalid filter format', + path: ['filter'], + }); + return z.NEVER; + } + }); + +export class ListAgentsQueryDto extends Z.class({ + ...paginationSchema, + filter: agentListFilterValidator, + sortBy: z.enum(AGENTS_LIST_SORT_OPTIONS).optional(), +}) {} export class CreateAgentDto extends Z.class({ name: z.string().min(1), @@ -61,6 +111,12 @@ export class AgentBuildResumeDto extends Z.class({ resumeData: interactiveResumeDataSchema, }) {} +export class AgentChatResumeDto extends Z.class({ + runId: z.string().min(1), + toolCallId: z.string().min(1), + resumeData: z.unknown(), +}) {} + export class AgentDisconnectIntegrationDto extends Z.class({ type: z.string().min(1), credentialId: z.string().min(1), diff --git a/packages/@n8n/api-types/src/agents/index.ts b/packages/@n8n/api-types/src/agents/index.ts index 79186dddb21..87dbc505ab1 100644 --- a/packages/@n8n/api-types/src/agents/index.ts +++ b/packages/@n8n/api-types/src/agents/index.ts @@ -6,13 +6,18 @@ export * from './agent-task.schema'; export * from './dto'; export * from './model-providers'; export * from './provider-capabilities'; -export type * from './sub-agent.schema'; +export * from './sub-agent.schema'; export * from './types'; export type { AgentSseEvent, AgentSseMessage, ToolSuspendedPayload } from '../agent-sse'; +export { + AGENT_BUILDER_AVAILABLE_AI_UTILITY_TOOL_NODE_TYPES, + AGENT_BUILDER_HIDDEN_AVAILABLE_TOOL_NODE_TYPES, +} from '../agent-builder-tool-node-types'; export { ASK_LLM_TOOL_NAME, ASK_CREDENTIAL_TOOL_NAME, ASK_QUESTION_TOOL_NAME, + APPROVAL_TOOL_NAME, interactiveToolNameSchema, askLlmInputSchema, askLlmResumeSchema, diff --git a/packages/@n8n/api-types/src/agents/sanitize-agent-json-config.ts b/packages/@n8n/api-types/src/agents/sanitize-agent-json-config.ts index 94759a8f19f..7518966968b 100644 --- a/packages/@n8n/api-types/src/agents/sanitize-agent-json-config.ts +++ b/packages/@n8n/api-types/src/agents/sanitize-agent-json-config.ts @@ -1,8 +1,49 @@ -import { SUPPORTED_AGENT_INTEGRATION_TYPES } from './agent-integration.schema'; +import { z, type ZodDiscriminatedUnionOption } from 'zod'; -const SUPPORTED_TOOL_TYPES = ['custom', 'workflow', 'node'] as const; -const SUPPORTED_SKILL_TYPES = ['skill'] as const; -const SUPPORTED_TASK_TYPES = ['task'] as const; +import { AgentJsonConfigSchema } from './agent-json-config.schema'; + +const TYPED_ARRAY_CONFIG_KEYS = ['integrations', 'tools', 'skills', 'tasks'] as const; + +type DiscriminatedUnionSchema = z.ZodDiscriminatedUnion< + string, + ReadonlyArray<ZodDiscriminatedUnionOption<string>> +>; + +function isZodOptionalSchema(schema: z.ZodTypeAny): schema is z.ZodOptional<z.ZodTypeAny> { + return schema instanceof z.ZodOptional; +} + +function isZodNullableSchema(schema: z.ZodTypeAny): schema is z.ZodNullable<z.ZodTypeAny> { + return schema instanceof z.ZodNullable; +} + +function isZodDefaultSchema(schema: z.ZodTypeAny): schema is z.ZodDefault<z.ZodTypeAny> { + return schema instanceof z.ZodDefault; +} + +function isZodEffectsSchema(schema: z.ZodTypeAny): schema is z.ZodEffects<z.ZodTypeAny> { + return schema instanceof z.ZodEffects; +} + +function isZodArraySchema(schema: z.ZodTypeAny): schema is z.ZodArray<z.ZodTypeAny> { + return schema instanceof z.ZodArray; +} + +function isZodRecordSchema(schema: z.ZodTypeAny): schema is z.ZodRecord<z.ZodString, z.ZodTypeAny> { + return schema instanceof z.ZodRecord; +} + +function isRecord(value: unknown): value is Record<string, unknown> { + return typeof value === 'object' && value !== null && !Array.isArray(value); +} + +function isZodObjectSchema(schema: z.ZodTypeAny): schema is z.ZodObject<z.ZodRawShape> { + return schema instanceof z.ZodObject; +} + +function isDiscriminatedUnionSchema(schema: z.ZodTypeAny): schema is DiscriminatedUnionSchema { + return schema instanceof z.ZodDiscriminatedUnion; +} function filterUnsupportedTypedEntries( entries: unknown, @@ -11,11 +52,11 @@ function filterUnsupportedTypedEntries( if (!Array.isArray(entries)) return entries; return entries.filter((entry) => { - if (typeof entry !== 'object' || entry === null) { + if (!isRecord(entry)) { return true; } - const type = (entry as { type?: unknown }).type; + const type = getObjectProperty(entry, 'type'); if (typeof type !== 'string') { return true; } @@ -24,9 +65,133 @@ function filterUnsupportedTypedEntries( }); } +function getObjectProperty(value: Record<string, unknown>, property: string): unknown { + return value[property]; +} + +function getObjectDiscriminatorLiteralValue( + schema: z.ZodObject<z.ZodRawShape>, + discriminator: string, +): string | undefined { + const discriminatorSchema = schema.shape[discriminator]; + if ( + discriminatorSchema instanceof z.ZodLiteral && + typeof discriminatorSchema.value === 'string' + ) { + return discriminatorSchema.value; + } + + return undefined; +} + +function getDiscriminatorLiteralValues(schema: z.ZodTypeAny, discriminator: string): string[] { + if (isZodObjectSchema(schema)) { + const value = getObjectDiscriminatorLiteralValue(schema, discriminator); + return value === undefined ? [] : [value]; + } + + if (isDiscriminatedUnionSchema(schema)) { + return schema.options + .map((option) => getObjectDiscriminatorLiteralValue(option, schema.discriminator)) + .filter((value): value is string => value !== undefined); + } + + return []; +} + +function getDiscriminatedUnionOption( + schema: DiscriminatedUnionSchema, + value: unknown, +): z.ZodObject<z.ZodRawShape> | undefined { + if (!isRecord(value)) return undefined; + + const discriminatorValue = getObjectProperty(value, schema.discriminator); + if (typeof discriminatorValue !== 'string') return undefined; + + return schema.options.find( + (option) => + getObjectDiscriminatorLiteralValue(option, schema.discriminator) === discriminatorValue, + ); +} + +function getWrappedSchema(schema: z.ZodTypeAny): z.ZodTypeAny | undefined { + if (isZodOptionalSchema(schema)) { + return schema.unwrap(); + } + + if (isZodNullableSchema(schema)) { + return schema.unwrap(); + } + + if (isZodDefaultSchema(schema)) { + return schema.removeDefault(); + } + + if (isZodEffectsSchema(schema)) { + return schema.innerType(); + } + + return undefined; +} + +function getArrayElementSchema(schema: z.ZodTypeAny): z.ZodTypeAny | undefined { + const wrappedSchema = getWrappedSchema(schema); + if (wrappedSchema !== undefined) { + return getArrayElementSchema(wrappedSchema); + } + + return isZodArraySchema(schema) ? schema.element : undefined; +} + +function stripUnknownSchemaFields(value: unknown, schema: z.ZodTypeAny): unknown { + const wrappedSchema = getWrappedSchema(schema); + if (wrappedSchema !== undefined) { + return stripUnknownSchemaFields(value, wrappedSchema); + } + + if (isZodArraySchema(schema)) { + if (!Array.isArray(value)) return value; + + return value.map((entry) => stripUnknownSchemaFields(entry, schema.element)); + } + + if (isZodRecordSchema(schema)) { + if (!isRecord(value)) return value; + + return Object.fromEntries( + Object.entries(value).map(([key, entryValue]) => [ + key, + stripUnknownSchemaFields(entryValue, schema.valueSchema), + ]), + ); + } + + if (isZodObjectSchema(schema)) { + if (!isRecord(value)) return value; + + const sanitized: Record<string, unknown> = {}; + for (const [key, entryValue] of Object.entries(value)) { + const childSchema: z.ZodTypeAny | undefined = schema.shape[key]; + if (childSchema !== undefined) { + sanitized[key] = stripUnknownSchemaFields(entryValue, childSchema); + } + } + return sanitized; + } + + if (isDiscriminatedUnionSchema(schema)) { + const option = getDiscriminatedUnionOption(schema, value); + return option === undefined ? value : stripUnknownSchemaFields(value, option); + } + + return value; +} + /** * Strip legacy or unsupported typed entries from agent JSON config before strict - * Zod validation. Unknown top-level keys are still dropped by `AgentJsonConfigSchema`. + * Zod validation. Unknown top-level keys are dropped from `AgentJsonConfigSchema`. + * This intentionally cleans unknown fields gracefully, so older persisted configs + * and generated drafts can move forward as the schema evolves. * * Entries with a supported `type` but invalid required fields are kept so validation * can surface the error instead of silently discarding user mistakes. @@ -36,26 +201,19 @@ export function sanitizeAgentJsonConfig(raw: unknown): unknown { return raw; } - const config = raw as Record<string, unknown>; - const sanitized: Record<string, unknown> = { ...config }; + const sanitized = stripUnknownSchemaFields(raw, AgentJsonConfigSchema); + if (!isRecord(sanitized)) return sanitized; - if ('integrations' in sanitized) { - sanitized.integrations = filterUnsupportedTypedEntries( - sanitized.integrations, - SUPPORTED_AGENT_INTEGRATION_TYPES, - ); - } + for (const key of TYPED_ARRAY_CONFIG_KEYS) { + if (key in sanitized) { + const schema = getArrayElementSchema(AgentJsonConfigSchema.shape[key]); + if (schema === undefined) continue; - if ('tools' in sanitized) { - sanitized.tools = filterUnsupportedTypedEntries(sanitized.tools, SUPPORTED_TOOL_TYPES); - } - - if ('skills' in sanitized) { - sanitized.skills = filterUnsupportedTypedEntries(sanitized.skills, SUPPORTED_SKILL_TYPES); - } - - if ('tasks' in sanitized) { - sanitized.tasks = filterUnsupportedTypedEntries(sanitized.tasks, SUPPORTED_TASK_TYPES); + sanitized[key] = filterUnsupportedTypedEntries( + sanitized[key], + getDiscriminatorLiteralValues(schema, 'type'), + ); + } } return sanitized; diff --git a/packages/@n8n/api-types/src/agents/sub-agent.schema.ts b/packages/@n8n/api-types/src/agents/sub-agent.schema.ts index d948925113b..1b44c3f9e53 100644 --- a/packages/@n8n/api-types/src/agents/sub-agent.schema.ts +++ b/packages/@n8n/api-types/src/agents/sub-agent.schema.ts @@ -1,5 +1,9 @@ import type { RunnableAgentJsonConfig } from './agent-json-config.schema'; +export const SUB_AGENT_MAX_CHILDREN_MIN = 1; +export const SUB_AGENT_MAX_CHILDREN_MAX = 20; +export const SUB_AGENT_MAX_CHILDREN_DEFAULT = 10; + /** * A sub-agent is always a saved n8n agent — optionally pinned to a published * version. @@ -17,8 +21,6 @@ export interface ResolvedSubAgentSource { export interface SubAgentRunPolicy { maxChildren?: number; - /** Host-enforced wall-clock timeout for a child run — the n8n runner aborts the child. */ - timeoutMs?: number; } /** diff --git a/packages/@n8n/api-types/src/api-keys.ts b/packages/@n8n/api-types/src/api-keys.ts index 935b281db20..520231998bd 100644 --- a/packages/@n8n/api-types/src/api-keys.ts +++ b/packages/@n8n/api-types/src/api-keys.ts @@ -10,6 +10,11 @@ export type ApiKeyOwner = { email: string; }; +export type ApiKeyOwnerSummary = ApiKeyOwner & { + /** Number of keys this owner holds in the `all` population. */ + keyCount: number; +}; + export type ApiKey = { id: string; label: string; @@ -27,9 +32,28 @@ export type ApiKey = { export type ApiKeyWithRawValue = ApiKey & { rawApiKey: string }; +export type ApiKeyOwnership = 'mine' | 'all'; + export type ApiKeyList = { items: ApiKey[]; - count: number; + /** + * Per-ownership totals after the label filter is applied. + * `counts[ownership]` drives pagination of the returned page. + */ + counts: { mine: number; all: number }; + /** + * Per-ownership totals ignoring the label filter, so callers can render + * tab badges and empty-state CTAs against the true population. Equals + * `counts` when no label filter was passed. + */ + totals: { mine: number; all: number }; + /** + * Distinct owners who hold at least one key in the `all` population (with + * their key counts), regardless of the active label/owner filters, so + * callers can populate an owner filter. Empty for callers without + * `apiKey:manage`. + */ + owners: ApiKeyOwnerSummary[]; }; export type ApiKeyAudience = 'public-api' | 'mcp-server-api'; diff --git a/packages/@n8n/api-types/src/dto/ai/ai-build-request.dto.ts b/packages/@n8n/api-types/src/dto/ai/ai-build-request.dto.ts index 8b17b440b3a..4a3891eda10 100644 --- a/packages/@n8n/api-types/src/dto/ai/ai-build-request.dto.ts +++ b/packages/@n8n/api-types/src/dto/ai/ai-build-request.dto.ts @@ -106,9 +106,7 @@ export class AiBuilderChatRequestDto extends Z.class({ }), featureFlags: z .object({ - templateExamples: z.boolean().optional(), pinData: z.boolean().optional(), - planMode: z.boolean().optional(), mergeAskBuild: z.boolean().optional(), }) .optional(), diff --git a/packages/@n8n/api-types/src/dto/api-keys/__tests__/list-api-keys-query.dto.test.ts b/packages/@n8n/api-types/src/dto/api-keys/__tests__/list-api-keys-query.dto.test.ts new file mode 100644 index 00000000000..5963c73628d --- /dev/null +++ b/packages/@n8n/api-types/src/dto/api-keys/__tests__/list-api-keys-query.dto.test.ts @@ -0,0 +1,41 @@ +import { ListApiKeysQueryDto } from '../list-api-keys-query.dto'; + +const uuid = (n: number) => `00000000-0000-0000-0000-${String(n).padStart(12, '0')}`; + +describe('ListApiKeysQueryDto', () => { + describe('ownerIds', () => { + it('splits a comma-separated string, trimming blanks and empties', () => { + const result = ListApiKeysQueryDto.safeParse({ ownerIds: 'a, ,b, c,' }); + + expect(result.success).toBe(true); + expect(result.data?.ownerIds).toEqual(['a', 'b', 'c']); + }); + + it.each([ + ['absent', {}], + ['empty string', { ownerIds: '' }], + ])('is undefined when %s', (_label, data) => { + const result = ListApiKeysQueryDto.safeParse(data); + + expect(result.success).toBe(true); + expect(result.data?.ownerIds).toBeUndefined(); + }); + + it('accepts the full population of 100 UUID owners', () => { + // 100 UUIDs (36 chars each) comma-joined is 3699 chars — this must pass, + // i.e. the raw length guard cannot sit below the parsed 100-id limit. + const ids = Array.from({ length: 100 }, (_, i) => uuid(i)); + const result = ListApiKeysQueryDto.safeParse({ ownerIds: ids.join(',') }); + + expect(result.success).toBe(true); + expect(result.data?.ownerIds).toHaveLength(100); + }); + + it('rejects more than 100 owners', () => { + const ids = Array.from({ length: 101 }, (_, i) => uuid(i)); + const result = ListApiKeysQueryDto.safeParse({ ownerIds: ids.join(',') }); + + expect(result.success).toBe(false); + }); + }); +}); diff --git a/packages/@n8n/api-types/src/dto/api-keys/list-api-keys-query.dto.ts b/packages/@n8n/api-types/src/dto/api-keys/list-api-keys-query.dto.ts new file mode 100644 index 00000000000..736a2af6a8a --- /dev/null +++ b/packages/@n8n/api-types/src/dto/api-keys/list-api-keys-query.dto.ts @@ -0,0 +1,48 @@ +import { z } from 'zod'; + +import { Z } from '../../zod-class'; +import { paginationSchema } from '../pagination/pagination.dto'; + +export const LIST_API_KEYS_SORT_OPTIONS = [ + 'label:asc', + 'label:desc', + 'createdAt:asc', + 'createdAt:desc', + 'lastUsedAt:asc', + 'lastUsedAt:desc', + 'scopes:asc', + 'scopes:desc', +] as const; + +export type ListApiKeysSortOption = (typeof LIST_API_KEYS_SORT_OPTIONS)[number]; + +export class ListApiKeysQueryDto extends Z.class({ + ...paginationSchema, + ownership: z.enum(['mine', 'all']).optional(), + /** Case-insensitive substring match against the key's label. */ + label: z.string().trim().min(1).max(100).optional(), + /** + * Comma-separated owner ids to narrow the `all` view to keys owned by these + * users. Ignored for callers without `apiKey:manage`. Empty/absent means no + * owner narrowing (all owners). + */ + ownerIds: z + .string() + // Generous pre-split guard so we never split an unbounded string; sized to + // the parsed limits below (≤100 ids × ≤100 chars + 99 separators = 10099) + // so it never rejects an otherwise-valid multi-owner filter. + .max(10_099) + .optional() + .transform((val) => + val + ? val + .split(',') + .map((id) => id.trim()) + .filter(Boolean) + : undefined, + ) + // Bound the parsed list so a caller can't push an arbitrarily large + // `IN (...)` clause into the owner query. + .pipe(z.array(z.string().max(100)).max(100).optional()), + sortBy: z.enum(LIST_API_KEYS_SORT_OPTIONS).optional(), +}) {} diff --git a/packages/@n8n/api-types/src/dto/evaluations/dataset-row.dto.ts b/packages/@n8n/api-types/src/dto/evaluations/dataset-row.dto.ts new file mode 100644 index 00000000000..411e06d0e51 --- /dev/null +++ b/packages/@n8n/api-types/src/dto/evaluations/dataset-row.dto.ts @@ -0,0 +1,56 @@ +import { z } from 'zod'; + +import type { dataTableColumnTypeSchema } from '../../schemas/data-table.schema'; + +/** + * Where a data table column's value is sourced from when turning an execution + * into a dataset row: `input` = data that flowed into the evaluation's start + * node, `output` = data the end node produced. + */ +export const datasetFieldSourceSchema = z.enum(['input', 'output']); +export type DatasetFieldSource = z.infer<typeof datasetFieldSourceSchema>; + +/** + * Mapping for a single column. `null` leaves the column empty for the user to + * fill in later. + */ +export const datasetColumnMappingSchema = z + .object({ + source: datasetFieldSourceSchema, + field: z.string().min(1), + }) + .nullable(); +export type DatasetColumnMapping = z.infer<typeof datasetColumnMappingSchema>; + +export const addDatasetRowSchema = z.object({ + executionId: z.string().min(1), + // Keyed by data table column name. + mapping: z.record(z.string(), datasetColumnMappingSchema), +}); +export type AddDatasetRowDto = z.infer<typeof addDatasetRowSchema>; + +// --------------------------------------------------------------------------- +// Response shapes (not request-validated — plain interfaces). +// --------------------------------------------------------------------------- + +export interface DatasetColumnCandidate { + name: string; + type: z.infer<typeof dataTableColumnTypeSchema>; +} + +/** A field available on the execution, with a sample of its value for preview. */ +export interface DatasetCandidateField { + key: string; + sample: unknown; +} + +export interface DatasetCandidateResponse { + dataTableId: string; + columns: DatasetColumnCandidate[]; + fields: { + inputs: DatasetCandidateField[]; + outputs: DatasetCandidateField[]; + }; + /** Auto-suggested mapping keyed by column name; `null` means no match found. */ + suggestedMapping: Record<string, DatasetColumnMapping>; +} diff --git a/packages/@n8n/api-types/src/dto/evaluations/index.ts b/packages/@n8n/api-types/src/dto/evaluations/index.ts index 81260fa5947..d52b176e41b 100644 --- a/packages/@n8n/api-types/src/dto/evaluations/index.ts +++ b/packages/@n8n/api-types/src/dto/evaluations/index.ts @@ -1,2 +1,3 @@ +export * from './dataset-row.dto'; export * from './evaluation-config.dto'; export * from './evaluation-error-code'; diff --git a/packages/@n8n/api-types/src/dto/index.ts b/packages/@n8n/api-types/src/dto/index.ts index 10c8d2a9d5d..062932901c7 100644 --- a/packages/@n8n/api-types/src/dto/index.ts +++ b/packages/@n8n/api-types/src/dto/index.ts @@ -122,6 +122,11 @@ export { RetrieveTagQueryDto } from './tag/retrieve-tag-query.dto'; export { UpdateApiKeyRequestDto } from './api-keys/update-api-key-request.dto'; export { CreateApiKeyRequestDto } from './api-keys/create-api-key-request.dto'; +export { + ListApiKeysQueryDto, + LIST_API_KEYS_SORT_OPTIONS, + type ListApiKeysSortOption, +} from './api-keys/list-api-keys-query.dto'; export { CreateFolderDto } from './folders/create-folder.dto'; export { UpdateFolderDto } from './folders/update-folder.dto'; @@ -255,3 +260,6 @@ export { type EncryptionKeysSortOption, } from './encryption/list-encryption-keys-query.dto'; export type { EncryptionKeyResponseDto } from './encryption/encryption-key-response.dto'; + +export { UpdateOtelSettingsDto } from './otel/update-otel-settings.dto'; +export { TestOtelConnectionDto } from './otel/test-otel-connection.dto'; diff --git a/packages/@n8n/api-types/src/dto/otel/test-otel-connection.dto.ts b/packages/@n8n/api-types/src/dto/otel/test-otel-connection.dto.ts new file mode 100644 index 00000000000..f670ad00f66 --- /dev/null +++ b/packages/@n8n/api-types/src/dto/otel/test-otel-connection.dto.ts @@ -0,0 +1,12 @@ +import { UpdateOtelSettingsDto } from './update-otel-settings.dto'; +import { Z } from '../../zod-class'; + +export class TestOtelConnectionDto extends Z.class( + UpdateOtelSettingsDto.schema.pick({ + exporterEndpoint: true, + exporterTracingPath: true, + exporterServiceName: true, + exporterHeaders: true, + startupConnectivityTimeoutMs: true, + }).shape, +) {} diff --git a/packages/@n8n/api-types/src/dto/otel/update-otel-settings.dto.ts b/packages/@n8n/api-types/src/dto/otel/update-otel-settings.dto.ts new file mode 100644 index 00000000000..758f13169c6 --- /dev/null +++ b/packages/@n8n/api-types/src/dto/otel/update-otel-settings.dto.ts @@ -0,0 +1,16 @@ +import { z } from 'zod'; + +import { Z } from '../../zod-class'; + +export class UpdateOtelSettingsDto extends Z.class({ + enabled: z.boolean(), + exporterEndpoint: z.string().url(), + exporterTracingPath: z.string(), + exporterServiceName: z.string().min(1), + exporterHeaders: z.string(), + tracesSampleRate: z.number().min(0).max(1), + startupConnectivityTimeoutMs: z.number().int().nonnegative(), + includeNodeSpans: z.boolean(), + injectOutbound: z.boolean(), + productionExecutionsOnly: z.boolean(), +}) {} 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 681f08f0865..5063254ab95 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 @@ -2,23 +2,35 @@ import { ImportPackageRequestDto } from '../import-package-request.dto'; describe('ImportPackageRequestDto', () => { it('accepts omitted routing fields and defaults credential modes', () => { - const result = ImportPackageRequestDto.safeParse({}); + const result = ImportPackageRequestDto.safeParse({ workflowConflictPolicy: 'fail' }); expect(result.success).toBe(true); if (result.success) { expect(result.data).toEqual({ credentialMatchingMode: 'id-only', credentialMissingMode: 'must-preexist', + credentialBindings: {}, + workflowConflictPolicy: 'fail', + workflowPublishingPolicy: 'preserve-published-state', + workflowIdPolicy: 'new', }); } }); it('treats empty projectId and folderId as omitted', () => { - const result = ImportPackageRequestDto.safeParse({ projectId: '', folderId: ' ' }); + const result = ImportPackageRequestDto.safeParse({ + projectId: '', + folderId: ' ', + workflowConflictPolicy: 'fail', + }); expect(result.success).toBe(true); if (result.success) { expect(result.data).toEqual({ credentialMatchingMode: 'id-only', credentialMissingMode: 'must-preexist', + credentialBindings: {}, + workflowConflictPolicy: 'fail', + workflowPublishingPolicy: 'preserve-published-state', + workflowIdPolicy: 'new', }); } }); @@ -27,6 +39,7 @@ describe('ImportPackageRequestDto', () => { const result = ImportPackageRequestDto.safeParse({ projectId: ' proj-1 ', folderId: 'fld-1', + workflowConflictPolicy: 'new-version', }); expect(result.success).toBe(true); if (result.success) { @@ -35,6 +48,10 @@ describe('ImportPackageRequestDto', () => { folderId: 'fld-1', credentialMatchingMode: 'id-only', credentialMissingMode: 'must-preexist', + credentialBindings: {}, + workflowConflictPolicy: 'new-version', + workflowPublishingPolicy: 'preserve-published-state', + workflowIdPolicy: 'new', }); } }); @@ -42,6 +59,7 @@ describe('ImportPackageRequestDto', () => { it('strips unknown keys such as the package placeholder', () => { const result = ImportPackageRequestDto.safeParse({ projectId: 'proj-1', + workflowConflictPolicy: 'skip', package: '', }); expect(result.success).toBe(true); @@ -50,25 +68,97 @@ describe('ImportPackageRequestDto', () => { projectId: 'proj-1', credentialMatchingMode: 'id-only', credentialMissingMode: 'must-preexist', + credentialBindings: {}, + workflowConflictPolicy: 'skip', + workflowPublishingPolicy: 'preserve-published-state', + workflowIdPolicy: 'new', }); } }); it('rejects unsupported credentialMatchingMode values', () => { expect( - ImportPackageRequestDto.safeParse({ credentialMatchingMode: 'name-and-type' }).success, + ImportPackageRequestDto.safeParse({ + credentialMatchingMode: 'name-and-type', + workflowConflictPolicy: 'fail', + }).success, ).toBe(false); }); it('rejects unsupported credentialMissingMode values', () => { expect( - ImportPackageRequestDto.safeParse({ credentialMissingMode: 'create-stub' }).success, + ImportPackageRequestDto.safeParse({ + credentialMissingMode: 'create-stub', + workflowConflictPolicy: 'fail', + }).success, ).toBe(false); }); + it('parses credentialBindings from a JSON object string', () => { + const result = ImportPackageRequestDto.safeParse({ + credentialBindings: '{"source-cred":"target-cred"}', + workflowConflictPolicy: 'fail', + }); + + expect(result.success).toBe(true); + if (result.success) { + expect(result.data.credentialBindings).toEqual({ 'source-cred': 'target-cred' }); + } + }); + it.each([ - { name: 'non-string projectId', request: { projectId: 1 } }, - { name: 'non-string folderId', request: { folderId: false } }, + { name: 'invalid JSON', credentialBindings: 'not json' }, + { name: 'array JSON', credentialBindings: '[]' }, + { name: 'non-string target id', credentialBindings: '{"source":1}' }, + { name: 'empty source id', credentialBindings: '{"":"target"}' }, + { name: 'empty target id', credentialBindings: '{"source":""}' }, + ])('rejects credentialBindings with $name', ({ credentialBindings }) => { + expect( + ImportPackageRequestDto.safeParse({ + credentialBindings, + workflowConflictPolicy: 'fail', + }).success, + ).toBe(false); + }); + + it('rejects omitted workflowConflictPolicy', () => { + expect(ImportPackageRequestDto.safeParse({}).success).toBe(false); + }); + + describe('workflowIdPolicy', () => { + it('defaults to "new" when omitted', () => { + const result = ImportPackageRequestDto.safeParse({ workflowConflictPolicy: 'fail' }); + expect(result.success).toBe(true); + if (result.success) { + expect(result.data.workflowIdPolicy).toBe('new'); + } + }); + + it('accepts "source"', () => { + const result = ImportPackageRequestDto.safeParse({ + workflowConflictPolicy: 'fail', + workflowIdPolicy: 'source', + }); + expect(result.success).toBe(true); + if (result.success) { + expect(result.data.workflowIdPolicy).toBe('source'); + } + }); + + it('rejects unsupported workflowIdPolicy values', () => { + expect( + ImportPackageRequestDto.safeParse({ + workflowConflictPolicy: 'fail', + workflowIdPolicy: 'reuse', + }).success, + ).toBe(false); + }); + }); + + it.each([ + { name: 'non-string projectId', request: { projectId: 1, workflowConflictPolicy: 'fail' } }, + { name: 'non-string folderId', request: { folderId: false, workflowConflictPolicy: 'fail' } }, + { name: 'unknown workflowConflictPolicy', request: { workflowConflictPolicy: 'overwrite' } }, ])('rejects $name', ({ request }) => { expect(ImportPackageRequestDto.safeParse(request).success).toBe(false); }); 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 eb31b8ec167..2e7f77acc23 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 @@ -8,6 +8,10 @@ export const IMPORT_PACKAGE_REQUEST_FORM_FIELDS = [ 'folderId', 'credentialMatchingMode', 'credentialMissingMode', + 'credentialBindings', + 'workflowConflictPolicy', + 'workflowPublishingPolicy', + 'workflowIdPolicy', ] as const; /** Multipart text fields: empty / whitespace-only values become `undefined`. */ @@ -20,9 +24,54 @@ const optionalFormId = z return trimmed.length > 0 ? trimmed : undefined; }); +function isStringRecord(value: unknown): value is Record<string, string> { + if (typeof value !== 'object' || value === null || Array.isArray(value)) return false; + return Object.entries(value).every( + ([sourceId, targetId]) => + sourceId.length > 0 && typeof targetId === 'string' && targetId.length > 0, + ); +} + +const credentialBindingsSchema = z + .string() + .optional() + .transform((value, ctx) => { + if (value === undefined || value.trim().length === 0) return {}; + + let parsed: unknown; + try { + parsed = JSON.parse(value); + } catch { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: + 'credentialBindings must be a JSON object mapping source credential ids to target credential ids', + }); + return z.NEVER; + } + + if (!isStringRecord(parsed)) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: + 'credentialBindings must be a JSON object mapping source credential ids to target credential ids', + }); + return z.NEVER; + } + + return parsed; + }); + export class ImportPackageRequestDto extends Z.class({ projectId: optionalFormId, folderId: optionalFormId, credentialMatchingMode: z.enum(['id-only']).optional().default('id-only'), credentialMissingMode: z.enum(['must-preexist']).optional().default('must-preexist'), + credentialBindings: credentialBindingsSchema, + workflowConflictPolicy: z.enum(['new-version', 'fail', 'skip']), + workflowPublishingPolicy: z + .enum(['preserve-published-state', 'match-source', 'publish-all', 'unpublish-all']) + .optional() + .default('preserve-published-state'), + workflowIdPolicy: z.enum(['new', 'source']).optional().default('new'), }) {} diff --git a/packages/@n8n/api-types/src/dto/project/update-project.dto.ts b/packages/@n8n/api-types/src/dto/project/update-project.dto.ts index e222498dad1..96f8dbc3a4c 100644 --- a/packages/@n8n/api-types/src/dto/project/update-project.dto.ts +++ b/packages/@n8n/api-types/src/dto/project/update-project.dto.ts @@ -24,7 +24,7 @@ const updateProjectShape = { const trimmedKeys = tags.map((t) => t.key.trim()); return trimmedKeys.length === new Set(trimmedKeys).size; }, - { message: 'Duplicate keys are not allowed in customTelemetryTags' }, + { message: 'Duplicate keys are not allowed in custom span attributes' }, ) .optional(), }; diff --git a/packages/@n8n/api-types/src/dto/security-settings/security-settings.dto.ts b/packages/@n8n/api-types/src/dto/security-settings/security-settings.dto.ts index 62ca6fa35b9..0e7eea2a9b8 100644 --- a/packages/@n8n/api-types/src/dto/security-settings/security-settings.dto.ts +++ b/packages/@n8n/api-types/src/dto/security-settings/security-settings.dto.ts @@ -14,7 +14,7 @@ export class SecuritySettingsDto extends Z.class({ sharedPersonalWorkflowsCount: z.number(), sharedPersonalCredentialsCount: z.number(), managedByEnv: z.boolean(), - redactionEnforcement: redactionEnforcementFieldSchema.optional(), + redactionEnforcement: redactionEnforcementFieldSchema, }) {} export class UpdateSecuritySettingsDto extends Z.class({ 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 52b5c1660d7..61ddf0c1135 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 @@ -108,7 +108,7 @@ describe('CreateWorkflowDto', () => { expect(result.data?.tags).toEqual(['tag1', 'tag2']); }); - test('should preserve workflow custom telemetry tag settings', () => { + test('should preserve workflow custom span attribute settings', () => { const settings = { customTelemetryTags: [ { key: 'env', value: 'production' }, @@ -127,7 +127,7 @@ describe('CreateWorkflowDto', () => { expect(result.data?.settings).toEqual(settings); }); - test('should preserve workflow custom telemetry tag settings with keys that are unique after trim', () => { + test('should preserve workflow custom span attribute settings with keys that are unique after trim', () => { const settings = { customTelemetryTags: [ { key: ' env ', value: 'production' }, @@ -185,7 +185,7 @@ describe('CreateWorkflowDto', () => { expectedErrorPath: ['settings'], }, { - name: 'workflow custom telemetry tags as fixed collection object', + name: 'workflow custom span attributes as fixed collection object', request: { name: 'Test', nodes: [], @@ -199,7 +199,7 @@ describe('CreateWorkflowDto', () => { expectedErrorPath: ['settings', 'customTelemetryTags'], }, { - name: 'workflow custom telemetry tag with extra field', + name: 'workflow custom span attribute with extra field', request: { name: 'Test', nodes: [], @@ -211,7 +211,7 @@ describe('CreateWorkflowDto', () => { expectedErrorPath: ['settings', 'customTelemetryTags', 0], }, { - name: 'duplicate workflow custom telemetry tag keys', + name: 'duplicate workflow custom span attribute keys', request: { name: 'Test', nodes: [], @@ -226,7 +226,7 @@ describe('CreateWorkflowDto', () => { expectedErrorPath: ['settings', 'customTelemetryTags'], }, { - name: 'duplicate workflow custom telemetry tag keys after trim', + name: 'duplicate workflow custom span attribute keys after trim', request: { name: 'Test', nodes: [], @@ -241,7 +241,7 @@ describe('CreateWorkflowDto', () => { expectedErrorPath: ['settings', 'customTelemetryTags'], }, { - name: 'empty workflow custom telemetry tag key', + name: 'empty workflow custom span attribute key', request: { name: 'Test', nodes: [], @@ -253,7 +253,7 @@ describe('CreateWorkflowDto', () => { expectedErrorPath: ['settings', 'customTelemetryTags', 0, 'key'], }, { - name: 'whitespace-only workflow custom telemetry tag key', + name: 'whitespace-only workflow custom span attribute key', request: { name: 'Test', nodes: [], diff --git a/packages/@n8n/api-types/src/dto/workflows/__tests__/update-workflow.dto.test.ts b/packages/@n8n/api-types/src/dto/workflows/__tests__/update-workflow.dto.test.ts index dee2c7b0bda..40c374a61e5 100644 --- a/packages/@n8n/api-types/src/dto/workflows/__tests__/update-workflow.dto.test.ts +++ b/packages/@n8n/api-types/src/dto/workflows/__tests__/update-workflow.dto.test.ts @@ -85,7 +85,7 @@ describe('UpdateWorkflowDto', () => { expect(result.data?.tags).toEqual(['tag1', 'tag2']); }); - test('should preserve workflow custom telemetry tag settings', () => { + test('should preserve workflow custom span attribute settings', () => { const settings = { customTelemetryTags: [ { key: 'env', value: 'production' }, @@ -99,7 +99,7 @@ describe('UpdateWorkflowDto', () => { expect(result.data?.settings).toEqual(settings); }); - test('should preserve workflow custom telemetry tag settings with keys that are unique after trim', () => { + test('should preserve workflow custom span attribute settings with keys that are unique after trim', () => { const settings = { customTelemetryTags: [ { key: ' env ', value: 'production' }, @@ -147,7 +147,7 @@ describe('UpdateWorkflowDto', () => { expectedErrorPath: ['settings'], }, { - name: 'workflow custom telemetry tags as fixed collection object', + name: 'workflow custom span attributes as fixed collection object', request: { settings: { customTelemetryTags: { @@ -158,7 +158,7 @@ describe('UpdateWorkflowDto', () => { expectedErrorPath: ['settings', 'customTelemetryTags'], }, { - name: 'workflow custom telemetry tag with extra field', + name: 'workflow custom span attribute with extra field', request: { settings: { customTelemetryTags: [{ key: 'env', value: 'production', extra: 'field' }], @@ -167,7 +167,7 @@ describe('UpdateWorkflowDto', () => { expectedErrorPath: ['settings', 'customTelemetryTags', 0], }, { - name: 'duplicate workflow custom telemetry tag keys', + name: 'duplicate workflow custom span attribute keys', request: { settings: { customTelemetryTags: [ @@ -179,7 +179,7 @@ describe('UpdateWorkflowDto', () => { expectedErrorPath: ['settings', 'customTelemetryTags'], }, { - name: 'duplicate workflow custom telemetry tag keys after trim', + name: 'duplicate workflow custom span attribute keys after trim', request: { settings: { customTelemetryTags: [ @@ -191,7 +191,7 @@ describe('UpdateWorkflowDto', () => { expectedErrorPath: ['settings', 'customTelemetryTags'], }, { - name: 'empty workflow custom telemetry tag key', + name: 'empty workflow custom span attribute key', request: { settings: { customTelemetryTags: [{ key: '', value: 'production' }], @@ -200,7 +200,7 @@ describe('UpdateWorkflowDto', () => { expectedErrorPath: ['settings', 'customTelemetryTags', 0, 'key'], }, { - name: 'whitespace-only workflow custom telemetry tag key', + name: 'whitespace-only workflow custom span attribute key', request: { settings: { customTelemetryTags: [{ key: ' ', value: 'production' }], diff --git a/packages/@n8n/api-types/src/dto/workflows/base-workflow.dto.ts b/packages/@n8n/api-types/src/dto/workflows/base-workflow.dto.ts index 89daf8c514d..815a998caaf 100644 --- a/packages/@n8n/api-types/src/dto/workflows/base-workflow.dto.ts +++ b/packages/@n8n/api-types/src/dto/workflows/base-workflow.dto.ts @@ -41,20 +41,20 @@ const customTelemetryTagSchema = z .refine((key) => key.trim().length > 0, { message: 'Key must not be empty' }), value: z.string({ invalid_type_error: 'Value must be a string' }), }, - { invalid_type_error: 'Custom telemetry tag must be an object' }, + { invalid_type_error: 'Custom span attribute must be an object' }, ) - .strict({ message: 'Custom telemetry tag must only include key and value' }); + .strict({ message: 'Custom span attribute must only include key and value' }); const customTelemetryTagsSchema = z .array(customTelemetryTagSchema, { - invalid_type_error: 'Custom telemetry tags must be an array', + invalid_type_error: 'Custom span attributes must be an array', }) .refine( (tags) => { const trimmedKeys = tags.map((tag) => tag.key.trim()); return trimmedKeys.length === new Set(trimmedKeys).size; }, - { message: 'Duplicate keys are not allowed in customTelemetryTags' }, + { message: 'Duplicate keys are not allowed in custom span attributes' }, ); export const workflowSettingsSchema: z.ZodType<IWorkflowSettings | null> = z diff --git a/packages/@n8n/api-types/src/frontend-settings.ts b/packages/@n8n/api-types/src/frontend-settings.ts index 6001957f597..c66b89b43bf 100644 --- a/packages/@n8n/api-types/src/frontend-settings.ts +++ b/packages/@n8n/api-types/src/frontend-settings.ts @@ -66,6 +66,7 @@ export interface IEnterpriseSettings { customRoles: boolean; personalSpacePolicy: boolean; dataRedaction: boolean; + otelCustomSpanAttributes: boolean; } export interface FrontendSettings { @@ -298,6 +299,8 @@ export type FrontendModuleSettings = { sandboxEnabled: boolean; workflowBuilderAvailable: boolean; sandboxUnavailableReason: string | null; + /** When true, orchestrator LLM step / workflow code debug is captured (`N8N_INSTANCE_AI_RUN_DEBUG_ENABLED`). */ + runDebugEnabled: boolean; }; /** @@ -340,6 +343,12 @@ export type FrontendModuleSettings = { * `N8N_AGENTS_MODULES` */ modules: string[]; + /** + * Whether the agent knowledge base is enabled. Requires + * `N8N_AGENTS_AI_SANDBOX_ENABLED=true` and + * `N8N_AGENTS_AI_SANDBOX_PROVIDER=daytona` on the backend. + */ + knowledgeBaseEnabled: boolean; }; }; diff --git a/packages/@n8n/api-types/src/index.ts b/packages/@n8n/api-types/src/index.ts index 20ba96081a5..2898d55cadc 100644 --- a/packages/@n8n/api-types/src/index.ts +++ b/packages/@n8n/api-types/src/index.ts @@ -376,6 +376,11 @@ export type { InstanceAiEnsureThreadResponse, InstanceAiStoredMessage, InstanceAiThreadMessagesResponse, + InstanceAiRunDebugSummary, + InstanceAiRunDebugStep, + InstanceAiRunDebugWorkflowCodeSnapshot, + InstanceAiRunDebugResponse, + InstanceAiThreadDebugRunsResponse, InstanceAiRichMessagesResponse, InstanceAiThreadStatusResponse, InstanceAiAdminSettingsResponse, @@ -421,6 +426,20 @@ export { export type { AgentRunState, AgentNode } from './schemas/agent-run-reducer'; +export { + formatDebugJson, + summarizeJsonValue, + parseSystemPromptForDisplay, + parseMessageBlocks, + parseUsageSummary, + parseInputExtras, + parseOutputDisplayBlocks, + parseOutputExtras, + parseStepSummary, +} from './schemas/llm-step-display'; + +export type { ReadableContentBlock, ReadableSegment } from './schemas/llm-step-display'; + export { startTestRunPayloadSchema, StartTestRunRequestDto, diff --git a/packages/@n8n/api-types/src/push/execution.ts b/packages/@n8n/api-types/src/push/execution.ts index 3bf1dfc4fcc..0d6bae343ed 100644 --- a/packages/@n8n/api-types/src/push/execution.ts +++ b/packages/@n8n/api-types/src/push/execution.ts @@ -4,6 +4,7 @@ import type { ITaskStartedData, NodeConnectionType, WorkflowExecuteMode, + WorkflowExecutionSource, } from 'n8n-workflow'; export type ExecutionStarted = { @@ -11,6 +12,11 @@ export type ExecutionStarted = { data: { executionId: string; mode: WorkflowExecuteMode; + /** + * Who initiated the run. Absent for ordinary user runs; `'instance_ai'` + * when the AI assistant ran the workflow on the user's behalf. + */ + source?: WorkflowExecutionSource; startedAt: Date; workflowId: string; workflowName?: string; @@ -23,6 +29,7 @@ export type ExecutionWaiting = { type: 'executionWaiting'; data: { executionId: string; + source?: WorkflowExecutionSource; }; }; @@ -32,6 +39,11 @@ export type ExecutionFinished = { executionId: string; workflowId: string; status: ExecutionStatus; + /** + * Who initiated the run. Absent for ordinary user runs; `'instance_ai'` + * when the AI assistant ran the workflow on the user's behalf. + */ + source?: WorkflowExecutionSource; }; }; diff --git a/packages/@n8n/api-types/src/push/workflow.ts b/packages/@n8n/api-types/src/push/workflow.ts index 5f574640ec6..9d734b98489 100644 --- a/packages/@n8n/api-types/src/push/workflow.ts +++ b/packages/@n8n/api-types/src/push/workflow.ts @@ -18,6 +18,27 @@ export type WorkflowFailedToActivate = { }; }; +/** + * Sent when publishing a workflow succeeds for some triggers but not all: the + * new version stays published with the surviving triggers running, while + * `failedNodes` lists the triggers that could not be (re)activated (e.g. a + * webhook path conflict or a third-party registration error). The client + * surfaces the error and re-syncs the viewed workflow to `activeVersionId`. + */ +export type WorkflowPartiallyActivated = { + type: 'workflowPartiallyActivated'; + data: { + workflowId: string; + activeVersionId: string; + errorMessage: string; + failedNodes: Array<{ + nodeId: string; + nodeName: string; + errorMessage: string; + }>; + }; +}; + export type WorkflowDeactivated = { type: 'workflowDeactivated'; data: { @@ -52,6 +73,7 @@ export type WorkflowSettingsUpdated = { export type WorkflowPushMessage = | WorkflowActivated | WorkflowFailedToActivate + | WorkflowPartiallyActivated | WorkflowDeactivated | WorkflowAutoDeactivated | WorkflowUpdated diff --git a/packages/@n8n/api-types/src/schemas/__tests__/instance-ai.schema.test.ts b/packages/@n8n/api-types/src/schemas/__tests__/instance-ai.schema.test.ts index 57af1080b29..42ec7816538 100644 --- a/packages/@n8n/api-types/src/schemas/__tests__/instance-ai.schema.test.ts +++ b/packages/@n8n/api-types/src/schemas/__tests__/instance-ai.schema.test.ts @@ -2,6 +2,7 @@ import { applyBranchReadOnlyOverrides, DEFAULT_INSTANCE_AI_PERMISSIONS, InstanceAiAdminSettingsUpdateRequest, + instanceAiEventSchema, isDisplayableConfirmationRequest, isInstanceAiSandboxProvider, type InstanceAiConfirmationInputType, @@ -31,6 +32,19 @@ describe('sandbox provider', () => { }); }); +describe('instanceAiEventSchema', () => { + it('preserves traceId on run-start events', () => { + const event = { + type: 'run-start', + runId: 'run-1', + agentId: 'agent-1', + payload: { messageId: 'msg-1', traceId: 'trace-1' }, + }; + + expect(instanceAiEventSchema.parse(event)).toEqual(event); + }); +}); + describe('applyBranchReadOnlyOverrides', () => { it('should block all write permissions while preserving safe ones', () => { const result = applyBranchReadOnlyOverrides({ ...DEFAULT_INSTANCE_AI_PERMISSIONS }); diff --git a/packages/@n8n/api-types/src/schemas/__tests__/llm-step-display.test.ts b/packages/@n8n/api-types/src/schemas/__tests__/llm-step-display.test.ts new file mode 100644 index 00000000000..9cf33f1db3e --- /dev/null +++ b/packages/@n8n/api-types/src/schemas/__tests__/llm-step-display.test.ts @@ -0,0 +1,290 @@ +import { describe, expect, it } from 'vitest'; + +import { + parseInputExtras, + parseMessageBlocks, + parseOutputDisplayBlocks, + parseStepSummary, + parseSystemBlocks, + parseSystemPromptForDisplay, + parseToolCallBlocks, + parseToolResultBlocks, + parseUsageSummary, + summarizeJsonValue, + extractObservationsBlock, +} from '../llm-step-display'; + +describe('llm-step-display', () => { + it('parses string system prompts into readable blocks', () => { + expect(parseSystemBlocks('You are helpful')).toEqual([ + { + role: 'system', + content: 'You are helpful', + segments: [{ type: 'text', text: 'You are helpful' }], + }, + ]); + }); + + it('parses message content with role-first layout and collapsible metadata', () => { + const blocks = parseMessageBlocks([ + { + role: 'user', + content: 'Build a weather workflow', + providerOptions: { anthropic: { cacheControl: { type: 'ephemeral' } } }, + }, + ]); + + expect(blocks).toHaveLength(1); + expect(blocks[0]?.role).toBe('user'); + expect(blocks[0]?.content).toBe('Build a weather workflow'); + expect(blocks[0]?.segments).toEqual([{ type: 'text', text: 'Build a weather workflow' }]); + expect(blocks[0]?.metadata).toEqual({ + providerOptions: { anthropic: { cacheControl: { type: 'ephemeral' } } }, + }); + }); + + it('extracts structured tool-call segments from multipart assistant messages', () => { + const blocks = parseMessageBlocks([ + { + role: 'assistant', + content: [ + { type: 'text', text: 'Here is the plan.' }, + { type: 'tool-call', toolName: 'search_nodes', input: { query: 'webhook' } }, + ], + }, + ]); + + expect(blocks[0]?.segments).toEqual([ + { type: 'text', text: 'Here is the plan.' }, + { + type: 'tool-call', + name: 'search_nodes', + payload: { query: 'webhook' }, + metadata: undefined, + }, + ]); + }); + + it('extracts structured tool-result segments from tool messages', () => { + const blocks = parseMessageBlocks([ + { + role: 'tool', + content: [ + { + type: 'tool-result', + toolName: 'load_skill', + output: { type: 'json', value: { ok: true, skillId: 'workflow-builder' } }, + }, + ], + }, + ]); + + expect(blocks[0]?.segments?.[0]).toMatchObject({ + type: 'tool-result', + name: 'load_skill', + payload: { type: 'json', value: { ok: true, skillId: 'workflow-builder' } }, + }); + }); + + it('summarizes json payloads for collapsed previews', () => { + expect(summarizeJsonValue({ name: 'workflow-builder', extra: true })).toBe('{ name, extra }'); + expect(summarizeJsonValue({ type: 'json', value: { ok: true } })).toBe('{ ok: true }'); + }); + + it('formats tool calls with structured payload and metadata', () => { + const blocks = parseToolCallBlocks([ + { + toolCallId: 'tc-1', + toolName: 'build-workflow', + input: { code: 'workflow code' }, + }, + ]); + + expect(blocks[0]?.name).toBe('build-workflow'); + expect(blocks[0]?.kind).toBe('input'); + expect(blocks[0]?.payload).toEqual({ code: 'workflow code' }); + expect(blocks[0]?.content).toBe('{ code: workflow code }'); + expect(blocks[0]?.metadata).toEqual({ toolCallId: 'tc-1' }); + }); + + it('formats tool results with structured payload', () => { + const blocks = parseToolResultBlocks([ + { + toolCallId: 'tc-1', + toolName: 'build-workflow', + output: { success: true, workflowId: 'wf-1' }, + }, + ]); + + expect(blocks[0]?.name).toBe('build-workflow'); + expect(blocks[0]?.kind).toBe('output'); + expect(blocks[0]?.payload).toEqual({ success: true, workflowId: 'wf-1' }); + expect(blocks[0]?.content).toBe('{ success, workflowId }'); + }); + + it('parses standalone tool-result content objects as structured segments', () => { + const blocks = parseMessageBlocks([ + { + type: 'tool-result', + toolName: 'nodes', + output: { results: [], totalResults: 0 }, + toolCallId: 'tc-1', + }, + ]); + + expect(blocks[0]?.role).toBe('tool'); + expect(blocks[0]?.segments?.[0]).toMatchObject({ + type: 'tool-result', + name: 'nodes', + payload: { results: [], totalResults: 0 }, + metadata: { toolCallId: 'tc-1' }, + }); + expect(blocks[0]?.metadata).toBeUndefined(); + }); + + it('deduplicates overlapping tool call sources in output display blocks', () => { + const blocks = parseOutputDisplayBlocks({ + toolCalls: [ + { + toolCallId: 'tc-1', + toolName: 'nodes', + input: { action: 'search', nodeTypes: ['trigger'] }, + }, + ], + response: { + messages: [ + { + role: 'assistant', + toolCallId: 'tc-1', + providerMetadata: { anthropic: { cacheCreationInputTokens: 0 } }, + content: [ + { + type: 'tool-call', + toolName: 'nodes', + toolCallId: 'tc-1', + input: { action: 'search', nodeTypes: ['trigger'] }, + providerMetadata: { anthropic: { cacheCreationInputTokens: 0 } }, + }, + ], + }, + ], + }, + }); + + expect(blocks.filter((block) => block.role === 'assistant')).toHaveLength(1); + expect(blocks[0]?.metadata).toBeUndefined(); + expect(blocks[0]?.segments?.[0]).toMatchObject({ + type: 'tool-call', + name: 'nodes', + }); + }); + + it('builds unified output display blocks using the same message card shape', () => { + const blocks = parseOutputDisplayBlocks({ + toolResults: [ + { + toolCallId: 'tc-1', + toolName: 'nodes', + output: { results: [], totalResults: 0 }, + }, + ], + response: { + messages: [ + { + role: 'assistant', + content: [{ type: 'tool-call', toolName: 'nodes', input: { action: 'search' } }], + }, + ], + }, + }); + + expect(blocks[0]?.role).toBe('tool'); + expect(blocks[0]?.segments?.[0]).toMatchObject({ + type: 'tool-result', + name: 'nodes', + }); + expect(blocks[1]?.role).toBe('assistant'); + expect(blocks[1]?.segments?.[0]).toMatchObject({ + type: 'tool-call', + name: 'nodes', + payload: { action: 'search' }, + }); + }); + + it('summarizes steps for sidebar display', () => { + expect( + parseStepSummary( + { + system: 'x'.repeat(100), + messages: [{ role: 'user', content: 'Build a weather workflow please' }], + }, + { + finishReason: 'tool-calls', + toolCalls: [{ toolName: 'search_nodes' }, { toolName: 'build-workflow' }], + usage: { inputTokens: 100, outputTokens: 20, totalTokens: 120 }, + }, + ), + ).toEqual({ + finishReason: 'tool-calls', + toolNames: ['search_nodes', 'build-workflow'], + usageLabel: 'in: 100 · out: 20 · total: 120', + messagePreview: 'Build a weather workflow please', + systemCharCount: 100, + }); + }); + + it('includes full tools and config in input extras', () => { + expect( + parseInputExtras({ + system: 'prompt', + messages: [], + tools: { search: { description: 'search' } }, + toolChoice: 'auto', + activeTools: ['search'], + stepNumber: 0, + sdkStepNumber: 0, + }), + ).toEqual({ + tools: { search: { description: 'search' } }, + toolChoice: 'auto', + activeTools: ['search'], + }); + }); + + it('summarizes usage tokens for inline display', () => { + expect(parseUsageSummary({ inputTokens: 100, outputTokens: 20, totalTokens: 120 })?.label).toBe( + 'in: 100 · out: 20 · total: 120', + ); + }); + + it('extracts observations block from system prompt text', () => { + const systemPrompt = [ + 'You are helpful.', + '<observations>', + '* CRITICAL (14:28) User is rebuilding observational memory.', + '</observations>', + ].join('\n'); + + expect(extractObservationsBlock(systemPrompt)).toEqual({ + withoutObservations: 'You are helpful.', + observations: '* CRITICAL (14:28) User is rebuilding observational memory.', + }); + }); + + it('splits system prompt display into collapsed system and observations blocks', () => { + const parsed = parseSystemPromptForDisplay( + [ + 'Skill loading protocol', + '<observations>', + '* INFO (09:15) User prefers Slack notifications', + '</observations>', + ].join('\n'), + ); + + expect(parsed.observations).toBe('* INFO (09:15) User prefers Slack notifications'); + expect(parsed.systemBlocks[0]?.content).toBe('Skill loading protocol'); + expect(parsed.systemBlocks[0]?.segments).toEqual([ + { type: 'text', text: 'Skill loading protocol' }, + ]); + }); +}); 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 8d53a9d9016..6e4e3ceafd2 100644 --- a/packages/@n8n/api-types/src/schemas/instance-ai.schema.ts +++ b/packages/@n8n/api-types/src/schemas/instance-ai.schema.ts @@ -106,6 +106,7 @@ export function isSafeObjectKey(key: string): boolean { export const runStartPayloadSchema = z.object({ messageId: z.string().describe('Correlates with the user message that triggered this run'), + traceId: z.string().optional().describe('OpenTelemetry trace ID for correlating logs and errors'), messageGroupId: z .string() .optional() @@ -271,6 +272,7 @@ export type InstanceAiWorkflowSetupNode = z.infer<typeof workflowSetupNodeSchema export const taskItemSchema = z.object({ id: z.string().describe('Unique task identifier'), description: z.string().describe('What this task accomplishes'), + detail: z.string().optional().describe('Secondary lifecycle state or evidence for this task'), status: z.enum(['todo', 'in_progress', 'done', 'failed', 'cancelled']).describe('Current status'), }); @@ -290,6 +292,7 @@ export const plannedTaskArgSchema = z.object({ deps: z.array(z.string()), tools: z.array(z.string()).optional(), workflowId: z.string().optional(), + isSupportingWorkflow: z.boolean().optional(), }); export type PlannedTaskArg = z.infer<typeof plannedTaskArgSchema>; @@ -516,8 +519,20 @@ const mcpImageContentSchema = z.object({ data: z.string(), mimeType: z.string(), }); + +const mcpBlobResourceContentSchema = z.object({ + type: z.literal('resource'), + resource: z.object({ + uri: z.string(), + mimeType: z.string().optional(), + blob: z.string(), + }), +}); + export const mcpToolCallResultSchema = z.object({ - content: z.array(z.union([mcpTextContentSchema, mcpImageContentSchema])), + content: z.array( + z.union([mcpTextContentSchema, mcpImageContentSchema, mcpBlobResourceContentSchema]), + ), structuredContent: z.record(z.string(), z.unknown()).optional(), isError: z.boolean().optional(), }); @@ -679,6 +694,7 @@ export class InstanceAiCorrectTaskRequest extends Z.class({ export class InstanceAiEnsureThreadRequest extends Z.class({ threadId: z.string().uuid().optional(), + projectId: z.string().min(1), }) {} export const instanceAiGatewayKeySchema = z.string().min(1).max(256); @@ -786,7 +802,7 @@ export interface InstanceAiAgentNode { timeline: InstanceAiTimelineEntry[]; /** Latest task list — updated by tasks-update events. */ tasks?: TaskList; - /** Full planned task details — updated progressively by plan-with-agent via tasks-update. */ + /** Full planned task details — updated by create-tasks via tasks-update. */ planItems?: PlannedTaskArg[]; result?: string; error?: string; @@ -835,6 +851,7 @@ export interface InstanceAiThreadInfo { id: string; title?: string; resourceId: string; + projectId?: string; createdAt: string; updatedAt: string; metadata?: Record<string, unknown>; @@ -865,12 +882,57 @@ export interface InstanceAiThreadMessagesResponse { threadId: string; } +// --------------------------------------------------------------------------- +// Run debug buffer (dev panel — orchestrator LLM steps + workflow code) +// --------------------------------------------------------------------------- + +export interface InstanceAiRunDebugSummary { + runId: string; + threadId: string; + startedAt: number; + stepCount: number; + workflowCodeCount: number; + label?: string; +} + +export interface InstanceAiRunDebugStep { + stepNumber: number; + input?: Record<string, unknown>; + output?: Record<string, unknown>; +} + +export interface InstanceAiRunDebugWorkflowCodeSnapshot { + code: string; + source: 'full-code' | 'patch'; + patches?: unknown; + workflowId?: string; + toolCallId?: string; + success: boolean; + errors?: string[]; + capturedAt: number; +} + +export interface InstanceAiRunDebugResponse { + threadId: string; + runId: string; + startedAt: number; + label?: string; + steps: InstanceAiRunDebugStep[]; + workflowCode: InstanceAiRunDebugWorkflowCodeSnapshot[]; +} + +export interface InstanceAiThreadDebugRunsResponse { + runs: InstanceAiRunDebugSummary[]; + threadId: string; +} + // --------------------------------------------------------------------------- // Rich messages response (session-restored view with agent trees) // --------------------------------------------------------------------------- export interface InstanceAiRichMessagesResponse { threadId: string; + projectId?: string; messages: InstanceAiMessage[]; /** Next SSE event ID for this thread — use as cursor to avoid replaying events already covered by these messages. */ nextEventId: number; @@ -1083,7 +1145,7 @@ export function getRenderHint(toolName: string): InstanceAiToolCallState['render if (toolName === 'delegate') return 'delegate'; if (toolName === 'build-workflow' || toolName === 'build-workflow-with-agent') return 'builder'; if (toolName === 'research-with-agent') return 'researcher'; - if (toolName === 'plan') return 'planner'; + if (toolName === 'create-tasks') return 'planner'; if (toolName === 'eval-setup-with-agent') return 'eval-setup'; if (toolName === 'list_skills' || toolName === 'load_skill') return 'skill'; return 'default'; diff --git a/packages/@n8n/api-types/src/schemas/llm-step-display.ts b/packages/@n8n/api-types/src/schemas/llm-step-display.ts new file mode 100644 index 00000000000..63c28da8046 --- /dev/null +++ b/packages/@n8n/api-types/src/schemas/llm-step-display.ts @@ -0,0 +1,773 @@ +/** + * Shared LLM step display helpers for Instance AI run debug. + * + * Used by the frontend debug modal, eval HTML reports, and any tooling + * that renders InstanceAiRunDebug* API payloads. + */ + +export interface ReadableContentBlock { + role: string; + content: string; + segments?: ReadableSegment[]; + metadata?: unknown; +} + +export type ReadableSegment = + | { type: 'text'; text: string } + | { type: 'tool-call'; name: string; payload?: unknown; metadata?: unknown } + | { type: 'tool-result'; name?: string; payload?: unknown; metadata?: unknown } + | { type: 'json'; payload: unknown; label?: string } + | { type: 'reasoning'; text: string }; + +export interface ReadableToolCallBlock { + name: string; + kind?: 'input' | 'output'; + payload?: unknown; + content: string; + metadata?: unknown; +} + +export interface StepDebugSummary { + finishReason?: string; + toolNames: string[]; + usageLabel?: string; + messagePreview?: string; + systemCharCount?: number; +} + +export interface ReadableUsageSummary { + label: string; + metadata: unknown; +} + +export interface ParsedSystemPromptDisplay { + systemBlocks: ReadableContentBlock[]; + observations: string | null; +} + +const OBSERVATIONS_BLOCK_PATTERN = /<observations>([\s\S]*?)<\/observations>/i; + +function isRecord(value: unknown): value is Record<string, unknown> { + return typeof value === 'object' && value !== null && !Array.isArray(value); +} + +export function formatDebugJson(value: unknown): string { + try { + return JSON.stringify(value, null, 2); + } catch { + return String(value); + } +} + +function looksLikeJsonString(value: string): boolean { + const trimmed = value.trim(); + return ( + (trimmed.startsWith('{') && trimmed.endsWith('}')) || + (trimmed.startsWith('[') && trimmed.endsWith(']')) + ); +} + +function unwrapJsonPayload(value: unknown): unknown { + if (isRecord(value) && value.type === 'json' && 'value' in value) { + return value.value; + } + return value; +} + +export function summarizeJsonValue(value: unknown): string { + const unwrapped = unwrapJsonPayload(value); + + if (unwrapped === null) return 'null'; + if (unwrapped === undefined) return 'undefined'; + if (typeof unwrapped === 'string') { + const trimmed = unwrapped.trim(); + if (looksLikeJsonString(trimmed)) { + try { + return summarizeJsonValue(JSON.parse(trimmed)); + } catch { + // fall through + } + } + return trimmed.length > 96 ? `${trimmed.slice(0, 96)}…` : trimmed; + } + if (typeof unwrapped === 'number' || typeof unwrapped === 'boolean') { + return String(unwrapped); + } + if (Array.isArray(unwrapped)) { + return `[${unwrapped.length} items]`; + } + if (isRecord(unwrapped)) { + const keys = Object.keys(unwrapped); + if (keys.length === 0) return '{}'; + if (keys.length === 1) { + const key = keys[0] ?? 'key'; + const entry = summarizeJsonValue(unwrapped[key]); + return `{ ${key}: ${entry} }`; + } + const preview = keys.slice(0, 2).join(', '); + return keys.length > 2 ? `{ ${preview}, +${keys.length - 2} }` : `{ ${preview} }`; + } + + const formatted = formatDebugJson(unwrapped); + return formatted.length > 96 ? `${formatted.slice(0, 96)}…` : formatted; +} + +function omitKeys(record: Record<string, unknown>, keys: ReadonlySet<string>): unknown { + const rest: Record<string, unknown> = {}; + for (const [key, value] of Object.entries(record)) { + if (!keys.has(key)) { + rest[key] = value; + } + } + return Object.keys(rest).length > 0 ? rest : undefined; +} + +function parsePartSegment(part: unknown): ReadableSegment[] { + if (!isRecord(part)) { + return [{ type: 'json', payload: part }]; + } + + if (part.type === 'text' && typeof part.text === 'string') { + return [{ type: 'text', text: part.text }]; + } + + if (part.type === 'tool-call') { + const name = + (typeof part.toolName === 'string' && part.toolName) || + (typeof part.name === 'string' && part.name) || + 'tool'; + const input = part.input ?? part.args; + return [ + { + type: 'tool-call', + name, + payload: input, + metadata: omitKeys(part, new Set(['type', 'toolName', 'name', 'input', 'args'])), + }, + ]; + } + + if (part.type === 'tool-result') { + const name = + (typeof part.toolName === 'string' && part.toolName) || + (typeof part.name === 'string' && part.name) || + undefined; + const output = part.output ?? part.result ?? part; + return [ + { + type: 'tool-result', + name, + payload: output, + metadata: omitKeys(part, new Set(['type', 'toolName', 'name', 'output', 'result'])), + }, + ]; + } + + if (part.type === 'reasoning' && typeof part.text === 'string') { + return [{ type: 'reasoning', text: part.text }]; + } + + if (part.type === 'file') { + const mediaType = typeof part.mediaType === 'string' ? part.mediaType : 'file'; + return [{ type: 'json', payload: part, label: `file: ${mediaType}` }]; + } + + return [ + { + type: 'json', + payload: part, + label: typeof part.type === 'string' ? String(part.type) : undefined, + }, + ]; +} + +function parseContentSegments(content: unknown): ReadableSegment[] { + if (typeof content === 'string') { + const trimmed = content.trim(); + if (trimmed.length === 0) return []; + if (looksLikeJsonString(trimmed)) { + try { + return [{ type: 'json', payload: JSON.parse(trimmed) }]; + } catch { + // fall through + } + } + return [{ type: 'text', text: content }]; + } + + if (Array.isArray(content)) { + return content.flatMap((part) => parsePartSegment(part)); + } + + if (isRecord(content)) { + if (typeof content.type === 'string') { + return parsePartSegment(content); + } + return [{ type: 'json', payload: content }]; + } + + if (content === undefined || content === null) { + return []; + } + + return [{ type: 'json', payload: content }]; +} + +function segmentsToPreview(segments: ReadableSegment[]): string { + return segments + .map((segment) => { + switch (segment.type) { + case 'text': + return segment.text; + case 'tool-call': + return `[tool-call: ${segment.name}]`; + case 'tool-result': + return segment.name ? `[tool-result: ${segment.name}]` : '[tool-result]'; + case 'reasoning': + return segment.text; + case 'json': + return summarizeJsonValue(segment.payload); + } + }) + .filter((entry) => entry.length > 0) + .join('\n\n'); +} + +function inferRoleFromValue(value: Record<string, unknown>, fallback: string): string { + if (typeof value.role === 'string') { + return value.role; + } + if (value.type === 'tool-result') { + return 'tool'; + } + if (value.type === 'tool-call') { + return 'assistant'; + } + return fallback; +} + +function createTextBlock( + role: string, + text: string, + segmentType: 'text' | 'reasoning' = 'text', +): ReadableContentBlock { + if (segmentType === 'reasoning') { + return { + role, + content: text, + segments: [{ type: 'reasoning', text }], + }; + } + + return { + role, + content: text, + segments: [{ type: 'text', text }], + }; +} + +function toolCallToBlock(toolCall: ReadableToolCallBlock): ReadableContentBlock { + return { + role: 'assistant', + content: `[tool-call: ${toolCall.name}]`, + segments: [ + { + type: 'tool-call', + name: toolCall.name, + payload: toolCall.payload, + metadata: toolCall.metadata, + }, + ], + }; +} + +function toolResultToBlock(toolResult: ReadableToolCallBlock): ReadableContentBlock { + return { + role: 'tool', + content: toolResult.name ? `[tool-result: ${toolResult.name}]` : '[tool-result]', + segments: [ + { + type: 'tool-result', + name: toolResult.name, + payload: toolResult.payload, + metadata: toolResult.metadata, + }, + ], + }; +} + +function parseContentBlock( + role: string, + value: unknown, + contentKey = 'content', +): ReadableContentBlock { + if (typeof value === 'string') { + const segments = parseContentSegments(value); + return { + role, + content: segmentsToPreview(segments) || value, + segments: segments.length > 0 ? segments : undefined, + }; + } + + if (!isRecord(value)) { + const segments = [{ type: 'json' as const, payload: value }]; + return { + role, + content: summarizeJsonValue(value), + segments, + }; + } + + const resolvedRole = inferRoleFromValue(value, role); + const rawContent = value[contentKey] ?? value.text ?? value; + const segments = parseContentSegments(rawContent); + const metadataKeys = new Set<string>([contentKey, 'text', 'role']); + if (rawContent === value) { + for (const key of ['type', 'toolName', 'name', 'input', 'args', 'output', 'result']) { + metadataKeys.add(key); + } + } + const hasToolSegments = segments.some( + (segment) => segment.type === 'tool-call' || segment.type === 'tool-result', + ); + if (hasToolSegments) { + for (const key of ['toolCallId', 'providerMetadata', 'providerOptions']) { + metadataKeys.add(key); + } + } + const metadata = omitKeys(value, metadataKeys); + + return { + role: resolvedRole, + content: segmentsToPreview(segments) || summarizeJsonValue(rawContent), + segments: segments.length > 0 ? segments : undefined, + metadata, + }; +} + +export function parseSystemBlocks(system: unknown): ReadableContentBlock[] { + if (system === undefined || system === null) { + return []; + } + + if (typeof system === 'string') { + return [{ role: 'system', content: system, segments: [{ type: 'text', text: system }] }]; + } + + if (Array.isArray(system)) { + return system.flatMap((entry, index) => { + const block = parseContentBlock('system', entry); + return [{ ...block, role: block.role === 'system' ? `system ${index + 1}` : block.role }]; + }); + } + + return [parseContentBlock('system', system)]; +} + +export function extractObservationsBlock(text: string): { + withoutObservations: string; + observations: string | null; +} { + const match = text.match(OBSERVATIONS_BLOCK_PATTERN); + if (!match) { + return { withoutObservations: text, observations: null }; + } + + const observations = match[1]?.trim() ?? null; + const withoutObservations = text.replace(OBSERVATIONS_BLOCK_PATTERN, '').trim(); + + return { + withoutObservations, + observations: observations && observations.length > 0 ? observations : null, + }; +} + +function extractObservationsFromBlock(block: ReadableContentBlock): { + block: ReadableContentBlock; + observations: string | null; +} { + if (block.segments?.length) { + let observations: string | null = null; + const segments: ReadableSegment[] = block.segments.flatMap((segment): ReadableSegment[] => { + if (segment.type !== 'text') { + return [segment]; + } + + const extracted = extractObservationsBlock(segment.text); + if (extracted.observations) { + observations = observations + ? `${observations}\n\n${extracted.observations}` + : extracted.observations; + } + + if (extracted.withoutObservations.trim().length === 0) { + return []; + } + + return [{ ...segment, text: extracted.withoutObservations }]; + }); + + return { + block: { + ...block, + content: segmentsToPreview(segments), + segments: segments.length > 0 ? segments : undefined, + }, + observations, + }; + } + + const extracted = extractObservationsBlock(block.content); + return { + block: { + ...block, + content: extracted.withoutObservations, + segments: extracted.withoutObservations + ? [{ type: 'text', text: extracted.withoutObservations }] + : undefined, + }, + observations: extracted.observations, + }; +} + +export function parseSystemPromptForDisplay(system: unknown): ParsedSystemPromptDisplay { + const blocks = parseSystemBlocks(system); + const observationsParts: string[] = []; + const systemBlocks: ReadableContentBlock[] = []; + + for (const block of blocks) { + const extracted = extractObservationsFromBlock(block); + if (extracted.observations) { + observationsParts.push(extracted.observations); + } + if (extracted.block.content.trim().length > 0 || extracted.block.segments?.length) { + systemBlocks.push(extracted.block); + } + } + + return { + systemBlocks, + observations: observationsParts.length > 0 ? observationsParts.join('\n\n') : null, + }; +} + +export function parseMessageBlocks(messages: unknown): ReadableContentBlock[] { + if (messages === undefined || messages === null) { + return []; + } + + if (!Array.isArray(messages)) { + return [parseContentBlock('message', messages)]; + } + + return messages.map((message, index) => { + const block = parseContentBlock(`message ${index + 1}`, message); + return { + ...block, + role: block.role.startsWith('message ') ? block.role : block.role || `message ${index + 1}`, + }; + }); +} + +export function parseToolCallBlocks(toolCalls: unknown): ReadableToolCallBlock[] { + if (toolCalls === undefined || toolCalls === null) { + return []; + } + + if (!Array.isArray(toolCalls)) { + return [ + { + name: 'tool', + payload: toolCalls, + content: summarizeJsonValue(toolCalls), + }, + ]; + } + + return (toolCalls as unknown[]).map((toolCall: unknown, index) => { + if (!isRecord(toolCall)) { + return { + name: `tool ${index + 1}`, + payload: toolCall, + content: summarizeJsonValue(toolCall), + }; + } + + const name = + (typeof toolCall.toolName === 'string' && toolCall.toolName) || + (typeof toolCall.name === 'string' && toolCall.name) || + `tool ${index + 1}`; + const input = toolCall.input ?? toolCall.args; + const payload = input ?? toolCall; + const metadata = omitKeys( + toolCall, + new Set(['toolName', 'name', 'input', 'args', 'output', 'result']), + ); + + return { + name, + kind: 'input', + payload, + content: summarizeJsonValue(payload), + metadata, + }; + }); +} + +export function parseToolResultBlocks(toolResults: unknown): ReadableToolCallBlock[] { + if (toolResults === undefined || toolResults === null) { + return []; + } + + if (!Array.isArray(toolResults)) { + return [ + { + name: 'tool result', + payload: toolResults, + content: summarizeJsonValue(toolResults), + }, + ]; + } + + return (toolResults as unknown[]).map((toolResult: unknown, index) => { + if (!isRecord(toolResult)) { + return { + name: `result ${index + 1}`, + payload: toolResult, + content: summarizeJsonValue(toolResult), + }; + } + + const name = + (typeof toolResult.toolName === 'string' && toolResult.toolName) || + (typeof toolResult.name === 'string' && toolResult.name) || + `tool ${index + 1}`; + const output = toolResult.output ?? toolResult.result; + const payload = output ?? toolResult; + const metadata = omitKeys( + toolResult, + new Set(['toolName', 'name', 'output', 'result', 'input', 'args']), + ); + + return { + name, + kind: 'output', + payload, + content: summarizeJsonValue(payload), + metadata, + }; + }); +} + +export function parseUsageSummary(usage: unknown): ReadableUsageSummary | undefined { + if (usage === undefined || usage === null) { + return undefined; + } + + if (!isRecord(usage)) { + return { label: formatDebugJson(usage), metadata: usage }; + } + + const inputTokens = usage.inputTokens ?? usage.promptTokens; + const outputTokens = usage.outputTokens ?? usage.completionTokens; + const totalTokens = usage.totalTokens; + + const parts: string[] = []; + if (typeof inputTokens === 'number') parts.push(`in: ${inputTokens}`); + if (typeof outputTokens === 'number') parts.push(`out: ${outputTokens}`); + if (typeof totalTokens === 'number') parts.push(`total: ${totalTokens}`); + + return { + label: parts.length > 0 ? parts.join(' · ') : formatDebugJson(usage), + metadata: usage, + }; +} + +export function parseInputExtras(input: Record<string, unknown> | undefined): unknown { + if (!input) return undefined; + + const extras: Record<string, unknown> = {}; + const primaryKeys = new Set(['system', 'messages', 'stepNumber', 'sdkStepNumber']); + + for (const [key, value] of Object.entries(input)) { + if (!primaryKeys.has(key)) { + extras[key] = value; + } + } + + return Object.keys(extras).length > 0 ? extras : undefined; +} + +function getBlockDedupeKey(block: ReadableContentBlock): string { + if (block.segments?.length) { + return block.segments + .map((segment) => { + switch (segment.type) { + case 'text': + return `text:${segment.text}`; + case 'reasoning': + return `reasoning:${segment.text}`; + case 'tool-call': { + const toolCallId = + isRecord(segment.metadata) && typeof segment.metadata.toolCallId === 'string' + ? segment.metadata.toolCallId + : ''; + return `tool-call:${segment.name}:${toolCallId}:${formatDebugJson(segment.payload ?? null)}`; + } + case 'tool-result': { + const toolCallId = + isRecord(segment.metadata) && typeof segment.metadata.toolCallId === 'string' + ? segment.metadata.toolCallId + : ''; + return `tool-result:${segment.name ?? ''}:${toolCallId}:${formatDebugJson(segment.payload ?? null)}`; + } + case 'json': + return `json:${formatDebugJson(segment.payload)}`; + } + }) + .join('|'); + } + + return `${block.role}:${block.content}`; +} + +function dedupeContentBlocks(blocks: ReadableContentBlock[]): ReadableContentBlock[] { + const seen = new Set<string>(); + return blocks.filter((block) => { + const key = getBlockDedupeKey(block); + if (seen.has(key)) { + return false; + } + seen.add(key); + return true; + }); +} + +function parsePrimaryOutputMessageBlocks(output: Record<string, unknown>): ReadableContentBlock[] { + if (isRecord(output.response) && Array.isArray(output.response.messages)) { + const messages = parseMessageBlocks(output.response.messages); + if (messages.length > 0) { + return messages; + } + } + + if (output.content !== undefined && output.content !== null) { + const contentBlocks = parseMessageBlocks(output.content); + if (contentBlocks.length > 0) { + return contentBlocks; + } + } + + return parseToolCallBlocks(output.toolCalls).map(toolCallToBlock); +} + +export function parseOutputDisplayBlocks( + output: Record<string, unknown> | undefined, +): ReadableContentBlock[] { + if (!output) { + return []; + } + + const blocks: ReadableContentBlock[] = []; + + if (typeof output.text === 'string' && output.text.trim()) { + blocks.push(createTextBlock('assistant', output.text)); + } + + if (typeof output.reasoningText === 'string' && output.reasoningText.trim()) { + blocks.push(createTextBlock('reasoning', output.reasoningText, 'reasoning')); + } + + blocks.push(...parseToolResultBlocks(output.toolResults).map(toolResultToBlock)); + blocks.push(...parsePrimaryOutputMessageBlocks(output)); + + return dedupeContentBlocks(blocks); +} + +export function parseOutputExtras(output: Record<string, unknown> | undefined): unknown { + if (!output) return undefined; + + const extras: Record<string, unknown> = {}; + const primaryKeys = new Set([ + 'text', + 'toolCalls', + 'toolResults', + 'usage', + 'response', + 'finishReason', + 'stepNumber', + 'sdkStepNumber', + 'content', + 'reasoning', + 'reasoningText', + ]); + + for (const [key, value] of Object.entries(output)) { + if (!primaryKeys.has(key)) { + extras[key] = value; + } + } + + if (isRecord(output.response)) { + const responseMeta: Record<string, unknown> = {}; + for (const [key, value] of Object.entries(output.response)) { + if (key !== 'messages') { + responseMeta[key] = value; + } + } + if (Object.keys(responseMeta).length > 0) { + extras.responseMeta = responseMeta; + } + } + + return Object.keys(extras).length > 0 ? extras : undefined; +} + +export function parseStepSummary( + input?: Record<string, unknown>, + output?: Record<string, unknown>, +): StepDebugSummary { + const toolNames: string[] = []; + + if (Array.isArray(output?.toolCalls)) { + for (const toolCall of output.toolCalls) { + if (!isRecord(toolCall)) continue; + const name = + (typeof toolCall.toolName === 'string' && toolCall.toolName) || + (typeof toolCall.name === 'string' && toolCall.name) || + undefined; + if (name && !toolNames.includes(name)) { + toolNames.push(name); + } + } + } + + let messagePreview: string | undefined; + if (Array.isArray(input?.messages) && input.messages.length > 0) { + const blocks = parseMessageBlocks(input.messages); + const lastBlock = blocks[blocks.length - 1]; + if (lastBlock?.content) { + const trimmed = lastBlock.content.trim(); + messagePreview = trimmed.length > 72 ? `${trimmed.slice(0, 72)}…` : trimmed; + } + } + + let systemCharCount: number | undefined; + if (typeof input?.system === 'string') { + systemCharCount = input.system.length; + } else if (Array.isArray(input?.system)) { + systemCharCount = parseSystemBlocks(input.system).reduce( + (total, block) => total + block.content.length, + 0, + ); + } + + return { + finishReason: typeof output?.finishReason === 'string' ? output.finishReason : undefined, + toolNames, + usageLabel: parseUsageSummary(output?.usage)?.label, + messagePreview, + systemCharCount, + }; +} 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 5b5b466bc8e..5f73311daca 100644 --- a/packages/@n8n/api-types/src/schemas/mcp-registry.schema.ts +++ b/packages/@n8n/api-types/src/schemas/mcp-registry.schema.ts @@ -32,7 +32,6 @@ export interface McpRegistryServerResponse { updatedAt: string; icons: McpRegistryServerIconResponse[]; websiteUrl?: string; - authType: 'oauth2'; /** * Resolved n8n credential type name for this server (e.g. * `notionMcpOAuth2Api`). Matches the credential type generated by diff --git a/packages/@n8n/api-types/src/schemas/project.schema.ts b/packages/@n8n/api-types/src/schemas/project.schema.ts index 69352e2a01a..d1a3144a1c2 100644 --- a/packages/@n8n/api-types/src/schemas/project.schema.ts +++ b/packages/@n8n/api-types/src/schemas/project.schema.ts @@ -9,6 +9,7 @@ export type ProjectType = z.infer<typeof projectTypeSchema>; export const projectIconSchema = z.object({ type: z.enum(['emoji', 'icon']), value: z.string().min(1), + color: z.string().optional(), }); export type ProjectIcon = z.infer<typeof projectIconSchema>; diff --git a/packages/@n8n/api-types/tsconfig.build.json b/packages/@n8n/api-types/tsconfig.build.json index ee0e3e20fda..e08cb937d03 100644 --- a/packages/@n8n/api-types/tsconfig.build.json +++ b/packages/@n8n/api-types/tsconfig.build.json @@ -3,8 +3,7 @@ "compilerOptions": { "composite": true, "rootDir": "src", - "outDir": "dist", - "tsBuildInfoFile": "dist/build.tsbuildinfo" + "outDir": "dist" }, "include": ["src/**/*.ts"], "exclude": ["src/**/__tests__/**"] diff --git a/packages/@n8n/api-types/tsconfig.json b/packages/@n8n/api-types/tsconfig.json index 170975fbeba..35487f800a9 100644 --- a/packages/@n8n/api-types/tsconfig.json +++ b/packages/@n8n/api-types/tsconfig.json @@ -1,8 +1,7 @@ { "extends": "@n8n/typescript-config/tsconfig.common.json", "compilerOptions": { - "types": ["node", "vitest/globals"], - "tsBuildInfoFile": "dist/typecheck.tsbuildinfo" + "types": ["node", "vitest/globals"] }, "include": ["src/**/*.ts"], "references": [ diff --git a/packages/@n8n/backend-common/package.json b/packages/@n8n/backend-common/package.json index c189c76c865..7c8ac0e40dd 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.25.0", + "version": "1.27.0", "scripts": { "clean": "rimraf dist .turbo", "dev": "pnpm watch", @@ -45,5 +45,6 @@ "vitest": "catalog:", "vitest-mock-extended": "catalog:", "zod": "catalog:" - } + }, + "license": "LicenseRef-n8n-sustainable-use" } diff --git a/packages/@n8n/backend-common/src/__tests__/typed-emitter.test.ts b/packages/@n8n/backend-common/src/__tests__/typed-emitter.test.ts new file mode 100644 index 00000000000..3d488bc90b0 --- /dev/null +++ b/packages/@n8n/backend-common/src/__tests__/typed-emitter.test.ts @@ -0,0 +1,72 @@ +import { TypedEmitter } from '../typed-emitter'; + +type TestEvents = { + ping: { value: number }; +}; + +describe('TypedEmitter', () => { + describe('debouncedEmit', () => { + beforeEach(() => { + vi.useFakeTimers(); + }); + + afterEach(() => { + vi.useRealTimers(); + }); + + it('should emit after the debounce delay', () => { + const emitter = new (class extends TypedEmitter<TestEvents> { + trigger(value: number) { + this.debouncedEmit('ping', { value }); + } + })(); + const listener = vi.fn(); + emitter.on('ping', listener); + + emitter.trigger(1); + expect(listener).not.toHaveBeenCalled(); + + vi.advanceTimersByTime(300); + expect(listener).toHaveBeenCalledOnce(); + expect(listener).toHaveBeenCalledWith({ value: 1 }); + }); + + it('should debounce multiple calls within the delay window', () => { + const emitter = new (class extends TypedEmitter<TestEvents> { + trigger(value: number) { + this.debouncedEmit('ping', { value }); + } + })(); + const listener = vi.fn(); + emitter.on('ping', listener); + + emitter.trigger(1); + emitter.trigger(2); + emitter.trigger(3); + + vi.advanceTimersByTime(300); + + expect(listener).toHaveBeenCalledOnce(); + expect(listener).toHaveBeenCalledWith({ value: 3 }); + }); + + it('should emit again after a second call following the delay', () => { + const emitter = new (class extends TypedEmitter<TestEvents> { + trigger(value: number) { + this.debouncedEmit('ping', { value }); + } + })(); + const listener = vi.fn(); + emitter.on('ping', listener); + + emitter.trigger(1); + vi.advanceTimersByTime(300); + expect(listener).toHaveBeenCalledOnce(); + + emitter.trigger(2); + vi.advanceTimersByTime(300); + expect(listener).toHaveBeenCalledTimes(2); + expect(listener).toHaveBeenLastCalledWith({ value: 2 }); + }); + }); +}); diff --git a/packages/@n8n/backend-common/src/index.ts b/packages/@n8n/backend-common/src/index.ts index f49c0d10306..67a3749904a 100644 --- a/packages/@n8n/backend-common/src/index.ts +++ b/packages/@n8n/backend-common/src/index.ts @@ -11,3 +11,4 @@ export { isContainedWithin, safeJoinPath } from './utils/path-util'; export { assertDir, exists } from './utils/fs'; export { parseFlatted } from './utils/parse-flatted'; export { CliParser } from './cli-parser'; +export { TypedEmitter } from './typed-emitter'; diff --git a/packages/@n8n/backend-common/src/license-state.ts b/packages/@n8n/backend-common/src/license-state.ts index 6c05688685a..3f4c67aba4a 100644 --- a/packages/@n8n/backend-common/src/license-state.ts +++ b/packages/@n8n/backend-common/src/license-state.ts @@ -126,6 +126,10 @@ export class LicenseState { return this.isLicensed('feat:binaryDataS3'); } + isExecutionDataS3Licensed() { + return this.isLicensed('feat:executionDataS3'); + } + isMultiMainLicensed() { return this.isLicensed('feat:multipleMainInstances'); } @@ -194,6 +198,10 @@ export class LicenseState { return this.isLicensed(['feat:saml', 'feat:oidc']); } + isOtelCustomSpanAttributesLicensed() { + return this.isLicensed(LICENSE_FEATURES.OTEL_CUSTOM_SPAN_ATTRIBUTES); + } + // -------------------- // integers // -------------------- @@ -234,6 +242,11 @@ export class LicenseState { return this.getValue('quota:maxTeamProjects') ?? 0; } + isTeamProjectsLicensed() { + const quota = this.getMaxTeamProjects(); + return quota === UNLIMITED_LICENSE_QUOTA || quota > 0; + } + getMaxWorkflowsWithEvaluations() { return this.getValue('quota:evaluations:maxWorkflows') ?? 0; } diff --git a/packages/@n8n/backend-common/src/modules/__tests__/module-registry.test.ts b/packages/@n8n/backend-common/src/modules/__tests__/module-registry.test.ts index 82ac42cf602..4c218238341 100644 --- a/packages/@n8n/backend-common/src/modules/__tests__/module-registry.test.ts +++ b/packages/@n8n/backend-common/src/modules/__tests__/module-registry.test.ts @@ -24,6 +24,7 @@ describe('eligibleModules', () => { 'external-secrets', 'community-packages', 'data-table', + 'oauth-server', 'mcp', 'provisioning', 'breaking-changes', @@ -57,6 +58,7 @@ describe('eligibleModules', () => { 'external-secrets', 'community-packages', 'data-table', + 'oauth-server', 'mcp', 'provisioning', 'breaking-changes', diff --git a/packages/@n8n/backend-common/src/modules/module-registry.ts b/packages/@n8n/backend-common/src/modules/module-registry.ts index ef256619ca4..386eb4ba701 100644 --- a/packages/@n8n/backend-common/src/modules/module-registry.ts +++ b/packages/@n8n/backend-common/src/modules/module-registry.ts @@ -35,6 +35,9 @@ export class ModuleRegistry { 'external-secrets', 'community-packages', 'data-table', + // oauth-server precedes mcp: the mcp module registers its protected + // resource with the oauth-server module's registry on init. + 'oauth-server', 'mcp', 'provisioning', 'breaking-changes', diff --git a/packages/@n8n/backend-common/src/modules/modules.config.ts b/packages/@n8n/backend-common/src/modules/modules.config.ts index a8130f61ac4..d033aea37ae 100644 --- a/packages/@n8n/backend-common/src/modules/modules.config.ts +++ b/packages/@n8n/backend-common/src/modules/modules.config.ts @@ -8,6 +8,7 @@ export const MODULE_NAMES = [ 'external-secrets', 'community-packages', 'data-table', + 'oauth-server', 'mcp', 'provisioning', 'breaking-changes', diff --git a/packages/cli/src/typed-emitter.ts b/packages/@n8n/backend-common/src/typed-emitter.ts similarity index 71% rename from packages/cli/src/typed-emitter.ts rename to packages/@n8n/backend-common/src/typed-emitter.ts index 403c90dfa20..1cc690e7eb4 100644 --- a/packages/cli/src/typed-emitter.ts +++ b/packages/@n8n/backend-common/src/typed-emitter.ts @@ -1,4 +1,3 @@ -import debounce from 'lodash/debounce'; import { EventEmitter } from 'node:events'; type Payloads<ListenerMap> = { @@ -8,7 +7,9 @@ type Payloads<ListenerMap> = { type Listener<Payload> = (payload: Payload) => void; export class TypedEmitter<ListenerMap extends Payloads<ListenerMap>> extends EventEmitter { - private debounceWait = 300; // milliseconds + private readonly debounceWait = 300; // milliseconds + + private debouncedEmitTimer: NodeJS.Timeout | undefined; override on<EventName extends keyof ListenerMap & string>( eventName: EventName, @@ -38,11 +39,11 @@ export class TypedEmitter<ListenerMap extends Payloads<ListenerMap>> extends Eve return super.emit(eventName, payload); } - protected debouncedEmit = debounce( - <EventName extends keyof ListenerMap & string>( - eventName: EventName, - payload?: ListenerMap[EventName], - ) => super.emit(eventName, payload), - this.debounceWait, - ); + protected debouncedEmit<EventName extends keyof ListenerMap & string>( + eventName: EventName, + payload?: ListenerMap[EventName], + ) { + clearTimeout(this.debouncedEmitTimer); + this.debouncedEmitTimer = setTimeout(() => this.emit(eventName, payload), this.debounceWait); + } } diff --git a/packages/@n8n/backend-common/tsconfig.build.json b/packages/@n8n/backend-common/tsconfig.build.json index ee0e3e20fda..e08cb937d03 100644 --- a/packages/@n8n/backend-common/tsconfig.build.json +++ b/packages/@n8n/backend-common/tsconfig.build.json @@ -3,8 +3,7 @@ "compilerOptions": { "composite": true, "rootDir": "src", - "outDir": "dist", - "tsBuildInfoFile": "dist/build.tsbuildinfo" + "outDir": "dist" }, "include": ["src/**/*.ts"], "exclude": ["src/**/__tests__/**"] diff --git a/packages/@n8n/backend-common/tsconfig.json b/packages/@n8n/backend-common/tsconfig.json index 554e0c08007..6d2eeded716 100644 --- a/packages/@n8n/backend-common/tsconfig.json +++ b/packages/@n8n/backend-common/tsconfig.json @@ -2,7 +2,6 @@ "extends": "@n8n/typescript-config/tsconfig.common.json", "compilerOptions": { "types": ["node", "vitest/globals"], - "tsBuildInfoFile": "dist/typecheck.tsbuildinfo", "experimentalDecorators": true, "emitDecoratorMetadata": true }, diff --git a/packages/@n8n/backend-network/README.md b/packages/@n8n/backend-network/README.md new file mode 100644 index 00000000000..217b3df7a26 --- /dev/null +++ b/packages/@n8n/backend-network/README.md @@ -0,0 +1,15 @@ +# @n8n/backend-network + +The single home for n8n's backend outbound-network concerns. + +## Why this package exists + +Today network behavior is scattered across `packages/core` and several `@n8n/*` packages. + +This package consolidates into one place behind a single factory contract: +SSRF/DNS guarding, proxy handling, and the HTTP client plumbing. +The eventual goal is to make backend network behavior reviewable and controllable from a single entry point. + +## Roadmap + +Tracked in [CAT-3365](https://linear.app/n8n/issue/CAT-3365/unify-http-concerns-scope-the-backend-network-layer-into-n8nbackend). \ No newline at end of file diff --git a/packages/@n8n/backend-network/eslint.config.mjs b/packages/@n8n/backend-network/eslint.config.mjs new file mode 100644 index 00000000000..48b5ee443ee --- /dev/null +++ b/packages/@n8n/backend-network/eslint.config.mjs @@ -0,0 +1,32 @@ +import { defineConfig } from 'eslint/config'; +import { baseConfig } from '@n8n/eslint-config/base'; + +// TODO will be cleaned up after the http unification. See CAT-3390 +export default defineConfig( + baseConfig, + { + rules: { + 'unicorn/filename-case': ['error', { case: 'kebabCase' }], + }, + }, + { + files: ['src/http/**/*.ts'], + rules: { + 'no-prototype-builtins': 'warn', + '@typescript-eslint/naming-convention': 'warn', + '@typescript-eslint/prefer-nullish-coalescing': 'warn', + '@typescript-eslint/no-unsafe-member-access': 'warn', + '@typescript-eslint/require-await': 'warn', + }, + }, + { + files: ['**/*.test.ts'], + rules: { + 'n8n-local-rules/no-uncaught-json-parse': 'warn', + '@typescript-eslint/no-unsafe-return': 'warn', + '@typescript-eslint/no-unsafe-assignment': 'warn', + '@typescript-eslint/no-unsafe-argument': 'warn', + '@typescript-eslint/unbound-method': 'warn', + }, + }, +); diff --git a/packages/@n8n/backend-network/package.json b/packages/@n8n/backend-network/package.json new file mode 100644 index 00000000000..0cc74df7cae --- /dev/null +++ b/packages/@n8n/backend-network/package.json @@ -0,0 +1,72 @@ +{ + "name": "@n8n/backend-network", + "version": "1.1.0", + "scripts": { + "clean": "rimraf dist .turbo", + "dev": "pnpm watch", + "typecheck": "tsc --noEmit", + "build": "tsc -p tsconfig.build.json", + "build:unchecked": "tsc -p tsconfig.build.json --noCheck", + "format": "biome format --write .", + "format:check": "biome ci .", + "lint": "eslint . --quiet", + "lint:fix": "eslint . --fix", + "watch": "tsc -p tsconfig.build.json --watch", + "test": "vitest run", + "test:unit": "vitest run", + "test:dev": "vitest --silent=false" + }, + "main": "dist/index.js", + "module": "src/index.ts", + "types": "dist/index.d.ts", + "exports": { + ".": { + "types": "./dist/index.d.ts", + "import": "./src/index.ts", + "require": "./dist/index.js" + }, + "./testing": { + "types": "./dist/testing.d.ts", + "import": "./src/testing.ts", + "require": "./dist/testing.js" + } + }, + "typesVersions": { + "*": { + "testing": [ + "dist/testing.d.ts" + ] + } + }, + "files": [ + "dist/**/*" + ], + "dependencies": { + "@n8n/backend-common": "workspace:*", + "@n8n/config": "workspace:*", + "@n8n/constants": "workspace:*", + "@n8n/di": "workspace:*", + "axios": "catalog:", + "cache-manager": "catalog:", + "form-data": "catalog:", + "http-proxy-agent": "catalog:", + "https-proxy-agent": "catalog:", + "iconv-lite": "catalog:", + "n8n-workflow": "workspace:*", + "proxy-from-env": "catalog:", + "qs": "catalog:", + "reflect-metadata": "catalog:", + "undici": "catalog:undici-v7", + "zod": "catalog:" + }, + "devDependencies": { + "@n8n/typescript-config": "workspace:*", + "@n8n/vitest-config": "workspace:*", + "@types/proxy-from-env": "catalog:", + "@vitest/coverage-v8": "catalog:", + "nock": "catalog:", + "vitest": "catalog:", + "vitest-mock-extended": "catalog:" + }, + "license": "LicenseRef-n8n-sustainable-use" +} diff --git a/packages/cli/src/services/ssrf/__tests__/dns-resolver.test.ts b/packages/@n8n/backend-network/src/dns/__tests__/dns-resolver.test.ts similarity index 98% rename from packages/cli/src/services/ssrf/__tests__/dns-resolver.test.ts rename to packages/@n8n/backend-network/src/dns/__tests__/dns-resolver.test.ts index e1500c3003c..e41189ab30b 100644 --- a/packages/cli/src/services/ssrf/__tests__/dns-resolver.test.ts +++ b/packages/@n8n/backend-network/src/dns/__tests__/dns-resolver.test.ts @@ -1,16 +1,16 @@ -import { mock } from 'jest-mock-extended'; import { promises as dns } from 'node:dns'; +import { mock } from 'vitest-mock-extended'; import { DnsResolver } from '../dns-resolver'; import type { InMemoryDnsCache } from '../in-memory-dns-cache.service'; -jest.mock('node:dns', () => ({ +vi.mock('node:dns', () => ({ promises: { - lookup: jest.fn(), + lookup: vi.fn(), }, })); -const mockedDns = jest.mocked(dns); +const mockedDns = vi.mocked(dns); function asLookupResult(value: unknown): Awaited<ReturnType<typeof dns.lookup>> { return value as Awaited<ReturnType<typeof dns.lookup>>; @@ -18,7 +18,7 @@ function asLookupResult(value: unknown): Awaited<ReturnType<typeof dns.lookup>> describe('DnsResolver', () => { beforeEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); }); it('should return cached IPs when available', async () => { diff --git a/packages/cli/src/services/ssrf/__tests__/in-memory-dns-cache.service.test.ts b/packages/@n8n/backend-network/src/dns/__tests__/in-memory-dns-cache.service.test.ts similarity index 64% rename from packages/cli/src/services/ssrf/__tests__/in-memory-dns-cache.service.test.ts rename to packages/@n8n/backend-network/src/dns/__tests__/in-memory-dns-cache.service.test.ts index 29135f18c1d..a06c620fcc3 100644 --- a/packages/cli/src/services/ssrf/__tests__/in-memory-dns-cache.service.test.ts +++ b/packages/@n8n/backend-network/src/dns/__tests__/in-memory-dns-cache.service.test.ts @@ -5,18 +5,18 @@ import { InMemoryDnsCache } from '../in-memory-dns-cache.service'; describe('InMemoryDnsCache', () => { // lru-cache captures `const perf = performance` at import time and uses perf.now() - // for TTL checks. jest.useFakeTimers replaces globalThis.performance with a new + // for TTL checks. vi.useFakeTimers replaces globalThis.performance with a new // object, but lru-cache still references the original. We mock performance.now // directly so lru-cache sees our controlled time via its captured reference. let perfNow: number; beforeEach(() => { perfNow = 1000; - jest.spyOn(performance, 'now').mockImplementation(() => perfNow); + vi.spyOn(performance, 'now').mockImplementation(() => perfNow); }); afterEach(() => { - jest.restoreAllMocks(); + vi.restoreAllMocks(); }); function advanceTime(ms: number) { @@ -123,4 +123,67 @@ describe('InMemoryDnsCache', () => { expect(await cache.get('other.com')).toBeUndefined(); }); }); + + describe('size', () => { + it('should return 0 before the cache is initialised', () => { + const cache = new InMemoryDnsCache(createConfig()); + + expect(cache.size).toBe(0); + }); + + it('should reflect the number of entries after sets', async () => { + const cache = new InMemoryDnsCache(createConfig()); + + await cache.set('a.example.com', [addr('1.1.1.1')], 300); + await cache.set('b.example.com', [addr('2.2.2.2')], 300); + + expect(cache.size).toBe(2); + }); + }); + + describe('events', () => { + it('should emit hit when get returns a cached entry', async () => { + const cache = new InMemoryDnsCache(createConfig()); + const hitSpy = vi.fn(); + cache.events.on('hit', hitSpy); + + await cache.set('example.com', [addr('1.1.1.1')], 300); + await cache.get('example.com'); + + expect(hitSpy).toHaveBeenCalledTimes(1); + }); + + it('should emit miss when get returns undefined', async () => { + const cache = new InMemoryDnsCache(createConfig()); + const missSpy = vi.fn(); + cache.events.on('miss', missSpy); + + await cache.get('unknown.example.com'); + + expect(missSpy).toHaveBeenCalledTimes(1); + }); + + it('should emit eviction with post-eviction size when an entry is evicted due to LRU capacity pressure', async () => { + // Each entry (~37 bytes) — maxSize=40 fits only one entry + const cache = new InMemoryDnsCache(createConfig({ dnsCacheMaxSize: 40 })); + const evictionSpy = vi.fn(); + cache.events.on('eviction', evictionSpy); + + await cache.set('first.example.com', [addr('1.1.1.1')], 300); + await cache.set('second.example.com', [addr('2.2.2.2')], 300); + + expect(evictionSpy).toHaveBeenCalledTimes(1); + expect(evictionSpy).toHaveBeenCalledWith({ size: 1 }); + }); + + it('should not emit eviction when no entry is evicted', async () => { + const cache = new InMemoryDnsCache(createConfig()); + const evictionSpy = vi.fn(); + cache.events.on('eviction', evictionSpy); + + await cache.set('example.com', [addr('1.1.1.1')], 300); + + expect(evictionSpy).not.toHaveBeenCalled(); + }); + }); }); diff --git a/packages/cli/src/services/ssrf/dns-resolver.ts b/packages/@n8n/backend-network/src/dns/dns-resolver.ts similarity index 100% rename from packages/cli/src/services/ssrf/dns-resolver.ts rename to packages/@n8n/backend-network/src/dns/dns-resolver.ts diff --git a/packages/cli/src/services/ssrf/in-memory-dns-cache.service.ts b/packages/@n8n/backend-network/src/dns/in-memory-dns-cache.service.ts similarity index 67% rename from packages/cli/src/services/ssrf/in-memory-dns-cache.service.ts rename to packages/@n8n/backend-network/src/dns/in-memory-dns-cache.service.ts index 0dc73289f99..e3bc52727af 100644 --- a/packages/cli/src/services/ssrf/in-memory-dns-cache.service.ts +++ b/packages/@n8n/backend-network/src/dns/in-memory-dns-cache.service.ts @@ -1,3 +1,4 @@ +import { TypedEmitter } from '@n8n/backend-common'; import { SsrfProtectionConfig } from '@n8n/config'; import { Time } from '@n8n/constants'; import { Service } from '@n8n/di'; @@ -5,7 +6,13 @@ import type { MemoryCache } from 'cache-manager'; import { caching } from 'cache-manager'; import { jsonStringify } from 'n8n-workflow'; import assert from 'node:assert'; -import { LookupAddress } from 'node:dns'; +import type { LookupAddress } from 'node:dns'; + +export type DnsCacheEventMap = { + hit: undefined; + miss: undefined; + eviction: { size: number }; +}; /** * In-memory DNS cache backed by LRU eviction and per-entry TTL. @@ -14,6 +21,8 @@ import { LookupAddress } from 'node:dns'; export class InMemoryDnsCache { private cache: MemoryCache | undefined; + readonly events = new TypedEmitter<DnsCacheEventMap>(); + constructor(private readonly ssrfConfig: SsrfProtectionConfig) {} private async ensureCache(): Promise<MemoryCache> { @@ -28,15 +37,28 @@ export class InMemoryDnsCache { sizeCalculation, ttl: 0, ttlResolution: 0, + dispose: (_value, _key, reason) => { + if (reason === 'evict') { + // dispose fires before the entry is removed from the size counter, + // so subtract 1 to report the post-eviction size. + this.events.emit('eviction', { size: Math.max(this.size - 1, 0) }); + } + }, }); } return this.cache; } + get size(): number { + return this.cache?.store?.size ?? 0; + } + async get(hostname: string): Promise<LookupAddress[] | undefined> { const cache = await this.ensureCache(); - return await cache.get<LookupAddress[]>(hostname); + const result = await cache.get<LookupAddress[]>(hostname); + this.events.emit(result !== undefined ? 'hit' : 'miss'); + return result; } /** diff --git a/packages/@n8n/backend-network/src/dns/index.ts b/packages/@n8n/backend-network/src/dns/index.ts new file mode 100644 index 00000000000..1367c42cc9c --- /dev/null +++ b/packages/@n8n/backend-network/src/dns/index.ts @@ -0,0 +1,2 @@ +export { DnsResolver } from './dns-resolver'; +export { InMemoryDnsCache } from './in-memory-dns-cache.service'; diff --git a/packages/@n8n/backend-network/src/http/__tests__/binary-buffer.test.ts b/packages/@n8n/backend-network/src/http/__tests__/binary-buffer.test.ts new file mode 100644 index 00000000000..67f34b6db53 --- /dev/null +++ b/packages/@n8n/backend-network/src/http/__tests__/binary-buffer.test.ts @@ -0,0 +1,33 @@ +import { UnexpectedError } from 'n8n-workflow'; +import { Readable } from 'node:stream'; +import { createGunzip } from 'node:zlib'; + +import { binaryToBuffer } from '../binary-buffer'; + +describe('binaryToBuffer', () => { + it('should handle buffer objects', async () => { + const body = Buffer.from('test'); + expect((await binaryToBuffer(body)).toString()).toEqual('test'); + }); + + it('should handle valid uncompressed Readable streams', async () => { + const body = Readable.from(Buffer.from('test')); + expect((await binaryToBuffer(body)).toString()).toEqual('test'); + }); + + it('should handle valid compressed Readable streams', async () => { + const gunzip = createGunzip(); + const body = Readable.from( + Buffer.from('1f8b08000000000000032b492d2e01000c7e7fd804000000', 'hex'), + ).pipe(gunzip); + expect((await binaryToBuffer(body)).toString()).toEqual('test'); + }); + + it('should throw on invalid compressed Readable streams', async () => { + const gunzip = createGunzip(); + const body = Readable.from(Buffer.from('0001f8b080000000000000000', 'hex')).pipe(gunzip); + const promise = binaryToBuffer(body); + await expect(promise).rejects.toThrow(UnexpectedError); + await expect(promise).rejects.toThrow('Failed to decompress response'); + }); +}); diff --git a/packages/@n8n/backend-network/src/http/__tests__/binary-string.test.ts b/packages/@n8n/backend-network/src/http/__tests__/binary-string.test.ts new file mode 100644 index 00000000000..adf29a9f39c --- /dev/null +++ b/packages/@n8n/backend-network/src/http/__tests__/binary-string.test.ts @@ -0,0 +1,115 @@ +import { IncomingMessage } from 'http'; +import { Readable } from 'stream'; + +import { binaryToString } from '../binary-string'; + +const bufferToIncomingMessage = (buffer: Buffer, encoding = 'utf-8') => { + const incomingMessage = Readable.from(buffer) as IncomingMessage; + incomingMessage.headers = { 'content-type': `application/json;charset=${encoding}` }; + Object.setPrototypeOf(incomingMessage, IncomingMessage.prototype); + return incomingMessage; +}; + +describe('binaryToString', () => { + const ENCODING_SAMPLES = { + utf8: { + text: 'Hello, 世界! τεστ мир ⚡️ é à ü ñ', + buffer: Buffer.from([ + 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x2c, 0x20, 0xe4, 0xb8, 0x96, 0xe7, 0x95, 0x8c, 0x21, 0x20, + 0xcf, 0x84, 0xce, 0xb5, 0xcf, 0x83, 0xcf, 0x84, 0x20, 0xd0, 0xbc, 0xd0, 0xb8, 0xd1, 0x80, + 0x20, 0xe2, 0x9a, 0xa1, 0xef, 0xb8, 0x8f, 0x20, 0xc3, 0xa9, 0x20, 0xc3, 0xa0, 0x20, 0xc3, + 0xbc, 0x20, 0xc3, 0xb1, + ]), + }, + + 'iso-8859-15': { + text: 'Café € personnalité', + buffer: Buffer.from([ + 0x43, 0x61, 0x66, 0xe9, 0x20, 0xa4, 0x20, 0x70, 0x65, 0x72, 0x73, 0x6f, 0x6e, 0x6e, 0x61, + 0x6c, 0x69, 0x74, 0xe9, + ]), + }, + + latin1: { + text: 'señor année déjà', + buffer: Buffer.from([ + 0x73, 0x65, 0xf1, 0x6f, 0x72, 0x20, 0x61, 0x6e, 0x6e, 0xe9, 0x65, 0x20, 0x64, 0xe9, 0x6a, + 0xe0, + ]), + }, + + ascii: { + text: 'Hello, World! 123', + buffer: Buffer.from([ + 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x2c, 0x20, 0x57, 0x6f, 0x72, 0x6c, 0x64, 0x21, 0x20, 0x31, + 0x32, 0x33, + ]), + }, + + 'windows-1252': { + text: '€ Smart "quotes" • bullet', + buffer: Buffer.from([ + 0x80, 0x20, 0x53, 0x6d, 0x61, 0x72, 0x74, 0x20, 0x22, 0x71, 0x75, 0x6f, 0x74, 0x65, 0x73, + 0x22, 0x20, 0x95, 0x20, 0x62, 0x75, 0x6c, 0x6c, 0x65, 0x74, + ]), + }, + + 'shift-jis': { + text: 'こんにちは世界', + buffer: Buffer.from([ + 0x82, 0xb1, 0x82, 0xf1, 0x82, 0xc9, 0x82, 0xbf, 0x82, 0xcd, 0x90, 0xa2, 0x8a, 0x45, + ]), + }, + + big5: { + text: '哈囉世界', + buffer: Buffer.from([0xab, 0xa2, 0xc5, 0x6f, 0xa5, 0x40, 0xac, 0xc9]), + }, + + 'koi8-r': { + text: 'Привет мир', + buffer: Buffer.from([0xf0, 0xd2, 0xc9, 0xd7, 0xc5, 0xd4, 0x20, 0xcd, 0xc9, 0xd2]), + }, + }; + + describe('should handle Buffer', () => { + for (const [encoding, { text, buffer }] of Object.entries(ENCODING_SAMPLES)) { + test(`with ${encoding}`, async () => { + const data = await binaryToString(buffer, encoding); + expect(data).toBe(text); + }); + } + }); + + describe('should handle streams', () => { + for (const [encoding, { text, buffer }] of Object.entries(ENCODING_SAMPLES)) { + test(`with ${encoding}`, async () => { + const stream = Readable.from(buffer); + const data = await binaryToString(stream, encoding); + expect(data).toBe(text); + }); + } + }); + + describe('should handle IncomingMessage', () => { + for (const [encoding, { text, buffer }] of Object.entries(ENCODING_SAMPLES)) { + test(`with ${encoding}`, async () => { + const incomingMessage = bufferToIncomingMessage(buffer, encoding); + const data = await binaryToString(incomingMessage); + expect(data).toBe(text); + }); + } + }); + + it('should handle undefined encoding', async () => { + const buffer = Buffer.from('Test'); + const result = await binaryToString(buffer); + expect(result).toBe('Test'); + }); + + it('should handle stream with no explicit encoding', async () => { + const stream = Readable.from(Buffer.from('Test')); + const result = await binaryToString(stream); + expect(result).toBe('Test'); + }); +}); diff --git a/packages/@n8n/backend-network/src/http/__tests__/env-proxy-http-agent.test.ts b/packages/@n8n/backend-network/src/http/__tests__/env-proxy-http-agent.test.ts new file mode 100644 index 00000000000..a6563ba34a4 --- /dev/null +++ b/packages/@n8n/backend-network/src/http/__tests__/env-proxy-http-agent.test.ts @@ -0,0 +1,60 @@ +import http from 'node:http'; +import type { MockInstance } from 'vitest'; + +import { EnvProxyHttpAgent } from '../env-proxy-http-agent'; + +// Routing/caching is covered in env-proxy-router.test.ts; here we only assert +// the agent's wiring: delegate to the resolved proxy agent, else dispatch +// directly via `super.addRequest`. The proxy agent is mocked and `getProxyForUrl` +// drives which branch runs, so nothing hits the network. +const { getProxyForUrl, proxyAddRequest } = vi.hoisted(() => ({ + getProxyForUrl: vi.fn<(url: string) => string>(), + proxyAddRequest: vi.fn(), +})); + +vi.mock('proxy-from-env', () => ({ getProxyForUrl })); +vi.mock('http-proxy-agent', () => ({ + HttpProxyAgent: class { + addRequest = proxyAddRequest; + }, +})); + +const req = {} as http.ClientRequest; +const options = (o: Partial<http.RequestOptions>): http.RequestOptions => o as http.RequestOptions; + +describe('EnvProxyHttpAgent', () => { + let superAddRequest: MockInstance; + + beforeEach(() => { + getProxyForUrl.mockReset(); + proxyAddRequest.mockReset(); + // `super.addRequest` is the only path that would open a real socket. + // `addRequest` is an internal Agent method untyped on the public types. + superAddRequest = vi + .spyOn(http.Agent.prototype, 'addRequest') + .mockImplementation(() => undefined) as unknown as MockInstance; + }); + + afterEach(() => superAddRequest.mockRestore()); + + it('delegates to the http proxy agent when a proxy applies', () => { + getProxyForUrl.mockReturnValue('http://proxy.internal:3128'); + const opts = options({ host: 'a.example', port: 80 }); + + new EnvProxyHttpAgent().addRequest(req, opts); + + expect(getProxyForUrl).toHaveBeenCalledWith('http://a.example'); + expect(proxyAddRequest).toHaveBeenCalledWith(req, opts); + expect(superAddRequest).not.toHaveBeenCalled(); + }); + + it('serves the request directly when no proxy applies', () => { + getProxyForUrl.mockReturnValue(''); + const opts = options({ host: 'direct.example', port: 80 }); + + new EnvProxyHttpAgent().addRequest(req, opts); + + expect(proxyAddRequest).not.toHaveBeenCalled(); + expect(superAddRequest).toHaveBeenCalledWith(req, opts); + }); +}); diff --git a/packages/@n8n/backend-network/src/http/__tests__/env-proxy-https-agent.test.ts b/packages/@n8n/backend-network/src/http/__tests__/env-proxy-https-agent.test.ts new file mode 100644 index 00000000000..6ab3d7bdaf6 --- /dev/null +++ b/packages/@n8n/backend-network/src/http/__tests__/env-proxy-https-agent.test.ts @@ -0,0 +1,62 @@ +import type http from 'node:http'; +import https from 'node:https'; +import type { MockInstance } from 'vitest'; + +import { EnvProxyHttpsAgent } from '../env-proxy-https-agent'; + +// Routing/caching is covered in env-proxy-router.test.ts; here we only assert +// the agent's wiring: delegate to the resolved proxy agent, else dispatch +// directly via `super.addRequest`. The proxy agent is mocked and `getProxyForUrl` +// drives which branch runs, so nothing hits the network. +const { getProxyForUrl, proxyAddRequest } = vi.hoisted(() => ({ + getProxyForUrl: vi.fn<(url: string) => string>(), + proxyAddRequest: vi.fn(), +})); + +vi.mock('proxy-from-env', () => ({ getProxyForUrl })); +vi.mock('https-proxy-agent', () => ({ + HttpsProxyAgent: class { + addRequest = proxyAddRequest; + }, +})); + +const req = {} as http.ClientRequest; +const options = (o: Partial<https.RequestOptions>): https.RequestOptions => + o as https.RequestOptions; + +describe('EnvProxyHttpsAgent', () => { + let superAddRequest: MockInstance; + + beforeEach(() => { + getProxyForUrl.mockReset(); + proxyAddRequest.mockReset(); + // `super.addRequest` is the only path that would open a real socket. + // `addRequest` is an internal Agent method untyped on the public types. + superAddRequest = vi + .spyOn(https.Agent.prototype, 'addRequest') + .mockImplementation(() => undefined) as unknown as MockInstance; + }); + + afterEach(() => superAddRequest.mockRestore()); + + it('delegates to the https proxy agent when a proxy applies', () => { + getProxyForUrl.mockReturnValue('http://proxy.internal:3128'); + const opts = options({ host: 'a.example', port: 443 }); + + new EnvProxyHttpsAgent().addRequest(req, opts); + + expect(getProxyForUrl).toHaveBeenCalledWith('https://a.example'); + expect(proxyAddRequest).toHaveBeenCalledWith(req, opts); + expect(superAddRequest).not.toHaveBeenCalled(); + }); + + it('serves the request directly when no proxy applies', () => { + getProxyForUrl.mockReturnValue(''); + const opts = options({ host: 'direct.example', port: 443 }); + + new EnvProxyHttpsAgent().addRequest(req, opts); + + expect(proxyAddRequest).not.toHaveBeenCalled(); + expect(superAddRequest).toHaveBeenCalledWith(req, opts); + }); +}); diff --git a/packages/@n8n/backend-network/src/http/__tests__/env-proxy-router.test.ts b/packages/@n8n/backend-network/src/http/__tests__/env-proxy-router.test.ts new file mode 100644 index 00000000000..0a023b683d2 --- /dev/null +++ b/packages/@n8n/backend-network/src/http/__tests__/env-proxy-router.test.ts @@ -0,0 +1,113 @@ +import { Logger } from '@n8n/backend-common'; +import { Container } from '@n8n/di'; +import type http from 'node:http'; +import { mock } from 'vitest-mock-extended'; + +import { EnvProxyRouter } from '../env-proxy-router'; + +// `getProxyForUrl` decides per request whether a proxy applies; the proxy agent +// is a plain factory callback, so the routing logic tests without any network +// or agent machinery. +const { getProxyForUrl } = vi.hoisted(() => ({ + getProxyForUrl: vi.fn<(url: string) => string>(), +})); + +vi.mock('proxy-from-env', () => ({ getProxyForUrl })); + +const options = (o: Partial<http.RequestOptions>): http.RequestOptions => o as http.RequestOptions; +const createAgent = () => vi.fn((proxyUrl: string) => ({ proxyUrl })); + +describe('EnvProxyRouter', () => { + beforeEach(() => getProxyForUrl.mockReset()); + + describe('proxy-resolution URL', () => { + it.each([ + { scheme: 'http', defaultPort: 80, opts: { host: 'h', port: 80 }, url: 'http://h' }, + { scheme: 'http', defaultPort: 80, opts: { host: 'h' }, url: 'http://h' }, + { scheme: 'http', defaultPort: 80, opts: { host: 'h', port: 8080 }, url: 'http://h:8080' }, + { scheme: 'http', defaultPort: 80, opts: { host: 'h', port: '8080' }, url: 'http://h:8080' }, + { scheme: 'http', defaultPort: 80, opts: { port: 80 }, url: 'http://localhost' }, + { scheme: 'https', defaultPort: 443, opts: { host: 'h', port: 443 }, url: 'https://h' }, + { scheme: 'https', defaultPort: 443, opts: { host: 'h', port: 8443 }, url: 'https://h:8443' }, + { scheme: 'http', defaultPort: 80, opts: { host: 'h', port: 'abc' }, url: 'http://h' }, + ] as const)('resolves $opts against $url', ({ scheme, defaultPort, opts, url }) => { + getProxyForUrl.mockReturnValue(''); + + new EnvProxyRouter(scheme, defaultPort, createAgent()).resolve(options(opts)); + + expect(getProxyForUrl).toHaveBeenCalledWith(url); + }); + }); + + it('warns and falls back to the default port when the port is unparseable', () => { + const logger = mock<Logger>(); + Container.set(Logger, logger); + getProxyForUrl.mockReturnValue(''); + + new EnvProxyRouter('http', 80, createAgent()).resolve(options({ host: 'h', port: 'abc' })); + + expect(getProxyForUrl).toHaveBeenCalledWith('http://h'); + expect(logger.warn).toHaveBeenCalledWith(expect.stringContaining('abc')); + }); + + it('does not warn when no port is provided', () => { + const logger = mock<Logger>(); + Container.set(Logger, logger); + getProxyForUrl.mockReturnValue(''); + + new EnvProxyRouter('http', 80, createAgent()).resolve(options({ host: 'h' })); + + expect(logger.warn).not.toHaveBeenCalled(); + }); + + it('returns undefined when no proxy applies', () => { + getProxyForUrl.mockReturnValue(''); + + expect( + new EnvProxyRouter('http', 80, createAgent()).resolve(options({ host: 'h' })), + ).toBeUndefined(); + }); + + it('creates one proxy agent per proxy URL and reuses it', () => { + getProxyForUrl.mockReturnValue('http://proxy.internal:3128'); + const createProxyAgent = createAgent(); + const router = new EnvProxyRouter('http', 80, createProxyAgent); + + const first = router.resolve(options({ host: 'a.example' })); + const second = router.resolve(options({ host: 'b.example' })); + + expect(createProxyAgent).toHaveBeenCalledTimes(1); + expect(first).toBe(second); + }); + + it('warns once and stops caching when the cache cap is exceeded', () => { + const logger = mock<Logger>(); + Container.set(Logger, logger); + // A distinct proxy URL per request, so every call is a fresh cache entry. + getProxyForUrl.mockImplementation((url: string) => `http://proxy-${url}:3128`); + const createProxyAgent = createAgent(); + const router = new EnvProxyRouter('http', 80, createProxyAgent); + + // 64 entries fill the cache; the 65th and 66th exceed the cap. + for (let i = 0; i < 66; i++) { + router.resolve(options({ host: `h${i}.example` })); + } + + expect(logger.warn).toHaveBeenCalledTimes(1); + expect(logger.warn).toHaveBeenCalledWith(expect.stringContaining('reached its limit')); + }); + + it('creates a separate proxy agent per distinct proxy URL', () => { + getProxyForUrl + .mockReturnValueOnce('http://proxy-a:3128') + .mockReturnValueOnce('http://proxy-b:3128'); + const createProxyAgent = createAgent(); + const router = new EnvProxyRouter('http', 80, createProxyAgent); + + const a = router.resolve(options({ host: 'a.example' })); + const b = router.resolve(options({ host: 'b.example' })); + + expect(createProxyAgent).toHaveBeenCalledTimes(2); + expect(a).not.toBe(b); + }); +}); diff --git a/packages/core/src/__tests__/http-proxy.test.ts b/packages/@n8n/backend-network/src/http/__tests__/http-proxy.test.ts similarity index 78% rename from packages/core/src/__tests__/http-proxy.test.ts rename to packages/@n8n/backend-network/src/http/__tests__/http-proxy.test.ts index 02184498939..3c1b72d3570 100644 --- a/packages/core/src/__tests__/http-proxy.test.ts +++ b/packages/@n8n/backend-network/src/http/__tests__/http-proxy.test.ts @@ -4,7 +4,9 @@ import type { AddressInfo } from 'net'; import nock from 'nock'; import { promisify } from 'util'; -import { installGlobalProxyAgent, uninstallGlobalProxyAgent } from '../http-proxy'; +import { EnvProxyHttpAgent } from '../env-proxy-http-agent'; +import { EnvProxyHttpsAgent } from '../env-proxy-https-agent'; +import { installGlobalProxyAgent, resolveProxyUrl, uninstallGlobalProxyAgent } from '../http-proxy'; interface TestResponse { message: string; @@ -233,6 +235,60 @@ describe('HTTP Proxy Tests', () => { } }); + describe('resolveProxyUrl', () => { + test('returns the configured proxy for a matching target', () => { + process.env.HTTP_PROXY = proxyServer.url; + + expect(resolveProxyUrl('http://api.example.com:8080/test')).toBe(proxyServer.url); + }); + + test('returns undefined when no proxy is configured', () => { + expect(resolveProxyUrl('http://api.example.com:8080/test')).toBeUndefined(); + }); + + test('returns undefined when the target is excluded by NO_PROXY', () => { + process.env.HTTP_PROXY = proxyServer.url; + process.env.NO_PROXY = 'api.example.com'; + + expect(resolveProxyUrl('http://api.example.com:8080/test')).toBeUndefined(); + }); + + test('resolves ALL_PROXY when no scheme-specific proxy is set', () => { + process.env.ALL_PROXY = proxyServer.url; + + expect(resolveProxyUrl('http://api.example.com:8080/test')).toBe(proxyServer.url); + }); + }); + + describe('global agent lifecycle', () => { + test('installs env-proxy agents when a proxy env var is set', () => { + process.env.HTTP_PROXY = proxyServer.url; + + installGlobalProxyAgent(); + + expect(http.globalAgent).toBeInstanceOf(EnvProxyHttpAgent); + expect(https.globalAgent).toBeInstanceOf(EnvProxyHttpsAgent); + }); + + test('is a no-op when no proxy env var is set', () => { + installGlobalProxyAgent(); + + expect(http.globalAgent).not.toBeInstanceOf(EnvProxyHttpAgent); + expect(https.globalAgent).not.toBeInstanceOf(EnvProxyHttpsAgent); + }); + + test('uninstall restores plain agents', () => { + process.env.HTTP_PROXY = proxyServer.url; + installGlobalProxyAgent(); + + uninstallGlobalProxyAgent(); + + expect(http.globalAgent).toBeInstanceOf(http.Agent); + expect(http.globalAgent).not.toBeInstanceOf(EnvProxyHttpAgent); + expect(https.globalAgent).not.toBeInstanceOf(EnvProxyHttpsAgent); + }); + }); + function setupDirectRequestMock(targetUrl: string) { if (!nock.isActive()) nock.activate(); const url = new URL(targetUrl); diff --git a/packages/@n8n/backend-network/src/http/__tests__/legacy-request.test.ts b/packages/@n8n/backend-network/src/http/__tests__/legacy-request.test.ts new file mode 100644 index 00000000000..0a5adda20fc --- /dev/null +++ b/packages/@n8n/backend-network/src/http/__tests__/legacy-request.test.ts @@ -0,0 +1,298 @@ +import type { Logger } from '@n8n/backend-common'; +import nock from 'nock'; +import { mock } from 'vitest-mock-extended'; + +import type { SsrfBridge, SsrfProtectionService } from '../../ssrf'; +import { OutboundHttp } from '../outbound-http'; + +function makeFacade(): OutboundHttp { + return new OutboundHttp(mock<SsrfProtectionService>(), mock<Logger>()); +} + +describe('OutboundHttp.requests requestLegacy', () => { + beforeEach(() => { + nock.cleanAll(); + }); + + describe('request handling', () => { + const baseUrl = 'https://example.test'; + + it('returns the body and fires onFetched on success', async () => { + nock(baseUrl).get('/ok').reply(200, 'hello'); + const onFetched = vi.fn(); + const client = makeFacade().requests({ ssrf: 'disabled' }); + + const body = await client.requestLegacy({ url: `${baseUrl}/ok` }, { onFetched }); + + expect(body).toBe('hello'); + expect(onFetched).toHaveBeenCalledTimes(1); + }); + + it('returns the full response when resolveWithFullResponse is set', async () => { + nock(baseUrl).get('/ok').reply(200, 'hello'); + const client = makeFacade().requests({ ssrf: 'disabled' }); + + const response = await client.requestLegacy({ + url: `${baseUrl}/ok`, + resolveWithFullResponse: true, + }); + + expect(response).toMatchObject({ body: 'hello', statusCode: 200 }); + }); + + it('rethrows an enriched error carrying the status, without firing onFetched', async () => { + nock(baseUrl).get('/bad').reply(403, 'Forbidden', { 'content-type': 'text/plain' }); + const onFetched = vi.fn(); + const client = makeFacade().requests({ ssrf: 'disabled' }); + + await expect( + client.requestLegacy({ url: `${baseUrl}/bad` }, { onFetched }), + ).rejects.toMatchObject({ + statusCode: 403, + status: 403, + message: '403 - "Forbidden"', + config: undefined, + request: undefined, + options: { method: 'get', url: `${baseUrl}/bad` }, + response: { status: 403 }, + }); + expect(onFetched).not.toHaveBeenCalled(); + }); + + it('returns the error body and fires onFetched when simple is false', async () => { + nock(baseUrl).get('/missing').reply(404, 'Not Found'); + const onFetched = vi.fn(); + const client = makeFacade().requests({ ssrf: 'disabled' }); + + const body = await client.requestLegacy( + { url: `${baseUrl}/missing`, simple: false }, + { onFetched }, + ); + + expect(body).toBe('Not Found'); + expect(onFetched).toHaveBeenCalledTimes(1); + }); + + it('returns the full error response when simple is false and resolveWithFullResponse is set', async () => { + nock(baseUrl).get('/missing').reply(404, 'Not Found'); + const client = makeFacade().requests({ ssrf: 'disabled' }); + + const response = await client.requestLegacy({ + url: `${baseUrl}/missing`, + simple: false, + resolveWithFullResponse: true, + }); + + expect(response).toMatchObject({ + body: 'Not Found', + statusCode: 404, + statusMessage: 'Not Found', + }); + }); + }); + + describe('redirects', () => { + const baseUrl = 'https://example.test'; + const otherOrigin = 'https://otherdomain.test'; + const basicAuth = 'Basic dGVzdHVzZXI6dGVzdHBhc3N3b3Jk'; + + const reflectHeaders = function (this: { req: { headers: unknown } }) { + return this.req.headers; + }; + + it.each([[undefined], [true]])( + 'forwards the authorization header on cross-origin redirects when sendCredentialsOnCrossOriginRedirect is %s', + async (sendCredentialsOnCrossOriginRedirect) => { + nock(baseUrl) + .get('/redirect') + .reply(301, '', { Location: `${otherOrigin}/test` }); + nock(otherOrigin).get('/test').reply(200, reflectHeaders); + const client = makeFacade().requests({ ssrf: 'disabled' }); + + const response = (await client.requestLegacy({ + url: `${baseUrl}/redirect`, + auth: { username: 'testuser', password: 'testpassword' }, + headers: { 'X-Other-Header': 'otherHeaderContent' }, + resolveWithFullResponse: true, + sendCredentialsOnCrossOriginRedirect, + })) as { statusCode: number; body: string }; + + expect(response.statusCode).toBe(200); + const forwardedHeaders = JSON.parse(response.body); + expect(forwardedHeaders.authorization).toBe(basicAuth); + expect(forwardedHeaders['x-other-header']).toBe('otherHeaderContent'); + }, + ); + + it('does not forward the authorization header on cross-origin redirects when sendCredentialsOnCrossOriginRedirect is false', async () => { + nock(baseUrl) + .get('/redirect') + .reply(301, '', { Location: `${otherOrigin}/test` }); + nock(otherOrigin).get('/test').reply(200, reflectHeaders); + const client = makeFacade().requests({ ssrf: 'disabled' }); + + const response = (await client.requestLegacy({ + url: `${baseUrl}/redirect`, + auth: { username: 'testuser', password: 'testpassword' }, + headers: { 'X-Other-Header': 'otherHeaderContent' }, + resolveWithFullResponse: true, + sendCredentialsOnCrossOriginRedirect: false, + })) as { statusCode: number; body: string }; + + expect(response.statusCode).toBe(200); + const forwardedHeaders = JSON.parse(response.body); + expect(forwardedHeaders.authorization).toBeUndefined(); + expect(forwardedHeaders['x-other-header']).toBe('otherHeaderContent'); + }); + + it.each([[undefined], [true], [false]])( + 'forwards the authorization header on same-origin redirects when sendCredentialsOnCrossOriginRedirect is %s', + async (sendCredentialsOnCrossOriginRedirect) => { + nock(baseUrl) + .get('/redirect') + .reply(301, '', { Location: `${baseUrl}/test` }); + nock(baseUrl).get('/test').reply(200, reflectHeaders); + const client = makeFacade().requests({ ssrf: 'disabled' }); + + const response = (await client.requestLegacy({ + url: `${baseUrl}/redirect`, + auth: { username: 'testuser', password: 'testpassword' }, + headers: { 'X-Other-Header': 'otherHeaderContent' }, + resolveWithFullResponse: true, + sendCredentialsOnCrossOriginRedirect, + })) as { statusCode: number; body: string }; + + expect(response.statusCode).toBe(200); + const forwardedHeaders = JSON.parse(response.body); + expect(forwardedHeaders.authorization).toBe(basicAuth); + expect(forwardedHeaders['x-other-header']).toBe('otherHeaderContent'); + }, + ); + + it('follows redirects by default', async () => { + nock(baseUrl) + .get('/redirect') + .reply(301, '', { Location: `${baseUrl}/test` }); + nock(baseUrl).get('/test').reply(200, 'Redirected'); + const client = makeFacade().requests({ ssrf: 'disabled' }); + + const response = await client.requestLegacy({ + url: `${baseUrl}/redirect`, + resolveWithFullResponse: true, + }); + + expect(response).toMatchObject({ body: 'Redirected', statusCode: 200 }); + }); + + it('does not follow redirects when followRedirect is false', async () => { + nock(baseUrl) + .get('/redirect') + .reply(301, '', { Location: `${baseUrl}/test` }); + nock(baseUrl).get('/test').reply(200, 'Redirected'); + const client = makeFacade().requests({ ssrf: 'disabled' }); + + await expect( + client.requestLegacy({ + url: `${baseUrl}/redirect`, + resolveWithFullResponse: true, + followRedirect: false, + }), + ).rejects.toMatchObject({ statusCode: 301 }); + }); + }); + + describe('SSRF policy', () => { + const baseUrl = 'https://example.test'; + + it('validates the URL through the provided bridge', async () => { + nock(baseUrl).get('/ok').reply(200, 'ok'); + const validateUrl = vi.fn().mockResolvedValue({ ok: true, result: undefined }); + const bridge = { + validateUrl, + validateIp: vi.fn().mockReturnValue({ ok: true, result: undefined }), + validateRedirectSync: vi.fn(), + createSecureLookup: vi.fn().mockReturnValue(vi.fn()), + } as unknown as SsrfBridge; + const client = makeFacade().requests({ ssrf: bridge }); + + await client.requestLegacy({ baseURL: baseUrl, url: '/ok' }); + + expect(validateUrl).toHaveBeenCalledWith(new URL(`${baseUrl}/ok`)); + }); + }); + + describe('domain allowlist', () => { + const baseUrl = 'https://example.com'; + + it('blocks requests to disallowed domains', async () => { + const client = makeFacade().requests({ ssrf: 'disabled' }); + + await expect( + client.requestLegacy({ url: `${baseUrl}/data`, allowedDomains: 'other.com' }), + ).rejects.toThrow('Domain not allowed'); + }); + + it.each([['example.com'], [undefined]])( + 'allows requests to allowed domains when allowedDomains is %s', + async (allowedDomains) => { + nock(baseUrl).get('/data').reply(200, 'ok'); + const client = makeFacade().requests({ ssrf: 'disabled' }); + + const body = await client.requestLegacy({ url: `${baseUrl}/data`, allowedDomains }); + + expect(body).toBe('ok'); + }, + ); + + it('blocks redirects to disallowed domains', async () => { + nock(baseUrl).get('/redirect').reply(301, '', { Location: 'https://not-allowed.com/data' }); + nock('https://not-allowed.com').get('/data').reply(200, 'not-ok'); + const client = makeFacade().requests({ ssrf: 'disabled' }); + + await expect( + client.requestLegacy({ + url: `${baseUrl}/redirect`, + allowedDomains: 'example.com', + followAllRedirects: true, + }), + ).rejects.toThrow('Domain not allowed'); + }); + + it.each([['example.com, allowed.com'], [undefined]])( + 'allows redirects to allowed domains when allowedDomains is %s', + async (allowedDomains) => { + nock(baseUrl).get('/redirect').reply(301, '', { Location: 'https://allowed.com/data' }); + nock('https://allowed.com').get('/data').reply(200, 'ok'); + const client = makeFacade().requests({ ssrf: 'disabled' }); + + const body = await client.requestLegacy({ + url: `${baseUrl}/redirect`, + allowedDomains, + followAllRedirects: true, + }); + + expect(body).toBe('ok'); + }, + ); + + it('supports wildcard domains in allowedDomains', async () => { + nock('https://api.example.com').get('/data').reply(200, 'ok'); + const client = makeFacade().requests({ ssrf: 'disabled' }); + + const body = await client.requestLegacy({ + url: 'https://api.example.com/data', + allowedDomains: '*.example.com', + }); + + expect(body).toBe('ok'); + }); + + it('blocks wildcard domains that do not match', async () => { + const client = makeFacade().requests({ ssrf: 'disabled' }); + + await expect( + client.requestLegacy({ url: 'https://blocked.com/data', allowedDomains: '*.example.com' }), + ).rejects.toThrow('Domain not allowed'); + }); + }); +}); 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 new file mode 100644 index 00000000000..14c003dae78 --- /dev/null +++ b/packages/@n8n/backend-network/src/http/__tests__/node-agents.test.ts @@ -0,0 +1,201 @@ +import { HttpProxyAgent } from 'http-proxy-agent'; +import { HttpsProxyAgent } from 'https-proxy-agent'; +import http from 'node:http'; +import https from 'node:https'; + +import type { SsrfBridge } from '../../ssrf'; +import { makeLookupFn, makeSsrfBridge } from '../../ssrf/__tests__/mock-ssrf-bridge'; +import { EnvProxyHttpAgent } from '../env-proxy-http-agent'; +import { EnvProxyHttpsAgent } from '../env-proxy-https-agent'; +import { buildNodeAgents, installConnectionGuard } from '../node-agents'; + +// HttpsProxyAgent stores `lookup` in `connectOpts` rather than `options` +// (unlike http.Agent and HttpProxyAgent which use `options`). +function getAgentLookup(agent: http.Agent | https.Agent): unknown { + const a = agent as { + options?: { lookup?: unknown }; + connectOpts?: { lookup?: unknown }; + }; + return a.options?.lookup ?? a.connectOpts?.lookup; +} + +// `http.Agent['options']` is not exposed on the public Node types. +function getAgentOptions(agent: http.Agent | https.Agent): { keepAlive?: boolean } { + return (agent as unknown as { options?: { keepAlive?: boolean } }).options ?? {}; +} + +// --------------------------------------------------------------------------- +// buildNodeAgents — shared builder (single source of truth for the undici +// factory, the axios transport layer, and the global proxy agents) +// --------------------------------------------------------------------------- + +describe('buildNodeAgents', () => { + describe('agent classes per proxy mode', () => { + it('proxy: false → plain http/https.Agent (no proxy class)', () => { + const { httpAgent, httpsAgent } = buildNodeAgents(false, 'disabled'); + + expect(httpAgent).toBeInstanceOf(http.Agent); + expect(httpsAgent).toBeInstanceOf(https.Agent); + expect(httpAgent).not.toBeInstanceOf(HttpProxyAgent); + expect(httpsAgent).not.toBeInstanceOf(HttpsProxyAgent); + }); + + it('proxy: env → EnvProxy agents', () => { + const { httpAgent, httpsAgent } = buildNodeAgents('env', 'disabled'); + + expect(httpAgent).toBeInstanceOf(EnvProxyHttpAgent); + expect(httpsAgent).toBeInstanceOf(EnvProxyHttpsAgent); + }); + + it('proxy: explicit URL → HttpProxyAgent / HttpsProxyAgent', () => { + const { httpAgent, httpsAgent } = buildNodeAgents('http://proxy.internal:3128', 'disabled'); + + expect(httpAgent).toBeInstanceOf(HttpProxyAgent); + expect(httpsAgent).toBeInstanceOf(HttpsProxyAgent); + }); + }); + + describe('agent options forwarding', () => { + it('forwards options to plain agents (proxy: false)', () => { + const { httpAgent, httpsAgent } = buildNodeAgents(false, 'disabled', { keepAlive: true }); + + expect(getAgentOptions(httpAgent).keepAlive).toBe(true); + expect(getAgentOptions(httpsAgent).keepAlive).toBe(true); + }); + + it('forwards options to the env agent (which serves NO_PROXY targets directly)', () => { + const { httpAgent } = buildNodeAgents('env', 'disabled', { keepAlive: true }); + + expect(getAgentOptions(httpAgent).keepAlive).toBe(true); + }); + }); + + describe('rejects a caller-provided lookup (managed by the SSRF policy)', () => { + const lookup = makeLookupFn(); + + it.each([ + ['ssrf disabled', 'disabled' as const], + ['ssrf active', makeSsrfBridge()], + ])('throws when agentOptions.lookup is set (%s)', (_label, ssrf) => { + expect(() => buildNodeAgents(false, ssrf, { lookup })).toThrow( + '`agentOptions.lookup` is not supported', + ); + }); + + it('allows other agentOptions without a lookup', () => { + expect(() => buildNodeAgents(false, 'disabled', { keepAlive: true })).not.toThrow(); + }); + }); + + describe('SSRF lookup placement (direct connections only)', () => { + it('proxy: false → injects the secure lookup on both agents', () => { + const lookupFn = makeLookupFn(); + const bridge = makeSsrfBridge({ createSecureLookup: vi.fn().mockReturnValue(lookupFn) }); + + const { httpAgent, httpsAgent } = buildNodeAgents(false, bridge); + + expect(getAgentLookup(httpAgent)).toBe(lookupFn); + expect(getAgentLookup(httpsAgent)).toBe(lookupFn); + }); + + it('proxy: env → injects the secure lookup for the direct path', () => { + const lookupFn = makeLookupFn(); + const bridge = makeSsrfBridge({ createSecureLookup: vi.fn().mockReturnValue(lookupFn) }); + + const { httpAgent, httpsAgent } = buildNodeAgents('env', bridge); + + expect(getAgentLookup(httpAgent)).toBe(lookupFn); + expect(getAgentLookup(httpsAgent)).toBe(lookupFn); + }); + + it('proxy: explicit URL → does NOT inject the lookup (proxy validates the target)', () => { + const lookupFn = makeLookupFn(); + const bridge = makeSsrfBridge({ createSecureLookup: vi.fn().mockReturnValue(lookupFn) }); + + const { httpAgent, httpsAgent } = buildNodeAgents('http://proxy.internal:3128', bridge); + + expect(getAgentLookup(httpAgent)).toBeUndefined(); + expect(getAgentLookup(httpsAgent)).toBeUndefined(); + }); + + it('ssrf disabled → no lookup on the direct path', () => { + const { httpAgent, httpsAgent } = buildNodeAgents('env', 'disabled'); + + expect(getAgentLookup(httpAgent)).toBeUndefined(); + expect(getAgentLookup(httpsAgent)).toBeUndefined(); + }); + }); + + describe('direct-IP validation (installConnectionGuard)', () => { + type ConnFn = ( + options: { host?: string | null; hostname?: string | null; port?: number }, + onConnect?: (error: Error | null, stream?: unknown) => void, + ) => unknown; + + const connectionOf = (agent: http.Agent): ConnFn => + (agent as unknown as { createConnection: ConnFn }).createConnection; + + function guarded(bridge: SsrfBridge) { + const original = vi.fn().mockReturnValue('SOCKET'); + const agent = { createConnection: original } as unknown as http.Agent; + installConnectionGuard(agent, bridge); + return { createConnection: connectionOf(agent), original }; + } + + it('blocks a connection the bridge rejects without opening a socket', () => { + const error = new Error('blocked'); + const bridge = makeSsrfBridge({ + validateConnectionHost: vi.fn().mockReturnValue({ ok: false, error }), + }); + const { createConnection, original } = guarded(bridge); + const onCreate = vi.fn(); + + const result = createConnection({ host: '169.254.169.254', port: 80 }, onCreate); + + expect(bridge.validateConnectionHost).toHaveBeenCalledWith('169.254.169.254'); + expect(onCreate).toHaveBeenCalledWith(error); + expect(original).not.toHaveBeenCalled(); + expect(result).toBeUndefined(); + }); + + it('delegates to the underlying connection when the bridge allows the host', () => { + const bridge = makeSsrfBridge(); + const { createConnection, original } = guarded(bridge); + + const socket = createConnection({ host: '93.184.216.34', port: 80 }, vi.fn()); + + expect(bridge.validateConnectionHost).toHaveBeenCalledWith('93.184.216.34'); + expect(original).toHaveBeenCalledTimes(1); + expect(socket).toBe('SOCKET'); + }); + + it('passes the raw host through to the bridge (normalization is the service’s job)', () => { + const bridge = makeSsrfBridge(); + const { createConnection } = guarded(bridge); + + createConnection({ host: '[::1]', port: 80 }, vi.fn()); + + expect(bridge.validateConnectionHost).toHaveBeenCalledWith('[::1]'); + }); + + it.each(['false', 'env'] as const)( + 'buildNodeAgents (proxy: %s) blocks rejected direct connections on both agents', + (mode) => { + const error = new Error('blocked'); + const bridge = makeSsrfBridge({ + validateConnectionHost: vi.fn().mockReturnValue({ ok: false, error }), + }); + const proxy = mode === 'false' ? false : 'env'; + const { httpAgent, httpsAgent } = buildNodeAgents(proxy, bridge); + + const onHttp = vi.fn(); + const onHttps = vi.fn(); + connectionOf(httpAgent)({ host: '10.0.0.1', port: 80 }, onHttp); + connectionOf(httpsAgent)({ host: '10.0.0.1', port: 443 }, onHttps); + + expect(onHttp).toHaveBeenCalledWith(error); + expect(onHttps).toHaveBeenCalledWith(error); + }, + ); + }); +}); diff --git a/packages/@n8n/backend-network/src/http/__tests__/outbound-http.dispatcher.test.ts b/packages/@n8n/backend-network/src/http/__tests__/outbound-http.dispatcher.test.ts new file mode 100644 index 00000000000..50f757b4fe2 --- /dev/null +++ b/packages/@n8n/backend-network/src/http/__tests__/outbound-http.dispatcher.test.ts @@ -0,0 +1,54 @@ +import type { Logger } from '@n8n/backend-common'; +import { Agent, EnvHttpProxyAgent, ProxyAgent } from 'undici'; +import { mock } from 'vitest-mock-extended'; + +import type { SsrfProtectionService } from '../../ssrf'; +import { OutboundHttp } from '../outbound-http'; + +// `getDispatcher()` proxy routing. SSRF is disabled in the proxy-class +// assertions so we inspect the concrete underlying dispatcher: with SSRF +// enabled `getDispatcher()` returns an undici `ComposedDispatcher` wrapper and +// the `instanceof` checks would not see the proxy class. + +function makeTransport(options?: Parameters<OutboundHttp['transport']>[0]) { + return new OutboundHttp(mock<SsrfProtectionService>(), mock<Logger>()).transport(options); +} + +describe('transport getDispatcher proxy routing', () => { + it('defaults to env-based proxy (EnvHttpProxyAgent dispatcher)', () => { + const dispatcher = makeTransport({ ssrf: 'disabled' }).getDispatcher(); + + expect(dispatcher).toBeInstanceOf(EnvHttpProxyAgent); + }); + + it('proxy: false → plain undici Agent', () => { + const dispatcher = makeTransport({ proxy: false, ssrf: 'disabled' }).getDispatcher(); + + expect(dispatcher).toBeInstanceOf(Agent); + expect(dispatcher).not.toBeInstanceOf(EnvHttpProxyAgent); + expect(dispatcher).not.toBeInstanceOf(ProxyAgent); + }); + + it('proxy: env → EnvHttpProxyAgent', () => { + const dispatcher = makeTransport({ proxy: 'env', ssrf: 'disabled' }).getDispatcher(); + + expect(dispatcher).toBeInstanceOf(EnvHttpProxyAgent); + }); + + it('proxy: explicit URL → ProxyAgent', () => { + const dispatcher = makeTransport({ + proxy: 'http://proxy.internal:3128', + ssrf: 'disabled', + }).getDispatcher(); + + expect(dispatcher).toBeInstanceOf(ProxyAgent); + expect(dispatcher).not.toBeInstanceOf(Agent); + expect(dispatcher).not.toBeInstanceOf(EnvHttpProxyAgent); + }); + + it('returns the same dispatcher instance on repeated calls', () => { + const transport = makeTransport(); + + expect(transport.getDispatcher()).toBe(transport.getDispatcher()); + }); +}); diff --git a/packages/@n8n/backend-network/src/http/__tests__/outbound-http.node-agent.test.ts b/packages/@n8n/backend-network/src/http/__tests__/outbound-http.node-agent.test.ts new file mode 100644 index 00000000000..fc735f214b6 --- /dev/null +++ b/packages/@n8n/backend-network/src/http/__tests__/outbound-http.node-agent.test.ts @@ -0,0 +1,140 @@ +import type { Logger } from '@n8n/backend-common'; +import { HttpProxyAgent } from 'http-proxy-agent'; +import { HttpsProxyAgent } from 'https-proxy-agent'; +import http from 'node:http'; +import https from 'node:https'; +import { mock } from 'vitest-mock-extended'; + +import type { SsrfProtectionService } from '../../ssrf'; +import { makeLookupFn, makeSsrfBridge } from '../../ssrf/__tests__/mock-ssrf-bridge'; +import { OutboundHttp } from '../outbound-http'; + +function makeFacade(): OutboundHttp { + const service = mock<SsrfProtectionService>(); + vi.mocked(service.createSecureLookup).mockReturnValue(makeLookupFn()); + return new OutboundHttp(service, mock<Logger>()); +} + +// HttpsProxyAgent stores `lookup` in `connectOpts` rather than `options` +// (unlike http.Agent and HttpProxyAgent which use `options`). +function getAgentLookup(agent: http.Agent | https.Agent): unknown { + const a = agent as { + options?: { lookup?: unknown }; + connectOpts?: { lookup?: unknown }; + }; + return a.options?.lookup ?? a.connectOpts?.lookup; +} + +// --------------------------------------------------------------------------- +// getNodeAgent — proxy routing +// --------------------------------------------------------------------------- + +describe('getNodeAgent', () => { + it('proxy: false → plain http/https.Agent (no proxy class)', () => { + const { httpAgent, httpsAgent } = makeFacade().transport({ proxy: false }).getNodeAgent(); + + expect(httpAgent).toBeInstanceOf(http.Agent); + expect(httpsAgent).toBeInstanceOf(https.Agent); + expect(httpAgent).not.toBeInstanceOf(HttpProxyAgent); + expect(httpsAgent).not.toBeInstanceOf(HttpsProxyAgent); + }); + + it('proxy: explicit URL → HttpProxyAgent / HttpsProxyAgent', () => { + const { httpAgent, httpsAgent } = makeFacade() + .transport({ proxy: 'http://proxy.internal:3128' }) + .getNodeAgent(); + + expect(httpAgent).toBeInstanceOf(HttpProxyAgent); + expect(httpsAgent).toBeInstanceOf(HttpsProxyAgent); + }); + + it('proxy: env → custom env-routing agents (http/https.Agent subclasses)', () => { + const { httpAgent, httpsAgent } = makeFacade().transport({ proxy: 'env' }).getNodeAgent(); + + expect(httpAgent).toBeInstanceOf(http.Agent); + expect(httpsAgent).toBeInstanceOf(https.Agent); + }); + + it('returns the same agent instances on repeated calls', () => { + const client = makeFacade().transport(); + const a1 = client.getNodeAgent(); + const a2 = client.getNodeAgent(); + + expect(a1.httpAgent).toBe(a2.httpAgent); + expect(a1.httpsAgent).toBe(a2.httpsAgent); + }); + + it('builds fresh agents that forward per-call agent options', () => { + const client = makeFacade().transport({ proxy: false }); + const cached = client.getNodeAgent(); + const custom = client.getNodeAgent({ rejectUnauthorized: false }); + + expect(custom.httpsAgent).not.toBe(cached.httpsAgent); + expect(custom.httpsAgent.options.rejectUnauthorized).toBe(false); + }); +}); + +// --------------------------------------------------------------------------- +// getNodeAgent — SSRF lookup injection +// --------------------------------------------------------------------------- + +describe('getNodeAgent SSRF lookup injection', () => { + describe('proxy: false', () => { + it('injects createSecureLookup when SSRF is enabled', () => { + const lookupFn = makeLookupFn(); + const bridge = makeSsrfBridge({ + createSecureLookup: vi.fn().mockReturnValue(lookupFn), + }); + const { httpAgent, httpsAgent } = makeFacade() + .transport({ ssrf: bridge, proxy: false }) + .getNodeAgent(); + + expect(bridge.createSecureLookup).toHaveBeenCalledTimes(1); + expect(getAgentLookup(httpAgent)).toBe(lookupFn); + expect(getAgentLookup(httpsAgent)).toBe(lookupFn); + }); + + it('does NOT inject lookup when SSRF is disabled', () => { + const { httpAgent, httpsAgent } = makeFacade() + .transport({ ssrf: 'disabled', proxy: false }) + .getNodeAgent(); + + expect(getAgentLookup(httpAgent)).toBeUndefined(); + expect(getAgentLookup(httpsAgent)).toBeUndefined(); + }); + }); + + describe('proxy: explicit URL', () => { + it('does NOT inject lookup behind an explicit proxy (proxy validates the target)', () => { + const lookupFn = makeLookupFn(); + const bridge = makeSsrfBridge({ + createSecureLookup: vi.fn().mockReturnValue(lookupFn), + }); + const { httpAgent, httpsAgent } = makeFacade() + .transport({ ssrf: bridge, proxy: 'http://proxy.internal:3128' }) + .getNodeAgent(); + + // SSRF lookup is applied to direct connections only. Behind a proxy it + // would resolve the proxy host, not the final target, so it is omitted. + expect(getAgentLookup(httpAgent)).toBeUndefined(); + expect(getAgentLookup(httpsAgent)).toBeUndefined(); + }); + }); + + describe('proxy: env', () => { + it('injects createSecureLookup when SSRF is enabled', () => { + const lookupFn = makeLookupFn(); + const bridge = makeSsrfBridge({ + createSecureLookup: vi.fn().mockReturnValue(lookupFn), + }); + const { httpAgent, httpsAgent } = makeFacade() + .transport({ ssrf: bridge, proxy: 'env' }) + .getNodeAgent(); + + expect(bridge.createSecureLookup).toHaveBeenCalledTimes(1); + // EnvProxy* agents inherit from http/https.Agent and pass lookup to super() + expect(getAgentLookup(httpAgent)).toBe(lookupFn); + expect(getAgentLookup(httpsAgent)).toBe(lookupFn); + }); + }); +}); diff --git a/packages/@n8n/backend-network/src/http/__tests__/outbound-http.requests.test.ts b/packages/@n8n/backend-network/src/http/__tests__/outbound-http.requests.test.ts new file mode 100644 index 00000000000..8f772ae4e68 --- /dev/null +++ b/packages/@n8n/backend-network/src/http/__tests__/outbound-http.requests.test.ts @@ -0,0 +1,67 @@ +import type { Logger } from '@n8n/backend-common'; +import type { IHttpRequestOptions } from 'n8n-workflow'; +import { mock } from 'vitest-mock-extended'; + +import type { SsrfBridge, SsrfProtectionService } from '../../ssrf'; +import { httpRequest } from '../axios/request'; +import { OutboundHttp } from '../outbound-http'; + +vi.mock('../axios/request', () => ({ + httpRequest: vi.fn().mockResolvedValue({ statusCode: 200, body: 'ok' }), +})); + +const mockedHttpRequest = vi.mocked(httpRequest); + +// `httpRequest` is mocked, so the service is only passed through as the SSRF +// bridge — its methods are never actually invoked here. +function makeService(): SsrfProtectionService { + return mock<SsrfProtectionService>(); +} + +function makeFacade(service: SsrfProtectionService = makeService()): OutboundHttp { + return new OutboundHttp(service, mock<Logger>()); +} + +const REQUEST: IHttpRequestOptions = { url: 'https://example.test/x', method: 'GET' }; + +describe('OutboundHttp.requests', () => { + beforeEach(() => { + mockedHttpRequest.mockClear(); + }); + + it('forwards the request and returns the response', async () => { + const client = makeFacade().requests(); + + const res = await client.request(REQUEST); + + expect(res).toEqual({ statusCode: 200, body: 'ok' }); + expect(mockedHttpRequest).toHaveBeenCalledTimes(1); + expect(mockedHttpRequest).toHaveBeenCalledWith(REQUEST, expect.anything()); + }); + + it('uses the container SSRF service as the bridge by default', async () => { + const service = makeService(); + const client = makeFacade(service).requests(); + + await client.request(REQUEST); + + expect(mockedHttpRequest).toHaveBeenCalledWith(REQUEST, service); + }); + + it('passes an explicit SSRF bridge through to the request', async () => { + const bridge = mock<SsrfBridge>(); + const client = makeFacade().requests({ ssrf: bridge }); + + await client.request(REQUEST); + + expect(mockedHttpRequest).toHaveBeenCalledWith(REQUEST, bridge); + }); + + it('omits the bridge when SSRF protection is disabled', async () => { + const client = makeFacade().requests({ ssrf: 'disabled' }); + + await client.request(REQUEST); + + expect(mockedHttpRequest).toHaveBeenCalledWith(REQUEST, undefined); + }); +}); diff --git a/packages/@n8n/backend-network/src/http/__tests__/outbound-http.ssrf.test.ts b/packages/@n8n/backend-network/src/http/__tests__/outbound-http.ssrf.test.ts new file mode 100644 index 00000000000..47f6151991e --- /dev/null +++ b/packages/@n8n/backend-network/src/http/__tests__/outbound-http.ssrf.test.ts @@ -0,0 +1,257 @@ +import type { Logger } from '@n8n/backend-common'; +import type { Dispatcher } from 'undici'; +import { mock } from 'vitest-mock-extended'; + +import type { SsrfBridge, SsrfProtectionService } from '../../ssrf'; +import { makeSsrfBridge } from '../../ssrf/__tests__/mock-ssrf-bridge'; +import { type LocalServer, startServer } from '../local-server'; +import { OutboundHttp } from '../outbound-http'; +import { createSsrfInterceptor } from '../undici/transport'; + +// SSRF enforcement lives in a single place: the dispatcher interceptor. +// This file proves it at two levels: +// (a) a direct unit test of `createSsrfInterceptor`, and +// (b) end-to-end tests against a real local server (no mocked `fetch`), so the +// interceptor actually runs and we assert that a 30x cannot smuggle a +// request past SSRF protection — via both `asCustomFetch()` and the +// dispatcher returned by `getDispatcher()`. + +// Drain the microtask queue so the interceptor's async `validateUrl().then(...)` +// has settled before we assert. +const flush = async () => await new Promise((resolve) => setTimeout(resolve, 0)); + +// The interceptor hands `validateUrl` a `URL` object (not a string), so we match +// on its `href` rather than comparing against a raw string. +const validatedUrl = (href: string) => expect.objectContaining({ href }) as unknown as URL; + +// --------------------------------------------------------------------------- +// (a) createSsrfInterceptor — unit +// --------------------------------------------------------------------------- + +function makeInterceptedDispatch(bridge: SsrfBridge) { + const innerDispatch = vi.fn(); + const dispatch = createSsrfInterceptor(bridge)( + innerDispatch as unknown as Dispatcher['dispatch'], + ); + return { innerDispatch, dispatch }; +} + +function makeHandler() { + return { onResponseError: vi.fn(), onError: vi.fn() } as unknown as Dispatcher.DispatchHandler & { + onResponseError: ReturnType<typeof vi.fn>; + onError: ReturnType<typeof vi.fn>; + }; +} + +function makeOpts(path: string, origin?: string) { + return { path, origin } as unknown as Dispatcher.DispatchOptions; +} + +describe('createSsrfInterceptor', () => { + it('validates the reconstructed target URL and dispatches when allowed', async () => { + const bridge = makeSsrfBridge(); + const { innerDispatch, dispatch } = makeInterceptedDispatch(bridge); + const handler = makeHandler(); + + const ret = dispatch(makeOpts('/data', 'https://api.example.com'), handler); + await flush(); + + expect(ret).toBe(true); + expect(bridge.validateUrl).toHaveBeenCalledWith(validatedUrl('https://api.example.com/data')); + expect(innerDispatch).toHaveBeenCalledTimes(1); + expect(handler.onResponseError).not.toHaveBeenCalled(); + }); + + it('fails the dispatch and does not dispatch when SSRF rejects the target', async () => { + const error = new Error('SSRF: blocked'); + const bridge = makeSsrfBridge({ + validateUrl: vi.fn().mockResolvedValue({ ok: false, error }), + }); + const { innerDispatch, dispatch } = makeInterceptedDispatch(bridge); + const handler = makeHandler(); + + dispatch(makeOpts('/secret', 'http://10.0.0.1'), handler); + await flush(); + + expect(innerDispatch).not.toHaveBeenCalled(); + expect(handler.onResponseError).toHaveBeenCalledWith(null, error); + }); + + it('fails closed when the target URL cannot be derived', async () => { + const bridge = makeSsrfBridge(); + const { innerDispatch, dispatch } = makeInterceptedDispatch(bridge); + const handler = makeHandler(); + + dispatch(makeOpts('not a url'), handler); + await flush(); + + expect(bridge.validateUrl).not.toHaveBeenCalled(); + expect(innerDispatch).not.toHaveBeenCalled(); + expect(handler.onResponseError).toHaveBeenCalled(); + }); + + it('falls back to onError when onResponseError is unavailable', async () => { + const error = new Error('SSRF: blocked'); + const bridge = makeSsrfBridge({ + validateUrl: vi.fn().mockResolvedValue({ ok: false, error }), + }); + const { dispatch } = makeInterceptedDispatch(bridge); + const handler = { onError: vi.fn() } as unknown as Dispatcher.DispatchHandler & { + onError: ReturnType<typeof vi.fn>; + }; + + dispatch(makeOpts('/secret', 'http://10.0.0.1'), handler); + await flush(); + + expect(handler.onError).toHaveBeenCalledWith(error); + }); +}); + +// --------------------------------------------------------------------------- +// (b) end-to-end — real local server, real interceptor +// --------------------------------------------------------------------------- + +async function startRedirectServer(): Promise<LocalServer> { + let serverUrl = ''; + const server = await startServer((req, res) => { + if (req.url === '/start') { + res.writeHead(302, { Location: `${serverUrl}/internal` }); + res.end(); + return; + } + res.writeHead(200, { 'content-type': 'text/plain' }); + res.end(`reached:${req.url}`); + }); + serverUrl = server.url; + return server; +} + +function makeBridge(blockedPath: string): { bridge: SsrfBridge; error: Error } { + const error = new Error(`SSRF: blocked ${blockedPath}`); + const bridge = makeSsrfBridge({ + validateUrl: vi.fn(async (url: string | URL) => { + const href = typeof url === 'string' ? url : url.href; + return href.includes(blockedPath) + ? { ok: false as const, error } + : { ok: true as const, result: undefined }; + }), + }); + return { bridge, error }; +} + +function makeTransport(options?: Parameters<OutboundHttp['transport']>[0]) { + return new OutboundHttp(mock<SsrfProtectionService>(), mock<Logger>()).transport(options); +} + +// Walk the `cause` chain to the deepest error message. undici wraps a +// pre-dispatch failure as `TypeError: fetch failed` with the original error in +// `.cause`, so the SSRF reason lives down the chain. +function rootCauseMessage(error: unknown): string { + let current = error; + const seen = new Set<unknown>(); + while ( + current instanceof Error && + current.cause !== undefined && + current.cause !== null && + !seen.has(current) + ) { + seen.add(current); + current = current.cause; + } + return current instanceof Error ? current.message : String(current); +} + +describe('SSRF end-to-end', () => { + let server: LocalServer; + + beforeEach(async () => { + server = await startRedirectServer(); + }); + + afterEach(async () => { + await server.close(); + }); + + describe('asCustomFetch', () => { + it('blocks the initial request when SSRF rejects its URL', async () => { + const { bridge, error } = makeBridge('/start'); + const fetchFn = makeTransport({ ssrf: bridge, proxy: false }).asCustomFetch(); + + const rejection = await fetchFn(`${server.url}/start`).catch((e: unknown) => e); + + expect(rejection).toBeInstanceOf(Error); + expect(rootCauseMessage(rejection)).toBe(error.message); + expect(bridge.validateUrl).toHaveBeenCalledWith(validatedUrl(`${server.url}/start`)); + expect(server.captured).not.toContain('/start'); + }); + + it('blocks a redirect to a target that SSRF rejects, even though the initial URL is allowed', async () => { + const { bridge } = makeBridge('/internal'); + const fetchFn = makeTransport({ ssrf: bridge, proxy: false }).asCustomFetch(); + + await expect(fetchFn(`${server.url}/start`)).rejects.toThrow(); + + expect(bridge.validateUrl).toHaveBeenCalledWith(validatedUrl(`${server.url}/start`)); + expect(bridge.validateUrl).toHaveBeenCalledWith(validatedUrl(`${server.url}/internal`)); + expect(server.captured).toContain('/start'); + expect(server.captured).not.toContain('/internal'); + }); + + it('follows a redirect when every hop passes SSRF validation', async () => { + const { bridge } = makeBridge('/never-matches'); + const fetchFn = makeTransport({ ssrf: bridge, proxy: false }).asCustomFetch(); + + const res = await fetchFn(`${server.url}/start`); + + expect(res.status).toBe(200); + await expect(res.text()).resolves.toBe('reached:/internal'); + expect(server.captured).toEqual(['/start', '/internal']); + }); + + it('follows the redirect without validation when SSRF is disabled', async () => { + const { bridge } = makeBridge('/internal'); + const fetchFn = makeTransport({ ssrf: 'disabled', proxy: false }).asCustomFetch(); + + const res = await fetchFn(`${server.url}/start`); + + expect(res.status).toBe(200); + await expect(res.text()).resolves.toBe('reached:/internal'); + expect(bridge.validateUrl).not.toHaveBeenCalled(); + expect(server.captured).toEqual(['/start', '/internal']); + }); + }); + + describe('getDispatcher', () => { + it('enforces SSRF on the dispatcher: a redirect to a rejected target is blocked', async () => { + const { bridge } = makeBridge('/internal'); + const client = makeTransport({ ssrf: bridge, proxy: false }); + const dispatcher = client.getDispatcher(); + + const { fetch: undiciFetch } = await import('undici'); + await expect(undiciFetch(`${server.url}/start`, { dispatcher })).rejects.toThrow(); + + expect(bridge.validateUrl).toHaveBeenCalledWith(validatedUrl(`${server.url}/start`)); + expect(bridge.validateUrl).toHaveBeenCalledWith(validatedUrl(`${server.url}/internal`)); + expect(server.captured).toContain('/start'); + expect(server.captured).not.toContain('/internal'); + + await dispatcher.close(); + }); + + it('does not validate when SSRF is disabled (bare dispatcher)', async () => { + const { bridge } = makeBridge('/internal'); + const client = makeTransport({ ssrf: 'disabled', proxy: false }); + const dispatcher = client.getDispatcher(); + + const { fetch: undiciFetch } = await import('undici'); + const res = await undiciFetch(`${server.url}/start`, { dispatcher }); + + expect(res.status).toBe(200); + await expect(res.text()).resolves.toBe('reached:/internal'); + expect(bridge.validateUrl).not.toHaveBeenCalled(); + expect(server.captured).toEqual(['/start', '/internal']); + + await dispatcher.close(); + }); + }); +}); diff --git a/packages/@n8n/backend-network/src/http/__tests__/outbound-http.test.ts b/packages/@n8n/backend-network/src/http/__tests__/outbound-http.test.ts new file mode 100644 index 00000000000..2b5f646078d --- /dev/null +++ b/packages/@n8n/backend-network/src/http/__tests__/outbound-http.test.ts @@ -0,0 +1,97 @@ +import type { Logger } from '@n8n/backend-common'; +import { Container } from '@n8n/di'; +import { fetch as undiciFetch } from 'undici'; +import { mock } from 'vitest-mock-extended'; + +import type { SsrfProtectionService } from '../../ssrf'; +import { makeLookupFn } from '../../ssrf/__tests__/mock-ssrf-bridge'; +import { OutboundHttp } from '../outbound-http'; + +// Core facade wiring. `undiciFetch` is stubbed so no real network call is made +// and the SSRF dispatcher interceptor never runs here +vi.mock('undici', async (importOriginal) => { + // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion + const mod = (await importOriginal()) as Record<string, unknown>; + return { + ...mod, + fetch: vi.fn().mockResolvedValue({ + ok: true, + status: 200, + text: async () => 'ok', + }), + }; +}); + +function makeFacade(): OutboundHttp { + const service = mock<SsrfProtectionService>(); + vi.mocked(service.createSecureLookup).mockReturnValue(makeLookupFn()); + vi.mocked(service.validateUrl).mockResolvedValue({ ok: true, result: undefined }); + return new OutboundHttp(service, mock<Logger>()); +} + +describe('DI registration', () => { + it('should be resolvable from the container', () => { + expect(Container.get(OutboundHttp)).toBeInstanceOf(OutboundHttp); + }); +}); + +describe('transport asCustomFetch', () => { + beforeEach(() => { + vi.clearAllMocks(); + }); + + it('dispatches through the same guarded dispatcher returned by getDispatcher() when SSRF is enabled', async () => { + const transport = makeFacade().transport({ proxy: false }); + const fetchFn = transport.asCustomFetch(); + + await fetchFn('https://api.example.com/data'); + + const [, calledInit] = vi.mocked(undiciFetch).mock.calls[0] as [ + unknown, + { dispatcher: unknown }, + ]; + expect(calledInit.dispatcher).toBe(transport.getDispatcher()); + }); + + it('dispatches through the bare dispatcher returned by getDispatcher() when SSRF is disabled', async () => { + const transport = makeFacade().transport({ proxy: false, ssrf: 'disabled' }); + const fetchFn = transport.asCustomFetch(); + + await fetchFn('https://api.example.com/data'); + + const [, calledInit] = vi.mocked(undiciFetch).mock.calls[0] as [ + unknown, + { dispatcher: unknown }, + ]; + expect(calledInit.dispatcher).toBe(transport.getDispatcher()); + }); + + it('forwards the input unchanged to undiciFetch', async () => { + const fetchFn = makeFacade().transport().asCustomFetch(); + const url = new URL('https://api.example.com/data'); + + await fetchFn(url); + + const [calledInput] = vi.mocked(undiciFetch).mock.calls[0]; + expect(calledInput).toBe(url); + }); + + it('passes init options through to undiciFetch', async () => { + const fetchFn = makeFacade().transport().asCustomFetch(); + const init: RequestInit = { method: 'POST', headers: { 'Content-Type': 'application/json' } }; + + await fetchFn('https://api.example.com/data', init); + + const [, calledInit] = vi.mocked(undiciFetch).mock.calls[0] as [ + unknown, + Record<string, unknown>, + ]; + expect(calledInit).toMatchObject({ method: 'POST' }); + }); + + it('returns a new function on each call (fresh closure)', () => { + const transport = makeFacade().transport(); + + expect(transport.asCustomFetch()).not.toBe(transport.asCustomFetch()); + }); +}); diff --git a/packages/core/src/execution-engine/node-execution-context/utils/__tests__/parse-incoming-message.test.ts b/packages/@n8n/backend-network/src/http/__tests__/parse-incoming-message.test.ts similarity index 100% rename from packages/core/src/execution-engine/node-execution-context/utils/__tests__/parse-incoming-message.test.ts rename to packages/@n8n/backend-network/src/http/__tests__/parse-incoming-message.test.ts diff --git a/packages/@n8n/backend-network/src/http/__tests__/transport-integration.test.ts b/packages/@n8n/backend-network/src/http/__tests__/transport-integration.test.ts new file mode 100644 index 00000000000..5f248a52b9d --- /dev/null +++ b/packages/@n8n/backend-network/src/http/__tests__/transport-integration.test.ts @@ -0,0 +1,201 @@ +import type { AxiosRequestConfig } from 'axios'; +import axios from 'axios'; +import dns from 'node:dns'; +import http from 'node:http'; +import type { LookupFunction } from 'node:net'; + +import { makeSsrfBridge } from '../../ssrf/__tests__/mock-ssrf-bridge'; +import { getBeforeRedirectFn, setAxiosAgents } from '../axios/utils'; +import { type LocalServer, startServer } from '../local-server'; +import { buildNodeAgents } from '../node-agents'; + +// End-to-end parity tests for the outbound transport layer. These spin up real +// local HTTP servers (a target and a proxy) and drive requests through the +// agents produced by `buildNodeAgents` / `setAxiosAgents` — exactly the way +// axios uses them — so they assert observable routing behaviour rather than +// implementation details. + +async function httpGetWithAgent(url: string, agent: http.Agent): Promise<string> { + return await new Promise((resolve, reject) => { + const req = http.get(url, { agent, timeout: 5000 }, (res) => { + let data = ''; + res.on('data', (chunk) => (data += chunk)); + res.on('end', () => resolve(data)); + }); + req.on('error', reject); + req.on('timeout', () => { + req.destroy(); + reject(new Error('timeout')); + }); + }); +} + +describe('outbound transport integration', () => { + let target: LocalServer; + let proxy: LocalServer; + const ORIGINAL_ENV = { ...process.env }; + + beforeAll(async () => { + target = await startServer((req, res) => { + if (req.url === '/redirect') { + res.writeHead(301, { Location: `${target.url}/final` }); + res.end(); + return; + } + const message = req.url === '/final' ? 'final' : 'direct'; + res.setHeader('Content-Type', 'application/json'); + res.end(JSON.stringify({ message })); + }); + proxy = await startServer((_req, res) => { + res.setHeader('Content-Type', 'application/json'); + res.end(JSON.stringify({ message: 'proxied' })); + }); + }); + + afterAll(async () => { + await target.close(); + await proxy.close(); + }); + + beforeEach(() => { + delete process.env.HTTP_PROXY; + delete process.env.HTTPS_PROXY; + delete process.env.NO_PROXY; + delete process.env.ALL_PROXY; + target.clear(); + proxy.clear(); + }); + + afterEach(() => { + process.env = { ...ORIGINAL_ENV }; + }); + + describe('setAxiosAgents routing', () => { + it('routes through an explicit custom proxy', async () => { + const config: AxiosRequestConfig = { url: `${target.url}/x`, method: 'GET', proxy: false }; + setAxiosAgents(config, undefined, proxy.url); + + const res = await axios(config); + + expect(res.data.message).toBe('proxied'); + expect(proxy.captured.length).toBeGreaterThan(0); + expect(target.captured).toHaveLength(0); + }); + + it('routes through the env proxy (HTTP_PROXY)', async () => { + process.env.HTTP_PROXY = proxy.url; + const config: AxiosRequestConfig = { + url: 'http://proxied-target.invalid/x', + method: 'GET', + proxy: false, + }; + setAxiosAgents(config, undefined, undefined); + + const res = await axios(config); + + expect(res.data.message).toBe('proxied'); + expect(proxy.captured.length).toBeGreaterThan(0); + }); + + it('connects directly when no proxy is configured', async () => { + const config: AxiosRequestConfig = { url: `${target.url}/x`, method: 'GET', proxy: false }; + setAxiosAgents(config, undefined, undefined); + + const res = await axios(config); + + expect(res.data.message).toBe('direct'); + expect(proxy.captured).toHaveLength(0); + }); + + it('bypasses the env proxy for NO_PROXY targets', async () => { + process.env.HTTP_PROXY = proxy.url; + process.env.NO_PROXY = '127.0.0.1'; + const config: AxiosRequestConfig = { url: `${target.url}/x`, method: 'GET', proxy: false }; + setAxiosAgents(config, undefined, undefined); + + const res = await axios(config); + + expect(res.data.message).toBe('direct'); + expect(proxy.captured).toHaveLength(0); + }); + }); + + describe('SSRF secure lookup is applied to direct connections only', () => { + it('invokes the secure lookup for a direct (hostname) connection', async () => { + const lookupSpy = vi.fn((hostname: string, options: dns.LookupOptions, onResult: unknown) => + dns.lookup(hostname, options, onResult as never), + ); + const bridge = makeSsrfBridge({ + createSecureLookup: () => lookupSpy as unknown as LookupFunction, + }); + + const config: AxiosRequestConfig = { + url: `http://localhost:${target.hostWithPort.split(':')[1]}/x`, + method: 'GET', + proxy: false, + }; + setAxiosAgents(config, undefined, undefined, bridge); + + const res = await axios(config); + + expect(res.data.message).toBe('direct'); + expect(lookupSpy).toHaveBeenCalledWith('localhost', expect.anything(), expect.anything()); + }); + + it('does NOT invoke the secure lookup when routed through a proxy', async () => { + process.env.HTTP_PROXY = proxy.url; + const lookupSpy = vi.fn((hostname: string, options: dns.LookupOptions, onResult: unknown) => + dns.lookup(hostname, options, onResult as never), + ); + const bridge = makeSsrfBridge({ + createSecureLookup: () => lookupSpy as unknown as LookupFunction, + }); + + const config: AxiosRequestConfig = { + url: 'http://proxied-target.invalid/x', + method: 'GET', + proxy: false, + }; + setAxiosAgents(config, undefined, undefined, bridge); + + const res = await axios(config); + + expect(res.data.message).toBe('proxied'); + // The proxy host is an IP (no lookup) and the proxy resolves the final + // target, so the secure lookup is never consulted on our side. + expect(lookupSpy).not.toHaveBeenCalled(); + }); + }); + + describe('env-proxy agent caching', () => { + it('reuses a single cached proxy agent for the same proxy URL', async () => { + process.env.HTTP_PROXY = proxy.url; + const { httpAgent } = buildNodeAgents('env', 'disabled'); + + await httpGetWithAgent('http://host-a.invalid/x', httpAgent); + await httpGetWithAgent('http://host-b.invalid/x', httpAgent); + + const proxyCache = (httpAgent as unknown as { router: { proxyCache: Map<string, unknown> } }) + .router.proxyCache; + expect(proxyCache.size).toBe(1); + expect(proxy.captured.length).toBeGreaterThanOrEqual(2); + }); + }); + + describe('getBeforeRedirectFn', () => { + it('rebuilds working agents and follows a redirect to completion', async () => { + const config: AxiosRequestConfig = { + url: `${target.url}/redirect`, + method: 'GET', + proxy: false, + maxRedirects: 5, + }; + config.beforeRedirect = getBeforeRedirectFn({}, config, undefined, true); + setAxiosAgents(config, {}, undefined); + + const res = await axios(config); + + expect(res.data.message).toBe('final'); + }); + }); +}); diff --git a/packages/core/src/execution-engine/node-execution-context/utils/request-helpers/__tests__/axios-config.test.ts b/packages/@n8n/backend-network/src/http/axios/__tests__/config.test.ts similarity index 91% rename from packages/core/src/execution-engine/node-execution-context/utils/request-helpers/__tests__/axios-config.test.ts rename to packages/@n8n/backend-network/src/http/axios/__tests__/config.test.ts index 02e6d0cb393..1f6a6f40292 100644 --- a/packages/core/src/execution-engine/node-execution-context/utils/request-helpers/__tests__/axios-config.test.ts +++ b/packages/@n8n/backend-network/src/http/axios/__tests__/config.test.ts @@ -3,7 +3,10 @@ import { Container } from '@n8n/di'; import type { InternalAxiosRequestConfig } from 'axios'; import axios, { AxiosHeaders } from 'axios'; -import '../axios-config'; +import { configureGlobalAxiosDefaults } from '../config'; + +// Registers the axios defaults and the vendor-header interceptor under test. +configureGlobalAxiosDefaults(); const getRequestInterceptor = () => { const { handlers } = axios.interceptors.request as unknown as { diff --git a/packages/@n8n/backend-network/src/http/axios/__tests__/legacy.test.ts b/packages/@n8n/backend-network/src/http/axios/__tests__/legacy.test.ts new file mode 100644 index 00000000000..72166a9aa8e --- /dev/null +++ b/packages/@n8n/backend-network/src/http/axios/__tests__/legacy.test.ts @@ -0,0 +1,271 @@ +import FormData from 'form-data'; +import type { Agent as HttpsAgent } from 'https'; +import type { IHttpRequestMethods, IRequestOptions } from 'n8n-workflow'; +import nock from 'nock'; +import type { SecureContextOptions } from 'tls'; +import { mock } from 'vitest-mock-extended'; + +import { buildAxiosConfigFromLegacyRequest } from '../legacy'; + +const TEST_CA_CERT = '-----BEGIN CERTIFICATE-----\nTEST\n-----END CERTIFICATE-----'; + +describe('buildAxiosConfigFromLegacyRequest', () => { + test('should handle basic request options', async () => { + const axiosOptions = await buildAxiosConfigFromLegacyRequest({ + url: 'https://example.com', + method: 'POST', + headers: { 'content-type': 'application/json' }, + body: { key: 'value' }, + }); + + expect(axiosOptions).toEqual( + expect.objectContaining({ + url: 'https://example.com', + method: 'POST', + headers: { + accept: '*/*', + 'content-type': 'application/json', + 'User-Agent': 'n8n', + }, + data: { key: 'value' }, + maxRedirects: 0, + }), + ); + }); + + test('should set default User-Agent when none provided', async () => { + const axiosOptions = await buildAxiosConfigFromLegacyRequest({ + url: 'https://example.com', + method: 'GET', + }); + + expect(axiosOptions.headers).toMatchObject({ 'User-Agent': 'n8n' }); + }); + + test('should preserve a caller-supplied User-Agent header', async () => { + const axiosOptions = await buildAxiosConfigFromLegacyRequest({ + url: 'https://example.com', + method: 'GET', + headers: { 'User-Agent': 'MyCustomNode/1.0' }, + }); + + expect(axiosOptions.headers).toMatchObject({ 'User-Agent': 'MyCustomNode/1.0' }); + expect(axiosOptions.headers).not.toMatchObject({ 'User-Agent': 'n8n' }); + }); + + test('should set correct headers for FormData', async () => { + const formData = new FormData(); + formData.append('key', 'value'); + + const axiosOptions = await buildAxiosConfigFromLegacyRequest({ + url: 'https://example.com', + formData, + headers: { + 'content-type': 'multipart/form-data', + }, + }); + + expect(axiosOptions.headers).toMatchObject({ + accept: '*/*', + 'content-length': 163, + 'content-type': expect.stringMatching(/^multipart\/form-data; boundary=/), + }); + + expect(axiosOptions.data).toBeInstanceOf(FormData); + }); + + test('should handle FormData from a different module copy (duck-typing)', async () => { + // Simulate a FormData created by a different copy of the form-data package. + // instanceof FormData would return false, but duck-type check should pass. + const realFormData = new FormData(); + realFormData.append('key', 'value'); + + // Create a wrapper that breaks instanceof but preserves the interface + const foreignFormData: Record<string, unknown> = Object.create(null); + for (const prop of Object.getOwnPropertyNames(Object.getPrototypeOf(realFormData))) { + const value = (realFormData as unknown as Record<string, unknown>)[prop]; + if (typeof value === 'function') { + foreignFormData[prop] = value.bind(realFormData); + } + } + for (const prop of Object.getOwnPropertyNames(realFormData)) { + foreignFormData[prop] = (realFormData as unknown as Record<string, unknown>)[prop]; + } + + // Verify it's NOT an instanceof FormData + expect(foreignFormData instanceof FormData).toBe(false); + + const axiosOptions = await buildAxiosConfigFromLegacyRequest({ + url: 'https://example.com', + formData: foreignFormData as unknown as FormData, + headers: { + 'content-type': 'multipart/form-data', + }, + }); + + expect(axiosOptions.headers).toMatchObject({ + 'content-type': expect.stringMatching(/^multipart\/form-data; boundary=/), + }); + }); + + test('should forward a string form body unchanged', async () => { + const form = 'user=john%20doe&token=a%2Bb'; + + const axiosOptions = await buildAxiosConfigFromLegacyRequest({ + url: 'https://example.com', + method: 'POST', + // The legacy `request` library accepted pre-encoded string form bodies, + // even though the type only models object/FormData forms. + form: form as unknown as IRequestOptions['form'], + }); + + expect(axiosOptions.data).toBe(form); + expect(axiosOptions.headers).toMatchObject({ + 'Content-Type': 'application/x-www-form-urlencoded', + }); + }); + + test('should serialize an object form body as x-www-form-urlencoded', async () => { + const axiosOptions = await buildAxiosConfigFromLegacyRequest({ + url: 'https://example.com', + method: 'POST', + form: { foo: 'bar', baz: 'qux' }, + }); + + expect(axiosOptions.data).toBe('foo=bar&baz=qux'); + expect(axiosOptions.headers).toMatchObject({ + 'Content-Type': 'application/x-www-form-urlencoded', + }); + }); + + test('should not use Host header for SNI', async () => { + const axiosOptions = await buildAxiosConfigFromLegacyRequest({ + url: 'https://example.de/foo/bar', + headers: { Host: 'other.host.com' }, + }); + expect((axiosOptions.httpsAgent as HttpsAgent).options.servername).toEqual('example.de'); + }); + + describe('should set SSL certificates', () => { + const agentOptions: SecureContextOptions = { + ca: TEST_CA_CERT, + }; + const requestObject: IRequestOptions = { + method: 'GET', + uri: 'https://example.de', + agentOptions, + }; + + test('on regular requests', async () => { + const axiosOptions = await buildAxiosConfigFromLegacyRequest(requestObject); + expect((axiosOptions.httpsAgent as HttpsAgent).options).toMatchObject({ + servername: 'example.de', + ...agentOptions, + noDelay: true, + path: null, + }); + }); + + test('on redirected requests', async () => { + const axiosOptions = await buildAxiosConfigFromLegacyRequest(requestObject); + expect(axiosOptions.beforeRedirect).toBeDefined(); + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const redirectOptions: Record<string, any> = { + agents: {}, + hostname: 'example.de', + href: requestObject.uri, + }; + axiosOptions.beforeRedirect!(redirectOptions, mock(), mock()); + expect(redirectOptions.agent).toEqual(redirectOptions.agents.https); + expect((redirectOptions.agent as HttpsAgent).options).toMatchObject({ + servername: 'example.de', + ...agentOptions, + noDelay: true, + path: null, + }); + }); + }); + + describe('when followRedirect is true', () => { + test.each(['GET', 'HEAD'] as IHttpRequestMethods[])( + 'should set maxRedirects on %s ', + async (method) => { + const axiosOptions = await buildAxiosConfigFromLegacyRequest({ + method, + followRedirect: true, + maxRedirects: 1234, + }); + expect(axiosOptions.maxRedirects).toEqual(1234); + }, + ); + + test.each(['POST', 'PUT', 'PATCH', 'DELETE'] as IHttpRequestMethods[])( + 'should not set maxRedirects on %s ', + async (method) => { + const axiosOptions = await buildAxiosConfigFromLegacyRequest({ + method, + followRedirect: true, + maxRedirects: 1234, + }); + expect(axiosOptions.maxRedirects).toEqual(0); + }, + ); + }); + + describe('when followAllRedirects is true', () => { + test.each(['GET', 'HEAD', 'POST', 'PUT', 'PATCH', 'DELETE'] as IHttpRequestMethods[])( + 'should set maxRedirects on %s ', + async (method) => { + const axiosOptions = await buildAxiosConfigFromLegacyRequest({ + method, + followAllRedirects: true, + maxRedirects: 1234, + }); + expect(axiosOptions.maxRedirects).toEqual(1234); + }, + ); + }); + + describe('domain allowlist enforcement', () => { + const baseUrl = 'https://example.com'; + + beforeEach(() => { + nock.cleanAll(); + }); + + test('should pass allowedDomains to beforeRedirect', async () => { + const axiosOptions = await buildAxiosConfigFromLegacyRequest({ + url: `${baseUrl}/test`, + allowedDomains: 'example.com', + }); + const redirectOptions = { + agents: {}, + hostname: 'not-allowed.com', + href: 'https://not-allowed.com/data', + }; + + expect(axiosOptions.beforeRedirect).toBeDefined(); + expect(() => axiosOptions.beforeRedirect!(redirectOptions, mock(), mock())).toThrow( + 'Domain not allowed', + ); + }); + + test.each([['example.com'], [undefined]])( + 'should not block redirects when allowedDomains is %s', + async (allowedDomains) => { + const axiosOptions = await buildAxiosConfigFromLegacyRequest({ + url: `${baseUrl}/test`, + allowedDomains, + }); + const redirectOptions = { + agents: {}, + hostname: 'example.com', + href: 'https://example.com/data', + }; + + expect(axiosOptions.beforeRedirect).toBeDefined(); + expect(() => axiosOptions.beforeRedirect!(redirectOptions, mock(), mock())).not.toThrow(); + }, + ); + }); +}); diff --git a/packages/@n8n/backend-network/src/http/axios/__tests__/request.test.ts b/packages/@n8n/backend-network/src/http/axios/__tests__/request.test.ts new file mode 100644 index 00000000000..1a37d3026b5 --- /dev/null +++ b/packages/@n8n/backend-network/src/http/axios/__tests__/request.test.ts @@ -0,0 +1,806 @@ +import { AiConfig } from '@n8n/config'; +import { Container } from '@n8n/di'; +import FormData from 'form-data'; +import type { Agent as HttpsAgent } from 'https'; +import type { IHttpRequestMethods, IHttpRequestOptions, IRequestOptions } from 'n8n-workflow'; +import nock from 'nock'; +import { mock } from 'vitest-mock-extended'; + +import type { SsrfBridge } from '../../../ssrf'; +import { configureGlobalAxiosDefaults } from '../config'; +import { convertN8nRequestToAxios, httpRequest, invokeAxios, removeEmptyBody } from '../request'; + +// Sets axios defaults and registers the vendor-header interceptor. +configureGlobalAxiosDefaults(); + +const TEST_CA_CERT = '-----BEGIN CERTIFICATE-----\nTEST\n-----END CERTIFICATE-----'; + +describe('invokeAxios', () => { + const baseUrl = 'https://example.de'; + + beforeEach(() => { + nock.cleanAll(); + vi.clearAllMocks(); + }); + + it('should throw error for non-401 status codes', async () => { + nock(baseUrl).get('/test').reply(500, {}); + + await expect(invokeAxios({ url: `${baseUrl}/test` })).rejects.toThrow( + 'Request failed with status code 500', + ); + }); + + it('should throw error on 401 without digest auth challenge', async () => { + nock(baseUrl).get('/test').reply(401, {}); + + await expect( + invokeAxios( + { + url: `${baseUrl}/test`, + }, + { sendImmediately: false }, + ), + ).rejects.toThrow('Request failed with status code 401'); + }); + + it('should make successful requests', async () => { + nock(baseUrl).get('/test').reply(200, { success: true }); + + const response = await invokeAxios({ + url: `${baseUrl}/test`, + }); + + expect(response.status).toBe(200); + expect(response.data).toEqual({ success: true }); + }); + + it('should handle digest auth when receiving 401 with nonce', async () => { + nock(baseUrl) + .get('/test') + .matchHeader('authorization', 'Basic dXNlcjpwYXNz') + .once() + .reply(401, {}, { 'www-authenticate': 'Digest realm="test", nonce="abc123", qop="auth"' }); + + nock(baseUrl) + .get('/test') + .matchHeader( + 'authorization', + /^Digest username="user",realm="test",nonce="abc123",uri="\/test",qop="auth",algorithm="MD5",response="[0-9a-f]{32}"/, + ) + .reply(200, { success: true }); + + const response = await invokeAxios( + { + url: `${baseUrl}/test`, + auth: { + username: 'user', + password: 'pass', + }, + }, + { sendImmediately: false }, + ); + + expect(response.status).toBe(200); + expect(response.data).toEqual({ success: true }); + }); + + it('should include vendor headers in requests to OpenAi', async () => { + const { openAiDefaultHeaders } = Container.get(AiConfig); + nock('https://api.openai.com', { + reqheaders: openAiDefaultHeaders, + }) + .get('/chat') + .reply(200, { success: true }); + + const response = await invokeAxios({ + url: 'https://api.openai.com/chat', + }); + + expect(response.status).toBe(200); + expect(response.data).toEqual({ success: true }); + }); +}); + +describe('removeEmptyBody', () => { + test.each(['GET', 'HEAD', 'OPTIONS'] as IHttpRequestMethods[])( + 'Should remove empty body for %s', + async (method) => { + const requestOptions = { + method, + body: {}, + } as IHttpRequestOptions | IRequestOptions; + removeEmptyBody(requestOptions); + expect(requestOptions.body).toEqual(undefined); + }, + ); + + test.each(['GET', 'HEAD', 'OPTIONS'] as IHttpRequestMethods[])( + 'Should not remove non-empty body for %s', + async (method) => { + const requestOptions = { + method, + body: { test: true }, + } as IHttpRequestOptions | IRequestOptions; + removeEmptyBody(requestOptions); + expect(requestOptions.body).toEqual({ test: true }); + }, + ); + + test.each(['POST', 'PUT', 'PATCH', 'DELETE'] as IHttpRequestMethods[])( + 'Should not remove empty body for %s', + async (method) => { + const requestOptions = { + method, + body: {}, + } as IHttpRequestOptions | IRequestOptions; + removeEmptyBody(requestOptions); + expect(requestOptions.body).toEqual({}); + }, + ); + + describe('empty-body detection across body shapes (GET)', () => { + test.each([ + ['null', null], + ['undefined', undefined], + ['empty string', ''], + ['empty array', []], + ['empty buffer', Buffer.alloc(0)], + ['empty object', {}], + ])('treats %s as empty and removes it', (_label, body) => { + const requestOptions = { + method: 'GET', + body, + } as unknown as IHttpRequestOptions | IRequestOptions; + removeEmptyBody(requestOptions); + expect(requestOptions.body).toBeUndefined(); + }); + + test.each([ + ['non-empty string', 'data'], + ['non-empty array', [1]], + ['non-empty buffer', Buffer.from('x')], + ['non-empty object', { test: true }], + ['zero', 0], + ['false', false], + ])('treats %s as non-empty and keeps it', (_label, body) => { + const requestOptions = { + method: 'GET', + body, + } as unknown as IHttpRequestOptions | IRequestOptions; + removeEmptyBody(requestOptions); + expect(requestOptions.body).toEqual(body); + }); + }); +}); + +describe('convertN8nRequestToAxios', () => { + test('should convert basic HTTP request options', () => { + const requestOptions: IHttpRequestOptions = { + method: 'GET', + url: 'https://example.com', + headers: { 'Custom-Header': 'test' }, + qs: { param1: 'value1' }, + }; + + const axiosConfig = convertN8nRequestToAxios(requestOptions); + + expect(axiosConfig).toEqual( + expect.objectContaining({ + method: 'GET', + url: 'https://example.com', + headers: expect.objectContaining({ + 'Custom-Header': 'test', + 'User-Agent': 'n8n', + }), + params: { param1: 'value1' }, + }), + ); + }); + + test('should handle body and content type', () => { + const requestOptions: IHttpRequestOptions = { + method: 'POST', + url: 'https://example.com', + body: { key: 'value' }, + headers: { 'content-type': 'application/json' }, + }; + + const axiosConfig = convertN8nRequestToAxios(requestOptions); + + expect(axiosConfig).toEqual( + expect.objectContaining({ + method: 'POST', + data: { key: 'value' }, + headers: expect.objectContaining({ + 'content-type': 'application/json', + }), + }), + ); + }); + + test('should handle form data', () => { + const formData = new FormData(); + formData.append('key', 'value'); + + const requestOptions: IHttpRequestOptions = { + method: 'POST', + url: 'https://example.com', + body: formData, + }; + + const axiosConfig = convertN8nRequestToAxios(requestOptions); + + expect(axiosConfig).toEqual( + expect.objectContaining({ + method: 'POST', + data: formData, + headers: expect.objectContaining({ + ...formData.getHeaders(), + 'User-Agent': 'n8n', + }), + }), + ); + }); + + test('should handle disable follow redirect', () => { + const requestOptions: IHttpRequestOptions = { + method: 'GET', + url: 'https://example.com', + disableFollowRedirect: true, + }; + + const axiosConfig = convertN8nRequestToAxios(requestOptions); + + expect(axiosConfig.maxRedirects).toBe(0); + }); + + test('should handle SSL certificate validation', () => { + const requestOptions: IHttpRequestOptions = { + method: 'GET', + url: 'https://example.com', + skipSslCertificateValidation: true, + }; + + const axiosConfig = convertN8nRequestToAxios(requestOptions); + + expect(axiosConfig.httpsAgent?.options.rejectUnauthorized).toBe(false); + }); + + test('should ignore HTTP error except for the specified status codes', () => { + const requestOptions: IHttpRequestOptions = { + method: 'GET', + url: 'https://example.com', + ignoreHttpStatusErrors: { ignore: true, except: [401] }, + }; + + const axiosConfig = convertN8nRequestToAxios(requestOptions); + expect(axiosConfig.validateStatus).toBeDefined(); + expect(axiosConfig.validateStatus!(401)).toBe(false); + expect(axiosConfig.validateStatus!(500)).toBe(true); + }); + + test('should ignore all HTTP errors', () => { + const requestOptions: IHttpRequestOptions = { + method: 'GET', + url: 'https://example.com', + ignoreHttpStatusErrors: true, + }; + + const axiosConfig = convertN8nRequestToAxios(requestOptions); + expect(axiosConfig.validateStatus).toBeDefined(); + expect(axiosConfig.validateStatus!(401)).toBe(true); + expect(axiosConfig.validateStatus!(500)).toBe(true); + }); + + test('should pass agentOptions through to the https agent', () => { + const requestOptions: IHttpRequestOptions = { + method: 'GET', + url: 'https://example.com', + agentOptions: { + ca: TEST_CA_CERT, + }, + }; + + const axiosConfig = convertN8nRequestToAxios(requestOptions); + + expect((axiosConfig.httpsAgent as HttpsAgent).options.ca).toBe(TEST_CA_CERT); + }); + + test('should merge agentOptions with skipSslCertificateValidation', () => { + const requestOptions: IHttpRequestOptions = { + method: 'GET', + url: 'https://example.com', + skipSslCertificateValidation: true, + agentOptions: { + ca: TEST_CA_CERT, + }, + }; + + const axiosConfig = convertN8nRequestToAxios(requestOptions); + + expect((axiosConfig.httpsAgent as HttpsAgent).options.rejectUnauthorized).toBe(false); + expect((axiosConfig.httpsAgent as HttpsAgent).options.ca).toBe(TEST_CA_CERT); + }); +}); + +describe('httpRequest', () => { + const baseUrl = 'https://example.com'; + + beforeEach(() => { + nock.cleanAll(); + }); + + test('should make a simple GET request', async () => { + const scope = nock(baseUrl) + .get('/users') + .reply(200, { users: ['John', 'Jane'] }); + + const response = await httpRequest({ + method: 'GET', + url: `${baseUrl}/users`, + }); + + expect(response).toEqual({ users: ['John', 'Jane'] }); + scope.done(); + }); + + test('should ignore invalid baseURL when url is absolute', async () => { + const scope = nock(baseUrl) + .get('/users') + .reply(200, { users: ['John', 'Jane'] }); + + const response = await httpRequest({ + method: 'GET', + url: `${baseUrl}/users`, + baseURL: 'not-a-valid-url', + }); + + expect(response).toEqual({ users: ['John', 'Jane'] }); + scope.done(); + }); + + test('should make a POST request with JSON body', async () => { + const requestBody = { name: 'John', age: 30 }; + const scope = nock(baseUrl) + .post('/users', requestBody) + .reply(201, { id: '123', ...requestBody }); + + const response = await httpRequest({ + method: 'POST', + url: `${baseUrl}/users`, + body: requestBody, + json: true, + }); + + expect(response).toEqual({ id: '123', name: 'John', age: 30 }); + scope.done(); + }); + + test('should return full response when returnFullResponse is true', async () => { + const scope = nock(baseUrl).get('/data').reply( + 200, + { key: 'value' }, + { + 'X-Custom-Header': 'test-header', + }, + ); + + const response = await httpRequest({ + method: 'GET', + url: `${baseUrl}/data`, + returnFullResponse: true, + }); + + expect(response).toEqual({ + body: { key: 'value' }, + headers: expect.objectContaining({ + 'x-custom-header': 'test-header', + }), + statusCode: 200, + statusMessage: 'OK', + }); + scope.done(); + }); + + test('should handle form data request', async () => { + const formData = new FormData(); + formData.append('file', 'test content', 'file.txt'); + + const scope = nock(baseUrl) + .post('/upload') + .matchHeader('content-type', /multipart\/form-data; boundary=/) + .reply(200, { success: true }); + + const response = await httpRequest({ + method: 'POST', + url: `${baseUrl}/upload`, + body: formData, + }); + + expect(response).toEqual({ success: true }); + scope.done(); + }); + + test('should handle query parameters', async () => { + const scope = nock(baseUrl) + .get('/search') + .query({ q: 'test', page: '1' }) + .reply(200, { results: ['result1', 'result2'] }); + + const response = await httpRequest({ + method: 'GET', + url: `${baseUrl}/search`, + qs: { q: 'test', page: '1' }, + }); + + expect(response).toEqual({ results: ['result1', 'result2'] }); + scope.done(); + }); + + test('should ignore HTTP status errors when configured', async () => { + const scope = nock(baseUrl).get('/error').reply(500, { error: 'Internal Server Error' }); + + const response = await httpRequest({ + method: 'GET', + url: `${baseUrl}/error`, + ignoreHttpStatusErrors: true, + }); + + expect(response).toEqual({ error: 'Internal Server Error' }); + scope.done(); + }); + + test('should handle different array formats in query parameters', async () => { + const scope = nock(baseUrl) + .get('/list') + .query({ + tags: ['tag1', 'tag2'], + categories: ['cat1', 'cat2'], + }) + .reply(200, { success: true }); + + const response = await httpRequest({ + method: 'GET', + url: `${baseUrl}/list`, + qs: { + tags: ['tag1', 'tag2'], + categories: ['cat1', 'cat2'], + }, + arrayFormat: 'indices', + }); + + expect(response).toEqual({ success: true }); + scope.done(); + }); + + test('should remove empty body for GET requests', async () => { + const scope = nock(baseUrl).get('/data').reply(200, { success: true }); + + const response = await httpRequest({ + method: 'GET', + url: `${baseUrl}/data`, + body: {}, + }); + + expect(response).toEqual({ success: true }); + scope.done(); + }); + + test('should set default user agent', async () => { + const scope = nock(baseUrl, { + reqheaders: { + 'user-agent': 'n8n', + }, + }) + .get('/test') + .reply(200, { success: true }); + + const response = await httpRequest({ + method: 'GET', + url: `${baseUrl}/test`, + }); + + expect(response).toEqual({ success: true }); + scope.done(); + }); + + test('should respect custom headers', async () => { + const scope = nock(baseUrl, { + reqheaders: { + 'X-Custom-Header': 'custom-value', + 'user-agent': 'n8n', + }, + }) + .get('/test') + .reply(200, { success: true }); + + const response = await httpRequest({ + method: 'GET', + url: `${baseUrl}/test`, + headers: { 'X-Custom-Header': 'custom-value' }, + }); + + expect(response).toEqual({ success: true }); + scope.done(); + }); + + it('should include vendor headers in requests to OpenAi', async () => { + const { openAiDefaultHeaders } = Container.get(AiConfig); + const scope = nock('https://api.openai.com', { + reqheaders: openAiDefaultHeaders, + }) + .get('/chat') + .reply(200, { success: true }); + + const response = await httpRequest({ + method: 'GET', + url: 'https://api.openai.com/chat', + headers: { 'X-Custom-Header': 'custom-value' }, + }); + expect(response).toEqual({ success: true }); + scope.done(); + }); + + describe('redirects', () => { + test.each([[undefined], [true]])( + 'should forward authorization header on cross-origin redirects when sendCredentialsOnCrossOriginRedirect is %s', + async (sendCredentialsOnCrossOriginRedirect) => { + nock(baseUrl).get('/redirect').reply(301, '', { Location: 'https://otherdomain.com/test' }); + nock('https://otherdomain.com') + .get('/test') + .reply(200, function () { + return this.req.headers; + }); + + const response = (await httpRequest({ + url: `${baseUrl}/redirect`, + auth: { + username: 'testuser', + password: 'testpassword', + }, + headers: { + 'X-Other-Header': 'otherHeaderContent', + }, + sendCredentialsOnCrossOriginRedirect, + })) as { authorization: string; 'x-other-header': string }; + + expect(response.authorization).toBe('Basic dGVzdHVzZXI6dGVzdHBhc3N3b3Jk'); + expect(response['x-other-header']).toBe('otherHeaderContent'); + }, + ); + + test('should not forward authorization header on cross-origin redirects when sendCredentialsOnCrossOriginRedirect is false', async () => { + nock(baseUrl).get('/redirect').reply(301, '', { Location: 'https://otherdomain.com/test' }); + nock('https://otherdomain.com') + .get('/test') + .reply(200, function () { + return this.req.headers; + }); + + const response = (await httpRequest({ + url: `${baseUrl}/redirect`, + auth: { + username: 'testuser', + password: 'testpassword', + }, + headers: { + 'X-Other-Header': 'otherHeaderContent', + }, + sendCredentialsOnCrossOriginRedirect: false, + })) as { authorization: undefined; 'x-other-header': string }; + + expect(response.authorization).toBeUndefined(); + expect(response['x-other-header']).toBe('otherHeaderContent'); + }); + + test.each([[undefined], [true], [false]])( + 'should forward authorization header on same-origin redirects when sendCredentialsOnCrossOriginRedirect is %s', + async (sendCredentialsOnCrossOriginRedirect) => { + nock(baseUrl) + .get('/redirect') + .reply(301, '', { Location: `${baseUrl}/test` }); + nock(baseUrl) + .get('/test') + .reply(200, function () { + return this.req.headers; + }); + + const response = (await httpRequest({ + url: `${baseUrl}/redirect`, + auth: { + username: 'testuser', + password: 'testpassword', + }, + headers: { + 'X-Other-Header': 'otherHeaderContent', + }, + sendCredentialsOnCrossOriginRedirect, + })) as { authorization: string; 'x-other-header': string }; + + expect(response.authorization).toBe('Basic dGVzdHVzZXI6dGVzdHBhc3N3b3Jk'); + expect(response['x-other-header']).toBe('otherHeaderContent'); + }, + ); + }); +}); + +describe('SSRF protection', () => { + const baseUrl = 'https://example.com'; + + const createSsrfBridge = (overrides?: Partial<SsrfBridge>): SsrfBridge => ({ + validateIp: vi.fn().mockReturnValue({ ok: true, result: undefined }), + validateUrl: vi.fn().mockResolvedValue({ ok: true, result: undefined }), + validateConnectionHost: vi.fn().mockReturnValue({ ok: true, result: undefined }), + validateRedirectSync: vi.fn(), + createSecureLookup: vi.fn().mockReturnValue(vi.fn()), + ...overrides, + }); + + beforeEach(() => { + nock.cleanAll(); + }); + + describe('convertN8nRequestToAxios with ssrfBridge', () => { + test('should inject secureLookup into agent options when no proxy', () => { + const lookupFn = vi.fn(); + const ssrfBridge = createSsrfBridge({ + createSecureLookup: vi.fn().mockReturnValue(lookupFn), + }); + + const axiosConfig = convertN8nRequestToAxios( + { method: 'GET', url: 'https://example.com/test' }, + ssrfBridge, + ); + + expect(ssrfBridge.createSecureLookup).toHaveBeenCalled(); + expect((axiosConfig.httpsAgent as HttpsAgent).options.lookup).toBe(lookupFn); + }); + + test('should NOT inject secureLookup when proxy is configured', () => { + const lookupFn = vi.fn(); + const ssrfBridge = createSsrfBridge({ + createSecureLookup: vi.fn().mockReturnValue(lookupFn), + }); + + const axiosConfig = convertN8nRequestToAxios( + { + method: 'GET', + url: 'https://example.com/test', + proxy: { host: 'my-proxy', port: 8080 }, + }, + ssrfBridge, + ); + + expect((axiosConfig.httpsAgent as HttpsAgent).options.lookup).toBeUndefined(); + }); + + test('should not inject secureLookup when ssrfBridge is absent', () => { + const axiosConfig = convertN8nRequestToAxios({ + method: 'GET', + url: 'https://example.com/test', + }); + + expect((axiosConfig.httpsAgent as HttpsAgent).options.lookup).toBeUndefined(); + }); + }); + + describe('domain allowlist enforcement', () => { + describe('httpRequest', () => { + test('should block requests to disallowed domains', async () => { + await expect( + httpRequest({ + method: 'GET', + url: `${baseUrl}/data`, + allowedDomains: 'other.com', + }), + ).rejects.toThrow('Domain not allowed'); + }); + + test.each([['example.com'], [undefined]])( + 'should allow requests to allowed domains when allowedDomains is %s', + async (allowedDomains) => { + nock(baseUrl).get('/data').reply(200, 'ok'); + + const response = await httpRequest({ + method: 'GET', + url: `${baseUrl}/data`, + allowedDomains, + }); + + expect(response).toEqual('ok'); + }, + ); + + test('should block redirects to disallowed domains', async () => { + nock(baseUrl).get('/redirect').reply(301, '', { Location: 'https://not-allowed.com/data' }); + nock('https://not-allowed.com').get('/data').reply(200, 'not-ok'); + + await expect( + httpRequest({ + method: 'GET', + url: `${baseUrl}/redirect`, + allowedDomains: 'example.com', + }), + ).rejects.toThrow('Domain not allowed'); + }); + + test.each([['example.com, allowed.com'], [undefined]])( + 'should allow redirects to allowed domains when allowedDomains is %s', + async (allowedDomains) => { + nock(baseUrl).get('/redirect').reply(301, '', { Location: 'https://allowed.com/data' }); + nock('https://allowed.com').get('/data').reply(200, 'ok'); + + const response = await httpRequest({ + method: 'GET', + url: `${baseUrl}/redirect`, + allowedDomains, + }); + + expect(response).toEqual('ok'); + }, + ); + + test('should support wildcard domains in allowedDomains', async () => { + nock('https://api.example.com').get('/data').reply(200, 'ok'); + + const response = await httpRequest({ + method: 'GET', + url: 'https://api.example.com/data', + allowedDomains: '*.example.com', + }); + + expect(response).toEqual('ok'); + }); + + test('should block wildcard domains that do not match', async () => { + await expect( + httpRequest({ + method: 'GET', + url: 'https://blocked.com/data', + allowedDomains: '*.example.com', + }), + ).rejects.toThrow('Domain not allowed'); + }); + }); + + describe('convertN8nRequestToAxios', () => { + test('should pass allowedDomains to beforeRedirect', () => { + const axiosConfig = convertN8nRequestToAxios({ + method: 'GET', + url: `${baseUrl}/test`, + allowedDomains: 'example.com', + }); + const redirectOptions = { + agents: {}, + hostname: 'not-allowed.com', + href: 'https://not-allowed.com/data', + }; + + expect(axiosConfig.beforeRedirect).toBeDefined(); + expect(() => axiosConfig.beforeRedirect!(redirectOptions, mock(), mock())).toThrow( + 'Domain not allowed', + ); + }); + + test.each([['example.com'], [undefined]])( + 'should not block redirects when allowedDomains is %s', + (allowedDomains) => { + const axiosConfig = convertN8nRequestToAxios({ + method: 'GET', + url: `${baseUrl}/test`, + allowedDomains, + }); + const redirectOptions = { + agents: {}, + hostname: 'example.com', + href: 'https://example.com/data', + }; + + expect(axiosConfig.beforeRedirect).toBeDefined(); + expect(() => axiosConfig.beforeRedirect!(redirectOptions, mock(), mock())).not.toThrow(); + }, + ); + }); + }); +}); diff --git a/packages/core/src/execution-engine/node-execution-context/utils/__tests__/outbound-user-agent.test.ts b/packages/@n8n/backend-network/src/http/axios/__tests__/user-agent.test.ts similarity index 96% rename from packages/core/src/execution-engine/node-execution-context/utils/__tests__/outbound-user-agent.test.ts rename to packages/@n8n/backend-network/src/http/axios/__tests__/user-agent.test.ts index 0a6594c274f..93f24c96a82 100644 --- a/packages/core/src/execution-engine/node-execution-context/utils/__tests__/outbound-user-agent.test.ts +++ b/packages/@n8n/backend-network/src/http/axios/__tests__/user-agent.test.ts @@ -2,7 +2,7 @@ import { HttpRequestConfig } from '@n8n/config'; import { Container } from '@n8n/di'; import * as nodePathActual from 'node:path'; -import { buildRfcStyleUserAgent, getDefaultN8nOutboundUserAgent } from '../outbound-user-agent'; +import { buildRfcStyleUserAgent, getDefaultN8nOutboundUserAgent } from '../user-agent'; describe('outbound-user-agent', () => { const originalConfig = new HttpRequestConfig(); @@ -69,7 +69,7 @@ describe('outbound-user-agent', () => { const di = await import('@n8n/di'); const config = await import('@n8n/config'); - const mod = await import('../outbound-user-agent'); + const mod = await import('../user-agent'); di.Container.set(config.HttpRequestConfig, { enforceGlobalUserAgent: true, diff --git a/packages/core/src/execution-engine/node-execution-context/utils/request-helpers/__tests__/axios-utils.test.ts b/packages/@n8n/backend-network/src/http/axios/__tests__/utils.test.ts similarity index 85% rename from packages/core/src/execution-engine/node-execution-context/utils/request-helpers/__tests__/axios-utils.test.ts rename to packages/@n8n/backend-network/src/http/axios/__tests__/utils.test.ts index 37a0254c3ea..154ef300081 100644 --- a/packages/core/src/execution-engine/node-execution-context/utils/request-helpers/__tests__/axios-utils.test.ts +++ b/packages/@n8n/backend-network/src/http/axios/__tests__/utils.test.ts @@ -1,8 +1,11 @@ +import { Logger } from '@n8n/backend-common'; +import { Container } from '@n8n/di'; import type { AxiosRequestConfig, AxiosResponse } from 'axios'; import FormData from 'form-data'; +import { mock } from 'vitest-mock-extended'; -import { createHttpProxyAgent, createHttpsProxyAgent } from '@/http-proxy'; - +import { makeSsrfBridge } from '../../../ssrf/__tests__/mock-ssrf-bridge'; +import { buildNodeAgents } from '../../node-agents'; import { buildTargetUrl, createFormDataObject, @@ -15,11 +18,18 @@ import { searchForHeader, setAxiosAgents, tryParseUrl, -} from '../axios-utils'; +} from '../utils'; -vi.mock('@/http-proxy', () => ({ - createHttpProxyAgent: vi.fn((_proxy, _url, opts) => ({ type: 'http', ...opts })), - createHttpsProxyAgent: vi.fn((_proxy, _url, opts) => ({ type: 'https', ...opts })), +// Agent construction is owned by `buildNodeAgents` (./factory). +// SSRF lookup injection is exercised there; here we only assert the transport +// policy (proxy + ssrf option) that the axios utils forward to it. +vi.mock('../../node-agents', () => ({ + buildNodeAgents: vi.fn((_proxy, _ssrf, opts) => ({ + httpAgent: { type: 'http', ...opts }, + httpsAgent: { type: 'https', ...opts }, + })), + isSupportedProxyUrl: (value: string) => + value.startsWith('http://') || value.startsWith('https://'), })); describe('isIgnoreStatusErrorConfig', () => { @@ -142,6 +152,7 @@ describe('getBeforeRedirectFn', () => { createSecureLookup: vi.fn().mockReturnValue(vi.fn()), validateIp: vi.fn(), validateUrl: vi.fn(), + validateConnectionHost: vi.fn(), }; const beforeRedirect = getBeforeRedirectFn( @@ -164,9 +175,8 @@ describe('getBeforeRedirectFn', () => { expect(ssrfBridge.validateRedirectSync).toHaveBeenCalledWith('https://example.com/other'); }); - test('should resolve proxy URL from proxyConfig and pass it to agent factories', () => { - vi.mocked(createHttpProxyAgent).mockClear(); - vi.mocked(createHttpsProxyAgent).mockClear(); + test('should resolve proxy URL from proxyConfig and pass it to buildNodeAgents', () => { + vi.mocked(buildNodeAgents).mockClear(); const beforeRedirect = getBeforeRedirectFn( agentOptions, @@ -183,14 +193,9 @@ describe('getBeforeRedirectFn', () => { beforeRedirect(redirectedRequest); - expect(createHttpProxyAgent).toHaveBeenCalledWith( + expect(buildNodeAgents).toHaveBeenCalledWith( 'http://proxy:8080', - 'https://example.com/other', - expect.objectContaining({ servername: 'example.com' }), - ); - expect(createHttpsProxyAgent).toHaveBeenCalledWith( - 'http://proxy:8080', - 'https://example.com/other', + 'disabled', expect.objectContaining({ servername: 'example.com' }), ); }); @@ -450,15 +455,14 @@ describe('setAxiosAgents', () => { vi.clearAllMocks(); }); - it('should set httpAgent and httpsAgent on config', () => { + it('should set httpAgent and httpsAgent on config (env proxy by default)', () => { const config: AxiosRequestConfig = { url: 'https://example.com/api' }; setAxiosAgents(config); expect(config.httpAgent).toEqual({ type: 'http' }); expect(config.httpsAgent).toEqual({ type: 'https' }); - expect(createHttpProxyAgent).toHaveBeenCalledWith(null, 'https://example.com/api', undefined); - expect(createHttpsProxyAgent).toHaveBeenCalledWith(null, 'https://example.com/api', undefined); + expect(buildNodeAgents).toHaveBeenCalledWith('env', 'disabled', undefined); }); it('should not override existing agents', () => { @@ -471,7 +475,7 @@ describe('setAxiosAgents', () => { setAxiosAgents(config); expect(config.httpAgent).toBe(existingAgent); - expect(createHttpProxyAgent).not.toHaveBeenCalled(); + expect(buildNodeAgents).not.toHaveBeenCalled(); }); it('should not set agents when url is missing', () => { @@ -483,39 +487,44 @@ describe('setAxiosAgents', () => { expect(config.httpsAgent).toBeUndefined(); }); - it('should pass proxy URL to agent factories', () => { + it('should pass a custom proxy URL through to buildNodeAgents', () => { const config: AxiosRequestConfig = { url: 'https://example.com' }; setAxiosAgents(config, undefined, 'http://proxy:8080'); - expect(createHttpProxyAgent).toHaveBeenCalledWith( - 'http://proxy:8080', - 'https://example.com', - undefined, - ); + expect(buildNodeAgents).toHaveBeenCalledWith('http://proxy:8080', 'disabled', undefined); }); - it('should inject secureLookup when no proxy is configured', () => { + it('should forward the ssrf option to buildNodeAgents when no proxy is configured', () => { const config: AxiosRequestConfig = { url: 'https://example.com' }; - const secureLookup = vi.fn(); + const ssrf = makeSsrfBridge(); - setAxiosAgents(config, {}, undefined, secureLookup as never); + setAxiosAgents(config, {}, undefined, ssrf); - expect(createHttpProxyAgent).toHaveBeenCalledWith(null, 'https://example.com', { - lookup: secureLookup, - }); + // SSRF lookup injection is buildNodeAgents' responsibility (env path + // applies it to direct connections only). + expect(buildNodeAgents).toHaveBeenCalledWith('env', ssrf, {}); }); - it('should not inject secureLookup when proxy is configured', () => { + it('should forward the ssrf option to buildNodeAgents when a proxy is configured', () => { const config: AxiosRequestConfig = { url: 'https://example.com' }; - const secureLookup = vi.fn(); + const ssrf = makeSsrfBridge(); - setAxiosAgents(config, {}, 'http://proxy:8080', secureLookup as never); + setAxiosAgents(config, {}, 'http://proxy:8080', ssrf); - expect(createHttpProxyAgent).toHaveBeenCalledWith( - 'http://proxy:8080', - 'https://example.com', - {}, - ); + // Behind a proxy, buildNodeAgents omits the lookup; the proxy validates + // the final target. + expect(buildNodeAgents).toHaveBeenCalledWith('http://proxy:8080', ssrf, {}); + }); + + it('should fall back to env proxy and warn on an unsupported proxy URL', () => { + const logger = mock<Logger>(); + Container.set(Logger, logger); + const config: AxiosRequestConfig = { url: 'https://example.com' }; + + setAxiosAgents(config, undefined, 'socks5://proxy:1080'); + + expect(buildNodeAgents).toHaveBeenCalledWith('env', 'disabled', undefined); + expect(logger.warn).toHaveBeenCalledWith(expect.stringContaining('socks5://proxy:1080')); }); }); diff --git a/packages/@n8n/backend-network/src/http/axios/config.ts b/packages/@n8n/backend-network/src/http/axios/config.ts new file mode 100644 index 00000000000..9e108a4d82f --- /dev/null +++ b/packages/@n8n/backend-network/src/http/axios/config.ts @@ -0,0 +1,56 @@ +import { AiConfig } from '@n8n/config'; +import { Container } from '@n8n/di'; +import axios from 'axios'; +import type { InternalAxiosRequestConfig } from 'axios'; +import { stringify } from 'qs'; + +import { setAxiosAgents } from './utils'; + +let configured = false; + +/** + * Applies n8n's global axios defaults. + * These are process-wide side effects. + * Calling it more than once is a no-op. + */ +export function configureGlobalAxiosDefaults(): void { + if (!configured) { + configured = true; + + // Global axios defaults + + axios.defaults.timeout = 300000; + // Prevent axios from adding x-form-www-urlencoded headers by default + axios.defaults.headers.post = {}; + axios.defaults.headers.put = {}; + axios.defaults.headers.patch = {}; + axios.defaults.paramsSerializer = (params) => { + if (params instanceof URLSearchParams) { + return params.toString(); + } + return stringify(params, { arrayFormat: 'indices' }); + }; + // Disable axios proxy, we handle it ourselves + // Axios proxy option has problems: https://github.com/axios/axios/issues/4531 + axios.defaults.proxy = false; + + // Interceptor + axios.interceptors.request.use((config) => { + // If no content-type is set by us, prevent axios from force-setting the content-type to `application/x-www-form-urlencoded` + if (config.data === undefined) { + config.headers.setContentType(false, false); + } + + setAxiosAgents(config); + applyVendorHeaders(config); + + return config; + }); + } +} + +function applyVendorHeaders(config: InternalAxiosRequestConfig) { + if ([config.url, config.baseURL].some((url) => url?.startsWith('https://api.openai.com/'))) { + config.headers.set(Container.get(AiConfig).openAiDefaultHeaders, false); + } +} diff --git a/packages/@n8n/backend-network/src/http/axios/legacy.ts b/packages/@n8n/backend-network/src/http/axios/legacy.ts new file mode 100644 index 00000000000..24bad5fb7e3 --- /dev/null +++ b/packages/@n8n/backend-network/src/http/axios/legacy.ts @@ -0,0 +1,327 @@ +/* eslint-disable @typescript-eslint/prefer-nullish-coalescing */ +/* eslint-disable @typescript-eslint/no-unsafe-call */ +/* eslint-disable @typescript-eslint/no-unsafe-assignment */ +/* eslint-disable @typescript-eslint/no-unsafe-return */ +/* eslint-disable @typescript-eslint/no-unsafe-member-access */ + +import type { AxiosHeaders, AxiosRequestConfig } from 'axios'; +import crypto from 'crypto'; +import type FormData from 'form-data'; +import { type AgentOptions } from 'https'; +import type { GenericValue, IRequestOptions } from 'n8n-workflow'; +import { stringify } from 'qs'; + +import { applyDefaultOutboundUserAgent } from './user-agent'; +import { + createFormDataObject, + generateContentLengthHeader, + getBeforeRedirectFn, + getHostFromRequestObject, + isFormDataInstance, + searchForHeader, + setAxiosAgents, +} from './utils'; +import type { SsrfBridge } from '../../ssrf'; + +/** + * This function is a temporary implementation that translates all http requests + * done via the request library to axios directly. + * We are not using n8n's interface as it would an unnecessary step, + * considering the `request` helper has been be deprecated and should be removed. + * @deprecated This is only used by legacy request helpers, that are also deprecated + */ +export async function buildAxiosConfigFromLegacyRequest( + requestObject: IRequestOptions, + ssrfBridge?: SsrfBridge, +): Promise<AxiosRequestConfig> { + const axiosConfig: AxiosRequestConfig = {}; + + if (requestObject.headers !== undefined) { + axiosConfig.headers = requestObject.headers as AxiosHeaders; + } + + // Let's start parsing the hardest part, which is the request body. + // The process here is as following? + // - Check if we have a `content-type` header. If this was set, + // we will follow + // - Check if the `form` property was set. If yes, then it's x-www-form-urlencoded + // - Check if the `formData` property exists. If yes, then it's multipart/form-data + // - Lastly, we should have a regular `body` that is probably a JSON. + + const contentTypeHeaderKeyName = + axiosConfig.headers && + Object.keys(axiosConfig.headers).find( + (headerName) => headerName.toLowerCase() === 'content-type', + ); + const contentType = + contentTypeHeaderKeyName && + (axiosConfig.headers?.[contentTypeHeaderKeyName] as string | undefined); + if (contentType === 'application/x-www-form-urlencoded' && requestObject.formData === undefined) { + // there are nodes incorrectly created, informing the content type header + // and also using formData. Request lib takes precedence for the formData. + // We will do the same. + // Merge body and form properties. + if (typeof requestObject.body === 'string') { + axiosConfig.data = requestObject.body; + } else { + const allData = Object.assign(requestObject.body || {}, requestObject.form || {}) as Record< + string, + string + >; + if (requestObject.useQuerystring === true) { + axiosConfig.data = stringify(allData, { arrayFormat: 'repeat' }); + } else { + axiosConfig.data = stringify(allData); + } + } + } else if (contentType?.includes('multipart/form-data')) { + if (requestObject.formData !== undefined && isFormDataInstance(requestObject.formData)) { + axiosConfig.data = requestObject.formData; + } else { + const allData: Partial<FormData> = { + ...(requestObject.body as object | undefined), + ...(requestObject.formData as object | undefined), + }; + + axiosConfig.data = createFormDataObject(allData); + } + // replace the existing header with a new one that + // contains the boundary property. + delete axiosConfig.headers?.[contentTypeHeaderKeyName!]; + + const headers = axiosConfig.data.getHeaders(); + + axiosConfig.headers = Object.assign(axiosConfig.headers || {}, headers); + await generateContentLengthHeader(axiosConfig); + } else { + // When using the `form` property it means the content should be x-www-form-urlencoded. + if (requestObject.form !== undefined && requestObject.body === undefined) { + // If we have only form + axiosConfig.data = + typeof requestObject.form === 'string' + ? requestObject.form + : stringify(requestObject.form).toString(); + if (axiosConfig.headers !== undefined) { + const headerName = searchForHeader(axiosConfig, 'content-type'); + if (headerName) { + delete axiosConfig.headers[headerName]; + } + axiosConfig.headers['Content-Type'] = 'application/x-www-form-urlencoded'; + } else { + axiosConfig.headers = { + 'Content-Type': 'application/x-www-form-urlencoded', + }; + } + } else if (requestObject.formData !== undefined) { + // remove any "content-type" that might exist. + if (axiosConfig.headers !== undefined) { + const headers = Object.keys(axiosConfig.headers); + headers.forEach((header) => { + if (header.toLowerCase() === 'content-type') { + delete axiosConfig.headers?.[header]; + } + }); + } + + if (isFormDataInstance(requestObject.formData)) { + axiosConfig.data = requestObject.formData; + } else { + axiosConfig.data = createFormDataObject(requestObject.formData as Record<string, unknown>); + } + // Mix in headers as FormData creates the boundary. + + const headers = axiosConfig.data.getHeaders(); + + axiosConfig.headers = Object.assign(axiosConfig.headers || {}, headers); + await generateContentLengthHeader(axiosConfig); + } else if (requestObject.body !== undefined) { + // If we have body and possibly form + if (requestObject.form !== undefined && requestObject.body) { + // merge both objects when exist. + + requestObject.body = Object.assign(requestObject.body, requestObject.form); + } + axiosConfig.data = requestObject.body as FormData | GenericValue | GenericValue[]; + } + } + + if (requestObject.uri !== undefined) { + axiosConfig.url = requestObject.uri?.toString(); + } + + if (requestObject.url !== undefined) { + axiosConfig.url = requestObject.url?.toString(); + } + + if (requestObject.baseURL !== undefined) { + axiosConfig.baseURL = requestObject.baseURL?.toString(); + } + + if (requestObject.method !== undefined) { + axiosConfig.method = requestObject.method; + } + + if (requestObject.qs !== undefined && Object.keys(requestObject.qs as object).length > 0) { + axiosConfig.params = requestObject.qs; + } + + function hasArrayFormatOptions( + arg: IRequestOptions, + ): arg is Required<Pick<IRequestOptions, 'qsStringifyOptions'>> { + if ( + typeof arg.qsStringifyOptions === 'object' && + arg.qsStringifyOptions !== null && + !Array.isArray(arg.qsStringifyOptions) && + 'arrayFormat' in arg.qsStringifyOptions + ) { + return true; + } + + return false; + } + + if ( + requestObject.useQuerystring === true || + (hasArrayFormatOptions(requestObject) && + requestObject.qsStringifyOptions.arrayFormat === 'repeat') + ) { + axiosConfig.paramsSerializer = (params) => { + return stringify(params, { arrayFormat: 'repeat' }); + }; + } else if (requestObject.useQuerystring === false) { + axiosConfig.paramsSerializer = (params) => { + return stringify(params, { arrayFormat: 'indices' }); + }; + } + + if ( + hasArrayFormatOptions(requestObject) && + requestObject.qsStringifyOptions.arrayFormat === 'brackets' + ) { + axiosConfig.paramsSerializer = (params) => { + return stringify(params, { arrayFormat: 'brackets' }); + }; + } + + if (requestObject.auth !== undefined) { + // Check support for sendImmediately + if (requestObject.auth.bearer !== undefined) { + axiosConfig.headers = Object.assign(axiosConfig.headers || {}, { + Authorization: `Bearer ${requestObject.auth.bearer}`, + }); + } else { + const authObj = requestObject.auth; + // Request accepts both user/username and pass/password + axiosConfig.auth = { + username: (authObj.user || authObj.username) as string, + + password: (authObj.password || authObj.pass) as string, + }; + } + } + + // Only set header if we have a body, otherwise it may fail + if (requestObject.json === true) { + // Add application/json headers - do not set charset as it breaks a lot of stuff + // only add if no other accept headers was sent. + const acceptHeaderExists = + axiosConfig.headers === undefined + ? false + : Object.keys(axiosConfig.headers) + .map((headerKey) => headerKey.toLowerCase()) + .includes('accept'); + if (!acceptHeaderExists) { + axiosConfig.headers = Object.assign(axiosConfig.headers || {}, { + Accept: 'application/json', + }); + } + } + if (requestObject.json === false || requestObject.json === undefined) { + // Prevent json parsing + + axiosConfig.transformResponse = (res) => res; + } + + // Axios will follow redirects by default, so we simply tell it otherwise if needed. + const { method } = requestObject; + if ( + (requestObject.followRedirect !== false && + (!method || method === 'GET' || method === 'HEAD')) || + requestObject.followAllRedirects + ) { + axiosConfig.maxRedirects = requestObject.maxRedirects; + } else { + axiosConfig.maxRedirects = 0; + } + + const host = getHostFromRequestObject(requestObject); + const agentOptions: AgentOptions = { ...requestObject.agentOptions }; + if (host) { + agentOptions.servername = host; + } + if (requestObject.rejectUnauthorized === false) { + agentOptions.rejectUnauthorized = false; + agentOptions.secureOptions = crypto.constants.SSL_OP_LEGACY_SERVER_CONNECT; + } + + if (requestObject.timeout !== undefined) { + axiosConfig.timeout = requestObject.timeout; + } + + setAxiosAgents(axiosConfig, agentOptions, requestObject.proxy, ssrfBridge ?? 'disabled'); + + axiosConfig.beforeRedirect = getBeforeRedirectFn( + agentOptions, + axiosConfig, + requestObject.proxy, + requestObject.sendCredentialsOnCrossOriginRedirect ?? true, + requestObject.allowedDomains, + ssrfBridge ?? 'disabled', + ); + + if (requestObject.useStream) { + axiosConfig.responseType = 'stream'; + } else if (requestObject.encoding === null) { + // When downloading files, return an arrayBuffer. + axiosConfig.responseType = 'arraybuffer'; + } + + // If we don't set an accept header + // Axios forces "application/json, text/plan, */*" + // Which causes some nodes like NextCloud to break + // as the service returns XML unless requested otherwise. + const allHeaders = axiosConfig.headers ? Object.keys(axiosConfig.headers) : []; + if (!allHeaders.some((headerKey) => headerKey.toLowerCase() === 'accept')) { + axiosConfig.headers = Object.assign(axiosConfig.headers || {}, { accept: '*/*' }); + } + if ( + requestObject.json !== false && + axiosConfig.data !== undefined && + axiosConfig.data !== '' && + !(axiosConfig.data instanceof Buffer) && + !allHeaders.some((headerKey) => headerKey.toLowerCase() === 'content-type') + ) { + // Use default header for application/json + // If we don't specify this here, axios will add + // application/json; charset=utf-8 + // and this breaks a lot of stuff + + axiosConfig.headers = Object.assign(axiosConfig.headers || {}, { + 'content-type': 'application/json', + }); + } + + if (requestObject.simple === false) { + axiosConfig.validateStatus = () => true; + } + + applyDefaultOutboundUserAgent(axiosConfig); + + /** + * Missing properties: + * encoding (need testing) + * gzip (ignored - default already works) + * resolveWithFullResponse (implemented elsewhere) + */ + return axiosConfig; +} diff --git a/packages/@n8n/backend-network/src/http/axios/request.ts b/packages/@n8n/backend-network/src/http/axios/request.ts new file mode 100644 index 00000000000..700607e3cd8 --- /dev/null +++ b/packages/@n8n/backend-network/src/http/axios/request.ts @@ -0,0 +1,243 @@ +/* eslint-disable @typescript-eslint/no-unsafe-call */ + +import type { AxiosRequestConfig } from 'axios'; +import axios from 'axios'; +import type { AgentOptions } from 'https'; +import type { + IHttpRequestOptions, + IN8nHttpFullResponse, + IN8nHttpResponse, + IRequestOptions, +} from 'n8n-workflow'; +import { isObjectEmpty } from 'n8n-workflow'; +import { stringify } from 'qs'; + +import { applyDefaultOutboundUserAgent } from './user-agent'; +import { + buildTargetUrl, + digestAuthAxiosConfig, + getBeforeRedirectFn, + getHostFromRequestObject, + isFormDataInstance, + isIgnoreStatusErrorConfig, + searchForHeader, + setAxiosAgents, + throwIfDomainNotAllowed, + validateUrlSsrf, +} from './utils'; +import type { SsrfBridge } from '../../ssrf'; + +export async function invokeAxios( + axiosConfig: AxiosRequestConfig, + authOptions: IRequestOptions['auth'] = {}, +) { + try { + return await axios(axiosConfig); + } catch (error) { + if (authOptions.sendImmediately !== false || !(error instanceof axios.AxiosError)) throw error; + // for digest-auth + const { response } = error; + if (response?.status !== 401 || !response.headers['www-authenticate']?.includes('nonce')) { + throw error; + } + const { auth } = axiosConfig; + delete axiosConfig.auth; + axiosConfig = digestAuthAxiosConfig(axiosConfig, response, auth); + return await axios(axiosConfig); + } +} + +export function convertN8nRequestToAxios( + n8nRequest: IHttpRequestOptions, + ssrfBridge?: SsrfBridge, +): AxiosRequestConfig { + // Destructure properties with the same name first. + const { headers, method, timeout, auth, proxy, url } = n8nRequest; + + const axiosRequest: AxiosRequestConfig = { + headers: headers ?? {}, + method, + timeout, + auth, + url, + maxBodyLength: Infinity, + maxContentLength: Infinity, + } as AxiosRequestConfig; + + axiosRequest.params = n8nRequest.qs; + + if (n8nRequest.abortSignal) { + axiosRequest.signal = n8nRequest.abortSignal; + } + + if (n8nRequest.baseURL !== undefined) { + axiosRequest.baseURL = n8nRequest.baseURL; + } + + if (n8nRequest.disableFollowRedirect === true) { + axiosRequest.maxRedirects = 0; + } + + if (n8nRequest.encoding !== undefined) { + axiosRequest.responseType = n8nRequest.encoding; + } + + const host = getHostFromRequestObject(n8nRequest); + const agentOptions: AgentOptions = { ...n8nRequest.agentOptions }; + if (host) { + agentOptions.servername = host; + } + if (n8nRequest.skipSslCertificateValidation === true) { + agentOptions.rejectUnauthorized = false; + } + setAxiosAgents(axiosRequest, agentOptions, proxy, ssrfBridge ?? 'disabled'); + + axiosRequest.beforeRedirect = getBeforeRedirectFn( + agentOptions, + axiosRequest, + n8nRequest.proxy, + n8nRequest.sendCredentialsOnCrossOriginRedirect ?? true, + n8nRequest.allowedDomains, + ssrfBridge ?? 'disabled', + ); + + if (n8nRequest.arrayFormat !== undefined) { + axiosRequest.paramsSerializer = (params) => { + return stringify(params, { arrayFormat: n8nRequest.arrayFormat }); + }; + } + + const { body } = n8nRequest; + if (body) { + // Let's add some useful header standards here. + const existingContentTypeHeaderKey = searchForHeader(axiosRequest, 'content-type'); + if (existingContentTypeHeaderKey === undefined) { + axiosRequest.headers = axiosRequest.headers || {}; + // We are only setting content type headers if the user did + // not set it already manually. We're not overriding, even if it's wrong. + if (isFormDataInstance(body)) { + axiosRequest.headers = { + ...axiosRequest.headers, + ...body.getHeaders(), + }; + } else if (body instanceof URLSearchParams) { + axiosRequest.headers['Content-Type'] = 'application/x-www-form-urlencoded'; + } + } else if ( + axiosRequest.headers?.[existingContentTypeHeaderKey] === 'application/x-www-form-urlencoded' + ) { + axiosRequest.data = new URLSearchParams(n8nRequest.body as Record<string, string>); + } + // if there is a body and it's empty (does not have properties), + // make sure not to send anything in it as some services fail when + // sending GET request with empty body. + if (typeof body === 'string' || (typeof body === 'object' && !isObjectEmpty(body))) { + axiosRequest.data = body; + } + } + + if (n8nRequest.json) { + const key = searchForHeader(axiosRequest, 'accept'); + // If key exists, then the user has set both accept + // header and the json flag. Header should take precedence. + if (!key) { + axiosRequest.headers = { + ...axiosRequest.headers, + Accept: 'application/json', + }; + } + } + + applyDefaultOutboundUserAgent(axiosRequest); + + if (n8nRequest.ignoreHttpStatusErrors) { + const ignoreHttpStatusErrors = n8nRequest.ignoreHttpStatusErrors; + if (isIgnoreStatusErrorConfig(ignoreHttpStatusErrors)) { + axiosRequest.validateStatus = (status) => { + return !ignoreHttpStatusErrors.except.includes(status); + }; + } else { + axiosRequest.validateStatus = () => true; + } + } + + return axiosRequest; +} + +const NoBodyHttpMethods = ['GET', 'HEAD', 'OPTIONS']; + +/** + * Checks whether a request body should be considered empty. + */ +function isEmpty(value: unknown): boolean { + if (value === null || value === undefined) { + return true; + } + if (typeof value === 'string' || Array.isArray(value) || Buffer.isBuffer(value)) { + return value.length === 0; + } + if (typeof value === 'object') { + return Object.keys(value).length === 0; + } + return false; +} + +/** Remove empty request body on GET, HEAD, and OPTIONS requests */ +export function removeEmptyBody(requestOptions: IHttpRequestOptions | IRequestOptions) { + const method = requestOptions.method || 'GET'; + if (NoBodyHttpMethods.includes(method) && isEmpty(requestOptions.body)) { + delete requestOptions.body; + } +} + +/** + * @deprecated Prefer the package's single entry point: + * `Container.get(OutboundHttp).requests({ ssrf }).request(options)`. + * Kept exported for callers not yet migrated to the facade. + */ +export async function httpRequest( + requestOptions: IHttpRequestOptions & { returnFullResponse: true }, + ssrfBridge?: SsrfBridge, +): Promise<IN8nHttpFullResponse>; +export async function httpRequest( + requestOptions: IHttpRequestOptions & { returnFullResponse?: false }, + ssrfBridge?: SsrfBridge, +): Promise<IN8nHttpResponse>; +export async function httpRequest( + requestOptions: IHttpRequestOptions, + ssrfBridge?: SsrfBridge, +): Promise<IN8nHttpFullResponse | IN8nHttpResponse>; +export async function httpRequest( + requestOptions: IHttpRequestOptions, + ssrfBridge?: SsrfBridge, +): Promise<IN8nHttpFullResponse | IN8nHttpResponse> { + removeEmptyBody(requestOptions); + + const url = buildTargetUrl(requestOptions.url, requestOptions.baseURL) ?? requestOptions.url; + await validateUrlSsrf(url, ssrfBridge); + + const axiosRequest = convertN8nRequestToAxios(requestOptions, ssrfBridge); + if ( + axiosRequest.data === undefined || + (axiosRequest.method !== undefined && axiosRequest.method.toUpperCase() === 'GET') + ) { + delete axiosRequest.data; + } + + throwIfDomainNotAllowed(axiosRequest, requestOptions.allowedDomains); + + const result = await invokeAxios(axiosRequest, requestOptions.auth); + + if (requestOptions.returnFullResponse) { + return { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + body: result.data, + headers: result.headers, + statusCode: result.status, + statusMessage: result.statusText, + }; + } + + // eslint-disable-next-line @typescript-eslint/no-unsafe-return + return result.data; +} diff --git a/packages/core/src/execution-engine/node-execution-context/utils/outbound-user-agent.ts b/packages/@n8n/backend-network/src/http/axios/user-agent.ts similarity index 97% rename from packages/core/src/execution-engine/node-execution-context/utils/outbound-user-agent.ts rename to packages/@n8n/backend-network/src/http/axios/user-agent.ts index bf7ec439620..be6ac82205a 100644 --- a/packages/core/src/execution-engine/node-execution-context/utils/outbound-user-agent.ts +++ b/packages/@n8n/backend-network/src/http/axios/user-agent.ts @@ -3,7 +3,7 @@ import { Container } from '@n8n/di'; import type { AxiosRequestConfig } from 'axios'; import { join } from 'node:path'; -import { searchForHeader } from './request-helpers'; +import { searchForHeader } from './utils'; const N8N_PRODUCT_URL = 'https://n8n.io/'; const LEGACY_USER_AGENT = 'n8n'; diff --git a/packages/core/src/execution-engine/node-execution-context/utils/request-helpers/axios-utils.ts b/packages/@n8n/backend-network/src/http/axios/utils.ts similarity index 81% rename from packages/core/src/execution-engine/node-execution-context/utils/request-helpers/axios-utils.ts rename to packages/@n8n/backend-network/src/http/axios/utils.ts index a48343e378c..5de4f92133e 100644 --- a/packages/core/src/execution-engine/node-execution-context/utils/request-helpers/axios-utils.ts +++ b/packages/@n8n/backend-network/src/http/axios/utils.ts @@ -8,11 +8,13 @@ import type { AgentOptions } from 'https'; import { assertUrlAllowed, type IHttpRequestOptions, + type IRequestOptions, type IgnoreStatusErrorConfig, } from 'n8n-workflow'; -import type { SsrfBridge } from '@/execution-engine'; -import { createHttpProxyAgent, createHttpsProxyAgent } from '@/http-proxy'; +import type { SsrfBridge } from '../../ssrf'; +import { buildNodeAgents, isSupportedProxyUrl } from '../node-agents'; +import type { ProxyOption, SsrfOption } from '../node-agents'; export function throwIfDomainNotAllowed( configOrUrl: AxiosRequestConfig | string, @@ -70,6 +72,26 @@ export const getHostFromRequestObject = ( } }; +/** + * Resolves a custom proxy URL (a runtime string) into a {@link ProxyOption}. + * Falls back to `'env'` when no custom proxy is configured, + * or when the configured value is not a supported proxy URL. + */ +function resolveProxyOption(customProxyUrl: string | null): ProxyOption { + if (!customProxyUrl) { + return 'env'; + } + + if (isSupportedProxyUrl(customProxyUrl)) { + return customProxyUrl; + } + + Container.get(Logger).warn( + `Ignoring unsupported proxy URL "${customProxyUrl}", falling back to environment proxy settings`, + ); + return 'env'; +} + /* eslint-disable @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access */ /** Returns an axios `beforeRedirect` callback that re-applies agents and auth headers. */ @@ -80,14 +102,14 @@ export const getBeforeRedirectFn = proxyConfig: IHttpRequestOptions['proxy'] | string | undefined, sendCredentialsOnCrossOriginRedirect: boolean, allowedDomains?: string, - ssrfBridge?: SsrfBridge, + ssrf: SsrfOption = 'disabled', ) => (redirectedRequest: Record<string, any>) => { throwIfDomainNotAllowed(redirectedRequest.href, allowedDomains); // SSRF: validate redirect target synchronously for direct-IP URIs. // Hostname-based redirect targets are caught by secureLookup on the agent. - if (ssrfBridge) { - ssrfBridge.validateRedirectSync(redirectedRequest.href); + if (ssrf !== 'disabled') { + ssrf.validateRedirectSync(redirectedRequest.href); } const redirectAgentOptions: AgentOptions = { @@ -95,17 +117,12 @@ export const getBeforeRedirectFn = servername: redirectedRequest.hostname, }; const customProxyUrl = proxyConfig ? getUrlFromProxyConfig(proxyConfig) : null; + const proxy = resolveProxyOption(customProxyUrl); - // Inject secureLookup into redirect agents for non-proxy paths - const effectiveRedirectOptions = - ssrfBridge && !customProxyUrl - ? { ...redirectAgentOptions, lookup: ssrfBridge.createSecureLookup() } - : redirectAgentOptions; - - // Create both agents and set them + // SSRF lookup is applied to direct connections only; behind a proxy the + // proxy validates the final target. const targetUrl = redirectedRequest.href; - const httpAgent = createHttpProxyAgent(customProxyUrl, targetUrl, effectiveRedirectOptions); - const httpsAgent = createHttpsProxyAgent(customProxyUrl, targetUrl, effectiveRedirectOptions); + const { httpAgent, httpsAgent } = buildNodeAgents(proxy, ssrf, redirectAgentOptions); redirectedRequest.agent = redirectedRequest.href.startsWith('https://') ? httpsAgent @@ -291,22 +308,42 @@ export function setAxiosAgents( config: AxiosRequestConfig, agentOptions?: AgentOptions, proxyConfig?: IHttpRequestOptions['proxy'] | string, - secureLookup?: ReturnType<SsrfBridge['createSecureLookup']>, + ssrf: SsrfOption = 'disabled', ): void { if (config.httpAgent || config.httpsAgent) return; - const customProxyUrl = getUrlFromProxyConfig(proxyConfig); - const targetUrl = buildTargetUrl(config.url, config.baseURL); if (!targetUrl) return; - // Inject secureLookup only for non-proxy agents. When a proxy is used, - // the lookup option applies to resolving the proxy server hostname, not - // the target. Pre-request validateUrl covers the proxy path. - const effectiveOptions = - secureLookup && !customProxyUrl ? { ...agentOptions, lookup: secureLookup } : agentOptions; + const customProxyUrl = proxyConfig ? getUrlFromProxyConfig(proxyConfig) : null; + const proxy = resolveProxyOption(customProxyUrl); - config.httpAgent = createHttpProxyAgent(customProxyUrl, targetUrl, effectiveOptions); - config.httpsAgent = createHttpsProxyAgent(customProxyUrl, targetUrl, effectiveOptions); + // SSRF lookup is applied to direct connections only; behind a proxy the + // proxy validates the final target. + const { httpAgent, httpsAgent } = buildNodeAgents(proxy, ssrf, agentOptions); + config.httpAgent = httpAgent; + config.httpsAgent = httpsAgent; +} + +/** Validates a URL against SSRF protection rules. Throws UserError if blocked. */ +export async function validateUrlSsrf( + url: string | undefined, + ssrfBridge?: SsrfBridge, +): Promise<void> { + if (!ssrfBridge || !url) return; + + const parsed = tryParseUrl(url); + if (!parsed) return; + + const result = await ssrfBridge.validateUrl(parsed); + if (!result.ok) { + throw result.error; + } +} + +export function resolveLegacyRequestUrl(requestObject: IRequestOptions): string | undefined { + const rawUrl = requestObject.uri?.toString() ?? requestObject.url?.toString(); + const baseURL = requestObject.baseURL?.toString(); + return buildTargetUrl(rawUrl, baseURL) ?? rawUrl; } diff --git a/packages/@n8n/backend-network/src/http/binary-buffer.ts b/packages/@n8n/backend-network/src/http/binary-buffer.ts new file mode 100644 index 00000000000..703b826c288 --- /dev/null +++ b/packages/@n8n/backend-network/src/http/binary-buffer.ts @@ -0,0 +1,22 @@ +import { UnexpectedError } from 'n8n-workflow'; +import type { Readable } from 'stream'; + +/** Converts a readable stream to a buffer */ +export async function streamToBuffer(stream: Readable): Promise<Buffer> { + return await new Promise<Buffer>((resolve, reject) => { + const chunks: Buffer[] = []; + stream.on('data', (chunk: Buffer) => chunks.push(chunk)); + stream.on('end', () => resolve(Buffer.concat(chunks))); + stream.once('error', (cause) => { + if ('code' in cause && cause.code === 'Z_DATA_ERROR') + reject(new UnexpectedError('Failed to decompress response', { cause })); + else reject(cause); + }); + }); +} + +/** Converts a buffer or a readable stream to a buffer */ +export async function binaryToBuffer(body: Buffer | Readable): Promise<Buffer> { + if (Buffer.isBuffer(body)) return body; + return await streamToBuffer(body); +} diff --git a/packages/@n8n/backend-network/src/http/binary-string.ts b/packages/@n8n/backend-network/src/http/binary-string.ts new file mode 100644 index 00000000000..094ab36ab28 --- /dev/null +++ b/packages/@n8n/backend-network/src/http/binary-string.ts @@ -0,0 +1,19 @@ +import { IncomingMessage } from 'http'; +import { decode } from 'iconv-lite'; +import type { Readable } from 'stream'; + +import { binaryToBuffer } from './binary-buffer'; +import { parseIncomingMessage } from './parse-incoming-message'; + +/** + * Decodes a buffer or stream into a string, resolving the character encoding + * from an `IncomingMessage`'s content-type when no explicit encoding is given. + */ +export async function binaryToString(body: Buffer | Readable, encoding?: string) { + if (!encoding && body instanceof IncomingMessage) { + parseIncomingMessage(body); + encoding = body.encoding; + } + const buffer = await binaryToBuffer(body); + return decode(buffer, encoding ?? 'utf-8'); +} diff --git a/packages/@n8n/backend-network/src/http/env-proxy-http-agent.ts b/packages/@n8n/backend-network/src/http/env-proxy-http-agent.ts new file mode 100644 index 00000000000..1648e6a4d83 --- /dev/null +++ b/packages/@n8n/backend-network/src/http/env-proxy-http-agent.ts @@ -0,0 +1,42 @@ +import { HttpProxyAgent } from 'http-proxy-agent'; +import http from 'node:http'; +import type { LookupFunction } from 'node:net'; + +import { EnvProxyRouter } from './env-proxy-router'; +import type { NodeAgentOptions } from './node-agents'; + +type HttpAddRequestArgs = Parameters<HttpProxyAgent<string>['addRequest']>; +type HttpProxyClientReq = HttpAddRequestArgs[0]; +type HttpProxyReqOpts = HttpAddRequestArgs[1]; + +/** + * `http.Agent` that delegates per-request env-proxy routing and caching to a shared {@link EnvProxyRouter}. + * + * The optional SSRF `lookup` is applied to the direct path only + * (behind a proxy it would resolve the proxy host, so the proxy validates the target). + * + * Also backs `installGlobalProxyAgent` (http-proxy.ts), keeping a single env-proxy agent implementation. + */ +export class EnvProxyHttpAgent extends http.Agent { + private readonly router: EnvProxyRouter<HttpProxyAgent<string>>; + + constructor(lookup?: LookupFunction, agentOptions?: NodeAgentOptions) { + super({ ...agentOptions, lookup }); + this.router = new EnvProxyRouter( + 'http', + 80, + (proxyUrl) => new HttpProxyAgent(proxyUrl, { ...agentOptions }), + ); + } + + addRequest(req: http.ClientRequest, options: http.RequestOptions): void { + const proxyAgent = this.router.resolve(options); + + if (proxyAgent) { + return proxyAgent.addRequest(req as HttpProxyClientReq, options as HttpProxyReqOpts); + } + + // No proxy for this target: serve it directly from this agent's own pool. + super.addRequest(req, options); + } +} diff --git a/packages/@n8n/backend-network/src/http/env-proxy-https-agent.ts b/packages/@n8n/backend-network/src/http/env-proxy-https-agent.ts new file mode 100644 index 00000000000..e457ef03441 --- /dev/null +++ b/packages/@n8n/backend-network/src/http/env-proxy-https-agent.ts @@ -0,0 +1,36 @@ +import { HttpsProxyAgent } from 'https-proxy-agent'; +import type http from 'node:http'; +import https from 'node:https'; +import type { LookupFunction } from 'node:net'; + +import { EnvProxyRouter } from './env-proxy-router'; +import type { NodeAgentOptions } from './node-agents'; + +type HttpsProxyReqOpts = Parameters<HttpsProxyAgent<string>['addRequest']>[1]; + +/** + * `https.Agent` counterpart of {@link EnvProxyHttpAgent} + */ +export class EnvProxyHttpsAgent extends https.Agent { + private readonly router: EnvProxyRouter<HttpsProxyAgent<string>>; + + constructor(lookup?: LookupFunction, agentOptions?: NodeAgentOptions) { + super({ ...agentOptions, lookup }); + this.router = new EnvProxyRouter( + 'https', + 443, + (proxyUrl) => new HttpsProxyAgent(proxyUrl, { ...agentOptions }), + ); + } + + addRequest(req: http.ClientRequest, options: https.RequestOptions): void { + const proxyAgent = this.router.resolve(options); + + if (proxyAgent) { + return proxyAgent.addRequest(req, options as HttpsProxyReqOpts); + } + + // No proxy for this target: serve it directly from this agent's own pool. + super.addRequest(req, options); + } +} diff --git a/packages/@n8n/backend-network/src/http/env-proxy-router.ts b/packages/@n8n/backend-network/src/http/env-proxy-router.ts new file mode 100644 index 00000000000..07fbd3ef7df --- /dev/null +++ b/packages/@n8n/backend-network/src/http/env-proxy-router.ts @@ -0,0 +1,76 @@ +import { Logger } from '@n8n/backend-common'; +import { Container } from '@n8n/di'; +import type http from 'node:http'; +import { getProxyForUrl } from 'proxy-from-env'; + +const MAX_CACHED_AGENTS = 64; + +/** + * Per-request env-proxy routing. + * + * Owns the single per-proxy-URL agent cache and resolves each request target + * against the environment (HTTP_PROXY / HTTPS_PROXY / NO_PROXY) for its scheme. + * + * @typeParam TProxyAgent - the proxy-agent type for this scheme (`HttpProxyAgent` or `HttpsProxyAgent`). + */ +export class EnvProxyRouter<TProxyAgent> { + private readonly proxyCache = new Map<string, TProxyAgent>(); + + // Defensive upper bound on cached agents. Normally unreachable: the cache is keyed by the *proxy* URL. + private cacheLimitWarned = false; + + constructor( + private readonly scheme: 'http' | 'https', + private readonly defaultPort: number, + private readonly createProxyAgent: (proxyUrl: string) => TProxyAgent, + ) {} + + /** + * Resolves the request target to the proxy agent it should be dispatched through. + */ + resolve(options: http.RequestOptions): TProxyAgent | undefined { + const hostname = String(options.hostname ?? options.host ?? 'localhost'); + const port = this.resolvePort(options.port); + const portSuffix = port === this.defaultPort ? '' : `:${port}`; + const proxyUrl = getProxyForUrl(`${this.scheme}://${hostname}${portSuffix}`); + + if (!proxyUrl) { + return undefined; + } + + const cached = this.proxyCache.get(proxyUrl); + if (cached) { + return cached; + } + + const agent = this.createProxyAgent(proxyUrl); + this.cacheAgent(proxyUrl, agent); + return agent; + } + + private cacheAgent(proxyUrl: string, agent: TProxyAgent): void { + if (this.proxyCache.size >= MAX_CACHED_AGENTS) { + if (!this.cacheLimitWarned) { + this.cacheLimitWarned = true; + Container.get(Logger).warn( + `${this.scheme} proxy agent cache reached its limit of ${MAX_CACHED_AGENTS} entries; not caching further proxy agents. This is unexpected and likely indicates a misconfiguration.`, + ); + } + } else { + this.proxyCache.set(proxyUrl, agent); + } + } + + private resolvePort(rawPort: http.RequestOptions['port']): number { + const parsed = typeof rawPort === 'string' ? parseInt(rawPort, 10) : rawPort; + if (Number.isInteger(parsed)) { + return parsed as number; + } + if (rawPort !== undefined && rawPort !== null) { + Container.get(Logger).warn( + `Unparseable port "${String(rawPort)}" for ${this.scheme} proxy routing, falling back to default port ${this.defaultPort}`, + ); + } + return this.defaultPort; + } +} diff --git a/packages/@n8n/backend-network/src/http/http-proxy.ts b/packages/@n8n/backend-network/src/http/http-proxy.ts new file mode 100644 index 00000000000..004c50daffa --- /dev/null +++ b/packages/@n8n/backend-network/src/http/http-proxy.ts @@ -0,0 +1,80 @@ +import http from 'http'; +import { HttpProxyAgent } from 'http-proxy-agent'; +import https from 'https'; +import { HttpsProxyAgent } from 'https-proxy-agent'; +import { LoggerProxy } from 'n8n-workflow'; +import { getProxyForUrl } from 'proxy-from-env'; + +import { EnvProxyHttpAgent } from './env-proxy-http-agent'; +import { EnvProxyHttpsAgent } from './env-proxy-https-agent'; + +/** + * Resolves the proxy URL configured via environment variables + * (HTTP_PROXY, HTTPS_PROXY, NO_PROXY, etc.) for a given target URL. + * + * @param targetUrl - The target URL the request will be sent to. + * @returns The proxy URL to use, or undefined if no proxy applies. + */ +export function resolveProxyUrl(targetUrl: string): string | undefined { + return getProxyForUrl(targetUrl) || undefined; +} + +export function createHttpProxyAgent( + customProxyUrl: string | null = null, + targetUrl: string, + options?: http.AgentOptions, +): http.Agent { + const proxyUrl = customProxyUrl ?? getProxyForUrl(targetUrl); + + if (proxyUrl) { + return new HttpProxyAgent(proxyUrl, options); + } + + return new http.Agent(options); +} + +export function createHttpsProxyAgent( + customProxyUrl: string | null = null, + targetUrl: string, + options?: https.AgentOptions, +): https.Agent { + const proxyUrl = customProxyUrl ?? getProxyForUrl(targetUrl); + + if (proxyUrl) { + return new HttpsProxyAgent(proxyUrl, options); + } + + return new https.Agent(options); +} + +function hasProxyEnvironmentVariables(): boolean { + return Boolean( + process.env.HTTP_PROXY ?? + process.env.http_proxy ?? + process.env.HTTPS_PROXY ?? + process.env.https_proxy ?? + process.env.ALL_PROXY ?? + process.env.all_proxy, + ); +} + +export function installGlobalProxyAgent(): void { + if (hasProxyEnvironmentVariables()) { + LoggerProxy.debug('Installing global HTTP proxy agents', { + HTTP_PROXY: process.env.HTTP_PROXY ?? process.env.http_proxy, + HTTPS_PROXY: process.env.HTTPS_PROXY ?? process.env.https_proxy, + NO_PROXY: process.env.NO_PROXY ?? process.env.no_proxy, + ALL_PROXY: process.env.ALL_PROXY ?? process.env.all_proxy, + }); + + // Reuse the factory's env-proxy agents (no SSRF lookup at the global level; + // per-request SSRF enforcement is applied by the outbound HTTP client). + http.globalAgent = new EnvProxyHttpAgent(); + https.globalAgent = new EnvProxyHttpsAgent(); + } +} + +export function uninstallGlobalProxyAgent(): void { + http.globalAgent = new http.Agent(); + https.globalAgent = new https.Agent(); +} diff --git a/packages/core/src/http.d.ts b/packages/@n8n/backend-network/src/http/http.d.ts similarity index 100% rename from packages/core/src/http.d.ts rename to packages/@n8n/backend-network/src/http/http.d.ts diff --git a/packages/@n8n/backend-network/src/http/index.ts b/packages/@n8n/backend-network/src/http/index.ts new file mode 100644 index 00000000000..eaf92da7b6c --- /dev/null +++ b/packages/@n8n/backend-network/src/http/index.ts @@ -0,0 +1,22 @@ +export { + createHttpProxyAgent, + createHttpsProxyAgent, + installGlobalProxyAgent, + resolveProxyUrl, +} from './http-proxy'; +export { configureGlobalAxiosDefaults } from './axios/config'; +export { tryParseUrl } from './axios/utils'; +export { httpRequest, removeEmptyBody } from './axios/request'; +export { parseIncomingMessage } from './parse-incoming-message'; +export { binaryToBuffer, streamToBuffer } from './binary-buffer'; +export { binaryToString } from './binary-string'; +export type { NodeAgentOptions, ProxyOption, ProxyUrl, SsrfOption } from './node-agents'; +export type { CustomFetch } from './undici/transport'; +export { + OutboundHttp, + type HttpRequestClient, + type HttpRequestClientOptions, + type HttpTransport, + type HttpTransportOptions, +} from './outbound-http'; +export type { LegacyRequestCallbacks } from './legacy-request'; diff --git a/packages/@n8n/backend-network/src/http/legacy-request.ts b/packages/@n8n/backend-network/src/http/legacy-request.ts new file mode 100644 index 00000000000..b8cf8429c1a --- /dev/null +++ b/packages/@n8n/backend-network/src/http/legacy-request.ts @@ -0,0 +1,144 @@ +/* eslint-disable @typescript-eslint/no-unsafe-argument */ +/* eslint-disable @typescript-eslint/no-explicit-any */ +/* eslint-disable @typescript-eslint/no-unsafe-call */ +/* eslint-disable @typescript-eslint/no-unsafe-assignment */ +/* eslint-disable @typescript-eslint/no-unsafe-member-access */ + +import type { Logger } from '@n8n/backend-common'; +import type { AxiosRequestConfig } from 'axios'; +import type { IRequestOptions } from 'n8n-workflow'; +import { NodeSslError } from 'n8n-workflow'; +import { IncomingMessage } from 'node:http'; +import { Readable } from 'node:stream'; + +import { buildAxiosConfigFromLegacyRequest } from './axios/legacy'; +import { invokeAxios } from './axios/request'; +import { resolveLegacyRequestUrl, throwIfDomainNotAllowed, validateUrlSsrf } from './axios/utils'; +import { binaryToString } from './binary-string'; +import { parseIncomingMessage } from './parse-incoming-message'; +import type { SsrfBridge } from '../ssrf'; + +export interface LegacyRequestCallbacks { + /** + * Invoked once after the request successfully fetched data, before the result + * is returned. Not called when the request throws or when an error response is + * returned because `simple: false` was set. + */ + onFetched?: () => Promise<void> | void; +} + +/** + * Runs the deprecated `request`-style HTTP path (`IRequestOptions`): axios + * translation, SSRF pre-flight, domain allowlist enforcement, response + * normalisation and axios error massaging. + * + * Exposed to callers as {@link HttpRequestClient.requestLegacy}; kept in its own + * module so the whole legacy path can be removed in one go once the deprecated + * request helpers are gone. + * + * @deprecated Backs the deprecated `request` helpers. + */ +export async function executeLegacyRequest( + requestObject: IRequestOptions, + ssrfBridge: SsrfBridge | undefined, + logger: Logger, + callbacks?: LegacyRequestCallbacks, +): Promise<unknown> { + let axiosConfig: AxiosRequestConfig = { + maxBodyLength: Infinity, + // -1 is the Axios sentinel for "no limit". Infinity also means no limit but + // Axios 1.15.1+ treats any value > -1 as a finite cap, wrapping stream responses + // in Readable.from() even when the limit is Infinity. That breaks the downstream + // `instanceof IncomingMessage` checks in parseIncomingMessage / prepareBinaryData. + maxContentLength: -1, + }; + + const url = resolveLegacyRequestUrl(requestObject); + await validateUrlSsrf(url, ssrfBridge); + + axiosConfig = Object.assign( + axiosConfig, + await buildAxiosConfigFromLegacyRequest(requestObject, ssrfBridge), + ); + throwIfDomainNotAllowed(axiosConfig, requestObject.allowedDomains); + + try { + const response = await invokeAxios(axiosConfig, requestObject.auth); + let body = response.data; + if (body instanceof IncomingMessage && axiosConfig.responseType === 'stream') { + parseIncomingMessage(body); + } else if (body === '') { + body = axiosConfig.responseType === 'arraybuffer' ? Buffer.alloc(0) : undefined; + } + await callbacks?.onFetched?.(); + return requestObject.resolveWithFullResponse + ? { + body, + headers: { ...response.headers }, + statusCode: response.status, + statusMessage: response.statusText, + request: response.request, + } + : body; + } catch (error: any) { + const { config, response } = error; + + // Axios hydrates the original error with more data. We extract them. + // https://github.com/axios/axios/blob/master/lib/core/enhanceError.js + // Note: `code` is ignored as it's an expected part of the errorData. + if (error.isAxiosError) { + error.config = error.request = undefined; + // Carry only the config keys that were actually set, so the error shape + // matches the previous `pick(config, [...])` behaviour (no `undefined` + // keys for properties the request never had). + const options: Record<string, unknown> = {}; + for (const key of ['url', 'method', 'data', 'headers'] as const) { + if (config && key in config) { + options[key] = config[key]; + } + } + error.options = options; + if (response) { + logger.debug('Request proxied to Axios failed', { status: response.status }); + let responseData = response.data; + + if (Buffer.isBuffer(responseData) || responseData instanceof Readable) { + responseData = await binaryToString(responseData); + } + + if (requestObject.simple === false) { + if (requestObject.resolveWithFullResponse) { + return { + body: responseData, + headers: response.headers, + statusCode: response.status, + statusMessage: response.statusText, + }; + } else { + return responseData; + } + } + + error.message = `${response.status as number} - ${JSON.stringify(responseData)}`; + throw Object.assign(error, { + statusCode: response.status, + /** + * Axios adds `status` when serializing, causing `status` to be available only to the client. + * Hence we add it explicitly to allow the backend to use it when resolving expressions. + */ + status: response.status, + error: responseData, + response: { + headers: response.headers, + status: response.status, + statusText: response.statusText, + }, + }); + } else if ('rejectUnauthorized' in requestObject && error.code?.includes('CERT')) { + throw new NodeSslError(error); + } + } + + throw error; + } +} diff --git a/packages/@n8n/backend-network/src/http/local-server.ts b/packages/@n8n/backend-network/src/http/local-server.ts new file mode 100644 index 00000000000..c803a9bcfc6 --- /dev/null +++ b/packages/@n8n/backend-network/src/http/local-server.ts @@ -0,0 +1,34 @@ +import http from 'node:http'; +import type { AddressInfo } from 'node:net'; +import { promisify } from 'node:util'; + +export interface LocalServer { + url: string; + hostWithPort: string; + captured: string[]; + clear: () => void; + close: () => Promise<void>; +} + +const LOOPBACK = '127.0.0.1'; +export async function startServer(handler: http.RequestListener): Promise<LocalServer> { + const captured: string[] = []; + const server = http.createServer((req, res) => { + captured.push(req.url ?? ''); + handler(req, res); + }); + await new Promise<void>((resolve, reject) => { + server.listen(0, LOOPBACK, resolve); + server.on('error', reject); + }); + const { port } = server.address() as AddressInfo; + return { + url: `http://${LOOPBACK}:${port}`, + hostWithPort: `${LOOPBACK}:${port}`, + captured, + clear: () => { + captured.length = 0; + }, + close: async () => await promisify(server.close.bind(server))(), + }; +} diff --git a/packages/@n8n/backend-network/src/http/node-agents.ts b/packages/@n8n/backend-network/src/http/node-agents.ts new file mode 100644 index 00000000000..4bf263c354b --- /dev/null +++ b/packages/@n8n/backend-network/src/http/node-agents.ts @@ -0,0 +1,152 @@ +import { HttpProxyAgent } from 'http-proxy-agent'; +import { HttpsProxyAgent } from 'https-proxy-agent'; +import { UnexpectedError } from 'n8n-workflow'; +import http from 'node:http'; +import https from 'node:https'; +import type { LookupFunction } from 'node:net'; + +import { EnvProxyHttpAgent } from './env-proxy-http-agent'; +import { EnvProxyHttpsAgent } from './env-proxy-https-agent'; +import type { SsrfBridge } from '../ssrf'; + +/** + * An explicit proxy URL for routing all requests from this client. + * Only HTTP(S) forward proxies are supported: both the Node.js agents + * and the undici dispatcher (`ProxyAgent`) speak the HTTP CONNECT protocol, not SOCKS. + */ +export type ProxyUrl = `${'http' | 'https'}://${string}`; + +/** + * Type guard for {@link ProxyUrl}. + * Only HTTP(S) forward proxies are supported. + */ +export function isSupportedProxyUrl(value: string): value is ProxyUrl { + return value.startsWith('http://') || value.startsWith('https://'); +} + +/** + * Controls how outgoing requests are routed through a proxy. + * - `'env'` (default): read HTTP_PROXY / HTTPS_PROXY / NO_PROXY from the environment + * - `ProxyUrl`: route all requests through the given proxy + * - `false`: bypass all proxies, connect directly to the target + */ +export type ProxyOption = 'env' | ProxyUrl | false; + +/** + * Controls SSRF protection for an outbound HTTP client. + * Explicitly passing `'disabled'` makes the opt-out visible in calling code. + */ +export type SsrfOption = SsrfBridge | 'disabled'; + +/** + * Per-call Node.js agent options (TLS, keep-alive, `servername`, ...) + * forwarded to the underlying http/https agents. + */ +export type NodeAgentOptions = https.AgentOptions; + +/** + * Builds the `{ httpAgent, httpsAgent }` pair for a given proxy + SSRF policy. + * + * Single source of truth for outbound Node.js agent construction, shared by the + * undici factory (`undici/factory.ts`), the axios transport layer + * (`axios/utils.ts`) and the global proxy agents (`http-proxy.ts`). + * + * SSRF lookup is injected only for **direct** connections. Behind a proxy the + * lookup resolves the proxy host, not the final target, so it is omitted there + * and the proxy validates the final target. + * + * The `lookup` is owned by this builder: it is derived from the SSRF policy and + * always overrides anything in `agentOptions`. Passing `agentOptions.lookup` + * therefore has no effect and is rejected to avoid a false sense of control over + * DNS resolution. + */ +export function buildNodeAgents( + proxy: ProxyOption, + ssrf: SsrfOption, + agentOptions?: NodeAgentOptions, +): { httpAgent: http.Agent; httpsAgent: https.Agent } { + if (agentOptions?.lookup) { + throw new UnexpectedError( + '`agentOptions.lookup` is not supported: DNS resolution is managed by the SSRF policy. Remove it from `agentOptions`.', + ); + } + + const lookup: LookupFunction | undefined = + ssrf !== 'disabled' ? ssrf.createSecureLookup() : undefined; + + if (proxy === false) { + return applyConnectionGuard( + { + httpAgent: new http.Agent({ ...agentOptions, lookup }), + httpsAgent: new https.Agent({ ...agentOptions, lookup }), + }, + ssrf, + ); + } + + if (proxy === 'env') { + return applyConnectionGuard( + { + httpAgent: new EnvProxyHttpAgent(lookup, agentOptions), + httpsAgent: new EnvProxyHttpsAgent(lookup, agentOptions), + }, + ssrf, + ); + } + + // Explicit proxy URL. No direct path, so no SSRF lookup is injected. + return { + httpAgent: new HttpProxyAgent(proxy as string, { ...agentOptions }), + httpsAgent: new HttpsProxyAgent(proxy as string, { ...agentOptions }), + }; +} + +/** Subset of an agent's connection options we read to find the target host. */ +type ConnectionOptions = { host?: string | null; hostname?: string | null }; + +/** + * Runtime-only `createConnection` method of Node's http(s) agents. + */ +type CreateConnection = ( + options: ConnectionOptions, + onConnect?: (error: Error | null, stream?: unknown) => void, +) => unknown; + +/** + * Installs {@link installConnectionGuard} on a direct-path agent pair when SSRF protection is active. + */ +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); + } + return agents; +} + +/** + * Wraps an agent's `createConnection` to validate the connection target before the socket opens. + * Node invokes the custom `lookup` only to resolve hostnames, so it also requires a check at connection time. + */ +export function installConnectionGuard( + target: { createConnection: CreateConnection }, + ssrf: SsrfBridge, +): void { + const createConnection = target.createConnection.bind(target); + target.createConnection = (options, onConnect) => { + const host = options.host ?? options.hostname ?? undefined; + if (typeof host === 'string') { + const result = ssrf.validateConnectionHost(host); + if (!result.ok) { + if (onConnect) { + onConnect(result.error); + return undefined; + } + throw result.error; + } + } + return createConnection(options, onConnect); + }; +} diff --git a/packages/@n8n/backend-network/src/http/outbound-http.ts b/packages/@n8n/backend-network/src/http/outbound-http.ts new file mode 100644 index 00000000000..a4c880e8733 --- /dev/null +++ b/packages/@n8n/backend-network/src/http/outbound-http.ts @@ -0,0 +1,167 @@ +import { Logger } from '@n8n/backend-common'; +import { Service } from '@n8n/di'; +import type { + IHttpRequestOptions, + IN8nHttpFullResponse, + IN8nHttpResponse, + IRequestOptions, +} from 'n8n-workflow'; +import type http from 'node:http'; +import type https from 'node:https'; +import type { Dispatcher } from 'undici'; + +import { httpRequest } from './axios/request'; +import { executeLegacyRequest, type LegacyRequestCallbacks } from './legacy-request'; +import { buildNodeAgents } from './node-agents'; +import type { NodeAgentOptions, ProxyOption, SsrfOption } from './node-agents'; +import { SsrfProtectionService } from '../ssrf'; +import { buildDispatcher, dispatchedFetch, type CustomFetch } from './undici/transport'; + +export interface HttpRequestClientOptions { + /** + * SSRF protection level. Defaults to the container's `SsrfProtectionService`. + * Pass `'disabled'` to explicitly opt out. + */ + ssrf?: SsrfOption; +} + +export interface HttpTransportOptions { + /** + * Proxy routing for the transport. Defaults to `'env'` (HTTP(S)_PROXY / NO_PROXY). + * + * Fixed at creation: the transport hands a single dispatcher/agent to a foreign + * client that drives the calls afterwards, so the proxy cannot vary per call — + * unlike {@link HttpRequestClient}, which reads `proxy` from each request. + */ + proxy?: ProxyOption; + /** + * SSRF protection level. Defaults to the container's `SsrfProtectionService`. + * Pass `'disabled'` to explicitly opt out. + */ + ssrf?: SsrfOption; +} + +/** + * Engine for outbound HTTP requests made on behalf of n8n: you hand it a request + * descriptor and it performs the call and returns the response. + * + * Carries this client's SSRF policy. Proxy routing stays **per request** (read + * from `options.proxy` / the environment), because n8n requests choose their + * proxy per call rather than per client — so there is no proxy option here. + */ +export interface HttpRequestClient { + /** + * Performs an outbound HTTP request from an `IHttpRequestOptions` descriptor, + * applying this client's SSRF policy, user-agent defaults and proxy routing. + * + * @returns the full response when `options.returnFullResponse` is `true`. + */ + request( + options: IHttpRequestOptions & { returnFullResponse: true }, + ): Promise<IN8nHttpFullResponse>; + /** + * @returns the parsed body when `options.returnFullResponse` is unset or `false`. + */ + request(options: IHttpRequestOptions & { returnFullResponse?: false }): Promise<IN8nHttpResponse>; + /** + * Fallback for a non-literal `returnFullResponse` flag. + * + * @returns the parsed body, or the full response when `options.returnFullResponse` is set. + */ + request(options: IHttpRequestOptions): Promise<IN8nHttpFullResponse | IN8nHttpResponse>; + + /** + * Performs a request using the deprecated `request`-style options + * (`IRequestOptions`), applying the same SSRF policy as {@link request}. + * + * `callbacks.onFetched` runs once after data is successfully fetched (used by + * the execution engine to fire its `nodeFetchedData` hook). + * + * @deprecated Use {@link request} with `IHttpRequestOptions`. This exists only + * to back the deprecated `request` helpers. + */ + requestLegacy(options: IRequestOptions, callbacks?: LegacyRequestCallbacks): Promise<unknown>; +} + +/** + * Transport primitives to hand to a third-party HTTP stack (an SDK you do not + * drive yourself). You do not make the request here — you configure someone + * else's client. Carries a fixed proxy + SSRF policy. + * + * The three shapes are not interchangeable styles; which one you use is dictated + * by what the consuming library accepts: + * + * - **`asCustomFetch()`**: libraries that accept a full `fetch` replacement + * (e.g. an OIDC client's `customFetch`). + * - **`getDispatcher()`**: SDKs built on undici's `fetch` that accept a + * `dispatcher` (e.g. OpenAI / Anthropic JS SDKs via `fetchOptions.dispatcher`). + * Injects only the transport while the SDK keeps its own `fetch` (streaming, + * retries, error parsing). + * - **`getNodeAgent()`**: libraries built on Node's `http`/`https` that need + * `http.Agent` / `https.Agent` instances (e.g. AWS SDK v3 via `NodeHttpHandler`). + * + * SSRF coverage is identical for `asCustomFetch()` and `getDispatcher()` (same + * underlying dispatcher, validated per hop). For `getNodeAgent()` it is enforced + * via a connect-time secure DNS lookup, injected only for direct connections. + */ +export interface HttpTransport { + asCustomFetch(): CustomFetch; + getDispatcher(): Dispatcher; + getNodeAgent(agentOptions?: NodeAgentOptions): { httpAgent: http.Agent; httpsAgent: https.Agent }; +} + +/** + * The single entry point for outbound http requests in `@n8n/backend-network`. + * + * Injectable via `@n8n/di`. Pick by intent, not by transport library: + * + * - {@link requests}: you make a request and get a response (n8n request pipeline). + * - {@link transport}: you obtain transport primitives to hand to a third-party SDK. + */ +@Service() +export class OutboundHttp { + constructor( + private readonly ssrfProtection: SsrfProtectionService, + private readonly logger: Logger, + ) {} + + /** + * A {@link HttpRequestClient} carrying the given SSRF policy. + * Proxy is resolved per request from `IHttpRequestOptions.proxy` / the environment. + */ + requests(options?: HttpRequestClientOptions): HttpRequestClient { + const ssrf = options?.ssrf ?? this.ssrfProtection; + const ssrfBridge = ssrf === 'disabled' ? undefined : ssrf; + + return { + request: (async (requestOptions: IHttpRequestOptions) => + await httpRequest(requestOptions, ssrfBridge)) as HttpRequestClient['request'], + requestLegacy: async (requestOptions, callbacks) => + await executeLegacyRequest(requestOptions, ssrfBridge, this.logger, callbacks), + }; + } + + /** + * An {@link HttpTransport} carrying the given proxy + SSRF policy. + */ + transport(options?: HttpTransportOptions): HttpTransport { + const proxy = options?.proxy ?? 'env'; + const ssrf = options?.ssrf ?? this.ssrfProtection; + + const lazyDispatcher = lazy(() => buildDispatcher(proxy, ssrf)); + const lazyNodeAgents = lazy(() => buildNodeAgents(proxy, ssrf)); + + return { + asCustomFetch: () => async (input, init) => + await dispatchedFetch(lazyDispatcher(), input, init), + getDispatcher: () => lazyDispatcher(), + getNodeAgent: (agentOptions) => + agentOptions !== undefined ? buildNodeAgents(proxy, ssrf, agentOptions) : lazyNodeAgents(), + }; + } +} + +function lazy<T>(factory: () => T): () => T { + let cached: { value: T } | undefined; + return () => (cached ??= { value: factory() }).value; +} diff --git a/packages/core/src/execution-engine/node-execution-context/utils/parse-incoming-message.ts b/packages/@n8n/backend-network/src/http/parse-incoming-message.ts similarity index 100% rename from packages/core/src/execution-engine/node-execution-context/utils/parse-incoming-message.ts rename to packages/@n8n/backend-network/src/http/parse-incoming-message.ts diff --git a/packages/@n8n/backend-network/src/http/undici/transport.ts b/packages/@n8n/backend-network/src/http/undici/transport.ts new file mode 100644 index 00000000000..4dd896ca2ef --- /dev/null +++ b/packages/@n8n/backend-network/src/http/undici/transport.ts @@ -0,0 +1,103 @@ +import { ensureError } from 'n8n-workflow'; +import type { Dispatcher } from 'undici'; +import { Agent, EnvHttpProxyAgent, ProxyAgent, fetch as undiciFetch } from 'undici'; + +import type { SsrfBridge } from '../../ssrf'; +import type { ProxyOption, SsrfOption } from '../node-agents'; + +/** + * Drop-in replacement type for the global `fetch`. + */ +export type CustomFetch = (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>; + +/** + * Builds the undici dispatcher for a given proxy + SSRF policy — the transport + * plumbing behind `OutboundHttp.transport()`. When SSRF is active the dispatcher + * is composed with {@link createSsrfInterceptor} so every dispatched request, + * including each redirect hop, is validated. + */ +export function buildDispatcher(proxy: ProxyOption, ssrf: SsrfOption): Dispatcher { + const dispatcher = buildDispatcherFromProxy(proxy); + return ssrf === 'disabled' ? dispatcher : dispatcher.compose(createSsrfInterceptor(ssrf)); +} + +function buildDispatcherFromProxy(proxy: ProxyOption): Dispatcher { + if (proxy === false) { + return new Agent(); + } + if (proxy === 'env') { + return new EnvHttpProxyAgent(); + } + return new ProxyAgent(proxy); +} + +/** + * undici `compose` interceptor that runs SSRF validation against the target URL + * of every dispatched request. + * + * `fetch` re-dispatches through this dispatcher for each redirect hop, so this + * validates the initial request **and** every redirect target (both hostname + * and direct-IP targets), unlike a connect-time DNS lookup which never fires for + * IP-literal targets. Validation runs against the request target, never the + * proxy, so it is proxy-agnostic. + */ +export function createSsrfInterceptor(bridge: SsrfBridge): Dispatcher.DispatcherComposeInterceptor { + return (dispatch) => (opts, handler) => { + let targetUrl: URL; + try { + // `opts.path` is the request target. + // Behind a forward proxy it can be an absolute URI, otherwise it is path-only and resolved against the origin. + // Either form yields the final target URL. + targetUrl = new URL(opts.path, opts.origin?.toString()); + bridge.validateUrl(targetUrl).then( + (result) => { + if (result.ok) { + dispatch(opts, handler); + } else { + failDispatch(handler, result.error); + } + }, + (error: unknown) => failDispatch(handler, ensureError(error)), + ); + } catch (error: unknown) { + // Fail closed: if we cannot derive a target URL we cannot validate it + failDispatch(handler, ensureError(error)); + } + + return true; + }; +} + +/** + * Declared locally so it does not depend on undici's namespaced `DispatchHandler` / `DispatchController` types, + * whose resolution varies across undici versions in the tree) + */ +interface FailableDispatchHandler { + onResponseError?(controller: unknown, error: Error): void; + onError?(error: Error): void; +} + +/** + * Signals a pre-dispatch failure to an undici dispatch handler. + * Mirrors undici's own interceptors (e.g. the DNS interceptor), + * which pass a `null` controller when erroring before a request reaches the socket. + */ +function failDispatch(handler: FailableDispatchHandler, error: Error): void { + if (handler.onResponseError) { + handler.onResponseError(null, error); + } else { + handler.onError?.(error); + } +} + +/** Performs a `fetch` bound to the given undici dispatcher (the engine behind `asCustomFetch`). */ +export async function dispatchedFetch( + dispatcher: Dispatcher, + input: RequestInfo | URL, + init?: RequestInit, +): Promise<Response> { + return (await undiciFetch( + input as Parameters<typeof undiciFetch>[0], + { ...(init ?? {}), dispatcher } as Parameters<typeof undiciFetch>[1], + )) as unknown as Response; +} diff --git a/packages/@n8n/backend-network/src/index.ts b/packages/@n8n/backend-network/src/index.ts new file mode 100644 index 00000000000..66b4b04b5e8 --- /dev/null +++ b/packages/@n8n/backend-network/src/index.ts @@ -0,0 +1,3 @@ +export * from './dns'; +export * from './ssrf'; +export * from './http'; diff --git a/packages/cli/src/services/ssrf/__tests__/hostname-matcher.test.ts b/packages/@n8n/backend-network/src/ssrf/__tests__/hostname-matcher.test.ts similarity index 100% rename from packages/cli/src/services/ssrf/__tests__/hostname-matcher.test.ts rename to packages/@n8n/backend-network/src/ssrf/__tests__/hostname-matcher.test.ts diff --git a/packages/cli/src/services/ssrf/__tests__/ip-range-builder.test.ts b/packages/@n8n/backend-network/src/ssrf/__tests__/ip-range-builder.test.ts similarity index 100% rename from packages/cli/src/services/ssrf/__tests__/ip-range-builder.test.ts rename to packages/@n8n/backend-network/src/ssrf/__tests__/ip-range-builder.test.ts diff --git a/packages/@n8n/backend-network/src/ssrf/__tests__/mock-ssrf-bridge.ts b/packages/@n8n/backend-network/src/ssrf/__tests__/mock-ssrf-bridge.ts new file mode 100644 index 00000000000..1667bd95ab5 --- /dev/null +++ b/packages/@n8n/backend-network/src/ssrf/__tests__/mock-ssrf-bridge.ts @@ -0,0 +1,19 @@ +import type { LookupFunction } from 'node:net'; +import { vi } from 'vitest'; + +import type { SsrfBridge } from '..'; + +export function makeLookupFn(): LookupFunction { + return vi.fn() as unknown as LookupFunction; +} + +export function makeSsrfBridge(overrides?: Partial<SsrfBridge>): SsrfBridge { + return { + validateUrl: vi.fn().mockResolvedValue({ ok: true, result: undefined }), + validateIp: vi.fn().mockReturnValue({ ok: true, result: undefined }), + validateConnectionHost: vi.fn().mockReturnValue({ ok: true, result: undefined }), + validateRedirectSync: vi.fn(), + createSecureLookup: vi.fn().mockReturnValue(makeLookupFn()), + ...overrides, + }; +} diff --git a/packages/cli/src/services/ssrf/__tests__/ssrf-protection.service.test.ts b/packages/@n8n/backend-network/src/ssrf/__tests__/ssrf-protection.service.test.ts similarity index 68% rename from packages/cli/src/services/ssrf/__tests__/ssrf-protection.service.test.ts rename to packages/@n8n/backend-network/src/ssrf/__tests__/ssrf-protection.service.test.ts index b5bbfc86661..4ef34088b47 100644 --- a/packages/cli/src/services/ssrf/__tests__/ssrf-protection.service.test.ts +++ b/packages/@n8n/backend-network/src/ssrf/__tests__/ssrf-protection.service.test.ts @@ -1,8 +1,9 @@ import type { Logger } from '@n8n/backend-common'; import { SsrfProtectionConfig } from '@n8n/config'; -import { mock } from 'jest-mock-extended'; +import type { LookupAddress } from 'node:dns'; +import { mock } from 'vitest-mock-extended'; -import type { DnsResolver } from '../dns-resolver'; +import type { DnsResolver } from '../../dns'; import { SsrfBlockedIpError } from '../ssrf-blocked-ip.error'; import { SsrfProtectionService } from '../ssrf-protection.service'; @@ -13,7 +14,7 @@ function createConfig(overrides: Partial<SsrfProtectionConfig> = {}): SsrfProtec } const mockScopedLogger = mock<Logger>(); -const mockLogger = mock<Logger>({ scoped: jest.fn().mockReturnValue(mockScopedLogger) }); +const mockLogger = mock<Logger>({ scoped: vi.fn().mockReturnValue(mockScopedLogger) }); function createMockDnsResolver() { const resolver = mock<DnsResolver>(); @@ -43,7 +44,7 @@ const expectAllowed = (result: unknown) => { describe('SsrfProtectionService', () => { beforeEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); }); describe('validateIp', () => { @@ -273,6 +274,52 @@ describe('SsrfProtectionService', () => { }); }); + describe('validateConnectionHost', () => { + it('should block a direct IP-literal target', () => { + const { service } = createService(); + + expectBlocked(service.validateConnectionHost('169.254.169.254')); + expectBlocked(service.validateConnectionHost('10.0.0.1')); + }); + + it('should allow a public direct IP target', () => { + const { service } = createService(); + + expectAllowed(service.validateConnectionHost('93.184.216.34')); + }); + + it('should normalize IPv6 bracket notation before validating', () => { + const { service } = createService(); + + expectBlocked(service.validateConnectionHost('[::1]')); + }); + + it('should allow hostnames (deferred to the secure lookup)', () => { + const dnsResolver = createMockDnsResolver(); + const { service } = createService({}, dnsResolver); + + expectAllowed(service.validateConnectionHost('example.com')); + // No DNS resolution happens here — hostnames are validated by the lookup. + expect(dnsResolver.lookup).not.toHaveBeenCalled(); + }); + + it('should emit a connect_time event for IP-literal targets', () => { + const { service } = createService(); + const blocked = vi.fn(); + const allowed = vi.fn(); + service.events.on('ssrf.blocked', blocked); + service.events.on('ssrf.allowed', allowed); + + service.validateConnectionHost('10.0.0.1'); + service.validateConnectionHost('93.184.216.34'); + + expect(blocked).toHaveBeenCalledWith( + expect.objectContaining({ phase: 'connect_time', reason: 'blocked_ip' }), + ); + expect(allowed).toHaveBeenCalledWith(expect.objectContaining({ phase: 'connect_time' })); + }); + }); + describe('validateRedirectSync', () => { it('should block direct-IP redirect targets', () => { const { service } = createService(); @@ -306,38 +353,44 @@ describe('SsrfProtectionService', () => { }); describe('createSecureLookup', () => { - it('should resolve and validate IPs at connection time', (done) => { + it('should resolve and validate IPs at connection time', async () => { const dnsResolver = createMockDnsResolver(); dnsResolver.lookup.mockResolvedValue([{ address: '93.184.216.34', family: 4 }]); const { service } = createService({}, dnsResolver); const lookup = service.createSecureLookup(); - lookup('example.com', { all: false }, (lookupError, address, family) => { - expect(lookupError).toBeNull(); - expect(address).toBe('93.184.216.34'); - expect(family).toBe(4); - done(); - }); + const [error, address, family] = await new Promise< + [Error | null, string, number | undefined] + >((resolve) => + lookup('example.com', { all: false }, (lookupError, addr, fam) => + resolve([lookupError, addr as string, fam]), + ), + ); + + expect(error).toBeNull(); + expect(address).toBe('93.184.216.34'); + expect(family).toBe(4); }); - it('should reject blocked IPs during lookup', (done) => { + it('should reject blocked IPs during lookup', async () => { const dnsResolver = createMockDnsResolver(); dnsResolver.lookup.mockResolvedValue([{ address: '10.0.0.1', family: 4 }]); const { service } = createService({}, dnsResolver); const lookup = service.createSecureLookup(); - lookup('evil.com', { all: false }, (lookupError) => { - expect(lookupError).toBeTruthy(); - expect(lookupError?.message).toContain( - 'The request was blocked because it resolves to a restricted IP address', - ); - done(); - }); + const error = await new Promise<Error | null>((resolve) => + lookup('evil.com', { all: false }, (lookupError) => resolve(lookupError)), + ); + + expect(error).toBeTruthy(); + expect(error?.message).toContain( + 'The request was blocked because it resolves to a restricted IP address', + ); }); - it('should return all addresses when all=true', (done) => { + it('should return all addresses when all=true', async () => { const dnsResolver = createMockDnsResolver(); dnsResolver.lookup.mockResolvedValue([ { address: '93.184.216.34', family: 4 }, @@ -347,55 +400,68 @@ describe('SsrfProtectionService', () => { const { service } = createService({}, dnsResolver); const lookup = service.createSecureLookup(); - lookup('multi.example.com', { all: true }, (lookupError, addresses) => { - expect(lookupError).toBeNull(); - expect(addresses).toEqual([ - { address: '93.184.216.34', family: 4 }, - { address: '93.184.216.35', family: 4 }, - ]); - done(); - }); + const [error, addresses] = await new Promise<[Error | null, LookupAddress[]]>((resolve) => + lookup('multi.example.com', { all: true }, (lookupError, addrs) => + resolve([lookupError, addrs as LookupAddress[]]), + ), + ); + + expect(error).toBeNull(); + expect(addresses).toEqual([ + { address: '93.184.216.34', family: 4 }, + { address: '93.184.216.35', family: 4 }, + ]); }); - it('should respect family=6 and return only IPv6 addresses', (done) => { + it('should respect family=6 and return only IPv6 addresses', async () => { const dnsResolver = createMockDnsResolver(); dnsResolver.lookup.mockResolvedValue([{ address: '2606:4700::6810:85e5', family: 6 }]); const { service } = createService({}, dnsResolver); const lookup = service.createSecureLookup(); - lookup('dualstack.example.com', { all: false, family: 6 }, (lookupError, address, family) => { - expect(lookupError).toBeNull(); - expect(address).toBe('2606:4700::6810:85e5'); - expect(family).toBe(6); - expect(dnsResolver.lookup).toHaveBeenCalledWith('dualstack.example.com', { - all: false, - family: 6, - }); - done(); + const [error, address, family] = await new Promise< + [Error | null, string, number | undefined] + >((resolve) => + lookup('dualstack.example.com', { all: false, family: 6 }, (lookupError, addr, fam) => + resolve([lookupError, addr as string, fam]), + ), + ); + + expect(error).toBeNull(); + expect(address).toBe('2606:4700::6810:85e5'); + expect(family).toBe(6); + expect(dnsResolver.lookup).toHaveBeenCalledWith('dualstack.example.com', { + all: false, + family: 6, }); }); - it('should fail when requested family has no resolved addresses', (done) => { + it('should fail when requested family has no resolved addresses', async () => { const dnsResolver = createMockDnsResolver(); dnsResolver.lookup.mockResolvedValue([]); const { service } = createService({}, dnsResolver); const lookup = service.createSecureLookup(); - lookup('ipv4-only.example.com', { all: false, family: 6 }, (lookupError, address, family) => { - expect(lookupError).toBeTruthy(); - expect(address).toBe(''); - expect(family).toBeUndefined(); - expect(dnsResolver.lookup).toHaveBeenCalledWith('ipv4-only.example.com', { - all: false, - family: 6, - }); - done(); + const [error, address, family] = await new Promise< + [Error | null, string, number | undefined] + >((resolve) => + lookup('ipv4-only.example.com', { all: false, family: 6 }, (lookupError, addr, fam) => + resolve([lookupError, addr as string, fam]), + ), + ); + + expect(error).toBeTruthy(); + expect(address).toBe(''); + expect(family).toBeUndefined(); + expect(dnsResolver.lookup).toHaveBeenCalledWith('ipv4-only.example.com', { + all: false, + family: 6, }); }); - it('should allow hostnames in the allowlist without IP validation', (done) => { + it('should allow hostnames in the allowlist without IP validation', async () => { const dnsResolver = createMockDnsResolver(); dnsResolver.lookup.mockResolvedValue([{ address: '10.0.0.1', family: 4 }]); @@ -409,41 +475,54 @@ describe('SsrfProtectionService', () => { ); const lookup = service.createSecureLookup(); - lookup('api.internal.n8n.io', { all: false }, (lookupError, address) => { - expect(lookupError).toBeNull(); - expect(address).toBe('10.0.0.1'); - done(); - }); + const [error, address] = await new Promise<[Error | null, string]>((resolve) => + lookup('api.internal.n8n.io', { all: false }, (lookupError, addr) => + resolve([lookupError, addr as string]), + ), + ); + + expect(error).toBeNull(); + expect(address).toBe('10.0.0.1'); }); - it('should pass empty string and undefined family on non-all lookup errors', (done) => { + it('should pass empty string and undefined family on non-all lookup errors', async () => { const dnsResolver = createMockDnsResolver(); dnsResolver.lookup.mockRejectedValue(new Error('ENOTFOUND')); const { service } = createService({}, dnsResolver); const lookup = service.createSecureLookup(); - lookup('failing.example.com', { all: false }, (lookupError, address, family) => { - expect(lookupError).toBeTruthy(); - expect(address).toBe(''); - expect(family).toBeUndefined(); - done(); - }); + const [error, address, family] = await new Promise< + [Error | null, string, number | undefined] + >((resolve) => + lookup('failing.example.com', { all: false }, (lookupError, addr, fam) => + resolve([lookupError, addr as string, fam]), + ), + ); + + expect(error).toBeTruthy(); + expect(address).toBe(''); + expect(family).toBeUndefined(); }); - it('should pass empty array and undefined family on all=true lookup errors', (done) => { + it('should pass empty array and undefined family on all=true lookup errors', async () => { const dnsResolver = createMockDnsResolver(); dnsResolver.lookup.mockRejectedValue(new Error('ENOTFOUND')); const { service } = createService({}, dnsResolver); const lookup = service.createSecureLookup(); - lookup('failing.example.com', { all: true }, (lookupError, address, family) => { - expect(lookupError).toBeTruthy(); - expect(address).toEqual([]); - expect(family).toBeUndefined(); - done(); - }); + const [error, addresses, family] = await new Promise< + [Error | null, LookupAddress[], number | undefined] + >((resolve) => + lookup('failing.example.com', { all: true }, (lookupError, addrs, fam) => + resolve([lookupError, addrs as LookupAddress[], fam]), + ), + ); + + expect(error).toBeTruthy(); + expect(addresses).toEqual([]); + expect(family).toBeUndefined(); }); }); @@ -536,20 +615,21 @@ describe('SsrfProtectionService', () => { }); describe('DNS rebinding prevention (TOCTOU)', () => { - it('should validate IPs at connection time via secure lookup', (done) => { + it('should validate IPs at connection time via secure lookup', async () => { const dnsResolver = createMockDnsResolver(); dnsResolver.lookup.mockResolvedValueOnce([{ address: '10.0.0.1', family: 4 }]); const { service } = createService({}, dnsResolver); const lookup = service.createSecureLookup(); - lookup('rebinding.evil.com', { all: false }, (lookupError) => { - expect(lookupError).toBeTruthy(); - expect(lookupError?.message).toContain( - 'The request was blocked because it resolves to a restricted IP address', - ); - done(); - }); + const error = await new Promise<Error | null>((resolve) => + lookup('rebinding.evil.com', { all: false }, (lookupError) => resolve(lookupError)), + ); + + expect(error).toBeTruthy(); + expect(error?.message).toContain( + 'The request was blocked because it resolves to a restricted IP address', + ); }); }); @@ -595,4 +675,72 @@ describe('SsrfProtectionService', () => { ); }); }); + + describe('events', () => { + it('should emit ssrf.allowed for an allowed URL', async () => { + const dnsResolver = createMockDnsResolver(); + dnsResolver.lookup.mockResolvedValue([{ address: '93.184.216.34', family: 4 }]); + const { service } = createService({}, dnsResolver); + const allowed = vi.fn(); + service.events.on('ssrf.allowed', allowed); + + await service.validateUrl('http://example.com/'); + + expect(allowed).toHaveBeenCalledWith( + expect.objectContaining({ phase: 'pre_flight', durationMs: expect.any(Number) }), + ); + }); + + it('should emit ssrf.blocked with reason blocked_ip for a blocked URL', async () => { + const { service } = createService(); + const blocked = vi.fn(); + service.events.on('ssrf.blocked', blocked); + + await service.validateUrl('http://127.0.0.1/'); + + expect(blocked).toHaveBeenCalledWith( + expect.objectContaining({ phase: 'pre_flight', reason: 'blocked_ip' }), + ); + }); + + it('should emit ssrf.blocked with reason invalid_url for an unparseable URL', async () => { + const { service } = createService(); + const blocked = vi.fn(); + service.events.on('ssrf.blocked', blocked); + + await service.validateUrl('not a url'); + + expect(blocked).toHaveBeenCalledWith( + expect.objectContaining({ phase: 'pre_flight', reason: 'invalid_url' }), + ); + }); + + it('should emit ssrf.blocked with reason dns_error when DNS resolution rejects', async () => { + const dnsResolver = createMockDnsResolver(); + dnsResolver.lookup.mockRejectedValue(new Error('ENOTFOUND')); + const { service } = createService({}, dnsResolver); + const blocked = vi.fn(); + service.events.on('ssrf.blocked', blocked); + + await expect(service.validateUrl('http://nonexistent.example.com/')).rejects.toThrow( + 'ENOTFOUND', + ); + + expect(blocked).toHaveBeenCalledWith( + expect.objectContaining({ phase: 'pre_flight', reason: 'dns_error' }), + ); + }); + + it('should emit ssrf.blocked with reason blocked_ip for a blocked redirect', () => { + const { service } = createService(); + const blocked = vi.fn(); + service.events.on('ssrf.blocked', blocked); + + expect(() => service.validateRedirectSync('http://127.0.0.1/admin')).toThrow(); + + expect(blocked).toHaveBeenCalledWith( + expect.objectContaining({ phase: 'redirect', reason: 'blocked_ip' }), + ); + }); + }); }); diff --git a/packages/cli/src/services/ssrf/hostname-matcher.ts b/packages/@n8n/backend-network/src/ssrf/hostname-matcher.ts similarity index 100% rename from packages/cli/src/services/ssrf/hostname-matcher.ts rename to packages/@n8n/backend-network/src/ssrf/hostname-matcher.ts diff --git a/packages/@n8n/backend-network/src/ssrf/index.ts b/packages/@n8n/backend-network/src/ssrf/index.ts new file mode 100644 index 00000000000..91e0dfa9058 --- /dev/null +++ b/packages/@n8n/backend-network/src/ssrf/index.ts @@ -0,0 +1,3 @@ +export { SsrfProtectionService } from './ssrf-protection.service'; +export type { SsrfBridge } from './ssrf-protection.service'; +export { SsrfBlockedIpError } from './ssrf-blocked-ip.error'; diff --git a/packages/cli/src/services/ssrf/ip-range-builder.ts b/packages/@n8n/backend-network/src/ssrf/ip-range-builder.ts similarity index 100% rename from packages/cli/src/services/ssrf/ip-range-builder.ts rename to packages/@n8n/backend-network/src/ssrf/ip-range-builder.ts diff --git a/packages/cli/src/services/ssrf/ssrf-blocked-ip.error.ts b/packages/@n8n/backend-network/src/ssrf/ssrf-blocked-ip.error.ts similarity index 100% rename from packages/cli/src/services/ssrf/ssrf-blocked-ip.error.ts rename to packages/@n8n/backend-network/src/ssrf/ssrf-blocked-ip.error.ts diff --git a/packages/cli/src/services/ssrf/ssrf-protection.service.ts b/packages/@n8n/backend-network/src/ssrf/ssrf-protection.service.ts similarity index 63% rename from packages/cli/src/services/ssrf/ssrf-protection.service.ts rename to packages/@n8n/backend-network/src/ssrf/ssrf-protection.service.ts index cbbd98f5d7f..1813e06a4c8 100644 --- a/packages/cli/src/services/ssrf/ssrf-protection.service.ts +++ b/packages/@n8n/backend-network/src/ssrf/ssrf-protection.service.ts @@ -1,19 +1,46 @@ -import { Logger } from '@n8n/backend-common'; +import { Logger, TypedEmitter } from '@n8n/backend-common'; import { SsrfProtectionConfig } from '@n8n/config'; import { Service } from '@n8n/di'; -import { SsrfBridge, SsrfCheckResult } from 'n8n-core'; -import { createResultError, ensureError, Result, createResultOk } from 'n8n-workflow'; +import { createResultError, createResultOk, ensureError, Result } from 'n8n-workflow'; import assert from 'node:assert'; import type { LookupAddress, LookupOptions } from 'node:dns'; -import { isIP } from 'node:net'; import type { BlockList, LookupFunction } from 'node:net'; +import { isIP } from 'node:net'; -import { DnsResolver } from './dns-resolver'; +import { DnsResolver } from '../dns'; import { HostnameMatcher } from './hostname-matcher'; import { buildIpRangeList } from './ip-range-builder'; import { SsrfBlockedIpError } from './ssrf-blocked-ip.error'; -export type LookAndValidateResult = Result<LookupAddress[], Error>; +export type SsrfCheckResult = Result<void, Error>; + +type SsrfBlockedPayload = { phase: SsrfPhase; reason: string; durationMs: number }; +type SsrfAllowedPayload = { phase: SsrfPhase; durationMs: number }; + +/** + * The lifecycle stage at which an SSRF check was performed. + * - `pre_flight`: DNS-based check run before the request is sent + * - `connect_time`: DNS-based check run at actual socket connection + * - `redirect`: synchronous IP check run when an HTTP redirect is followed + */ +type SsrfPhase = 'pre_flight' | 'connect_time' | 'redirect'; + +export type SsrfEventMap = { + // eslint-disable-next-line @typescript-eslint/naming-convention + 'ssrf.blocked': SsrfBlockedPayload; + // eslint-disable-next-line @typescript-eslint/naming-convention + 'ssrf.allowed': SsrfAllowedPayload; +}; + +export interface SsrfBridge { + validateIp(ip: string): SsrfCheckResult; + validateUrl(url: string | URL): Promise<SsrfCheckResult>; + validateConnectionHost(host: string): SsrfCheckResult; + validateRedirectSync(url: string): void; + createSecureLookup(): LookupFunction; +} + +type LookAndValidateResult = Result<LookupAddress[], Error>; /** * Validates outbound HTTP requests against configurable blocklists and allowlists @@ -27,6 +54,8 @@ export type LookAndValidateResult = Result<LookupAddress[], Error>; */ @Service() export class SsrfProtectionService implements SsrfBridge { + readonly events = new TypedEmitter<SsrfEventMap>(); + private readonly logger: Logger; private readonly blockedIps: BlockList; @@ -68,17 +97,19 @@ export class SsrfProtectionService implements SsrfBridge { async validateUrl(url: string | URL): Promise<SsrfCheckResult> { const parsed = this.tryParseUrl(url); if (!parsed) { - return createResultError(new Error(`Invalid URL: ${url}`)); + this.events.emit('ssrf.blocked', { + phase: 'pre_flight', + reason: 'invalid_url', + durationMs: 0, + }); + return createResultError(new Error(`Invalid URL: ${String(url)}`)); } - const { hostname } = parsed; - - const result = await this.lookupAndValidate(hostname, { all: true }); - if (!result.ok) { - return result; - } - - return createResultOk(undefined); + const result = await this.withEvents( + 'pre_flight', + async () => await this.lookupAndValidate(parsed.hostname, { all: true }), + ); + return result.ok ? createResultOk(undefined) : result; } /** @@ -99,6 +130,21 @@ export class SsrfProtectionService implements SsrfBridge { return createResultOk(undefined); } + /** + * Connect-time validation for a host a socket is about to connect to directly. + * + * IP-literal hosts (including IPv6 bracket notation) are validated. + * Reason: Node skips the secure `lookup` when the target is already an IP. + * Hostnames are resolved and validated by {@link createSecureLookup} at resolution time. + */ + validateConnectionHost(host: string): SsrfCheckResult { + const ip = this.normalizeIpInHostname(host); + if (!isIP(ip)) { + return createResultOk(undefined); + } + return this.withEvents('connect_time', () => this.validateIp(ip)); + } + /** * Create a custom DNS lookup function that is a drop-in replacement for * Node.js `dns.lookup`. It can be passed to `socket.connect({ lookup })` @@ -144,7 +190,7 @@ export class SsrfProtectionService implements SsrfBridge { const cleanIp = this.normalizeIpInHostname(hostname); if (isIP(cleanIp)) { - const result = this.validateIp(cleanIp); + const result = this.withEvents('redirect', () => this.validateIp(cleanIp)); if (!result.ok) { throw result.error; } @@ -166,7 +212,10 @@ export class SsrfProtectionService implements SsrfBridge { hostname: string, options: LookupOptions, ): Promise<LookupAddress[]> { - const result = await this.lookupAndValidate(hostname, options); + const result = await this.withEvents( + 'connect_time', + async () => await this.lookupAndValidate(hostname, options), + ); if (!result.ok) { throw result.error; } @@ -220,6 +269,50 @@ export class SsrfProtectionService implements SsrfBridge { return createResultOk(resolved); } + /** Runs `fn` and emits `ssrf.allowed` or `ssrf.blocked` based on the result. */ + private withEvents<T>(phase: SsrfPhase, fn: () => Result<T, Error>): Result<T, Error>; + private withEvents<T>( + phase: SsrfPhase, + fn: () => Promise<Result<T, Error>>, + ): Promise<Result<T, Error>>; + private withEvents<T>( + phase: SsrfPhase, + fn: () => Result<T, Error> | Promise<Result<T, Error>>, + ): Result<T, Error> | Promise<Result<T, Error>> { + const start = performance.now(); + const result = fn(); + + const emitAndReturn = (result: Result<T, Error>): Result<T, Error> => { + const durationMs = performance.now() - start; + if (result.ok) { + this.events.emit('ssrf.allowed', { phase, durationMs }); + } else { + this.events.emit('ssrf.blocked', { + phase, + reason: this.toReason(result.error), + durationMs, + }); + } + return result; + }; + + const emitAndRethrow = (error: unknown): never => { + emitAndReturn(createResultError(ensureError(error))); + throw error; + }; + + return result instanceof Promise + ? result.then(emitAndReturn, emitAndRethrow) + : emitAndReturn(result); + } + + private toReason(error: Error): string { + if (error instanceof SsrfBlockedIpError) { + return 'blocked_ip'; + } + return 'dns_error'; + } + private tryParseUrl(url: string | URL): URL | null { try { return url instanceof URL ? url : new URL(url); diff --git a/packages/@n8n/backend-network/src/testing.ts b/packages/@n8n/backend-network/src/testing.ts new file mode 100644 index 00000000000..3dd2edf3106 --- /dev/null +++ b/packages/@n8n/backend-network/src/testing.ts @@ -0,0 +1,12 @@ +/** + * Test-only entry point (`@n8n/backend-network/testing`). + * + * These helpers are not part of the runtime contract: they exist so existing + * test suites in other packages can exercise the axios translation internals + * directly. Keep them out of the main barrel so the public surface stays + * limited to what production callers actually need. + */ +export { convertN8nRequestToAxios } from './http/axios/request'; +export { generateContentLengthHeader, isFormDataInstance } from './http/axios/utils'; +export { buildRfcStyleUserAgent, getDefaultN8nOutboundUserAgent } from './http/axios/user-agent'; +export { startServer, type LocalServer } from './http/local-server'; diff --git a/packages/@n8n/backend-network/tsconfig.build.json b/packages/@n8n/backend-network/tsconfig.build.json new file mode 100644 index 00000000000..ee0e3e20fda --- /dev/null +++ b/packages/@n8n/backend-network/tsconfig.build.json @@ -0,0 +1,11 @@ +{ + "extends": ["./tsconfig.json", "@n8n/typescript-config/tsconfig.build.json"], + "compilerOptions": { + "composite": true, + "rootDir": "src", + "outDir": "dist", + "tsBuildInfoFile": "dist/build.tsbuildinfo" + }, + "include": ["src/**/*.ts"], + "exclude": ["src/**/__tests__/**"] +} diff --git a/packages/@n8n/backend-network/tsconfig.json b/packages/@n8n/backend-network/tsconfig.json new file mode 100644 index 00000000000..a831509d190 --- /dev/null +++ b/packages/@n8n/backend-network/tsconfig.json @@ -0,0 +1,17 @@ +{ + "extends": "@n8n/typescript-config/tsconfig.common.json", + "compilerOptions": { + "types": ["node", "vitest/globals"], + "tsBuildInfoFile": "dist/typecheck.tsbuildinfo", + "experimentalDecorators": true, + "emitDecoratorMetadata": true + }, + "include": ["src/**/*.ts"], + "references": [ + { "path": "../../workflow/tsconfig.build.cjs.json" }, + { "path": "../backend-common/tsconfig.build.json" }, + { "path": "../config/tsconfig.build.json" }, + { "path": "../constants/tsconfig.build.json" }, + { "path": "../di/tsconfig.build.json" } + ] +} diff --git a/packages/@n8n/backend-network/vite.config.ts b/packages/@n8n/backend-network/vite.config.ts new file mode 100644 index 00000000000..b22ca6a517b --- /dev/null +++ b/packages/@n8n/backend-network/vite.config.ts @@ -0,0 +1,3 @@ +import { createVitestConfigWithDecorators } from '@n8n/vitest-config/node-decorators'; + +export default createVitestConfigWithDecorators(); diff --git a/packages/@n8n/backend-test-utils/package.json b/packages/@n8n/backend-test-utils/package.json index a5c8e051d28..f9db0099c72 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.25.0", + "version": "1.27.0", "scripts": { "clean": "rimraf dist .turbo", "dev": "pnpm watch", @@ -36,5 +36,6 @@ }, "devDependencies": { "@n8n/typescript-config": "workspace:*" - } + }, + "license": "LicenseRef-n8n-sustainable-use" } diff --git a/packages/@n8n/backend-test-utils/src/db/workflows.ts b/packages/@n8n/backend-test-utils/src/db/workflows.ts index 01e50682a18..86f9d1ac08c 100644 --- a/packages/@n8n/backend-test-utils/src/db/workflows.ts +++ b/packages/@n8n/backend-test-utils/src/db/workflows.ts @@ -7,6 +7,9 @@ import { WorkflowRepository, WorkflowHistoryRepository, WorkflowPublishHistoryRepository, + WorkflowDependencies, + WorkflowDependencyRepository, + WebhookRepository, } from '@n8n/db'; import { Container } from '@n8n/di'; import type { WorkflowSharingRole } from '@n8n/permissions'; @@ -43,6 +46,27 @@ export function newWorkflow(attributes: Partial<IWorkflowDb> = {}): IWorkflowDb return workflowEntity; } +async function populateWorkflowDependencies(workflow: IWorkflowDb) { + const dependencies = new WorkflowDependencies(workflow.id, workflow.versionCounter); + + for (const node of workflow.nodes) { + if (node.type) { + dependencies.add({ + dependencyType: 'nodeType', + dependencyKey: node.type, + dependencyInfo: { nodeId: node.id, nodeVersion: node.typeVersion }, + }); + } + } + + if (dependencies.dependencies.length > 0) { + await Container.get(WorkflowDependencyRepository).updateDependenciesForWorkflow( + workflow.id, + dependencies, + ); + } +} + /** * Store a workflow in the DB (without a trigger) and optionally assign it to a user. * @param attributes workflow attributes @@ -77,6 +101,8 @@ export async function createWorkflow( ); } + await populateWorkflowDependencies(workflow); + return workflow; } @@ -321,3 +347,8 @@ export async function createActiveWorkflow( return workflow; } + +export async function deleteWorkflowAndWebhooks(workflowId: string) { + await Container.get(WorkflowRepository).delete({ id: workflowId }); + await Container.get(WebhookRepository).delete({ workflowId }); +} diff --git a/packages/@n8n/backend-test-utils/src/test-db.ts b/packages/@n8n/backend-test-utils/src/test-db.ts index 9af13a725e1..cacbe2f3136 100644 --- a/packages/@n8n/backend-test-utils/src/test-db.ts +++ b/packages/@n8n/backend-test-utils/src/test-db.ts @@ -30,6 +30,10 @@ export const getBootstrapDBOptions = (): DataSourceOptions => { /** * Initialize one test DB per suite run, with bootstrap connection if needed. + * + * When `N8N_TEST_TEMPLATE_DB` is set (Postgres only), the new test DB is created + * via `CREATE DATABASE ... TEMPLATE <name>`, which clones the schema as a file + * copy and skips the multi-second migration replay per file. */ export async function init() { if (isInitialized) return; @@ -38,10 +42,16 @@ export async function init() { const dbType = globalConfig.database.type; testDbName = `${testDbPrefix}${randomString(6, 10).toLowerCase()}_${Date.now()}`; + const templateDb = dbType === 'postgresdb' ? process.env.N8N_TEST_TEMPLATE_DB : undefined; + if (dbType === 'postgresdb') { originalDatabase = globalConfig.database.postgresdb.database; const bootstrapPostgres = await new Connection(getBootstrapDBOptions()).initialize(); - await bootstrapPostgres.query(`CREATE DATABASE ${testDbName}`); + if (templateDb) { + await bootstrapPostgres.query(`CREATE DATABASE ${testDbName} TEMPLATE ${templateDb}`); + } else { + await bootstrapPostgres.query(`CREATE DATABASE ${testDbName}`); + } await bootstrapPostgres.destroy(); globalConfig.database.postgresdb.database = testDbName; @@ -49,13 +59,57 @@ export async function init() { const dbConnection = Container.get(DbConnection); await dbConnection.init(); - await dbConnection.migrate(); - await Container.get(AuthRolesService).init(); + if (templateDb) { + // Template already carries migrations + seeded roles — just mark state. + dbConnection.connectionState.migrated = true; + } else { + await dbConnection.migrate(); + await Container.get(AuthRolesService).init(); + } isInitialized = true; } +/** + * Build a Postgres template DB with all migrations + auth roles seeded. + * Idempotent: drops any existing DB with the same name first. + * Called from Jest globalSetup (orchestrator process) before workers fork — + * each worker's `init()` then clones from the template instead of replaying + * the full migration history. + */ +export async function initTemplateDb(templateName: string): Promise<void> { + const globalConfig = Container.get(GlobalConfig); + if (globalConfig.database.type !== 'postgresdb') { + throw new Error('initTemplateDb only supports postgresdb'); + } + + const originalDb = globalConfig.database.postgresdb.database; + + const bootstrap = await new Connection(getBootstrapDBOptions()).initialize(); + await bootstrap.query( + `UPDATE pg_database SET datistemplate = false WHERE datname = '${templateName}'`, + ); + await bootstrap.query(`DROP DATABASE IF EXISTS ${templateName}`); + await bootstrap.query(`CREATE DATABASE ${templateName}`); + await bootstrap.destroy(); + + globalConfig.database.postgresdb.database = templateName; + const dbConnection = Container.get(DbConnection); + await dbConnection.init(); + await dbConnection.migrate(); + await Container.get(AuthRolesService).init(); + await dbConnection.close(); + globalConfig.database.postgresdb.database = originalDb; + + // Mark as template so CREATE DATABASE ... TEMPLATE will accept it. + const finalizer = await new Connection(getBootstrapDBOptions()).initialize(); + await finalizer.query( + `UPDATE pg_database SET datistemplate = true WHERE datname = '${templateName}'`, + ); + await finalizer.destroy(); +} + export function isReady() { const { connectionState } = Container.get(DbConnection); return connectionState.connected && connectionState.migrated; @@ -85,6 +139,15 @@ export async function terminate() { testDbName = undefined; } + // Clear all cached DI singletons (DbConnection, DataSource, GlobalConfig, + // AuthRolesService, …). With persistent Jest workers (no per-file process + // recycling), the next test file's testDb.init() would otherwise reuse the + // DbConnection instance whose DataSource we just destroyed — and try to + // .initialize() it again, which hangs. Resetting forces the next get() to + // rebuild the whole chain from the freshly-set env vars (e.g. the new + // per-file Postgres database name we just switched to). + Container.reset(); + isInitialized = false; } diff --git a/packages/@n8n/backend-test-utils/tsconfig.build.json b/packages/@n8n/backend-test-utils/tsconfig.build.json index ee0e3e20fda..e08cb937d03 100644 --- a/packages/@n8n/backend-test-utils/tsconfig.build.json +++ b/packages/@n8n/backend-test-utils/tsconfig.build.json @@ -3,8 +3,7 @@ "compilerOptions": { "composite": true, "rootDir": "src", - "outDir": "dist", - "tsBuildInfoFile": "dist/build.tsbuildinfo" + "outDir": "dist" }, "include": ["src/**/*.ts"], "exclude": ["src/**/__tests__/**"] diff --git a/packages/@n8n/backend-test-utils/tsconfig.json b/packages/@n8n/backend-test-utils/tsconfig.json index 5fe436c08a3..3a807ec1f86 100644 --- a/packages/@n8n/backend-test-utils/tsconfig.json +++ b/packages/@n8n/backend-test-utils/tsconfig.json @@ -2,7 +2,6 @@ "extends": "@n8n/typescript-config/tsconfig.common.json", "compilerOptions": { "types": ["node", "jest"], - "tsBuildInfoFile": "dist/typecheck.tsbuildinfo", "experimentalDecorators": true, "emitDecoratorMetadata": true }, diff --git a/packages/@n8n/benchmark/Dockerfile b/packages/@n8n/benchmark/Dockerfile index 42fe1966edb..64ac83d69c0 100644 --- a/packages/@n8n/benchmark/Dockerfile +++ b/packages/@n8n/benchmark/Dockerfile @@ -1,5 +1,5 @@ # syntax=docker/dockerfile:1 -FROM node:24.15.0 AS base +FROM node:24.16.0 AS base # Install required dependencies RUN apt-get update && apt-get install -y gnupg2 curl diff --git a/packages/@n8n/benchmark/package.json b/packages/@n8n/benchmark/package.json index ee96c1ad11a..4cb48414d42 100644 --- a/packages/@n8n/benchmark/package.json +++ b/packages/@n8n/benchmark/package.json @@ -1,6 +1,6 @@ { "name": "@n8n/n8n-benchmark", - "version": "2.10.0", + "version": "2.12.0", "description": "Cli for running benchmark tests for n8n", "main": "dist/index", "scripts": { @@ -53,5 +53,6 @@ "bin": "n8n-benchmark", "commands": "./dist/commands", "topicSeparator": " " - } + }, + "license": "LicenseRef-n8n-sustainable-use" } diff --git a/packages/@n8n/benchmark/tsconfig.build.json b/packages/@n8n/benchmark/tsconfig.build.json index 917b2f83f98..afcbdd550ec 100644 --- a/packages/@n8n/benchmark/tsconfig.build.json +++ b/packages/@n8n/benchmark/tsconfig.build.json @@ -2,8 +2,7 @@ "extends": ["./tsconfig.json", "@n8n/typescript-config/tsconfig.build.json"], "compilerOptions": { "rootDir": "src", - "outDir": "dist", - "tsBuildInfoFile": "dist/build.tsbuildinfo" + "outDir": "dist" }, "include": ["src/**/*.ts"] } diff --git a/packages/@n8n/chat-hub/package.json b/packages/@n8n/chat-hub/package.json index 60370c60e5c..0f0c0931008 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.18.0", + "version": "1.20.0", "scripts": { "clean": "rimraf dist .turbo", "dev": "pnpm watch", @@ -30,5 +30,6 @@ }, "dependencies": { "@n8n/api-types": "workspace:*" - } + }, + "license": "LicenseRef-n8n-sustainable-use" } diff --git a/packages/@n8n/chat-hub/tsconfig.build.json b/packages/@n8n/chat-hub/tsconfig.build.json index 87d5dd2f856..c134a3ee7ea 100644 --- a/packages/@n8n/chat-hub/tsconfig.build.json +++ b/packages/@n8n/chat-hub/tsconfig.build.json @@ -3,8 +3,7 @@ "compilerOptions": { "composite": true, "rootDir": "src", - "outDir": "dist", - "tsBuildInfoFile": "dist/build.tsbuildinfo" + "outDir": "dist" }, "include": ["src/**/*.ts"], "exclude": ["src/**/__tests__/**", "src/**/*.test.ts"] diff --git a/packages/@n8n/chat-hub/tsconfig.json b/packages/@n8n/chat-hub/tsconfig.json index dc228c3c5d8..0eac8b7643e 100644 --- a/packages/@n8n/chat-hub/tsconfig.json +++ b/packages/@n8n/chat-hub/tsconfig.json @@ -1,8 +1,7 @@ { "extends": "@n8n/typescript-config/tsconfig.common.json", "compilerOptions": { - "types": ["node", "vitest/globals"], - "tsBuildInfoFile": "dist/typecheck.tsbuildinfo" + "types": ["node", "vitest/globals"] }, "include": ["src/**/*.ts"], "references": [{ "path": "../api-types/tsconfig.build.json" }] diff --git a/packages/@n8n/cli/README.md b/packages/@n8n/cli/README.md index cf0e1758d8e..3bac5ba89dc 100644 --- a/packages/@n8n/cli/README.md +++ b/packages/@n8n/cli/README.md @@ -61,6 +61,7 @@ n8n-cli --url=https://my-n8n.app.n8n.cloud --api-key=n8n_api_xxxxx workflow list | `user` | `list`, `get` | | `config` | `set-url`, `set-api-key`, `show` | | `source-control` | `pull` | +| `package` | `export`, `import` _(beta)_ | | `skill` | `install` | | `audit` | _(top-level)_ | | `login` / `logout` | _(top-level)_ | diff --git a/packages/@n8n/cli/docs/commands/package.md b/packages/@n8n/cli/docs/commands/package.md new file mode 100644 index 00000000000..31d78a64163 --- /dev/null +++ b/packages/@n8n/cli/docs/commands/package.md @@ -0,0 +1,48 @@ +# package + +Export and import workflows as portable n8n packages (`.n8np` archives). + +> **Beta — disabled by default.** These commands call beta endpoints that the +> target instance must opt into with `N8N_PUBLIC_API_PACKAGES_ENABLED=true`, and +> the n8n Packages feature must be licensed. While disabled, the instance returns +> `404` and the CLI prints a hint explaining how to enable it. + +## `package export` + +Export one or more workflows into a gzipped `.n8np` archive written to disk. + +```bash +n8n-cli package export --workflow-id=abc --output=export.n8np +n8n-cli package export -w abc -w def -o team.n8np +``` + +| Flag | Description | +|------|-------------| +| `-w, --workflow-id` | Workflow ID to include. Repeat the flag to export several. (required) | +| `-o, --output` | File to write the package to. Defaults to `export.n8np`. | + +Requires the API key to hold the `workflow:export` scope. + +## `package import` + +Import a `.n8np` archive into a project. + +```bash +n8n-cli package import --file=export.n8np --conflict-policy=fail +n8n-cli package import --file=export.n8np --project=<id> --conflict-policy=new-version +``` + +| Flag | Description | +|------|-------------| +| `--file` | Path to the `.n8np` package file. (required) | +| `--conflict-policy` | What to do when a workflow already exists by source ID: `new-version`, `fail`, or `skip`. (required) | +| `--project` | Target project ID. Defaults to your personal project. | +| `--folder` | Target folder ID within the project. Defaults to the project root. | +| `--workflow-id-policy` | Whether imported workflows keep their source ID (`source`) or receive a new one (`new`). | +| `--credential-matching-mode` | How credential references are matched on the target instance (`id-only`). | +| `--credential-missing-mode` | What to do when a referenced credential cannot be resolved (`must-preexist`). | + +Requires the API key to hold the `workflow:import` scope. When the import is +blocked — for example by a workflow conflict under `--conflict-policy=fail`, or +by a credential that does not exist on the target instance — the command exits +non-zero and lists the blocking issues. diff --git a/packages/@n8n/cli/package.json b/packages/@n8n/cli/package.json index adc30713a14..adde7e0e75b 100644 --- a/packages/@n8n/cli/package.json +++ b/packages/@n8n/cli/package.json @@ -1,8 +1,8 @@ { "name": "@n8n/cli", - "version": "0.6.0", + "version": "0.8.0", "description": "[beta] Client CLI for n8n — manage workflows, executions, and credentials from the terminal", - "license": "SEE LICENSE IN LICENSE.md", + "license": "LicenseRef-n8n-sustainable-use", "bin": { "n8n-cli": "bin/n8n-cli.mjs" }, @@ -66,6 +66,9 @@ "source-control": { "description": "Pull changes from the configured source control provider" }, + "package": { + "description": "Export and import workflows as n8n packages (beta)" + }, "skill": { "description": "Install n8n CLI skills for AI coding agents" } diff --git a/packages/@n8n/cli/src/__tests__/client.test.ts b/packages/@n8n/cli/src/__tests__/client.test.ts new file mode 100644 index 00000000000..4dfa343d020 --- /dev/null +++ b/packages/@n8n/cli/src/__tests__/client.test.ts @@ -0,0 +1,123 @@ +import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'; + +import { ApiError, N8nClient } from '../client'; + +function jsonResponse(status: number, body: unknown): Response { + return { + ok: status >= 200 && status < 300, + status, + statusText: '', + headers: new Headers([['content-type', 'application/json']]), + json: vi.fn().mockResolvedValue(body), + text: vi.fn().mockResolvedValue(JSON.stringify(body)), + arrayBuffer: vi.fn().mockResolvedValue(new ArrayBuffer(0)), + } as unknown as Response; +} + +function binaryResponse(status: number, bytes: Uint8Array): Response { + return { + ok: status >= 200 && status < 300, + status, + statusText: '', + headers: new Headers([['content-type', 'application/gzip']]), + json: vi.fn().mockRejectedValue(new Error('not json')), + text: vi.fn().mockResolvedValue(''), + arrayBuffer: vi + .fn() + .mockResolvedValue(bytes.buffer.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength)), + } as unknown as Response; +} + +describe('N8nClient packages', () => { + const fetchMock = vi.fn(); + let client: N8nClient; + + beforeEach(() => { + vi.stubGlobal('fetch', fetchMock); + fetchMock.mockReset(); + client = new N8nClient({ baseUrl: 'https://n8n.example.com', apiKey: 'test-key' }); + }); + + afterEach(() => { + vi.unstubAllGlobals(); + }); + + describe('exportPackage', () => { + it('posts the workflow IDs as JSON and returns the archive bytes', async () => { + fetchMock.mockResolvedValue(binaryResponse(200, new Uint8Array([1, 2, 3]))); + + const result = await client.exportPackage(['a', 'b']); + + expect(Buffer.isBuffer(result)).toBe(true); + expect(result.equals(Buffer.from([1, 2, 3]))).toBe(true); + + const [url, init] = fetchMock.mock.calls[0] as [string, RequestInit]; + expect(url).toBe('https://n8n.example.com/api/v1/n8n-packages/export'); + expect(init.body).toBe(JSON.stringify({ workflowIds: ['a', 'b'] })); + }); + }); + + describe('importPackage', () => { + it('sends a multipart body with the file and non-empty fields', async () => { + fetchMock.mockResolvedValue(jsonResponse(200, { workflows: [], bindings: {} })); + + await client.importPackage( + { buffer: Buffer.from('package-bytes'), filename: 'export.n8np' }, + { + workflowConflictPolicy: 'fail', + projectId: 'proj-1', + folderId: '', + workflowIdPolicy: 'new', + credentialMatchingMode: undefined, + }, + ); + + const [url, init] = fetchMock.mock.calls[0] as [string, RequestInit]; + expect(url).toBe('https://n8n.example.com/api/v1/n8n-packages/import'); + expect(init.body).toBeInstanceOf(FormData); + + const form = init.body as FormData; + expect(form.get('workflowConflictPolicy')).toBe('fail'); + expect(form.get('projectId')).toBe('proj-1'); + expect(form.get('workflowIdPolicy')).toBe('new'); + // Empty/undefined fields are omitted entirely. + expect(form.has('folderId')).toBe(false); + expect(form.has('credentialMatchingMode')).toBe(false); + + const pkg = form.get('package'); + expect(pkg).toBeInstanceOf(Blob); + expect((pkg as File).name).toBe('export.n8np'); + + // Multipart requests must not carry the default JSON content type; + // fetch fills in multipart/form-data with its own boundary. + expect((init.headers as Headers).get('content-type')).toBeNull(); + }); + + it('throws an ApiError that preserves the blocking-issue details', async () => { + const body = { + message: 'Import blocked', + issues: [ + { + type: 'workflow-conflict', + name: 'Flow', + sourceWorkflowId: 's1', + existingWorkflowId: 'e1', + }, + ], + }; + fetchMock.mockResolvedValue(jsonResponse(409, body)); + + const error = await client + .importPackage( + { buffer: Buffer.from('p'), filename: 'x.n8np' }, + { workflowConflictPolicy: 'fail' }, + ) + .catch((e: unknown) => e); + + expect(error).toBeInstanceOf(ApiError); + expect((error as ApiError).statusCode).toBe(409); + expect((error as ApiError).message).toBe('Import blocked'); + expect((error as ApiError).details).toEqual(body); + }); + }); +}); diff --git a/packages/@n8n/cli/src/__tests__/package-error.test.ts b/packages/@n8n/cli/src/__tests__/package-error.test.ts new file mode 100644 index 00000000000..3c475378305 --- /dev/null +++ b/packages/@n8n/cli/src/__tests__/package-error.test.ts @@ -0,0 +1,63 @@ +import { describe, it, expect } from 'vitest'; + +import { ApiError } from '../client'; +import { toPackagesError } from '../commands/package/shared'; + +describe('toPackagesError', () => { + it('returns non-ApiError values unchanged', () => { + const error = new Error('boom'); + expect(toPackagesError(error)).toBe(error); + }); + + it('adds a beta-enablement hint for a 404', () => { + const result = toPackagesError(new ApiError(404, 'Not Found')); + + expect(result).toBeInstanceOf(ApiError); + expect((result as ApiError).statusCode).toBe(404); + expect((result as ApiError).hint).toContain('N8N_PUBLIC_API_PACKAGES_ENABLED=true'); + }); + + it('lists workflow-conflict issues for a 409', () => { + const result = toPackagesError( + new ApiError(409, 'Import blocked', undefined, { + issues: [ + { + type: 'workflow-conflict', + name: 'Flow', + sourceWorkflowId: 's1', + existingWorkflowId: 'e1', + }, + ], + }), + ); + + const hint = (result as ApiError).hint ?? ''; + expect(hint).toContain('Blocking issues:'); + expect(hint).toContain('workflow "Flow"'); + expect(hint).toContain('e1'); + }); + + it('lists credential-unresolved issues for a 422', () => { + const result = toPackagesError( + new ApiError(422, 'Import blocked', undefined, { + issues: [ + { + type: 'credential-unresolved', + kind: 'not_found', + sourceId: 'c1', + usedByWorkflows: ['w1', 'w2'], + }, + ], + }), + ); + + const hint = (result as ApiError).hint ?? ''; + expect(hint).toContain('credential c1 unresolved (not_found)'); + expect(hint).toContain('w1, w2'); + }); + + it('leaves other ApiErrors without issue details unchanged', () => { + const error = new ApiError(400, 'Bad request'); + expect(toPackagesError(error)).toBe(error); + }); +}); diff --git a/packages/@n8n/cli/src/__tests__/package-export.test.ts b/packages/@n8n/cli/src/__tests__/package-export.test.ts new file mode 100644 index 00000000000..946b447ea31 --- /dev/null +++ b/packages/@n8n/cli/src/__tests__/package-export.test.ts @@ -0,0 +1,43 @@ +import type { Config } from '@oclif/core'; +import * as fs from 'node:fs'; +import { describe, it, expect, vi, afterEach } from 'vitest'; + +import type { N8nClient } from '../client'; +import PackageExport from '../commands/package/export'; + +vi.mock('node:fs'); + +const mockedWriteFileSync = vi.mocked(fs.writeFileSync); + +/** The command methods we stub to isolate the file-writing behaviour from oclif/networking. */ +interface ExportInternals { + parse: () => Promise<{ flags: { workflowId: string[]; output: string } }>; + getClient: () => N8nClient; + succeed: () => void; +} + +describe('package export command', () => { + afterEach(() => { + vi.restoreAllMocks(); + }); + + it('writes the bytes returned by the client to the --output path', async () => { + const archive = Buffer.from([1, 2, 3]); + const exportPackage = vi.fn().mockResolvedValue(archive); + + const command = new PackageExport([], {} as Config); + const internals = command as unknown as ExportInternals; + // Bypass oclif arg parsing, connection setup, and the success/exit path; the + // behaviour under test is purely that the client's bytes land at flags.output. + vi.spyOn(internals, 'parse').mockResolvedValue({ + flags: { workflowId: ['wf-1', 'wf-2'], output: '/tmp/team.n8np' }, + }); + vi.spyOn(internals, 'getClient').mockReturnValue({ exportPackage } as unknown as N8nClient); + vi.spyOn(internals, 'succeed').mockImplementation(() => {}); + + await command.run(); + + expect(exportPackage).toHaveBeenCalledWith(['wf-1', 'wf-2']); + expect(mockedWriteFileSync).toHaveBeenCalledWith('/tmp/team.n8np', archive); + }); +}); diff --git a/packages/@n8n/cli/src/client.ts b/packages/@n8n/cli/src/client.ts index 8692f3d06d6..2a3328f6f76 100644 --- a/packages/@n8n/cli/src/client.ts +++ b/packages/@n8n/cli/src/client.ts @@ -9,11 +9,21 @@ export interface ClientOptions { debug?: (message: string) => void; } +export interface ImportPackageFields { + projectId?: string; + folderId?: string; + credentialMatchingMode?: string; + credentialMissingMode?: string; + workflowConflictPolicy: string; + workflowIdPolicy?: string; +} + export class ApiError extends Error { constructor( readonly statusCode: number, message: string, readonly hint?: string, + readonly details?: unknown, ) { super(message); this.name = 'ApiError'; @@ -47,7 +57,12 @@ export class N8nClient { private async request<T>( method: string, path: string, - options: { body?: unknown; query?: Record<string, string> } = {}, + options: { + body?: unknown; + query?: Record<string, string>; + formData?: FormData; + responseType?: 'json' | 'binary'; + } = {}, ): Promise<T> { const url = new URL(`${this.baseUrl}${path}`); if (options.query) { @@ -59,13 +74,18 @@ export class N8nClient { this.debug?.(`→ ${method} ${url}`); const start = Date.now(); + const headers = new Headers(this.headers); + let body: BodyInit | undefined; + if (options.formData) { + headers.delete('Content-Type'); + body = options.formData; + } else if (options.body !== undefined) { + body = JSON.stringify(options.body); + } + let response: Response; try { - response = await fetch(url.toString(), { - method, - headers: this.headers, - body: options.body ? JSON.stringify(options.body) : undefined, - }); + response = await fetch(url.toString(), { method, headers, body }); } catch (error) { const msg = error instanceof Error ? error.message : String(error); this.debug?.(`✗ Connection failed (${Date.now() - start}ms): ${msg}`); @@ -78,18 +98,11 @@ export class N8nClient { this.debug?.(`← ${response.status} ${response.statusText} (${Date.now() - start}ms)`); - if (response.status === 204) { - return undefined as T; - } - - const contentType = response.headers.get('content-type') ?? ''; - const isJson = contentType.includes('application/json'); - const data: unknown = isJson ? await response.json() : await response.text(); - if (!response.ok) { + const errorBody = await this.readBody(response); const message = - typeof data === 'object' && data !== null && 'message' in data - ? String((data as Record<string, unknown>).message) + typeof errorBody === 'object' && errorBody !== null && 'message' in errorBody + ? String((errorBody as Record<string, unknown>).message) : `Request failed (${response.status})`; const hint = response.status === 401 @@ -97,10 +110,23 @@ export class N8nClient { : response.status === 404 ? 'Resource not found. Verify the ID is correct.' : undefined; - throw new ApiError(response.status, message, hint); + throw new ApiError(response.status, message, hint, errorBody); } - return data as T; + if (response.status === 204) { + return undefined as T; + } + + if (options.responseType === 'binary') { + return Buffer.from(await response.arrayBuffer()) as T; + } + + return (await this.readBody(response)) as T; + } + + private async readBody(response: Response): Promise<unknown> { + const contentType = response.headers.get('content-type') ?? ''; + return contentType.includes('application/json') ? await response.json() : await response.text(); } private async get<T>(path: string, query?: Record<string, string>): Promise<T> { @@ -393,6 +419,29 @@ export class N8nClient { }); } + // ─── Packages (beta) ─────────────────────────────────────────── + + async exportPackage(workflowIds: string[]): Promise<Buffer> { + return await this.request<Buffer>('POST', '/n8n-packages/export', { + body: { workflowIds }, + responseType: 'binary', + }); + } + + async importPackage( + file: { buffer: Buffer; filename: string }, + fields: ImportPackageFields, + ): Promise<Record<string, unknown>> { + const form = new FormData(); + form.append('package', new Blob([new Uint8Array(file.buffer)]), file.filename); + for (const [key, value] of Object.entries(fields)) { + if (typeof value === 'string' && value !== '') form.append(key, value); + } + return await this.request<Record<string, unknown>>('POST', '/n8n-packages/import', { + formData: form, + }); + } + // ─── Audit ───────────────────────────────────────────────────── async audit(categories?: string[]) { diff --git a/packages/@n8n/cli/src/commands/package/export.ts b/packages/@n8n/cli/src/commands/package/export.ts new file mode 100644 index 00000000000..6ea633875f0 --- /dev/null +++ b/packages/@n8n/cli/src/commands/package/export.ts @@ -0,0 +1,48 @@ +import { Flags } from '@oclif/core'; +import * as fs from 'node:fs'; + +import { toPackagesError } from './shared'; +import { BaseCommand } from '../../base-command'; + +export default class PackageExport extends BaseCommand { + static override description = 'Export workflows as an n8n package (.n8np)'; + + static override examples = [ + '<%= config.bin %> package export --workflow-id=abc --output=export.n8np', + '<%= config.bin %> package export -w abc -w def -o team.n8np', + ]; + + static override flags = { + ...BaseCommand.baseFlags, + workflowId: Flags.string({ + char: 'w', + description: 'Workflow ID to include (repeat for multiple)', + multiple: true, + required: true, + aliases: ['workflow-id'], + }), + output: Flags.string({ + char: 'o', + description: 'File to write the package to', + default: 'export.n8np', + }), + }; + + async run(): Promise<void> { + const { flags } = await this.parse(PackageExport); + await this.execute(async () => { + const client = this.getClient(flags); + let archive: Buffer; + try { + archive = await client.exportPackage(flags.workflowId); + } catch (error) { + throw toPackagesError(error); + } + fs.writeFileSync(flags.output, archive); + this.succeed(`Exported ${flags.workflowId.length} workflow(s) to ${flags.output}`, flags, { + output: flags.output, + workflowIds: flags.workflowId, + }); + }); + } +} diff --git a/packages/@n8n/cli/src/commands/package/import.ts b/packages/@n8n/cli/src/commands/package/import.ts new file mode 100644 index 00000000000..3f355dfec6d --- /dev/null +++ b/packages/@n8n/cli/src/commands/package/import.ts @@ -0,0 +1,77 @@ +import { Flags } from '@oclif/core'; +import * as fs from 'node:fs'; +import * as path from 'node:path'; + +import { toPackagesError } from './shared'; +import { BaseCommand } from '../../base-command'; + +export default class PackageImport extends BaseCommand { + static override description = 'Import an n8n package (.n8np) into a project'; + + static override examples = [ + '<%= config.bin %> package import --file=export.n8np --conflict-policy=fail', + '<%= config.bin %> package import --file=export.n8np --project=<id> --conflict-policy=new-version', + ]; + + static override flags = { + ...BaseCommand.baseFlags, + file: Flags.string({ description: 'Path to the .n8np package file', required: true }), + project: Flags.string({ + description: 'Target project ID (defaults to your personal project)', + }), + folder: Flags.string({ + description: 'Target folder ID within the project (defaults to the project root)', + }), + conflictPolicy: Flags.string({ + description: 'What to do when a workflow already exists in the target project', + options: ['new-version', 'fail', 'skip'], + required: true, + aliases: ['conflict-policy'], + }), + workflowIdPolicy: Flags.string({ + description: 'Whether imported workflows keep their source ID or receive a new one', + options: ['new', 'source'], + aliases: ['workflow-id-policy'], + }), + credentialMatchingMode: Flags.string({ + description: 'How credential references are matched on the target instance', + options: ['id-only'], + aliases: ['credential-matching-mode'], + }), + credentialMissingMode: Flags.string({ + description: 'What to do when a referenced credential cannot be resolved', + options: ['must-preexist'], + aliases: ['credential-missing-mode'], + }), + }; + + async run(): Promise<void> { + const { flags } = await this.parse(PackageImport); + + if (!fs.existsSync(flags.file)) { + this.error(`File not found: ${flags.file}`); + } + + await this.execute(async () => { + const buffer = fs.readFileSync(flags.file); + const client = this.getClient(flags); + let result: Record<string, unknown>; + try { + result = await client.importPackage( + { buffer, filename: path.basename(flags.file) }, + { + projectId: flags.project, + folderId: flags.folder, + workflowConflictPolicy: flags.conflictPolicy, + workflowIdPolicy: flags.workflowIdPolicy, + credentialMatchingMode: flags.credentialMatchingMode, + credentialMissingMode: flags.credentialMissingMode, + }, + ); + } catch (error) { + throw toPackagesError(error); + } + this.output(result, flags); + }); + } +} diff --git a/packages/@n8n/cli/src/commands/package/shared.ts b/packages/@n8n/cli/src/commands/package/shared.ts new file mode 100644 index 00000000000..864c875e125 --- /dev/null +++ b/packages/@n8n/cli/src/commands/package/shared.ts @@ -0,0 +1,46 @@ +import { ApiError } from '../../client'; + +const BETA_HINT = + 'The n8n Packages API is beta and disabled by default. Enable it on the instance with ' + + 'N8N_PUBLIC_API_PACKAGES_ENABLED=true (requires the n8n Packages license).'; + +type BlockingIssue = + | { + type: 'workflow-conflict'; + sourceWorkflowId: string; + existingWorkflowId: string; + name: string; + } + | { type: 'credential-unresolved'; kind: string; sourceId: string; usedByWorkflows: string[] }; + +function formatIssue(issue: unknown): string { + if (typeof issue !== 'object' || issue === null) return JSON.stringify(issue); + const it = issue as Partial<BlockingIssue> & Record<string, unknown>; + if (it.type === 'workflow-conflict') { + return `workflow "${it.name}" (source ${it.sourceWorkflowId}) already exists as ${it.existingWorkflowId}`; + } + if (it.type === 'credential-unresolved') { + const usedBy = Array.isArray(it.usedByWorkflows) ? it.usedByWorkflows.join(', ') : ''; + return `credential ${it.sourceId} unresolved (${it.kind}), used by workflow(s) ${usedBy}`; + } + return JSON.stringify(issue); +} + +function issuesHint(details: unknown): string | undefined { + if (typeof details !== 'object' || details === null) return undefined; + const issues = (details as { issues?: unknown }).issues; + if (!Array.isArray(issues) || issues.length === 0) return undefined; + return ['Blocking issues:', ...issues.map((issue) => ` - ${formatIssue(issue)}`)].join('\n'); +} + +export function toPackagesError(error: unknown): unknown { + if (!(error instanceof ApiError)) return error; + if (error.statusCode === 404) { + return new ApiError(error.statusCode, error.message, BETA_HINT, error.details); + } + const hint = issuesHint(error.details); + if (hint) { + return new ApiError(error.statusCode, error.message, hint, error.details); + } + return error; +} diff --git a/packages/@n8n/cli/src/index.ts b/packages/@n8n/cli/src/index.ts index 5f4571d3b7c..8c051bb1a90 100644 --- a/packages/@n8n/cli/src/index.ts +++ b/packages/@n8n/cli/src/index.ts @@ -24,6 +24,8 @@ import ExecutionRetry from './commands/execution/retry'; import ExecutionStop from './commands/execution/stop'; import Login from './commands/login'; import Logout from './commands/logout'; +import PackageExport from './commands/package/export'; +import PackageImport from './commands/package/import'; import ProjectAddMember from './commands/project/add-member'; import ProjectCreate from './commands/project/create'; import ProjectDelete from './commands/project/delete'; @@ -121,5 +123,8 @@ export const commands = { 'source-control:pull': SourceControlPull, + 'package:export': PackageExport, + 'package:import': PackageImport, + audit: Audit, }; diff --git a/packages/@n8n/cli/tsconfig.build.json b/packages/@n8n/cli/tsconfig.build.json index 877e35d0928..a8561a96258 100644 --- a/packages/@n8n/cli/tsconfig.build.json +++ b/packages/@n8n/cli/tsconfig.build.json @@ -4,8 +4,7 @@ "composite": true, "rootDir": "src", "outDir": "dist", - "declaration": true, - "tsBuildInfoFile": "dist/build.tsbuildinfo" + "declaration": true }, "include": ["src/**/*.ts"], "exclude": ["src/**/__tests__/**", "src/**/*.test.ts"] diff --git a/packages/@n8n/client-oauth2/package.json b/packages/@n8n/client-oauth2/package.json index 70df32a4c49..4ee9f491f8b 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.7.0", + "version": "1.9.0", "scripts": { "clean": "rimraf dist .turbo", "dev": "pnpm watch", @@ -30,6 +30,8 @@ "@n8n/vitest-config": "workspace:*", "@vitest/coverage-v8": "catalog:", "vitest": "catalog:", - "vitest-mock-extended": "catalog:" - } + "vitest-mock-extended": "catalog:", + "nock": "catalog:" + }, + "license": "LicenseRef-n8n-sustainable-use" } diff --git a/packages/@n8n/client-oauth2/src/client-oauth2-token.ts b/packages/@n8n/client-oauth2/src/client-oauth2-token.ts index be4477b90eb..75848889372 100644 --- a/packages/@n8n/client-oauth2/src/client-oauth2-token.ts +++ b/packages/@n8n/client-oauth2/src/client-oauth2-token.ts @@ -83,6 +83,7 @@ export class ClientOAuth2Token { const body: Record<string, string> = { refresh_token: this.refreshToken, grant_type: 'refresh_token', + ...(options.resource ? { resource: options.resource } : {}), }; // Handle different authentication methods diff --git a/packages/@n8n/client-oauth2/src/client-oauth2.ts b/packages/@n8n/client-oauth2/src/client-oauth2.ts index 58ad2168ca8..222cfec98b8 100644 --- a/packages/@n8n/client-oauth2/src/client-oauth2.ts +++ b/packages/@n8n/client-oauth2/src/client-oauth2.ts @@ -34,6 +34,7 @@ export interface ClientOAuth2Options { additionalBodyProperties?: Record<string, any>; body?: Record<string, any>; query?: qs.ParsedUrlQuery; + resource?: string; ignoreSSLIssues?: boolean; } diff --git a/packages/@n8n/client-oauth2/src/code-flow.ts b/packages/@n8n/client-oauth2/src/code-flow.ts index d28091c6d62..68270b368ca 100644 --- a/packages/@n8n/client-oauth2/src/code-flow.ts +++ b/packages/@n8n/client-oauth2/src/code-flow.ts @@ -10,6 +10,7 @@ interface CodeFlowBody { grant_type: 'authorization_code'; redirect_uri?: string; client_id?: string; + resource?: string; } /** @@ -37,6 +38,7 @@ export class CodeFlow { redirect_uri: options.redirectUri, response_type: 'code', state: options.state, + ...(options.resource ? { resource: options.resource } : {}), ...(options.scopes ? { scope: options.scopes.join(options.scopesSeparator ?? ' ') } : {}), }; @@ -96,6 +98,7 @@ export class CodeFlow { code: data.code, grant_type: 'authorization_code', redirect_uri: options.redirectUri, + ...(options.resource ? { resource: options.resource } : {}), }; // `client_id`: REQUIRED, if the client is not authenticating with the diff --git a/packages/@n8n/client-oauth2/src/types.ts b/packages/@n8n/client-oauth2/src/types.ts index 72385d0b3f3..6ce287aaae2 100644 --- a/packages/@n8n/client-oauth2/src/types.ts +++ b/packages/@n8n/client-oauth2/src/types.ts @@ -19,10 +19,23 @@ export interface OAuth2CredentialData { oauthTokenData?: { access_token: string; refresh_token?: string; + resource?: string; }; useDynamicClientRegistration?: boolean; serverUrl?: string; + /* + * Resource indicator lifecycle: + * - `resourceUrl` – raw user input from the credential form (optional override) + * - `resource` – resolved value after discovery / validation, ephemeral for auth URI generation + * - `oauthTokenData.resource` – persisted with tokens so it can be re‑sent on refresh + */ + resourceUrl?: string; jweEnabled?: boolean; + /** + * The resolved RFC 8707 resource indicator, set after discovery/validation. + * Populated from either the discovered metadata or the user's resourceUrl override. + */ + resource?: string; inlineJwks?: boolean; } diff --git a/packages/@n8n/client-oauth2/test/client-oauth2.test.ts b/packages/@n8n/client-oauth2/test/client-oauth2.test.ts index 1b4b12427c2..f0032e134c3 100644 --- a/packages/@n8n/client-oauth2/test/client-oauth2.test.ts +++ b/packages/@n8n/client-oauth2/test/client-oauth2.test.ts @@ -198,4 +198,134 @@ describe('ClientOAuth2', () => { expect(result.body).toEqual('Redirected'); }); }); + + describe('RFC 8707 resource parameter', () => { + const resource = 'https://mcp.example.com/resource'; + + afterEach(() => { + nock.cleanAll(); + vi.restoreAllMocks(); + }); + + const makeClient = (overrides: Partial<ConstructorParameters<typeof ClientOAuth2>[0]> = {}) => + new ClientOAuth2({ + clientId: config.clientId, + clientSecret: config.clientSecret, + accessTokenUri: config.accessTokenUri, + authorizationUri: config.authorizationUri, + redirectUri: config.redirectUri, + authentication: 'header', + state: config.state, + ...overrides, + }); + + const parseBody = (body: unknown) => + new URLSearchParams(typeof body === 'string' ? body : (body as Record<string, string>)); + + const expectPostBody = (expected: Record<string, string>) => + nock(config.baseUrl) + .post('/login/oauth/access_token', (body) => { + const params = parseBody(body); + return Object.entries(expected).every(([key, value]) => params.get(key) === value); + }) + .reply( + 200, + JSON.stringify({ + access_token: config.accessToken, + refresh_token: config.refreshToken, + }), + { 'Content-Type': 'application/json' }, + ); + + it('should include resource in authorization URI when configured', () => { + const uri = makeClient({ resource }).code.getUri(); + + expect(new URL(uri).searchParams.get('resource')).toBe(resource); + }); + + it('should omit resource from authorization URI when not configured', () => { + const uri = makeClient().code.getUri(); + + expect(new URL(uri).searchParams.has('resource')).toBe(false); + }); + + it('should include resource in authorization code token request body when configured', async () => { + const scope = expectPostBody({ + code: config.code, + grant_type: 'authorization_code', + redirect_uri: config.redirectUri, + resource, + }); + + await makeClient({ resource }).code.getToken( + `${config.redirectUri}?code=${config.code}&state=${config.state}`, + ); + + scope.done(); + }); + + it('should omit resource from authorization code token request body when not configured', async () => { + const scope = nock(config.baseUrl) + .post('/login/oauth/access_token', (body) => { + const params = parseBody(body); + return !params.has('resource'); + }) + .reply( + 200, + JSON.stringify({ + access_token: config.accessToken, + refresh_token: config.refreshToken, + }), + { 'Content-Type': 'application/json' }, + ); + + await makeClient().code.getToken( + `${config.redirectUri}?code=${config.code}&state=${config.state}`, + ); + + scope.done(); + }); + + it('should include resource in refresh token request body when configured', async () => { + const scope = expectPostBody({ + refresh_token: config.refreshToken, + grant_type: 'refresh_token', + resource, + }); + + await makeClient({ resource }) + .createToken({ + access_token: config.accessToken, + refresh_token: config.refreshToken, + }) + .refresh(); + + scope.done(); + }); + + it('should omit resource from refresh token request body when not configured', async () => { + const scope = nock(config.baseUrl) + .post('/login/oauth/access_token', (body) => { + const params = parseBody(body); + return !params.has('resource'); + }) + .reply( + 200, + JSON.stringify({ + access_token: config.refreshedAccessToken, + refresh_token: config.refreshedRefreshToken, + }), + { 'Content-Type': 'application/json' }, + ); + + await makeClient() + .createToken({ + access_token: config.accessToken, + refresh_token: config.refreshToken, + }) + .refresh(); + + scope.done(); + }); + }); }); diff --git a/packages/@n8n/client-oauth2/tsconfig.build.json b/packages/@n8n/client-oauth2/tsconfig.build.json index 0794319028b..ff87f685ba6 100644 --- a/packages/@n8n/client-oauth2/tsconfig.build.json +++ b/packages/@n8n/client-oauth2/tsconfig.build.json @@ -3,8 +3,7 @@ "compilerOptions": { "composite": true, "rootDir": "src", - "outDir": "dist", - "tsBuildInfoFile": "dist/build.tsbuildinfo" + "outDir": "dist" }, "include": ["src/**/*.ts"], "exclude": ["test/**"] diff --git a/packages/@n8n/client-oauth2/tsconfig.json b/packages/@n8n/client-oauth2/tsconfig.json index 3c77b23fc6e..36f8f0ffe6d 100644 --- a/packages/@n8n/client-oauth2/tsconfig.json +++ b/packages/@n8n/client-oauth2/tsconfig.json @@ -4,8 +4,7 @@ "types": ["node", "vitest/globals"], "paths": { "@/*": ["./src/*"] - }, - "tsBuildInfoFile": "dist/typecheck.tsbuildinfo" + } }, "include": ["src/**/*.ts", "test/**/*.ts"] } diff --git a/packages/@n8n/codemirror-lang-html/package.json b/packages/@n8n/codemirror-lang-html/package.json index a3151b2c9f0..73fd4117644 100644 --- a/packages/@n8n/codemirror-lang-html/package.json +++ b/packages/@n8n/codemirror-lang-html/package.json @@ -1,6 +1,6 @@ { "name": "@n8n/codemirror-lang-html", - "version": "1.3.0", + "version": "1.5.0", "description": "HTML + n8n expression language support for CodeMirror 6", "scripts": { "clean": "rimraf dist .turbo", diff --git a/packages/@n8n/codemirror-lang-html/test/test-complete.ts b/packages/@n8n/codemirror-lang-html/test/test-complete.ts index c52c0e45628..c4bac57354f 100644 --- a/packages/@n8n/codemirror-lang-html/test/test-complete.ts +++ b/packages/@n8n/codemirror-lang-html/test/test-complete.ts @@ -1,3 +1,4 @@ +import { ensureSyntaxTree } from '@codemirror/language'; import { EditorState } from '@codemirror/state'; import { CompletionContext, CompletionResult, CompletionSource } from '@codemirror/autocomplete'; import { html } from '../dist/index.js'; @@ -6,11 +7,17 @@ import ist from 'ist'; function get(doc: string, conf: { explicit?: boolean } = {}) { let cur = doc.indexOf('|'); doc = doc.slice(0, cur) + doc.slice(cur + 1); - let state = EditorState.create({ + let initialState = EditorState.create({ doc, selection: { anchor: cur }, extensions: [html()], }); + // `EditorState.create` only parses within a 20ms wall-clock budget, which a + // contended CI runner can starve, leaving a truncated tree with no language + // data so `languageDataAt` returns []. Fully parse and commit the tree into + // the language state field via an empty transaction for determinism. + ensureSyntaxTree(initialState, initialState.doc.length, 1e9); + let state = initialState.update({}).state; let result = state.languageDataAt<CompletionSource>('autocomplete', cur)[0]( new CompletionContext(state, cur, !!conf.explicit), ); diff --git a/packages/@n8n/codemirror-lang-sql/package.json b/packages/@n8n/codemirror-lang-sql/package.json index 3366d5b4297..de6610fad0e 100644 --- a/packages/@n8n/codemirror-lang-sql/package.json +++ b/packages/@n8n/codemirror-lang-sql/package.json @@ -1,6 +1,6 @@ { "name": "@n8n/codemirror-lang-sql", - "version": "1.7.0", + "version": "1.9.0", "description": "SQL + n8n expression language support for CodeMirror 6", "scripts": { "clean": "rimraf dist .turbo", @@ -42,6 +42,7 @@ "@codemirror/autocomplete": "catalog:", "@codemirror/language": "catalog:", "@codemirror/state": "catalog:", + "@lezer/common": "catalog:", "@lezer/highlight": "catalog:", "@lezer/lr": "catalog:", "@n8n/codemirror-lang": "workspace:*" diff --git a/packages/@n8n/codemirror-lang-sql/test/complete.test.ts b/packages/@n8n/codemirror-lang-sql/test/complete.test.ts index 0265671abbc..19186cbceb7 100644 --- a/packages/@n8n/codemirror-lang-sql/test/complete.test.ts +++ b/packages/@n8n/codemirror-lang-sql/test/complete.test.ts @@ -11,7 +11,7 @@ function get(doc: string, conf: SQLConfig & { explicit?: boolean } = {}) { const dialect = conf.dialect || PostgreSQL; doc = doc.slice(0, cur) + doc.slice(cur + 1); - const state = EditorState.create({ + const initialState = EditorState.create({ doc, selection: { anchor: cur }, extensions: [ @@ -21,7 +21,14 @@ function get(doc: string, conf: SQLConfig & { explicit?: boolean } = {}) { }), ], }); - ensureSyntaxTree(state, state.doc.length, 1e9); + // `EditorState.create` only parses within a 20ms wall-clock budget, and + // `ensureSyntaxTree` advances a separate context tree rather than the one + // `languageDataAt` reads. Commit the fully-parsed tree into the language + // state field via an empty transaction so the lookup is deterministic + // regardless of host load (contended CI runners can otherwise starve that + // budget and leave a truncated tree with no language data). + ensureSyntaxTree(initialState, initialState.doc.length, 1e9); + const state = initialState.update({}).state; const result = state.languageDataAt<CompletionSource>('autocomplete', cur)[0]( new CompletionContext(state, cur, !!conf.explicit), ); diff --git a/packages/@n8n/codemirror-lang-sql/tsconfig.build.json b/packages/@n8n/codemirror-lang-sql/tsconfig.build.json index 32adf4995e9..8add09c23c3 100644 --- a/packages/@n8n/codemirror-lang-sql/tsconfig.build.json +++ b/packages/@n8n/codemirror-lang-sql/tsconfig.build.json @@ -2,8 +2,7 @@ "extends": ["./tsconfig.json", "@n8n/typescript-config/tsconfig.build.json"], "compilerOptions": { "rootDir": "src", - "outDir": "dist", - "tsBuildInfoFile": "dist/build.tsbuildinfo" + "outDir": "dist" }, "include": ["src/**/*.ts"], "exclude": ["test/**"] diff --git a/packages/@n8n/codemirror-lang-sql/tsconfig.json b/packages/@n8n/codemirror-lang-sql/tsconfig.json index 51ec87f4a8c..fa30143ebf1 100644 --- a/packages/@n8n/codemirror-lang-sql/tsconfig.json +++ b/packages/@n8n/codemirror-lang-sql/tsconfig.json @@ -2,7 +2,6 @@ "extends": "@n8n/typescript-config/tsconfig.common.json", "compilerOptions": { "rootDir": ".", - "tsBuildInfoFile": "dist/typecheck.tsbuildinfo", "types": ["node", "jest"] }, "include": ["src/**/*.ts", "test/**/*.ts"] diff --git a/packages/@n8n/codemirror-lang/package.json b/packages/@n8n/codemirror-lang/package.json index 20655fdfbdc..3edf54bd01e 100644 --- a/packages/@n8n/codemirror-lang/package.json +++ b/packages/@n8n/codemirror-lang/package.json @@ -1,6 +1,6 @@ { "name": "@n8n/codemirror-lang", - "version": "0.6.0", + "version": "0.8.0", "description": "Language support package for CodeMirror 6 in n8n", "sideEffects": false, "license": "MIT", @@ -39,13 +39,13 @@ "format": "biome format --write src test", "format:check": "biome ci src test" }, - "peerDependencies": { + "dependencies": { "@codemirror/language": "catalog:", "@lezer/highlight": "catalog:", - "@lezer/lr": "catalog:" + "@lezer/lr": "catalog:", + "@lezer/generator": "catalog:" }, "devDependencies": { - "@lezer/generator": "catalog:", "@n8n/typescript-config": "workspace:*", "@n8n/vitest-config": "workspace:*", "vitest": "catalog:" diff --git a/packages/@n8n/codemirror-lang/tsconfig.build.json b/packages/@n8n/codemirror-lang/tsconfig.build.json index 32adf4995e9..8add09c23c3 100644 --- a/packages/@n8n/codemirror-lang/tsconfig.build.json +++ b/packages/@n8n/codemirror-lang/tsconfig.build.json @@ -2,8 +2,7 @@ "extends": ["./tsconfig.json", "@n8n/typescript-config/tsconfig.build.json"], "compilerOptions": { "rootDir": "src", - "outDir": "dist", - "tsBuildInfoFile": "dist/build.tsbuildinfo" + "outDir": "dist" }, "include": ["src/**/*.ts"], "exclude": ["test/**"] diff --git a/packages/@n8n/codemirror-lang/tsconfig.json b/packages/@n8n/codemirror-lang/tsconfig.json index 51ec87f4a8c..fa30143ebf1 100644 --- a/packages/@n8n/codemirror-lang/tsconfig.json +++ b/packages/@n8n/codemirror-lang/tsconfig.json @@ -2,7 +2,6 @@ "extends": "@n8n/typescript-config/tsconfig.common.json", "compilerOptions": { "rootDir": ".", - "tsBuildInfoFile": "dist/typecheck.tsbuildinfo", "types": ["node", "jest"] }, "include": ["src/**/*.ts", "test/**/*.ts"] diff --git a/packages/@n8n/computer-use/package.json b/packages/@n8n/computer-use/package.json index 777079ed5c9..5a460d413d0 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.9.0", + "version": "0.11.0", "description": "Local AI gateway for n8n AI Assistant — filesystem, shell, screenshots, mouse/keyboard, and browser automation", "publishConfig": { "bin": { @@ -47,6 +47,7 @@ "@vscode/ripgrep": "^1.17.1", "eventsource": "^3.0.6", "fast-glob": "catalog:", + "mime-types": "catalog:", "node-screenshots": "^0.2.8", "picocolors": "catalog:", "yargs-parser": "21.1.1", @@ -56,9 +57,11 @@ "devDependencies": { "@n8n/typescript-config": "workspace:*", "@n8n/vitest-config": "workspace:*", + "@types/mime-types": "catalog:", "@types/node": "catalog:", "@types/yargs-parser": "21.0.0", "@vitest/coverage-v8": "catalog:", "vitest": "catalog:" - } + }, + "license": "LicenseRef-n8n-sustainable-use" } diff --git a/packages/@n8n/computer-use/spec/technical-spec.md b/packages/@n8n/computer-use/spec/technical-spec.md index 120113c4dbc..4bdd6e437a1 100644 --- a/packages/@n8n/computer-use/spec/technical-spec.md +++ b/packages/@n8n/computer-use/spec/technical-spec.md @@ -277,7 +277,7 @@ When the AI agent needs to invoke a local tool the call flows through ```mermaid sequenceDiagram - participant A as AI Agent (Mastra tool) + participant A as AI Agent (@n8n/agents tool) participant GW as LocalGateway participant SRV as Controller (SSE) participant D as computer-use Daemon @@ -304,7 +304,7 @@ rejects all outstanding promises immediately with `"Local gateway disconnected"` When a tool group operates in `Ask` mode and no stored rule matches the resource, the daemon returns a `GATEWAY_CONFIRMATION_REQUIRED` error instead -of a result. The Mastra tool layer handles this by suspending the agent — +of a result. The `@n8n/agents` tool layer handles this by suspending the agent — persisting its state to the database — and resuming it after the user responds. This means the confirmation survives page reloads and server restarts. @@ -316,7 +316,7 @@ sequenceDiagram participant DB as Database participant D as computer-use Daemon - Note over SRV: First invocation — tool execute() called by Mastra + Note over SRV: First invocation — tool execute() called by @n8n/agents SRV->>D: callTool({ name, args }) via LocalGateway D-->>SRV: { isError: true, content: ["GATEWAY_CONFIRMATION_REQUIRED::..."] } SRV->>SRV: parse GatewayConfirmationRequiredPayload diff --git a/packages/@n8n/computer-use/src/cli.ts b/packages/@n8n/computer-use/src/cli.ts index dff16551ede..b2fc7be7550 100644 --- a/packages/@n8n/computer-use/src/cli.ts +++ b/packages/@n8n/computer-use/src/cli.ts @@ -215,11 +215,14 @@ async function main( confirmResourceAccess: makeConfirmResourceAccess(parsed.nonInteractive, parsed.autoConfirm), }); + let shutdownPromise: Promise<void> | null = null; const shutdown = () => { - logger.info('Shutting down'); - void Promise.all([client.disconnect(), session.flush()]).finally(() => { - process.exit(0); - }); + shutdownPromise ??= (async () => { + logger.info('Shutting down'); + await Promise.all([client.disconnect(), session.flush()]).finally(() => { + process.exit(0); + }); + })(); }; process.on('SIGINT', shutdown); process.on('SIGTERM', shutdown); diff --git a/packages/@n8n/computer-use/src/tools/filesystem/constants.ts b/packages/@n8n/computer-use/src/tools/filesystem/constants.ts index fa2c67d8891..4ae7e585979 100644 --- a/packages/@n8n/computer-use/src/tools/filesystem/constants.ts +++ b/packages/@n8n/computer-use/src/tools/filesystem/constants.ts @@ -1 +1 @@ -export const MAX_FILE_SIZE = 512 * 1024; // 512 KB +export const MAX_FILE_SIZE = 1024 * 1024; // 1 MB diff --git a/packages/@n8n/computer-use/src/tools/filesystem/edit-file.test.ts b/packages/@n8n/computer-use/src/tools/filesystem/edit-file.test.ts index e93f95318a1..112c296b17f 100644 --- a/packages/@n8n/computer-use/src/tools/filesystem/edit-file.test.ts +++ b/packages/@n8n/computer-use/src/tools/filesystem/edit-file.test.ts @@ -175,8 +175,8 @@ describe('editFileTool', () => { ).rejects.toThrow('oldString not found'); }); - it('rejects files larger than 512 KB', async () => { - mockStat(600 * 1024); + it('rejects files larger than 1 MB', async () => { + mockStat(2 * 1024 * 1024); await expect( editFileTool.execute( diff --git a/packages/@n8n/computer-use/src/tools/filesystem/file-type.test.ts b/packages/@n8n/computer-use/src/tools/filesystem/file-type.test.ts new file mode 100644 index 00000000000..cc87d3c736c --- /dev/null +++ b/packages/@n8n/computer-use/src/tools/filesystem/file-type.test.ts @@ -0,0 +1,40 @@ +import { detectSupportedBinaryFile } from './file-type'; + +describe('detectSupportedBinaryFile', () => { + it.each([ + ['photo.jpg', 'image', 'image/jpeg'], + ['photo.jpeg', 'image', 'image/jpeg'], + ['photo.png', 'image', 'image/png'], + ['photo.gif', 'image', 'image/gif'], + ['photo.webp', 'image', 'image/webp'], + ['doc.pdf', 'pdf', 'application/pdf'], + ])('maps %s to %s/%s', (filePath, kind, mimeType) => { + expect(detectSupportedBinaryFile(filePath)).toEqual({ kind, mimeType }); + }); + + it.each([ + 'src/index.ts', + 'notes.md', + 'config.json', + 'README', + 'photo.svg', // SVG is XML — must not be classified as media + 'song.mp3', // audio — Claude does not accept audio input + 'song.wav', // audio — Claude does not accept audio input + 'song.flac', // not supported by Claude + 'movie.mp4', // video — out of scope + 'archive.zip', + ])('returns null for unsupported file %s', (filePath) => { + expect(detectSupportedBinaryFile(filePath)).toBeNull(); + }); + + it('returns null for paths without an extension', () => { + expect(detectSupportedBinaryFile('Makefile')).toBeNull(); + }); + + it('resolves relative paths the same way as absolute ones', () => { + expect(detectSupportedBinaryFile('/abs/path/photo.png')).toEqual({ + kind: 'image', + mimeType: 'image/png', + }); + }); +}); diff --git a/packages/@n8n/computer-use/src/tools/filesystem/file-type.ts b/packages/@n8n/computer-use/src/tools/filesystem/file-type.ts new file mode 100644 index 00000000000..1a8b8b921df --- /dev/null +++ b/packages/@n8n/computer-use/src/tools/filesystem/file-type.ts @@ -0,0 +1,36 @@ +import { lookup } from 'mime-types'; + +export type SupportedBinaryKind = 'image' | 'pdf'; + +export interface SupportedBinaryFile { + kind: SupportedBinaryKind; + mimeType: string; +} + +/** + * IANA media types (as returned by `mime-types.lookup()`) that Claude can + * consume natively. Audio is intentionally excluded — Anthropic's API does + * not accept audio content, so passing it through would surface a provider + * error to the user. + */ +const SUPPORTED_BINARY_MIMES = new Map<string, SupportedBinaryKind>([ + ['image/jpeg', 'image'], + ['image/png', 'image'], + ['image/gif', 'image'], + ['image/webp', 'image'], + ['application/pdf', 'pdf'], +]); + +/** + * Identify a file's binary kind from its path (extension-based via the + * `mime-types` package). Returns `null` when the extension is unknown or maps + * to a MIME type no supported model can consume natively — the caller should + * fall back to text reading in that case. + */ +export function detectSupportedBinaryFile(filePath: string): SupportedBinaryFile | null { + const mimeType = lookup(filePath); + if (!mimeType) return null; + const kind = SUPPORTED_BINARY_MIMES.get(mimeType); + if (!kind) return null; + return { kind, mimeType }; +} diff --git a/packages/@n8n/computer-use/src/tools/filesystem/read-file.test.ts b/packages/@n8n/computer-use/src/tools/filesystem/read-file.test.ts index 58084b416b6..e7a9f6f1d77 100644 --- a/packages/@n8n/computer-use/src/tools/filesystem/read-file.test.ts +++ b/packages/@n8n/computer-use/src/tools/filesystem/read-file.test.ts @@ -32,7 +32,7 @@ describe('readFileTool', () => { }); it('has a non-empty description', () => { - expect(readFileTool.description).toBe('Read the contents of a file'); + expect(readFileTool.description.length).toBeGreaterThan(0); }); }); @@ -129,34 +129,75 @@ describe('readFileTool', () => { expect(content.content).toBe('Line 5\nLine 6\nLine 7'); }); - it('rejects binary files', async () => { + it('rejects unsupported binary files', async () => { mockStat(100); const binary = Buffer.alloc(100); binary[50] = 0; mockReadFile(binary); await expect(readFileTool.execute({ filePath: 'binary.dat' }, CONTEXT)).rejects.toThrow( - 'Binary file', + 'Unsupported binary file', ); }); - it('rejects binary files without null bytes', async () => { + it('rejects unsupported binary files without null bytes', async () => { mockStat(100); - mockReadFile(Buffer.from([0xff, 0xfe, 0xfd, 0xfc])); + mockReadFile(Buffer.from([0xfe, 0xfd, 0xfc, 0xfb])); await expect(readFileTool.execute({ filePath: 'binary.dat' }, CONTEXT)).rejects.toThrow( - 'Binary file', + 'Unsupported binary file', ); }); - it('rejects files larger than 512KB', async () => { - mockStat(600 * 1024); + it('rejects files larger than 1MB', async () => { + mockStat(2 * 1024 * 1024); await expect(readFileTool.execute({ filePath: 'large.txt' }, CONTEXT)).rejects.toThrow( 'too large', ); }); + it('returns PNG as image content', async () => { + const bytes = Buffer.from([0xde, 0xad, 0xbe, 0xef]); + mockStat(bytes.length); + mockReadFile(bytes); + + const result = await readFileTool.execute({ filePath: 'pic.png' }, CONTEXT); + expect(result.content).toEqual([ + { type: 'image', data: bytes.toString('base64'), mimeType: 'image/png' }, + ]); + }); + + it.each([ + ['pic.jpg', 'image/jpeg'], + ['pic.jpeg', 'image/jpeg'], + ['pic.gif', 'image/gif'], + ['pic.webp', 'image/webp'], + ])('returns %s as image content with mime %s', async (filePath, mimeType) => { + mockStat(8); + mockReadFile(Buffer.alloc(8)); + + const result = await readFileTool.execute({ filePath }, CONTEXT); + expect(result.content[0]).toMatchObject({ type: 'image', mimeType }); + }); + + it('returns PDF as embedded resource', async () => { + const bytes = Buffer.from('PDF-bytes'); + mockStat(bytes.length); + mockReadFile(bytes); + + const result = await readFileTool.execute({ filePath: 'doc.pdf' }, CONTEXT); + expect(result.content).toHaveLength(1); + const item = result.content[0] as { + type: string; + resource: { uri: string; mimeType: string; blob: string }; + }; + expect(item.type).toBe('resource'); + expect(item.resource.mimeType).toBe('application/pdf'); + expect(item.resource.uri.startsWith('file://')).toBe(true); + expect(item.resource.blob).toBe(bytes.toString('base64')); + }); + it('rejects path traversal', async () => { await expect( readFileTool.execute({ filePath: '../../../etc/passwd' }, CONTEXT), diff --git a/packages/@n8n/computer-use/src/tools/filesystem/read-file.ts b/packages/@n8n/computer-use/src/tools/filesystem/read-file.ts index e10194529cd..76b8e708481 100644 --- a/packages/@n8n/computer-use/src/tools/filesystem/read-file.ts +++ b/packages/@n8n/computer-use/src/tools/filesystem/read-file.ts @@ -1,21 +1,32 @@ import * as fs from 'node:fs/promises'; +import { pathToFileURL } from 'node:url'; import { z } from 'zod'; -import type { ToolDefinition } from '../types'; +import type { CallToolResult, ToolDefinition } from '../types'; import { formatCallToolResult } from '../utils'; import { MAX_FILE_SIZE } from './constants'; +import { type SupportedBinaryFile, detectSupportedBinaryFile } from './file-type'; import { buildFilesystemResource, isLikelyBinaryContent, resolveReadablePath } from './fs-utils'; const DEFAULT_MAX_LINES = 200; const inputSchema = z.object({ filePath: z.string().describe('File path relative to root'), - startLine: z.number().int().optional().describe('Starting line number (1-based, default: 1)'), - maxLines: z.number().int().optional().describe('Maximum number of lines (default: 200)'), + startLine: z + .number() + .int() + .optional() + .describe('Starting line number (1-based, default: 1). Text files only.'), + maxLines: z + .number() + .int() + .optional() + .describe('Maximum number of lines (default: 200). Text files only.'), }); export const readFileTool: ToolDefinition<typeof inputSchema> = { name: 'read_file', - description: 'Read the contents of a file', + description: + 'Read a file. Text is returned line-by-line; supported binaries (PNG, JPEG, GIF, WebP, PDF) are returned as base64 content the model can consume directly.', inputSchema, annotations: { readOnlyHint: true }, async getAffectedResources({ filePath }, { dir }) { @@ -36,25 +47,59 @@ export const readFileTool: ToolDefinition<typeof inputSchema> = { const fileContent = await fs.readFile(resolvedPath); const buffer = Buffer.isBuffer(fileContent) ? fileContent : Buffer.from(fileContent); - if (isLikelyBinaryContent(buffer)) { - throw new Error('Binary file detected — cannot read binary files'); + const binaryType = detectSupportedBinaryFile(filePath); + if (binaryType) { + return buildBinaryResult(resolvedPath, buffer, binaryType); } - const fullContent = buffer.toString('utf-8'); - const allLines = fullContent.split('\n'); - const lines = maxLines ?? DEFAULT_MAX_LINES; - const start = startLine ?? 1; - const startIndex = Math.max(0, start - 1); - const slicedLines = allLines.slice(startIndex, startIndex + lines); - const truncated = allLines.length > startIndex + lines; + if (isLikelyBinaryContent(buffer)) { + throw new Error('Unsupported binary file — only PNG, JPEG, GIF, WebP and PDF are readable'); + } - const result = { - path: filePath, - content: slicedLines.join('\n'), - truncated, - totalLines: allLines.length, - }; - - return formatCallToolResult(result); + return buildTextResult(filePath, buffer.toString('utf-8'), startLine, maxLines); }, }; + +function buildTextResult( + filePath: string, + content: string, + startLine: number | undefined, + maxLines: number | undefined, +): CallToolResult { + const allLines = content.split('\n'); + const lines = maxLines ?? DEFAULT_MAX_LINES; + const start = startLine ?? 1; + const startIndex = Math.max(0, start - 1); + const slicedLines = allLines.slice(startIndex, startIndex + lines); + const truncated = allLines.length > startIndex + lines; + + return formatCallToolResult({ + path: filePath, + content: slicedLines.join('\n'), + truncated, + totalLines: allLines.length, + }); +} + +function buildBinaryResult( + resolvedPath: string, + buffer: Buffer, + type: SupportedBinaryFile, +): CallToolResult { + const data = buffer.toString('base64'); + if (type.kind === 'image') { + return { content: [{ type: 'image', data, mimeType: type.mimeType }] }; + } + return { + content: [ + { + type: 'resource', + resource: { + uri: pathToFileURL(resolvedPath).toString(), + mimeType: type.mimeType, + blob: data, + }, + }, + ], + }; +} diff --git a/packages/@n8n/computer-use/src/tools/filesystem/write-file.test.ts b/packages/@n8n/computer-use/src/tools/filesystem/write-file.test.ts index d5dadd4be30..e6ee85c5874 100644 --- a/packages/@n8n/computer-use/src/tools/filesystem/write-file.test.ts +++ b/packages/@n8n/computer-use/src/tools/filesystem/write-file.test.ts @@ -93,8 +93,8 @@ describe('writeFileTool', () => { expect(fs.writeFile).toHaveBeenCalledWith('/base/existing.txt', 'new data', 'utf-8'); }); - it('rejects content larger than 512 KB', async () => { - const largeContent = 'x'.repeat(600 * 1024); + it('rejects content larger than 1 MB', async () => { + const largeContent = 'x'.repeat(2 * 1024 * 1024); await expect( writeFileTool.execute({ filePath: 'large.txt', content: largeContent }, CONTEXT), diff --git a/packages/@n8n/computer-use/src/tools/filesystem/write-file.ts b/packages/@n8n/computer-use/src/tools/filesystem/write-file.ts index 15cf9b32aec..4f173d376eb 100644 --- a/packages/@n8n/computer-use/src/tools/filesystem/write-file.ts +++ b/packages/@n8n/computer-use/src/tools/filesystem/write-file.ts @@ -15,7 +15,7 @@ const inputSchema = z.object({ export const writeFileTool: ToolDefinition<typeof inputSchema> = { name: 'write_file', description: - 'Create a new file with the given content. Overwrites if the file already exists. Content must not exceed 512 KB.', + 'Create a new file with the given content. Overwrites if the file already exists. Content must not exceed 1 MB.', inputSchema, annotations: {}, async getAffectedResources({ filePath }, { dir }) { diff --git a/packages/@n8n/computer-use/tsconfig.build.json b/packages/@n8n/computer-use/tsconfig.build.json index 2565df60d45..7c9019949bd 100644 --- a/packages/@n8n/computer-use/tsconfig.build.json +++ b/packages/@n8n/computer-use/tsconfig.build.json @@ -3,8 +3,7 @@ "compilerOptions": { "composite": true, "rootDir": "src", - "outDir": "dist", - "tsBuildInfoFile": "dist/build.tsbuildinfo" + "outDir": "dist" }, "include": ["src/**/*.ts"], "exclude": ["src/**/__tests__/**", "src/**/__mocks__/**", "src/**/*.test.ts", "src/**/*.spec.ts"] diff --git a/packages/@n8n/computer-use/tsconfig.json b/packages/@n8n/computer-use/tsconfig.json index d41b2ba23b0..801a1e65587 100644 --- a/packages/@n8n/computer-use/tsconfig.json +++ b/packages/@n8n/computer-use/tsconfig.json @@ -1,8 +1,7 @@ { "extends": "@n8n/typescript-config/tsconfig.common.json", "compilerOptions": { - "types": ["node", "vitest/globals"], - "tsBuildInfoFile": "dist/typecheck.tsbuildinfo" + "types": ["node", "vitest/globals"] }, "include": ["src/**/*.ts"] } diff --git a/packages/@n8n/config/package.json b/packages/@n8n/config/package.json index ca9f5227f90..f047dd059bb 100644 --- a/packages/@n8n/config/package.json +++ b/packages/@n8n/config/package.json @@ -1,6 +1,6 @@ { "name": "@n8n/config", - "version": "2.23.0", + "version": "2.25.0", "scripts": { "clean": "rimraf dist .turbo", "dev": "pnpm watch", @@ -34,5 +34,6 @@ "@vitest/coverage-v8": "catalog:", "vitest": "catalog:", "vitest-mock-extended": "catalog:" - } + }, + "license": "LicenseRef-n8n-sustainable-use" } diff --git a/packages/@n8n/config/src/configs/agents.config.ts b/packages/@n8n/config/src/configs/agents.config.ts index e014ead50b8..f61f8dd0607 100644 --- a/packages/@n8n/config/src/configs/agents.config.ts +++ b/packages/@n8n/config/src/configs/agents.config.ts @@ -8,7 +8,7 @@ import { Config, Env } from '../decorators'; * `N8N_AGENTS_MODULES`. The backend fails fast on unknown tokens so typos * surface at startup instead of silently disabling a feature. */ -export const AGENTS_MODULE_NAMES = ['node-tools-searcher', 'knowledge-base'] as const; +export const AGENTS_MODULE_NAMES = ['node-tools-searcher'] as const; export type AgentsModuleName = (typeof AGENTS_MODULE_NAMES)[number]; @@ -32,27 +32,48 @@ export class AgentsConfig { @Env('N8N_AGENTS_CHECKPOINT_TTL') checkpointTtlSeconds: number = 96 * Time.hours.toSeconds; - /** Maximum number of sub-agents a single parent run may spawn. Bounds fan-out width. */ - @Env('N8N_AGENTS_SUBAGENT_MAX_CHILDREN') - subAgentMaxChildren: number = 5; - - /** Abort an individual sub-agent run after this many milliseconds. */ - @Env('N8N_AGENTS_SUBAGENT_TIMEOUT_MS') - subAgentTimeoutMs: number = 5 * Time.minutes.toMilliseconds; - /** * Comma-separated list of agent sub-feature modules to enable. Each entry * gates a specific frontend/runtime capability inside the agents module. * Currently known: * - `node-tools-searcher` — surfaces the "Built-in node tools" toggle in * the agent editor. - * - `knowledge-base` — enables the agent knowledge base: file upload/list/ - * delete endpoints, the files panel in the editor, and the - * `search_knowledge` runtime tool. * * Gates the UI surface only — existing agents persisted with a given * capability turned on continue to run even if its token is removed here. */ @Env('N8N_AGENTS_MODULES') modules: AgentsModuleArray = []; + + /** Enable Daytona sandbox for agent knowledge base operations. */ + @Env('N8N_AGENTS_AI_SANDBOX_ENABLED') + sandboxEnabled: boolean = false; + + /** Sandbox provider for agent knowledge base. Only `daytona` is supported. */ + @Env('N8N_AGENTS_AI_SANDBOX_PROVIDER') + sandboxProvider: string = ''; + + /** Docker image for the Daytona sandbox (default: daytonaio/sandbox:0.5.0). */ + @Env('N8N_AGENTS_AI_SANDBOX_IMAGE') + sandboxImage: string = 'daytonaio/sandbox:0.5.0'; + + /** Default command timeout in the sandbox (milliseconds). */ + @Env('N8N_AGENTS_AI_SANDBOX_TIMEOUT') + sandboxTimeout: number = 5 * Time.minutes.toMilliseconds; + + /** Prefix prepended to every Daytona sandbox name. */ + @Env('N8N_AGENTS_AI_SANDBOX_NAME_PREFIX') + sandboxNamePrefix: string = ''; + + /** Daytona volume ID for the agent knowledge base. */ + @Env('N8N_AGENTS_AI_SANDBOX_DAYTONA_VOLUME_ID') + daytonaVolumeId: string = ''; + + /** Daytona API URL (e.g. "https://app.daytona.io/api"). */ + @Env('DAYTONA_API_URL') + daytonaApiUrl: string = ''; + + /** Daytona API key for authentication. */ + @Env('DAYTONA_API_KEY') + daytonaApiKey: string = ''; } diff --git a/packages/@n8n/config/src/configs/data-table.config.ts b/packages/@n8n/config/src/configs/data-table.config.ts index 52550bc5291..5f35293716a 100644 --- a/packages/@n8n/config/src/configs/data-table.config.ts +++ b/packages/@n8n/config/src/configs/data-table.config.ts @@ -6,9 +6,9 @@ import { Config, Env } from '../decorators'; @Config export class DataTableConfig { - /** Maximum total size in bytes allowed for data tables. Default: 50 MiB. */ + /** Maximum total size in bytes allowed for data tables. Default: 200 MiB. */ @Env('N8N_DATA_TABLES_MAX_SIZE_BYTES') - maxSize: number = 50 * 1024 * 1024; + maxSize: number = 200 * 1024 * 1024; /** * Size in bytes at which to warn that a data table is nearing capacity. diff --git a/packages/@n8n/config/src/configs/database.config.ts b/packages/@n8n/config/src/configs/database.config.ts index a17322af70a..f8baea2c644 100644 --- a/packages/@n8n/config/src/configs/database.config.ts +++ b/packages/@n8n/config/src/configs/database.config.ts @@ -171,6 +171,65 @@ export class DatabaseConfig { @Env('DB_PING_TIMEOUT_MS') pingTimeoutMs: number = readLegacyPingTimeoutMs(); + /** + * How many consecutive health-check ping failures must occur before the + * connection is considered lost and the DataSource is torn down and + * reinitialized (full pool recovery). + * + * Recovery is disruptive (it destroys and recreates the connection pool), + * so this guards against a single transient blip triggering it. With the + * default `DB_PING_INTERVAL_SECONDS=2`, the default of 3 means recovery + * fires only after roughly 6s of sustained ping failures. + * + * Raise this if you see recovery triggering on brief network hiccups + * (false positives); lower it to react faster to genuinely dead connections. + * + * Must be >= 1: recovery fires only after at least one failed ping. + */ + @Env('DB_PING_MAX_FAILURES_BEFORE_RECOVERY', z.coerce.number().int().gte(1)) + pingMaxFailuresBeforeRecovery: number = 3; + + /** + * Initial delay in milliseconds before retrying a failed recovery attempt. + * + * Recovery retries use exponential backoff: each failed attempt waits + * `min(minRecoveryBackoffMs * 2 ** (attempt - 1), maxRecoveryBackoffMs)`. + * This is the delay after the first failed attempt (the floor of the curve). + * + * Must be >= 1 + */ + @Env('DB_RECOVERY_BACKOFF_MIN_MS', z.coerce.number().int().gte(1)) + minRecoveryBackoffMs: number = 1 * Time.seconds.toMilliseconds; + + /** + * Maximum delay in milliseconds between recovery attempts. + * + * Caps the exponential backoff so retries never wait longer than this, + * keeping recovery responsive once the database becomes reachable again. + * Must be greater than or equal to `DB_RECOVERY_BACKOFF_MIN_MS`. + * + * Must be >= 1 + */ + @Env('DB_RECOVERY_BACKOFF_MAX_MS', z.coerce.number().int().gte(1)) + maxRecoveryBackoffMs: number = 30 * Time.seconds.toMilliseconds; + + /** + * Maximum time in milliseconds a query waits for an in-progress connection + * recovery before failing fast. + * + * While recovery rebuilds the pool, every query that needs a connection parks + * until recovery completes. During a short blip that wait is invisible and the + * query succeeds against the fresh pool. During a long outage it would + * otherwise pile up parked queries for the whole outage, so this bounds the + * wait: once it elapses the query rejects with an `OperationalError` instead of + * holding the request open indefinitely. The default (30s) comfortably covers + * common-case recoveries while staying within typical HTTP gateway timeouts. + * + * Set to `0` to wait indefinitely (no timeout). + */ + @Env('DB_CONNECTION_ACQUISITION_TIMEOUT_MS', z.coerce.number().int().gte(0)) + connectionAcquisitionTimeoutMs: number = 30 * Time.seconds.toMilliseconds; + @Nested logging: LoggingConfig; diff --git a/packages/@n8n/config/src/configs/endpoints.config.ts b/packages/@n8n/config/src/configs/endpoints.config.ts index 288f97c60ea..838da798b64 100644 --- a/packages/@n8n/config/src/configs/endpoints.config.ts +++ b/packages/@n8n/config/src/configs/endpoints.config.ts @@ -3,7 +3,7 @@ import { z } from 'zod'; import { Config, Env, Nested } from '../decorators'; @Config -class PrometheusMetricsConfig { +export class PrometheusMetricsConfig { /** Whether to enable the `/metrics` endpoint to expose Prometheus metrics. */ @Env('N8N_METRICS') enable: boolean = false; @@ -83,6 +83,30 @@ class PrometheusMetricsConfig { /** Whether to include metrics for execution data reads and writes. */ @Env('N8N_METRICS_INCLUDE_EXECUTION_DATA_METRICS') includeExecutionDataMetrics: boolean = false; + + /** Whether to include metrics for SSRF protection checks. */ + @Env('N8N_METRICS_INCLUDE_SSRF_METRICS') + includeSsrfMetrics: boolean = false; + + /** Whether to include metrics for the DNS cache (currently only used by SSRF protection). */ + @Env('N8N_METRICS_INCLUDE_DNS_CACHE_METRICS') + includeDnsCacheMetrics: boolean = false; + + /** Whether to include a duration histogram metric for webhook requests. */ + @Env('N8N_METRICS_INCLUDE_WEBHOOK_METRICS') + includeWebhookMetrics: boolean = false; + + /** Whether to include a duration histogram metric for form submissions. */ + @Env('N8N_METRICS_INCLUDE_FORM_METRICS') + includeFormMetrics: boolean = false; + + /** Whether to include a gauge mapping workflow IDs to their human-readable names. */ + @Env('N8N_METRICS_INCLUDE_WORKFLOW_INFO') + includeWorkflowInfoMetrics: boolean = false; + + /** How often (in seconds) to refresh the workflow info metric cache. */ + @Env('N8N_METRICS_WORKFLOW_INFO_METRIC_INTERVAL') + workflowInfoMetricInterval: number = 60; } @Config diff --git a/packages/@n8n/config/src/configs/executions.config.ts b/packages/@n8n/config/src/configs/executions.config.ts index c9b8f45b15d..3add6e45dec 100644 --- a/packages/@n8n/config/src/configs/executions.config.ts +++ b/packages/@n8n/config/src/configs/executions.config.ts @@ -154,8 +154,4 @@ export class ExecutionsConfig { /** Whether to save execution data for manual executions. This default can be overridden at a workflow level. */ @Env('EXECUTIONS_DATA_SAVE_MANUAL_EXECUTIONS') saveDataManualExecutions: boolean = true; - - /** Whether scheduled executions receive a deduplication key enforced by a unique DB index. */ - @Env('N8N_SCHEDULED_EXECUTION_DEDUPLICATION_ENABLED') - scheduledExecutionDeduplicationEnabled: 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 b78385a4b48..d222d9e4600 100644 --- a/packages/@n8n/config/src/configs/instance-ai.config.ts +++ b/packages/@n8n/config/src/configs/instance-ai.config.ts @@ -72,6 +72,34 @@ export class InstanceAiConfig { @Env('N8N_INSTANCE_AI_SANDBOX_NAME_PREFIX') sandboxNamePrefix: string = ''; + /** + * When true, Daytona sandboxes are created ephemeral (auto-deleted on stop) instead of + * lingering stopped. Intended for throwaway eval instances so sandboxes don't accumulate. + */ + @Env('N8N_INSTANCE_AI_SANDBOX_EPHEMERAL') + sandboxEphemeral: boolean = false; + + /** + * Minutes an idle Daytona sandbox waits before it is stopped. Default 15 minutes. + * `0` disables auto-stop (the sandbox stays running). + */ + @Env('N8N_INSTANCE_AI_SANDBOX_AUTO_STOP_MINUTES') + sandboxAutoStopMinutes: number = 15; + + /** + * Minutes a stopped Daytona sandbox waits before it is archived to cold storage. + * Default 7 days. `0` uses Daytona's maximum interval. + */ + @Env('N8N_INSTANCE_AI_SANDBOX_AUTO_ARCHIVE_MINUTES') + sandboxAutoArchiveMinutes: number = 7 * 24 * 60; + + /** + * Minutes a stopped Daytona sandbox waits before it is deleted. Default 30 days. A negative + * value disables auto-delete; `0` deletes on stop. Ignored when {@link sandboxEphemeral} is true. + */ + @Env('N8N_INSTANCE_AI_SANDBOX_AUTO_DELETE_MINUTES') + sandboxAutoDeleteMinutes: number = 30 * 24 * 60; + /** * Skew (milliseconds) used to proactively refresh the Daytona proxy JWT before it expires. * Refresh fires when the cached token's remaining lifetime falls below this threshold. @@ -111,4 +139,24 @@ export class InstanceAiConfig { /** Timeout in milliseconds for HITL confirmation requests. 0 = no timeout. */ @Env('N8N_INSTANCE_AI_CONFIRMATION_TIMEOUT') confirmationTimeout: number = 24 * Time.hours.toMilliseconds; + + /** Scan and redact secrets/PII from agent output before it reaches the user. */ + @Env('N8N_INSTANCE_AI_OUTPUT_REDACTION_ENABLED') + outputRedactionEnabled: boolean = true; + + /** Redact credential/secret patterns from agent output. Applies only when output redaction is enabled. */ + @Env('N8N_INSTANCE_AI_OUTPUT_REDACTION_SECRETS') + outputRedactionSecrets: boolean = true; + + /** Comma-separated PII categories to redact from agent output. Available: email, phone, credit-card, ssn-us, iban, crypto-wallet, ip, mac, url. Empty = no PII scanning. */ + @Env('N8N_INSTANCE_AI_OUTPUT_REDACTION_PII') + outputRedactionPii: string = 'credit-card'; + + /** Replacement text substituted for each redacted match in agent output. */ + @Env('N8N_INSTANCE_AI_OUTPUT_REDACTION_PLACEHOLDER') + outputRedactionPlaceholder: string = '[REDACTED]'; + + /** Capture orchestrator LLM steps and workflow code snapshots for the dev debug panel. */ + @Env('N8N_INSTANCE_AI_RUN_DEBUG_ENABLED') + runDebugEnabled: boolean = false; } diff --git a/packages/@n8n/config/src/configs/logging.config.ts b/packages/@n8n/config/src/configs/logging.config.ts index 9f9d07084b2..e714ed29dd8 100644 --- a/packages/@n8n/config/src/configs/logging.config.ts +++ b/packages/@n8n/config/src/configs/logging.config.ts @@ -46,6 +46,8 @@ export const LOG_SCOPES = [ 'encryption-key-manager', 'oauth-jwe', 'mcp-registry', + 'workflow-publication', + 'metrics', ] as const; export type LogScope = (typeof LOG_SCOPES)[number]; diff --git a/packages/@n8n/config/src/configs/security.config.ts b/packages/@n8n/config/src/configs/security.config.ts index 6663963586a..e8e291aa460 100644 --- a/packages/@n8n/config/src/configs/security.config.ts +++ b/packages/@n8n/config/src/configs/security.config.ts @@ -55,7 +55,8 @@ export class SecurityConfig { * Configuration for the `Cross-Origin-Opener-Policy` header. */ @Env('N8N_CROSS_ORIGIN_OPENER_POLICY', crossOriginOpenerPolicySchema) - crossOriginOpenerPolicy: z.infer<typeof crossOriginOpenerPolicySchema> = 'same-origin'; + crossOriginOpenerPolicy: z.infer<typeof crossOriginOpenerPolicySchema> = + 'same-origin-allow-popups'; /** * Whether to disable HTML sandboxing for webhooks. The sandboxing mechanism uses CSP headers now, diff --git a/packages/@n8n/config/src/configs/sentry.config.ts b/packages/@n8n/config/src/configs/sentry.config.ts index 4074fc192c3..269eca1f6bf 100644 --- a/packages/@n8n/config/src/configs/sentry.config.ts +++ b/packages/@n8n/config/src/configs/sentry.config.ts @@ -35,6 +35,16 @@ export class SentryConfig { @Env('N8N_SENTRY_PROFILES_SAMPLE_RATE', sampleRateSchema) profilesSampleRate: number = 0; + /** + * Whether Sentry's native event-loop-block detection is enabled. When on, a + * native watchdog (`@sentry/node-native`) captures the main thread's stack + * whenever the event loop is blocked beyond the threshold below. + * + * @default false + */ + @Env('N8N_SENTRY_EVENT_LOOP_BLOCK_DETECTION_ENABLED') + eventLoopBlockDetectionEnabled: boolean = false; + /** * Threshold in milliseconds for event loop block detection. * When the event loop is blocked for longer than this threshold, diff --git a/packages/@n8n/config/src/configs/user-management.config.ts b/packages/@n8n/config/src/configs/user-management.config.ts index 296a0a408c8..20748e17697 100644 --- a/packages/@n8n/config/src/configs/user-management.config.ts +++ b/packages/@n8n/config/src/configs/user-management.config.ts @@ -77,6 +77,10 @@ export class TemplateConfig { /** Overrides default HTML template for notifying that a workflow failed in production (use full path) */ @Env('N8N_UM_EMAIL_TEMPLATES_WORKFLOW_FAILURE') 'workflow-failure': string = ''; + + /** Overrides default HTML template for notifying a user that their public API key was revoked by an admin (use full path) */ + @Env('N8N_UM_EMAIL_TEMPLATES_API_KEY_REVOKED') + 'api-key-revoked': string = ''; } const emailModeSchema = z.enum(['', 'smtp']); diff --git a/packages/@n8n/config/src/configs/workflows.config.ts b/packages/@n8n/config/src/configs/workflows.config.ts index 65827e5996c..99ab5bba42c 100644 --- a/packages/@n8n/config/src/configs/workflows.config.ts +++ b/packages/@n8n/config/src/configs/workflows.config.ts @@ -1,3 +1,4 @@ +import { Time } from '@n8n/constants'; import { z } from 'zod'; import { Config, Env } from '../decorators'; @@ -27,6 +28,10 @@ export class WorkflowsConfig { @Env('N8N_USE_WORKFLOW_PUBLICATION_SERVICE') useWorkflowPublicationService: boolean = false; + /** Interval in milliseconds between polls of the workflow publication outbox on the leader. */ + @Env('N8N_WORKFLOW_PUBLICATION_OUTBOX_POLL_INTERVAL_MS') + publicationOutboxPollIntervalMs: number = 15 * Time.seconds.toMilliseconds; + /** Whether to disable automatic workflow saving in the editor */ @Env('N8N_WORKFLOWS_AUTOSAVE_DISABLED') autosaveDisabled: boolean = false; diff --git a/packages/@n8n/config/src/index.ts b/packages/@n8n/config/src/index.ts index 431250e3adc..04a03b72ac3 100644 --- a/packages/@n8n/config/src/index.ts +++ b/packages/@n8n/config/src/index.ts @@ -15,7 +15,7 @@ import { DatabaseConfig } from './configs/database.config'; import { DeploymentConfig } from './configs/deployment.config'; import { DiagnosticsConfig } from './configs/diagnostics.config'; import { DynamicBannersConfig } from './configs/dynamic-banners.config'; -import { EndpointsConfig } from './configs/endpoints.config'; +import { EndpointsConfig, PrometheusMetricsConfig } from './configs/endpoints.config'; import { EvaluationConfig } from './configs/evaluation.config'; import { EventBusConfig } from './configs/event-bus.config'; import { ExecutionsConfig } from './configs/executions.config'; @@ -84,6 +84,7 @@ export { PasswordConfig } from './configs/password.config'; export { AgentsConfig } from './configs/agents.config'; export { CompressionNodeConfig } from './configs/compression.config'; export { RedisConfig } from './configs/redis.config'; +export { EndpointsConfig, PrometheusMetricsConfig }; const protocolSchema = z.enum(['http', 'https']); diff --git a/packages/@n8n/config/test/config.test.ts b/packages/@n8n/config/test/config.test.ts index 13245fb08d0..0bd0aa2f1c8 100644 --- a/packages/@n8n/config/test/config.test.ts +++ b/packages/@n8n/config/test/config.test.ts @@ -3,7 +3,7 @@ import { tmpdir } from 'node:os'; import path from 'node:path'; import type { DatabaseConfig } from '../src/index'; -import { ExecutionsConfig, GlobalConfig, SSRF_DEFAULT_BLOCKED_IP_RANGES } from '../src/index'; +import { GlobalConfig, SSRF_DEFAULT_BLOCKED_IP_RANGES } from '../src/index'; const { readFileSyncMock } = vi.hoisted(() => ({ readFileSyncMock: vi.fn(), @@ -74,7 +74,7 @@ describe('GlobalConfig', () => { canvasOnly: false, editorBaseUrl: '', dataTable: { - maxSize: 50 * 1024 * 1024, + maxSize: 200 * 1024 * 1024, sizeCheckCacheDuration: 5 * 1000, cleanupIntervalMs: 60 * 1000, fileMaxAgeMs: 2 * 60 * 1000, @@ -117,6 +117,10 @@ describe('GlobalConfig', () => { type: 'sqlite', pingIntervalSeconds: 2, pingTimeoutMs: 5_000, + pingMaxFailuresBeforeRecovery: 3, + minRecoveryBackoffMs: 1_000, + maxRecoveryBackoffMs: 30_000, + connectionAcquisitionTimeoutMs: 30_000, } as DatabaseConfig, credentials: { defaultName: 'My credentials', @@ -159,6 +163,7 @@ describe('GlobalConfig', () => { 'workflow-failure': '', 'workflow-shared': '', 'project-shared': '', + 'api-key-revoked': '', }, }, }, @@ -212,6 +217,7 @@ describe('GlobalConfig', () => { activationBatchSize: 1, indexingBatchSize: 10, useWorkflowPublicationService: false, + publicationOutboxPollIntervalMs: 15_000, autosaveDisabled: false, }, endpoints: { @@ -236,6 +242,12 @@ describe('GlobalConfig', () => { includeWorkflowStatistics: false, workflowStatisticsInterval: 300, includeExecutionDataMetrics: false, + includeSsrfMetrics: false, + includeDnsCacheMetrics: false, + includeWebhookMetrics: false, + includeFormMetrics: false, + includeWorkflowInfoMetrics: false, + workflowInfoMetricInterval: 60, }, additionalNonUIRoutes: '', disableProductionWebhooksOnMainProcess: false, @@ -297,6 +309,10 @@ describe('GlobalConfig', () => { n8nSandboxServiceApiKey: '', sandboxTimeout: 300000, sandboxNamePrefix: '', + sandboxEphemeral: false, + sandboxAutoStopMinutes: 15, + sandboxAutoArchiveMinutes: 10_080, + sandboxAutoDeleteMinutes: 43_200, daytonaTokenRefreshSkewMs: 300_000, builderSandboxTtlMs: 900_000, braveSearchApiKey: '', @@ -306,6 +322,11 @@ describe('GlobalConfig', () => { pruneInterval: 3_600_000, snapshotRetention: 86_400_000, confirmationTimeout: 86_400_000, + outputRedactionEnabled: true, + outputRedactionSecrets: true, + outputRedactionPii: 'credit-card', + outputRedactionPlaceholder: '[REDACTED]', + runDebugEnabled: false, }, queue: { health: { @@ -363,6 +384,7 @@ describe('GlobalConfig', () => { deploymentName: '', profilesSampleRate: 0, tracesSampleRate: 0, + eventLoopBlockDetectionEnabled: false, eventLoopBlockThreshold: 500, eventLoopBlockMaxEventsPerHour: 5, }, @@ -408,7 +430,7 @@ describe('GlobalConfig', () => { daysAbandonedWorkflow: 90, contentSecurityPolicy: '{}', contentSecurityPolicyReportOnly: false, - crossOriginOpenerPolicy: 'same-origin', + crossOriginOpenerPolicy: 'same-origin-allow-popups', disableWebhookHtmlSandboxing: false, disableFormHtmlSandboxing: false, disableBareRepos: true, @@ -448,7 +470,6 @@ describe('GlobalConfig', () => { saveDataOnSuccess: 'all', saveExecutionProgress: false, saveDataManualExecutions: true, - scheduledExecutionDeduplicationEnabled: false, }, diagnostics: { enabled: true, @@ -565,9 +586,15 @@ describe('GlobalConfig', () => { }, agents: { checkpointTtlSeconds: 345600, - subAgentMaxChildren: 5, - subAgentTimeoutMs: 300000, modules: [], + sandboxEnabled: false, + sandboxProvider: '', + sandboxImage: 'daytonaio/sandbox:0.5.0', + sandboxTimeout: 300000, + sandboxNamePrefix: '', + daytonaVolumeId: '', + daytonaApiUrl: '', + daytonaApiKey: '', }, } satisfies GlobalConfigShape; @@ -615,6 +642,10 @@ describe('GlobalConfig', () => { type: 'sqlite', pingIntervalSeconds: 2, pingTimeoutMs: 5_000, + pingMaxFailuresBeforeRecovery: 3, + minRecoveryBackoffMs: 1_000, + maxRecoveryBackoffMs: 30_000, + connectionAcquisitionTimeoutMs: 30_000, }, endpoints: { ...defaultConfig.endpoints, @@ -701,6 +732,64 @@ describe('GlobalConfig', () => { ); }); + describe('database recovery config validation', () => { + it('should reject DB_PING_MAX_FAILURES_BEFORE_RECOVERY below 1 and fall back to the default', () => { + process.env = { DB_PING_MAX_FAILURES_BEFORE_RECOVERY: '0' }; + const config = Container.get(GlobalConfig); + expect(config.database.pingMaxFailuresBeforeRecovery).toBe(3); + expect(consoleWarnMock).toHaveBeenCalledWith( + expect.stringContaining('DB_PING_MAX_FAILURES_BEFORE_RECOVERY'), + ); + }); + + it('should reject an empty DB_PING_MAX_FAILURES_BEFORE_RECOVERY (coerces to 0, not NaN)', () => { + process.env = { DB_PING_MAX_FAILURES_BEFORE_RECOVERY: '' }; + const config = Container.get(GlobalConfig); + expect(config.database.pingMaxFailuresBeforeRecovery).toBe(3); + }); + + it('should reject DB_RECOVERY_BACKOFF_MIN_MS of 0 and fall back to the default', () => { + process.env = { DB_RECOVERY_BACKOFF_MIN_MS: '0' }; + const config = Container.get(GlobalConfig); + expect(config.database.minRecoveryBackoffMs).toBe(1000); + expect(consoleWarnMock).toHaveBeenCalledWith( + expect.stringContaining('DB_RECOVERY_BACKOFF_MIN_MS'), + ); + }); + + it('should reject a negative DB_RECOVERY_BACKOFF_MAX_MS and fall back to the default', () => { + process.env = { DB_RECOVERY_BACKOFF_MAX_MS: '-5' }; + const config = Container.get(GlobalConfig); + expect(config.database.maxRecoveryBackoffMs).toBe(30000); + }); + + it('should accept 0 for DB_CONNECTION_ACQUISITION_TIMEOUT_MS (wait indefinitely)', () => { + process.env = { DB_CONNECTION_ACQUISITION_TIMEOUT_MS: '0' }; + const config = Container.get(GlobalConfig); + expect(config.database.connectionAcquisitionTimeoutMs).toBe(0); + }); + + it('should reject a negative DB_CONNECTION_ACQUISITION_TIMEOUT_MS and fall back to the default', () => { + process.env = { DB_CONNECTION_ACQUISITION_TIMEOUT_MS: '-1' }; + const config = Container.get(GlobalConfig); + expect(config.database.connectionAcquisitionTimeoutMs).toBe(30000); + }); + + it('should accept valid recovery overrides', () => { + process.env = { + DB_PING_MAX_FAILURES_BEFORE_RECOVERY: '5', + DB_RECOVERY_BACKOFF_MIN_MS: '500', + DB_RECOVERY_BACKOFF_MAX_MS: '60000', + DB_CONNECTION_ACQUISITION_TIMEOUT_MS: '10000', + }; + const config = Container.get(GlobalConfig); + expect(config.database.pingMaxFailuresBeforeRecovery).toBe(5); + expect(config.database.minRecoveryBackoffMs).toBe(500); + expect(config.database.maxRecoveryBackoffMs).toBe(60000); + expect(config.database.connectionAcquisitionTimeoutMs).toBe(10000); + }); + }); + it('should clamp password min length to valid range', () => { process.env = { N8N_PASSWORD_MIN_LENGTH: '100' }; const config = Container.get(GlobalConfig); @@ -733,11 +822,11 @@ describe('GlobalConfig', () => { it('should validate crossOriginOpenerPolicy enum values', () => { process.env = { - N8N_CROSS_ORIGIN_OPENER_POLICY: 'same-origin-allow-popups', + N8N_CROSS_ORIGIN_OPENER_POLICY: 'same-origin', }; const globalConfig = Container.get(GlobalConfig); - expect(globalConfig.security.crossOriginOpenerPolicy).toEqual('same-origin-allow-popups'); + expect(globalConfig.security.crossOriginOpenerPolicy).toEqual('same-origin'); }); it('should warn and fall back to default for invalid crossOriginOpenerPolicy', () => { @@ -746,7 +835,7 @@ describe('GlobalConfig', () => { }; const globalConfig = Container.get(GlobalConfig); - expect(globalConfig.security.crossOriginOpenerPolicy).toEqual('same-origin'); + expect(globalConfig.security.crossOriginOpenerPolicy).toEqual('same-origin-allow-popups'); }); }); @@ -778,20 +867,4 @@ describe('GlobalConfig', () => { expect(config.endpoints.health).toEqual('/api/v1/health'); }); }); - - describe('ExecutionsConfig', () => { - it('should default scheduledExecutionDeduplicationEnabled to false', () => { - process.env = {}; - const config = Container.get(ExecutionsConfig); - expect(config.scheduledExecutionDeduplicationEnabled).toBe(false); - }); - - it('should enable scheduledExecutionDeduplicationEnabled when env var is set to true', () => { - process.env = { - N8N_SCHEDULED_EXECUTION_DEDUPLICATION_ENABLED: 'true', - }; - const config = Container.get(ExecutionsConfig); - expect(config.scheduledExecutionDeduplicationEnabled).toBe(true); - }); - }); }); diff --git a/packages/@n8n/config/tsconfig.build.json b/packages/@n8n/config/tsconfig.build.json index ad061742795..cb6f7f235dc 100644 --- a/packages/@n8n/config/tsconfig.build.json +++ b/packages/@n8n/config/tsconfig.build.json @@ -3,8 +3,7 @@ "compilerOptions": { "composite": true, "rootDir": "src", - "outDir": "dist", - "tsBuildInfoFile": "dist/build.tsbuildinfo" + "outDir": "dist" }, "include": ["src/**/*.ts"], "exclude": ["test/**", "src/**/__tests__/**"] diff --git a/packages/@n8n/config/tsconfig.json b/packages/@n8n/config/tsconfig.json index 86192a71b78..0e71f865c75 100644 --- a/packages/@n8n/config/tsconfig.json +++ b/packages/@n8n/config/tsconfig.json @@ -4,8 +4,7 @@ "emitDecoratorMetadata": true, "experimentalDecorators": true, "strictPropertyInitialization": false, - "types": ["node", "vitest/globals"], - "tsBuildInfoFile": "dist/typecheck.tsbuildinfo" + "types": ["node", "vitest/globals"] }, "include": ["src/**/*.ts", "test/**/*.ts"], "references": [{ "path": "../di/tsconfig.build.json" }] diff --git a/packages/@n8n/constants/package.json b/packages/@n8n/constants/package.json index a81fe188d5e..40f2615e380 100644 --- a/packages/@n8n/constants/package.json +++ b/packages/@n8n/constants/package.json @@ -1,6 +1,6 @@ { "name": "@n8n/constants", - "version": "0.25.0", + "version": "0.27.0", "scripts": { "clean": "rimraf dist .turbo", "dev": "pnpm watch", @@ -12,7 +12,7 @@ "lint": "eslint . --quiet", "lint:fix": "eslint . --fix", "watch": "tsc -p tsconfig.build.json --watch", - "test": "jest" + "test": "jest --passWithNoTests" }, "main": "dist/index.js", "module": "src/index.ts", @@ -22,5 +22,6 @@ ], "devDependencies": { "@n8n/typescript-config": "workspace:*" - } + }, + "license": "LicenseRef-n8n-sustainable-use" } diff --git a/packages/@n8n/constants/src/index.ts b/packages/@n8n/constants/src/index.ts index 2af7b197f4a..9d42e38431f 100644 --- a/packages/@n8n/constants/src/index.ts +++ b/packages/@n8n/constants/src/index.ts @@ -20,6 +20,7 @@ export const LICENSE_FEATURES = { SHOW_NON_PROD_BANNER: 'feat:showNonProdBanner', DEBUG_IN_EDITOR: 'feat:debugInEditor', BINARY_DATA_S3: 'feat:binaryDataS3', + EXECUTION_DATA_S3: 'feat:executionDataS3', MULTIPLE_MAIN_INSTANCES: 'feat:multipleMainInstances', WORKER_VIEW: 'feat:workerView', ADVANCED_PERMISSIONS: 'feat:advancedPermissions', @@ -44,7 +45,7 @@ export const LICENSE_FEATURES = { PERSONAL_SPACE_POLICY: 'feat:personalSpacePolicy', TOKEN_EXCHANGE: 'feat:tokenExchange', DATA_REDACTION: 'feat:dataRedaction', - N8N_PACKAGES: 'feat:n8nPackages', + OTEL_CUSTOM_SPAN_ATTRIBUTES: 'feat:otel:customSpanAttributes', } as const; export const LICENSE_QUOTAS = { diff --git a/packages/@n8n/constants/tsconfig.build.json b/packages/@n8n/constants/tsconfig.build.json index b00e44f51a1..739279efaec 100644 --- a/packages/@n8n/constants/tsconfig.build.json +++ b/packages/@n8n/constants/tsconfig.build.json @@ -3,8 +3,7 @@ "compilerOptions": { "composite": true, "rootDir": "src", - "outDir": "dist", - "tsBuildInfoFile": "dist/build.tsbuildinfo" + "outDir": "dist" }, "include": ["src/**/*.ts"] } diff --git a/packages/@n8n/constants/tsconfig.json b/packages/@n8n/constants/tsconfig.json index 5fe436c08a3..3a807ec1f86 100644 --- a/packages/@n8n/constants/tsconfig.json +++ b/packages/@n8n/constants/tsconfig.json @@ -2,7 +2,6 @@ "extends": "@n8n/typescript-config/tsconfig.common.json", "compilerOptions": { "types": ["node", "jest"], - "tsBuildInfoFile": "dist/typecheck.tsbuildinfo", "experimentalDecorators": true, "emitDecoratorMetadata": true }, diff --git a/packages/@n8n/crdt/package.json b/packages/@n8n/crdt/package.json index 3a4c962d641..f2524c339fe 100644 --- a/packages/@n8n/crdt/package.json +++ b/packages/@n8n/crdt/package.json @@ -1,6 +1,6 @@ { "name": "@n8n/crdt", - "version": "0.5.0", + "version": "0.7.0", "description": "CRDT abstraction layer for n8n collaborative editing", "scripts": { "clean": "rimraf dist .turbo", @@ -39,5 +39,6 @@ "@n8n/vitest-config": "workspace:*", "vitest": "catalog:", "vitest-websocket-mock": "^0.5.0" - } + }, + "license": "LicenseRef-n8n-sustainable-use" } diff --git a/packages/@n8n/crdt/src/test-matchers.d.ts b/packages/@n8n/crdt/src/__tests__/test-matchers.d.ts similarity index 100% rename from packages/@n8n/crdt/src/test-matchers.d.ts rename to packages/@n8n/crdt/src/__tests__/test-matchers.d.ts diff --git a/packages/@n8n/crdt/tsconfig.build.json b/packages/@n8n/crdt/tsconfig.build.json index 1a1690337fc..664f2961e1a 100644 --- a/packages/@n8n/crdt/tsconfig.build.json +++ b/packages/@n8n/crdt/tsconfig.build.json @@ -3,8 +3,7 @@ "compilerOptions": { "composite": true, "rootDir": "src", - "outDir": "dist", - "tsBuildInfoFile": "dist/build.tsbuildinfo" + "outDir": "dist" }, "include": ["src/**/*.ts"], "exclude": ["src/**/*.test.ts", "src/__tests__/**"] diff --git a/packages/@n8n/crdt/tsconfig.json b/packages/@n8n/crdt/tsconfig.json index d41b2ba23b0..801a1e65587 100644 --- a/packages/@n8n/crdt/tsconfig.json +++ b/packages/@n8n/crdt/tsconfig.json @@ -1,8 +1,7 @@ { "extends": "@n8n/typescript-config/tsconfig.common.json", "compilerOptions": { - "types": ["node", "vitest/globals"], - "tsBuildInfoFile": "dist/typecheck.tsbuildinfo" + "types": ["node", "vitest/globals"] }, "include": ["src/**/*.ts"] } diff --git a/packages/@n8n/create-node/package.json b/packages/@n8n/create-node/package.json index 1ad5c1ef9f4..5234eaef1c4 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.33.0", + "version": "0.35.0", "description": "Official CLI to create new community nodes for n8n", "bin": { "create-node": "bin/create-node.cjs" @@ -21,5 +21,6 @@ }, "devDependencies": { "@n8n/typescript-config": "workspace:*" - } + }, + "license": "LicenseRef-n8n-sustainable-use" } diff --git a/packages/@n8n/db/package.json b/packages/@n8n/db/package.json index 555b0c64b2f..709e4996f29 100644 --- a/packages/@n8n/db/package.json +++ b/packages/@n8n/db/package.json @@ -1,8 +1,8 @@ { "name": "@n8n/db", - "version": "1.25.0", + "version": "1.27.0", "scripts": { - "clean": "rimraf dist .turbo", + "clean": "rimraf dist .turbo .tmp-schema-docs", "dev": "pnpm watch", "typecheck": "tsc --noEmit", "build": "tsc -p tsconfig.build.json", @@ -15,7 +15,13 @@ "test": "vitest run", "test:unit": "vitest run", "test:dev": "vitest --silent=false", - "migration:new": "node scripts/new-migration.mjs" + "migration:new": "node scripts/new-migration.mjs", + "schema:docs:sqlite": "node scripts/schema-docs.mjs doc --db=sqlite", + "schema:docs:postgres": "node scripts/schema-docs.mjs doc --db=postgres", + "schema:docs": "pnpm schema:docs:sqlite && pnpm schema:docs:postgres", + "schema:check:sqlite": "node scripts/schema-docs.mjs diff --db=sqlite", + "schema:check:postgres": "node scripts/schema-docs.mjs diff --db=postgres", + "schema:check": "pnpm schema:check:sqlite && pnpm schema:check:postgres" }, "main": "dist/index.js", "module": "src/index.ts", @@ -49,10 +55,13 @@ "@n8n/typescript-config": "workspace:*", "@n8n/vitest-config": "workspace:*", "@types/lodash": "catalog:", + "@testcontainers/postgresql": "catalog:", "@vitest/coverage-v8": "catalog:", "express": "5.1.0", + "testcontainers": "catalog:", "typescript": "catalog:", "vitest": "catalog:", "vitest-mock-extended": "catalog:" - } + }, + "license": "LicenseRef-n8n-sustainable-use" } diff --git a/packages/@n8n/db/scripts/schema-docs.mjs b/packages/@n8n/db/scripts/schema-docs.mjs new file mode 100644 index 00000000000..8cbbde31a09 --- /dev/null +++ b/packages/@n8n/db/scripts/schema-docs.mjs @@ -0,0 +1,272 @@ +#!/usr/bin/env node +// @ts-check +/** + * Generates (or verifies) the database schema documentation under `docs/generated/`. + * + * The schema is defined by the migrations, not the entities (entities run with + * `synchronize: false`). So we bring an empty database to the fully-migrated + * state by running the `@n8n/db` migration arrays, then point `tbls` at it to + * render Markdown + a Mermaid ER diagram. + * + * One database type per process: `migration-helpers.ts` captures `DB_TYPE` / + * `DB_TABLE_PREFIX` from the DI config at module-load time, so the env must be + * set BEFORE `@n8n/db` is imported and cannot be changed afterwards. + * + * node scripts/schema-docs.mjs <doc|diff> --db=<sqlite|postgres> [--docker] + * + * `--docker` (auto-enabled when `CI` is set) runs tbls via its image instead of + * a local binary. + */ +import { spawn, spawnSync } from 'node:child_process'; +import { mkdirSync, rmSync } from 'node:fs'; +import { dirname, relative, resolve } from 'node:path'; +import { fileURLToPath } from 'node:url'; + +const __dirname = dirname(fileURLToPath(import.meta.url)); +const PKG_ROOT = resolve(__dirname, '..'); +const REPO_ROOT = resolve(__dirname, '../../../../'); +const TMP_DIR = resolve(PKG_ROOT, '.tmp-schema-docs'); + +// Pinned by tag + digest for reproducible CI runs; bump deliberately. +const TBLS_IMAGE = + 'ghcr.io/k1low/tbls:v1.94.5@sha256:ae8a3bff6d4f8495d13a7982cd71fac3e8a3d1dd394888f2c44ef82216aa14e4'; + +/** Thrown for expected, user-facing failures so `main`'s cleanup still runs. */ +class FailError extends Error {} + +function fail(msg) { + throw new FailError(msg); +} + +/** Turns a spawn failure into an actionable message for missing binaries. */ +function spawnErrorMessage(cmd, err) { + if (err.code === 'ENOENT') { + if (cmd === 'tbls') { + return 'tbls is not installed. Install it with `brew install tbls` (see https://github.com/k1LoW/tbls#install), or re-run with --docker to use the tbls Docker image instead.'; + } + if (cmd === 'docker') { + return 'docker is not installed or not on PATH. Install Docker, or drop --docker to use a local tbls binary.'; + } + } + return `failed to spawn ${cmd}: ${err.message}`; +} + +function parseArgs(argv) { + const args = { command: null, dbType: null, docker: !!process.env.CI }; + for (const arg of argv) { + if (arg === '--docker') args.docker = true; + else if (arg.startsWith('--db=')) args.dbType = arg.slice('--db='.length); + else if (!arg.startsWith('--') && !args.command) args.command = arg; + } + return args; +} + +/** Runs a command, inheriting stdio. Resolves with the exit code. */ +function run(cmd, cmdArgs, env) { + return new Promise((res, rej) => { + const child = spawn(cmd, cmdArgs, { cwd: REPO_ROOT, env, stdio: 'inherit' }); + child.on('error', (err) => rej(new FailError(spawnErrorMessage(cmd, err)))); + child.on('close', (code) => res(code ?? 1)); + }); +} + +/** Runs a command, capturing stdout (used for `tbls diff`). */ +function capture(cmd, cmdArgs, env) { + return new Promise((res, rej) => { + let stdout = ''; + const child = spawn(cmd, cmdArgs, { cwd: REPO_ROOT, env }); + child.on('error', (err) => rej(new FailError(spawnErrorMessage(cmd, err)))); + child.stdout.on('data', (d) => (stdout += d)); + child.stderr.on('data', (d) => process.stderr.write(d)); + child.on('close', (code) => res({ code: code ?? 1, stdout })); + }); +} + +/** Spins up an empty database and returns its connection details + a cleanup fn. */ +async function provision(dbType) { + if (dbType === 'sqlite') { + const file = resolve(TMP_DIR, 'schema.sqlite'); + mkdirSync(TMP_DIR, { recursive: true }); + rmSync(file, { force: true }); + process.env.DB_TYPE = 'sqlite'; + process.env.DB_SQLITE_DATABASE = file; + process.env.DB_TABLE_PREFIX = ''; + return { + dataSourceOptions: { type: 'sqlite', database: file }, + file, + cleanup: () => rmSync(file, { force: true }), + }; + } + + // postgres: spin a throwaway container. Image tag matches the testcontainers + // default in `n8n-containers` (packages/testing/containers/test-containers.ts). + const { PostgreSqlContainer } = await import('@testcontainers/postgresql'); + const container = await new PostgreSqlContainer('postgres:18-alpine').start(); + const conn = { + host: container.getHost(), + port: container.getMappedPort(5432), + username: container.getUsername(), + password: container.getPassword(), + database: container.getDatabase(), + schema: 'public', + }; + process.env.DB_TYPE = 'postgresdb'; + process.env.DB_POSTGRESDB_HOST = conn.host; + process.env.DB_POSTGRESDB_PORT = String(conn.port); + process.env.DB_POSTGRESDB_DATABASE = conn.database; + process.env.DB_POSTGRESDB_USER = conn.username; + process.env.DB_POSTGRESDB_PASSWORD = conn.password; + process.env.DB_POSTGRESDB_SCHEMA = conn.schema; + process.env.DB_TABLE_PREFIX = ''; + return { + dataSourceOptions: { type: 'postgres', ...conn }, + cleanup: () => container.stop(), + }; +} + +/** Builds the tbls DSN for the freshly-migrated database. */ +function buildDsn(dbType, provisioned, docker) { + if (dbType === 'sqlite') { + // tbls reads the file directly; under Docker it lives in the /work mount. + const filePath = docker ? `/work/${relative(REPO_ROOT, provisioned.file)}` : provisioned.file; + return `sqlite://${filePath}`; + } + const conn = provisioned.dataSourceOptions; + // Under Docker, tbls runs in its own container and reaches the host-mapped + // Postgres port via host.docker.internal (added below with --add-host). + const host = docker ? 'host.docker.internal' : conn.host; + return `postgres://${conn.username}:${conn.password}@${host}:${conn.port}/${conn.database}?sslmode=disable&search_path=public`; +} + +/** Invokes tbls (binary locally, Docker image in CI). */ +async function tbls(command, dbType, dsn, docker) { + const config = `.tbls.${dbType}.yml`; + const env = { ...process.env, TBLS_DSN: dsn }; + const args = command === 'diff' ? ['diff'] : ['doc', '--force']; + args.push('-c', config); + + if (docker) { + const dockerArgs = [ + 'run', + '--rm', + '--add-host', + 'host.docker.internal:host-gateway', + '-e', + `TBLS_DSN=${dsn}`, + '-v', + `${REPO_ROOT}:/work`, + '-w', + '/work', + TBLS_IMAGE, + ...args, + ]; + return command === 'diff' + ? capture('docker', dockerArgs, env) + : { code: await run('docker', dockerArgs, env), stdout: '' }; + } + return command === 'diff' + ? capture('tbls', args, env) + : { code: await run('tbls', args, env), stdout: '' }; +} + +async function main() { + let { command, dbType, docker } = parseArgs(process.argv.slice(2)); + if (command !== 'doc' && command !== 'diff') { + fail('usage: schema-docs.mjs <doc|diff> --db=<sqlite|postgres> [--docker]'); + } + if (dbType !== 'sqlite' && dbType !== 'postgres') { + fail('--db must be sqlite or postgres'); + } + + // Resolve which tbls runtime to use, before spinning up a DB and running + // migrations. Prefer a local tbls binary; fall back to the Docker image when + // it's absent. `--docker` (or CI) forces the Docker path. + const probeBin = (cmd) => { + const { error, status } = spawnSync(cmd, ['version'], { stdio: 'ignore' }); + if (error) return 'missing'; + return status === 0 ? 'ok' : 'broken'; + }; + + if (docker) { + const state = probeBin('docker'); + if (state === 'missing') fail(spawnErrorMessage('docker', { code: 'ENOENT' })); + if (state === 'broken') + fail('docker is installed but not responding — is the Docker daemon running?'); + } else if (probeBin('tbls') !== 'ok') { + if (probeBin('docker') === 'ok') { + docker = true; + console.info( + 'tbls not available — falling back to running in Docker. ' + + 'Install tbls (`brew install tbls` or see ' + + 'https://github.com/k1LoW/tbls#install) to run locally.', + ); + } else { + fail( + 'neither tbls nor docker is available. Install tbls (`brew install tbls`, ' + + 'see https://github.com/k1LoW/tbls#install) or ensure Docker is set up.', + ); + } + } + + const provisioned = await provision(dbType); + try { + // Imported only now: env above must be set before @n8n/db evaluates its + // migration context from the DI config. + const { DataSource } = await import('@n8n/typeorm'); + // Imported from built dist by path: the package can't resolve its own name. + const { entities, sqliteMigrations, postgresMigrations, wrapMigration } = await import( + new URL('../dist/index.js', import.meta.url).href + ); + const migrations = dbType === 'sqlite' ? sqliteMigrations : postgresMigrations; + + const dataSource = new DataSource({ + ...provisioned.dataSourceOptions, + // Some migrations use the EntityManager, so entity metadata must be registered. + entities: Object.values(entities), + synchronize: false, + migrationsTableName: 'migrations', + migrations, + }); + await dataSource.initialize(); + // Wrap only after initialize(): TypeORM constructs each migration during + // metadata building, and wrapping installs a `transaction` getter that + // would clash with migrations setting `transaction` in their constructor. + migrations.forEach(wrapMigration); + await dataSource.runMigrations({ transaction: 'each' }); + await dataSource.destroy(); + + const dsn = buildDsn(dbType, provisioned, docker); + const { code, stdout } = await tbls(command, dbType, dsn, docker); + + if (command === 'diff') { + // `tbls diff` prints the unified diff to stdout and exits non-zero when + // the docs are stale. An empty stdout with a non-zero exit is a genuine + // tbls error (e.g. cannot connect), so check the diff output first. + if (stdout.trim() !== '') { + process.stdout.write(stdout); + fail( + `schema docs for ${dbType} are out of date. Run \`pnpm db:schema:docs\` and commit the changes.`, + ); + } + if (code !== 0) fail(`tbls diff failed (exit ${code})`); + console.log(`✓ ${dbType} schema docs are up to date`); + } else if (code !== 0) { + fail(`tbls doc failed (exit ${code})`); + } else { + console.log(`✓ generated ${dbType} schema docs in docs/generated/${dbType}-schema`); + } + } finally { + await provisioned.cleanup(); + } +} + +try { + await main(); +} catch (err) { + if (err instanceof FailError) { + console.error(`error: ${err.message}`); + process.exitCode = 1; + } else { + throw err; + } +} diff --git a/packages/@n8n/db/src/connection/__tests__/db-connection-monitor.recovery.postgres.test.ts b/packages/@n8n/db/src/connection/__tests__/db-connection-monitor.recovery.postgres.test.ts new file mode 100644 index 00000000000..8d9ca57d8d7 --- /dev/null +++ b/packages/@n8n/db/src/connection/__tests__/db-connection-monitor.recovery.postgres.test.ts @@ -0,0 +1,219 @@ +import type { Logger } from '@n8n/backend-common'; +import type { DatabaseConfig } from '@n8n/config'; +import { DataSource } from '@n8n/typeorm'; +import { PostgreSqlContainer, type StartedPostgreSqlContainer } from '@testcontainers/postgresql'; +import type { ErrorReporter } from 'n8n-core'; +import { getContainerRuntimeClient } from 'testcontainers'; +import { mock } from 'vitest-mock-extended'; + +import { DbConnectionMonitor } from '../db-connection-monitor'; + +/** + * Integration coverage for the connection-acquisition suspension (CAT-3455). + * + * Unlike the unit suite (which mocks the DataSource), this exercises a REAL + * Postgres pool through a REAL recovery (`destroy()` + `initialize()`) and proves + * that a real TypeORM query issued mid-recovery is held and then completes against + * the rebuilt pool, instead of throwing `Cannot use a pool after calling end on + * the pool` / `Driver not Connected`. + * + * The acquisition wrapper only exists for Postgres: it hooks `driver.obtainMasterConnection`, + * which is the genuine connection chokepoint for the Postgres driver. + * The sqlite driver's `obtainMasterConnection` is a no-op, + * so there is nothing to suspend there and no in-process substitute for this test. + * + * Connection source, in priority order: + * 1. The standard `DB_POSTGRESDB_*` environment variables, when set — the same + * convention the rest of the suite uses (see + * packages/cli/test/setup-testcontainers.js). This is how you run the suite + * locally: point them at any running Postgres. + * 2. Otherwise a throwaway Postgres container, when a container runtime is + * available. This is what lets the suite run on CI, whose unit lane has no + * external database but does have a usable container runtime. + * + * When neither is available the suite is skipped, so `pnpm test` still passes on + * a machine with no Postgres and no usable container runtime. + * + * To run it locally, boot a Postgres and export the host, e.g.: + * docker run --rm -e POSTGRES_PASSWORD=password -p 5432:5432 postgres:18-alpine + * DB_POSTGRESDB_HOST=localhost DB_POSTGRESDB_PASSWORD=password \ + * pnpm test db-connection-monitor.recovery.postgres + */ +const POSTGRES_IMAGE = 'postgres:18-alpine'; +const CONTAINER_TIMEOUT_MS = 180_000; +const TEST_TIMEOUT_MS = 60_000; + +// Prefer an externally-provided Postgres (local dev, cli-style integration lanes). +const externalHost = process.env.DB_POSTGRESDB_HOST ?? ''; +const useExternalPostgres = externalHost.length > 0; + +// The recovery trigger is private; expose it for the test without loosening prod typing. +type MonitorInternals = { recoverDataSource: () => Promise<void> }; + +type PgConnection = { + host: string; + port: number; + username: string; + password: string; + database: string; +}; + +const buildDatabaseConfig = () => + mock<DatabaseConfig>({ + pingTimeoutMs: 5_000, + pingMaxFailuresBeforeRecovery: 3, + minRecoveryBackoffMs: 1_000, + maxRecoveryBackoffMs: 30_000, + connectionAcquisitionTimeoutMs: 30_000, + }); + +const newDataSource = (conn: PgConnection) => + new DataSource({ + type: 'postgres', + host: conn.host, + port: conn.port, + username: conn.username, + password: conn.password, + database: conn.database, + // No entities/migrations — the test only runs trivial SELECTs through the driver. + synchronize: false, + }); + +describe('DbConnectionMonitor recovery against real Postgres', () => { + let container: StartedPostgreSqlContainer | undefined; + // Left undefined when no Postgres is reachable; the tests skip themselves in + // that case (see the `ctx.skip()` guards below). + let connection: PgConnection | undefined; + + beforeAll(async () => { + if (useExternalPostgres) { + connection = { + host: externalHost, + port: Number(process.env.DB_POSTGRESDB_PORT ?? '5432'), + username: process.env.DB_POSTGRESDB_USER ?? 'postgres', + password: process.env.DB_POSTGRESDB_PASSWORD ?? 'postgres', + database: process.env.DB_POSTGRESDB_DATABASE ?? 'postgres', + }; + return; + } + + // No external Postgres: fall back to a throwaway container, but only where a + // runtime is usable. Probe via testcontainers' own detection rather than + // `docker info` — the CLI can succeed while testcontainers fails to find a + // working runtime strategy, which would make `start()` throw instead of + // leaving the tests to skip. + const runtimeAvailable = await getContainerRuntimeClient().then( + () => true, + () => false, + ); + if (!runtimeAvailable) { + return; + } + + container = await new PostgreSqlContainer(POSTGRES_IMAGE).start(); + connection = { + host: container.getHost(), + port: container.getMappedPort(5432), + username: container.getUsername(), + password: container.getPassword(), + database: container.getDatabase(), + }; + }, CONTAINER_TIMEOUT_MS); + + afterAll(async () => { + await container?.stop(); + }, CONTAINER_TIMEOUT_MS); + + it( + 'control: acquiring a connection after the pool is torn down rejects', + async (ctx) => { + if (!connection) { + ctx.skip(); + return; + } + // Establishes that this environment reproduces the failure the wrapper guards + // against: with no monitor/wrapper installed, acquiring a connection after the + // pool is ended rejects with the exact error seen in production. + const dataSource = newDataSource(connection); + await dataSource.initialize(); + + const driver = dataSource.driver as unknown as MonitorInternals & + Record<'obtainMasterConnection', () => Promise<unknown>>; + + await dataSource.destroy(); + + await expect(driver.obtainMasterConnection()).rejects.toThrow( + /Cannot use a pool after calling end on the pool|Driver not Connected/, + ); + }, + TEST_TIMEOUT_MS, + ); + + it( + 'suspends a real query during recovery and runs it on the rebuilt pool', + async (ctx) => { + if (!connection) { + ctx.skip(); + return; + } + const dataSource = newDataSource(connection); + await dataSource.initialize(); + + const monitor = new DbConnectionMonitor( + dataSource, + () => {}, + buildDatabaseConfig(), + mock<Logger>(), + mock<ErrorReporter>(), + ); + // start() installs the obtainMasterConnection wrapper on the live driver. + // Under vitest (NODE_ENV=test) it does not schedule background pings, so the + // only recovery is the one we trigger explicitly below. + monitor.start(); + + try { + // Sanity: queries work before any recovery. + expect(await dataSource.query('SELECT 1 AS ok')).toEqual([{ ok: 1 }]); + + // A query runner bound to the *current* (soon-to-be-destroyed) driver. + const queryRunner = dataSource.createQueryRunner(); + + // Kick off a real recovery (destroy + reinitialize the live pool). The + // pending-recovery promise is set synchronously, before recovery's first + // await, so the query below is guaranteed to land inside the window. + let recoveryDone = false; + const recovery = (monitor as unknown as MonitorInternals).recoverDataSource().then(() => { + recoveryDone = true; + }); + + // PostgresQueryRunner.query -> connect() -> driver.obtainMasterConnection, + // i.e. the exact chokepoint. Without suspension this rejects with the + // pool-after-end error; with it, the call waits out recovery and retries against + // the rebuilt pool. + const rows = ( + await Promise.all([queryRunner.query('SELECT 42 AS answer'), recovery]) + )[0] as Array<{ answer: number }>; + + // The real proof of suspension is that the query produced its result at all: + // without the wrapper it would have rejected with the pool-after-end error + // ("Cannot use a pool after calling end on the pool") when it + // hit the torn-down pool, failing the `Promise.all` above before we reached + // this line. `recoveryDone` is necessarily true here (the `Promise.all` awaits + // `recovery`); we assert it only to pin that recovery actually ran. + expect(recoveryDone).toBe(true); + expect(rows).toEqual([{ answer: 42 }]); + + await queryRunner.release(); + + // The pool is healthy afterwards. + expect(await dataSource.query('SELECT 1 AS ok')).toEqual([{ ok: 1 }]); + } finally { + await monitor.stop(); + if (dataSource.isInitialized) { + await dataSource.destroy(); + } + } + }, + TEST_TIMEOUT_MS, + ); +}); diff --git a/packages/@n8n/db/src/connection/__tests__/db-connection-monitor.test.ts b/packages/@n8n/db/src/connection/__tests__/db-connection-monitor.test.ts index 61829b4cf4b..ba39d5d9af7 100644 --- a/packages/@n8n/db/src/connection/__tests__/db-connection-monitor.test.ts +++ b/packages/@n8n/db/src/connection/__tests__/db-connection-monitor.test.ts @@ -25,7 +25,13 @@ describe('DbConnectionMonitor', () => { let monitor: DbConnectionMonitor; let onConnectedChange: MockedFunction<(connected: boolean) => void>; const errorReporter = mock<ErrorReporter>(); - const databaseConfig = mock<DatabaseConfig>({ pingTimeoutMs: 5_000 }); + const databaseConfig = mock<DatabaseConfig>({ + pingTimeoutMs: 5_000, + pingMaxFailuresBeforeRecovery: 3, + minRecoveryBackoffMs: 1_000, + maxRecoveryBackoffMs: 30_000, + connectionAcquisitionTimeoutMs: 30_000, + }); const logger = mock<Logger>(); const dataSource = mockDeep<DataSource>({ options: { type: 'postgres' } }); @@ -132,7 +138,7 @@ describe('DbConnectionMonitor', () => { it('should not query if monitor is stopped', async () => { // @ts-expect-error readonly property dataSource.isInitialized = true; - monitor.stop(); + void monitor.stop(); // @ts-expect-error private property await monitor.ping(); @@ -270,7 +276,7 @@ describe('DbConnectionMonitor', () => { // eslint-disable-next-line @typescript-eslint/no-explicit-any const pingSpy = vi.spyOn(scheduledMonitor as any, 'ping'); - scheduledMonitor.stop(); + void scheduledMonitor.stop(); // @ts-expect-error private property scheduledMonitor.scheduleNextPing(); vi.advanceTimersByTime(1000); @@ -315,7 +321,7 @@ describe('DbConnectionMonitor', () => { }); it('should be a no-op when monitor is stopped', async () => { - monitor.stop(); + void monitor.stop(); // @ts-expect-error private property await monitor.recoverDataSource(); @@ -414,6 +420,50 @@ describe('DbConnectionMonitor', () => { ); }); + it('should not drop below the floor when max backoff is misconfigured below min', async () => { + // A misconfiguration (max < min) must degrade to a constant `min` delay rather + // than collapsing every retry onto the smaller max value, which would defeat the floor. + const misconfigured = mock<DatabaseConfig>({ + pingTimeoutMs: 5_000, + pingMaxFailuresBeforeRecovery: 3, + minRecoveryBackoffMs: 1_000, + maxRecoveryBackoffMs: 100, + }); + const misconfiguredMonitor = new DbConnectionMonitor( + dataSource, + onConnectedChange, + misconfigured, + logger, + errorReporter, + ); + + // @ts-expect-error readonly property + dataSource.isInitialized = true; + dataSource.destroy.mockResolvedValue(); + dataSource.initialize + .mockRejectedValueOnce(new Error('down')) + .mockRejectedValueOnce(new Error('down')) + .mockResolvedValueOnce(dataSource); + mockedSetTimeoutP.mockResolvedValue(undefined); + + // @ts-expect-error private property + await misconfiguredMonitor.recoverDataSource(); + + // Both backoffs clamp to the floor (1s) instead of the bogus 100ms max. + expect(mockedSetTimeoutP).toHaveBeenNthCalledWith( + 1, + 1_000, + undefined, + expect.objectContaining({ signal: expect.any(AbortSignal) }), + ); + expect(mockedSetTimeoutP).toHaveBeenNthCalledWith( + 2, + 1_000, + undefined, + expect.objectContaining({ signal: expect.any(AbortSignal) }), + ); + }); + it('should exit the recovery loop when stop() is called during backoff', async () => { // @ts-expect-error readonly property dataSource.isInitialized = true; @@ -433,7 +483,7 @@ describe('DbConnectionMonitor', () => { await flushMicrotasks(); expect(dataSource.initialize).toHaveBeenCalledTimes(1); - monitor.stop(); + void monitor.stop(); resolveBackoff(); await recoveryPromise; @@ -471,7 +521,7 @@ describe('DbConnectionMonitor', () => { expect.objectContaining({ signal: expect.any(AbortSignal) }), ); - monitor.stop(); + void monitor.stop(); await recoveryPromise; // AbortError is swallowed; the loop exits on the next iteration without retrying. @@ -489,8 +539,14 @@ describe('DbConnectionMonitor', () => { dataSource.destroy.mockResolvedValue(); dataSource.initialize.mockResolvedValue(dataSource); const on = vi.fn(); - (dataSource as unknown as { driver: { master: { on: Mock } } }).driver = { + ( + dataSource as unknown as { + driver: { master: { on: Mock }; obtainMasterConnection: () => Promise<unknown> }; + } + ).driver = { master: { on }, + // start()/recoverDataSource() wrap obtainMasterConnection unconditionally. + obtainMasterConnection: vi.fn().mockResolvedValue(undefined), }; // @ts-expect-error private property @@ -511,13 +567,90 @@ describe('DbConnectionMonitor', () => { const recoveryPromise = monitor.recoverDataSource(); // Stop while destroy is still pending. - monitor.stop(); + void monitor.stop(); await recoveryPromise; expect(dataSource.destroy).toHaveBeenCalled(); expect(dataSource.initialize).not.toHaveBeenCalled(); }); + + it('should await the in-flight recovery so teardown is ordered after it', async () => { + // stop() must not resolve until the fire-and-forget recovery launched by ping() + // has unwound, so the owner can destroy the DataSource without racing the loop. + // @ts-expect-error readonly property + dataSource.isInitialized = true; + let resolveDestroy: () => void = () => {}; + let destroyResolved = false; + dataSource.destroy.mockImplementation( + async () => + await new Promise<void>((resolve) => { + resolveDestroy = () => { + destroyResolved = true; + resolve(); + }; + }), + ); + + // Launch recovery exactly as a failed ping() does (`this.recoveryPromise = + // this.recoverDataSource()`), without driving the ping loop itself: the mock + // config has no pingIntervalSeconds, so scheduleNextPing() would spin a + // runaway ~1ms setTimeout while recovery is parked, which starves the event + // loop and times the test out under CI load. + // @ts-expect-error private property + monitor.recoveryPromise = monitor.recoverDataSource(); + await flushMicrotasks(); + // Recovery is parked inside the slow destroy(). + expect(dataSource.destroy).toHaveBeenCalled(); + + const stopPromise = monitor.stop(); + let stopResolved = false; + void stopPromise.then(() => (stopResolved = true)); + + // stop() cannot resolve while recovery is still draining destroy(). + await flushMicrotasks(); + expect(stopResolved).toBe(false); + + resolveDestroy(); + await stopPromise; + + expect(destroyResolved).toBe(true); + expect(stopResolved).toBe(true); + // The post-destroy `if (this.stopped) break;` prevents reinitialization. + expect(dataSource.initialize).not.toHaveBeenCalled(); + }); + }); + + describe('start', () => { + it('should warn once when max recovery backoff is configured below min', () => { + const misconfigured = mock<DatabaseConfig>({ + pingTimeoutMs: 5_000, + pingMaxFailuresBeforeRecovery: 3, + minRecoveryBackoffMs: 1_000, + maxRecoveryBackoffMs: 100, + }); + const misconfiguredMonitor = new DbConnectionMonitor( + dataSource, + onConnectedChange, + misconfigured, + logger, + errorReporter, + ); + + misconfiguredMonitor.start(); + + expect(logger.warn).toHaveBeenCalledWith( + expect.stringContaining('DB_RECOVERY_BACKOFF_MAX_MS'), + ); + }); + + it('should not warn when backoff bounds are valid', () => { + monitor.start(); + + expect(logger.warn).not.toHaveBeenCalledWith( + expect.stringContaining('DB_RECOVERY_BACKOFF_MAX_MS'), + ); + }); }); describe('attachPoolErrorHandler', () => { @@ -526,9 +659,15 @@ describe('DbConnectionMonitor', () => { // and matches the unsafe cast the production code uses to reach driver.master. type DriverShape = { master?: { on?: (event: string, handler: (cause: unknown) => void) => void }; + obtainMasterConnection?: () => Promise<unknown>; }; + // start() wraps obtainMasterConnection unconditionally, so every driver needs it present + // or wrapConnectionAcquisition throws. Default it; tests override what they assert on. const setDriver = (driver: DriverShape) => { - (dataSource as unknown as { driver: DriverShape }).driver = driver; + (dataSource as unknown as { driver: DriverShape }).driver = { + obtainMasterConnection: vi.fn().mockResolvedValue(undefined), + ...driver, + }; }; it('should attach an error listener to the Postgres driver pool', () => { @@ -560,6 +699,35 @@ describe('DbConnectionMonitor', () => { ); }); + it('should ignore errors from a pool that recovery has since replaced', () => { + // Recovery swaps in a fresh driver+pool but the old pool can still emit a late + // 'error' while tearing down. Acting on it would mark the just-recovered instance + // unhealthy, so the stale pool's handler must be inert. + let staleHandler: ((cause: unknown) => void) | undefined; + const on = vi.fn((_event: string, h: (cause: unknown) => void) => { + staleHandler = h; + }); + const stalePool = { on }; + setDriver({ master: stalePool }); + // @ts-expect-error private property + monitor.connected = true; + + monitor.start(); + expect(staleHandler).toBeDefined(); + + // A recovery replaced the driver's master with a brand-new pool. + (dataSource as unknown as { driver: DriverShape }).driver.master = { + on: vi.fn(), + }; + + staleHandler?.(new Error('terminating connection due to administrator command')); + + expect(onConnectedChange).not.toHaveBeenCalledWith(false); + expect(logger.debug).toHaveBeenCalledWith( + expect.stringContaining('Ignoring Postgres pool error'), + ); + }); + it('should skip attaching when the driver is not Postgres', () => { const sqliteDataSource = mockDeep<DataSource>({ options: { type: 'sqlite-pooled' } }); const sqliteMonitor = new DbConnectionMonitor( @@ -589,13 +757,240 @@ describe('DbConnectionMonitor', () => { }); }); + describe('connection acquisition during recovery', () => { + // Minimal driver shape, same rationale as the attachPoolErrorHandler block: + // avoids TS2590 on the full driver union and mirrors the production cast. + type AcquisitionDriverShape = { + master?: { on?: (event: string, handler: (cause: unknown) => void) => void }; + obtainMasterConnection?: () => Promise<unknown>; + }; + const setDriver = (driver: AcquisitionDriverShape) => { + (dataSource as unknown as { driver: AcquisitionDriverShape }).driver = driver; + }; + // The private recovery helpers, reached the same way the rest of this file + // pokes at internals. + const internals = () => + monitor as unknown as { + acquireConnection: (original: () => Promise<unknown>) => Promise<unknown>; + markRecoveryPending: () => void; + clearPendingRecovery: () => void; + recovering: boolean; + liveObtainMasterConnection: (() => Promise<unknown>) | undefined; + }; + + const POOL_ENDED = 'Cannot use a pool after calling end on the pool'; + + it('should wrap driver.obtainMasterConnection on start for Postgres', async () => { + const original = vi.fn().mockResolvedValue('connection'); + setDriver({ obtainMasterConnection: original }); + + monitor.start(); + + const driver = (dataSource as unknown as { driver: AcquisitionDriverShape }).driver; + // The instance method is now a wrapper, not the original. + expect(driver.obtainMasterConnection).not.toBe(original); + await expect(driver.obtainMasterConnection?.()).resolves.toBe('connection'); + expect(original).toHaveBeenCalledTimes(1); + }); + + it('should pass connection acquisition straight through when idle', async () => { + const original = vi.fn().mockResolvedValue('connection'); + + await expect(internals().acquireConnection(original)).resolves.toBe('connection'); + expect(original).toHaveBeenCalledTimes(1); + }); + + it('should hold connection acquisition while a recovery is in progress', async () => { + const original = vi.fn().mockResolvedValue('connection'); + internals().markRecoveryPending(); + + let settled = false; + const pending = internals() + .acquireConnection(original) + .then((result) => { + settled = true; + return result; + }); + + await flushMicrotasks(); + // Recovery is pending: acquisition must not have run yet. + expect(settled).toBe(false); + expect(original).not.toHaveBeenCalled(); + + internals().clearPendingRecovery(); + + await expect(pending).resolves.toBe('connection'); + expect(original).toHaveBeenCalledTimes(1); + }); + + it('should retry against the live driver when acquisition loses the destroy race', async () => { + // A query holding the previous (destroyed) driver hits the ended pool; once + // recovery has swapped in a new driver, the retry must reach the live pool. + const stale = vi.fn().mockRejectedValue(new Error(POOL_ENDED)); + const live = vi.fn().mockResolvedValue('fresh-connection'); + internals().recovering = true; + internals().liveObtainMasterConnection = live; + + await expect(internals().acquireConnection(stale)).resolves.toBe('fresh-connection'); + expect(stale).toHaveBeenCalledTimes(1); + expect(live).toHaveBeenCalledTimes(1); + }); + + it('should retry stale acquisition errors after recovery has completed', async () => { + const stale = vi.fn().mockRejectedValue(new Error(POOL_ENDED)); + const live = vi.fn().mockResolvedValue('fresh-connection'); + internals().recovering = false; + internals().liveObtainMasterConnection = live; + + await expect(internals().acquireConnection(stale)).resolves.toBe('fresh-connection'); + expect(stale).toHaveBeenCalledTimes(1); + expect(live).toHaveBeenCalledTimes(1); + }); + + it('should retry on a "Driver not Connected" error during recovery', async () => { + const stale = vi.fn().mockRejectedValue(new Error('Driver not Connected')); + const live = vi.fn().mockResolvedValue('fresh-connection'); + internals().recovering = true; + internals().liveObtainMasterConnection = live; + + await expect(internals().acquireConnection(stale)).resolves.toBe('fresh-connection'); + expect(live).toHaveBeenCalledTimes(1); + }); + + it('should surface a pool error when no recovery is in progress', async () => { + // Outside a recovery window the pool is genuinely unavailable; masking it + // with a retry would hide a real outage. + const original = vi.fn().mockRejectedValue(new Error(POOL_ENDED)); + internals().recovering = false; + internals().liveObtainMasterConnection = original; + + await expect(internals().acquireConnection(original)).rejects.toThrow(POOL_ENDED); + expect(original).toHaveBeenCalledTimes(1); + }); + + it('should not retry an unrelated error even during recovery', async () => { + const original = vi.fn().mockRejectedValue(new Error('syntax error at or near "FROM"')); + const live = vi.fn().mockResolvedValue('fresh-connection'); + internals().recovering = true; + internals().liveObtainMasterConnection = live; + + await expect(internals().acquireConnection(original)).rejects.toThrow('syntax error'); + expect(live).not.toHaveBeenCalled(); + }); + + it('should fail fast with an OperationalError when recovery exceeds the acquisition timeout', async () => { + // A long outage parks every query here; without the bound they would pile up for + // the whole outage. Once the timeout elapses the query must reject instead. + const original = vi.fn().mockResolvedValue('connection'); + internals().markRecoveryPending(); + // Fire the timeout side of the race immediately. + mockedSetTimeoutP.mockResolvedValueOnce(undefined); + + await expect(internals().acquireConnection(original)).rejects.toThrow( + 'Timed out after 30000ms waiting for database connection recovery', + ); + // The query never reached the pool. + expect(original).not.toHaveBeenCalled(); + }); + + it('should acquire normally when recovery completes before the acquisition timeout', async () => { + // The timeout must not fire when recovery wins the race. + const original = vi.fn().mockResolvedValue('connection'); + internals().markRecoveryPending(); + + const pending = internals().acquireConnection(original); + await flushMicrotasks(); + expect(original).not.toHaveBeenCalled(); + + // Recovery completes before the (never-resolving) timeout. + internals().clearPendingRecovery(); + + await expect(pending).resolves.toBe('connection'); + expect(original).toHaveBeenCalledTimes(1); + }); + + it('should wait indefinitely when the acquisition timeout is 0', async () => { + const noTimeoutMonitor = new DbConnectionMonitor( + dataSource, + onConnectedChange, + mock<DatabaseConfig>({ + pingTimeoutMs: 5_000, + pingMaxFailuresBeforeRecovery: 3, + minRecoveryBackoffMs: 1_000, + maxRecoveryBackoffMs: 30_000, + connectionAcquisitionTimeoutMs: 0, + }), + logger, + errorReporter, + ); + const noTimeoutInternals = noTimeoutMonitor as unknown as { + acquireConnection: (original: () => Promise<unknown>) => Promise<unknown>; + markRecoveryPending: () => void; + clearPendingRecovery: () => void; + }; + const original = vi.fn().mockResolvedValue('connection'); + noTimeoutInternals.markRecoveryPending(); + // Behavioural proof that no timeout is armed: if `awaitRecovery` ever raced a timeout here it would reject. + // Asserting on the shared `setTimeoutP` call count is unreliable because other tests leave a fire-and-forget ping loop calling it. + mockedSetTimeoutP.mockImplementation(async () => { + await Promise.resolve(); + throw new Error('timeout should not be armed when the acquisition timeout is 0'); + }); + + let settled = false; + const pending = noTimeoutInternals.acquireConnection(original).then((result) => { + settled = true; + return result; + }); + + await flushMicrotasks(); + // The acquisition stays parked on recovery rather than failing fast. + expect(settled).toBe(false); + + noTimeoutInternals.clearPendingRecovery(); + + // Resolves cleanly once recovery completes; never rejects on a timeout. + await expect(pending).resolves.toBe('connection'); + }); + + it('should release queued acquisitions when stop() is called', async () => { + const original = vi.fn().mockResolvedValue('connection'); + internals().markRecoveryPending(); + + const pending = internals().acquireConnection(original); + await flushMicrotasks(); + expect(original).not.toHaveBeenCalled(); + + void monitor.stop(); + + await expect(pending).resolves.toBe('connection'); + }); + + it('should re-wrap obtainMasterConnection after a successful recovery', async () => { + // initialize() builds a fresh driver instance, so the wrapper installed at + // start() is gone; without re-wrapping, the new pool would not wait during recovery. + // @ts-expect-error readonly property + dataSource.isInitialized = true; + dataSource.destroy.mockResolvedValue(); + dataSource.initialize.mockResolvedValue(dataSource); + const original = vi.fn().mockResolvedValue('connection'); + setDriver({ obtainMasterConnection: original }); + + // @ts-expect-error private property + await monitor.recoverDataSource(); + + const driver = (dataSource as unknown as { driver: AcquisitionDriverShape }).driver; + expect(driver.obtainMasterConnection).not.toBe(original); + }); + }); + describe('stop', () => { it('should clear the ping timer', () => { const clearTimeoutSpy = vi.spyOn(global, 'clearTimeout'); // @ts-expect-error private property monitor.pingTimer = setTimeout(() => {}, 1000); - monitor.stop(); + void monitor.stop(); expect(clearTimeoutSpy).toHaveBeenCalled(); // @ts-expect-error private property @@ -603,7 +998,7 @@ describe('DbConnectionMonitor', () => { }); it('should latch `stopped` so future scheduling is skipped', () => { - monitor.stop(); + void monitor.stop(); // @ts-expect-error private property expect(monitor.stopped).toBe(true); diff --git a/packages/@n8n/db/src/connection/db-connection-monitor.ts b/packages/@n8n/db/src/connection/db-connection-monitor.ts index 14383005c3d..2c539660243 100644 --- a/packages/@n8n/db/src/connection/db-connection-monitor.ts +++ b/packages/@n8n/db/src/connection/db-connection-monitor.ts @@ -2,21 +2,38 @@ import { inTest, type Logger } from '@n8n/backend-common'; import type { DatabaseConfig } from '@n8n/config'; import { Time } from '@n8n/constants'; import type { DataSource } from '@n8n/typeorm'; +import type { PostgresDriver } from '@n8n/typeorm/driver/postgres/PostgresDriver'; import type { ErrorReporter } from 'n8n-core'; import { ensureError, OperationalError } from 'n8n-workflow'; import { setTimeout as setTimeoutP } from 'timers/promises'; -const MAX_PING_FAILURES_BEFORE_RECOVERY = 3; -const MIN_RECOVERY_BACKOFF_MS = 1_000; -const MAX_RECOVERY_BACKOFF_MS = 30_000; +/** The chokepoint every TypeORM query funnels through to acquire a master connection. */ +type ObtainMasterConnection = PostgresDriver['obtainMasterConnection']; + +/** + * Error messages a connection acquisition throws when it reaches a pool that recovery + * has already torn down. These are matched by text because neither pg-pool nor TypeORM + * surfaces a stable error code for them; the strings are pinned by the integration test + * against a real driver, so a driver upgrade that renamed them would fail loudly there. + */ +const POOL_TORN_DOWN_MESSAGE = 'Cannot use a pool after calling end on the pool'; +const DRIVER_NOT_CONNECTED_MESSAGE = 'Driver not Connected'; /** * Watches a DataSource and recovers it when the connection goes bad. * - Pings on `databaseConfig.pingIntervalSeconds`, races against `databaseConfig.pingTimeoutMs`. - * - After `MAX_PING_FAILURES_BEFORE_RECOVERY` consecutive failures, destroys - * and reinitializes the DataSource with exponential backoff. + * - After `databaseConfig.pingMaxFailuresBeforeRecovery` consecutive failures, destroys + * and reinitializes the DataSource with exponential backoff + * (`databaseConfig.minRecoveryBackoffMs` .. `databaseConfig.maxRecoveryBackoffMs`). * - Attaches an error listener to the pg pool (Postgres only) so terminated * idle clients are caught instead of crashing the process. + * - Suspends connection acquisition during recovery so in-flight queries wait + * for the new pool instead of hitting the torn-down one. + * Recovery destroys and recreates the shared pool. + * Without this, any query acquiring a connection in that window throws + * `Cannot use a pool after calling end on the pool` / `Driver not Connected`. + * The wait is applied at `driver.obtainMasterConnection` + * (the single chokepoint every TypeORM query funnels through). * * Notifies the owner of connection transitions via `onConnectedChange`. * The owner is responsible for supplying the initial state via `initialConnected`, @@ -30,6 +47,29 @@ export class DbConnectionMonitor { private stopped = false; // Latched on stop() private stopAbortController = new AbortController(); + /** + * Pending while a recovery is in progress. + * Queued connection acquisitions await it. + * `undefined` when no recovery is running, so queries pass straight through with no added latency. + */ + private pendingRecovery: Promise<void> | undefined; + private resolvePendingRecovery: (() => void) | undefined; + + /** + * Handle on the in-flight recovery loop launched fire-and-forget from `ping()`. + * `stop()` awaits it after aborting so the owner's teardown is ordered + * after the loop's `destroy()`/`initialize()` rather than racing it. + * recoverDataSource` owns its own try/catch and never rejects. + */ + private recoveryPromise: Promise<void> | undefined; + + /** + * The current driver's *unwrapped* `obtainMasterConnection`, refreshed on every (re)initialize. + * `initialize()` builds a brand-new driver instance, + * so a query still holding the previous driver retries against this reference. + */ + private liveObtainMasterConnection: ObtainMasterConnection | undefined; + constructor( private readonly dataSource: DataSource, private readonly onConnectedChange: (connected: boolean) => void, @@ -43,22 +83,30 @@ export class DbConnectionMonitor { start() { this.attachPoolErrorHandler(); + this.wrapConnectionAcquisition(); + if (this.databaseConfig.maxRecoveryBackoffMs < this.databaseConfig.minRecoveryBackoffMs) { + this.logger.warn( + `DB_RECOVERY_BACKOFF_MAX_MS (${this.databaseConfig.maxRecoveryBackoffMs}) is below DB_RECOVERY_BACKOFF_MIN_MS (${this.databaseConfig.minRecoveryBackoffMs}); recovery will retry at a constant ${this.databaseConfig.minRecoveryBackoffMs}ms instead of backing off. Set max >= min.`, + ); + } this.logger.debug( - `Database connection monitor started (pingIntervalSeconds=${this.databaseConfig.pingIntervalSeconds}, pingTimeoutMs=${this.databaseConfig.pingTimeoutMs}, recoveryThreshold=${MAX_PING_FAILURES_BEFORE_RECOVERY})`, + `Database connection monitor started (pingIntervalSeconds=${this.databaseConfig.pingIntervalSeconds}, pingTimeoutMs=${this.databaseConfig.pingTimeoutMs}, recoveryThreshold=${this.databaseConfig.pingMaxFailuresBeforeRecovery})`, ); if (!inTest) { this.scheduleNextPing(); } } - stop() { + async stop() { this.stopped = true; - this.recovering = false; + this.stopRecovery(); this.stopAbortController.abort(); if (this.pingTimer) { clearTimeout(this.pingTimer); this.pingTimer = undefined; } + // Await any in-flight recovery so it has fully unwound (its `!this.stopped` guard exits the loop) before the caller tears down the DataSource. + await this.recoveryPromise; this.logger.debug('Database connection monitor stopped'); } @@ -104,18 +152,18 @@ export class DbConnectionMonitor { this.setConnected(false); this.consecutiveFailures += 1; this.logger.warn( - `Database ping failed (${this.consecutiveFailures}/${MAX_PING_FAILURES_BEFORE_RECOVERY}): ${ensureError(error).message}`, + `Database ping failed (${this.consecutiveFailures}/${this.databaseConfig.pingMaxFailuresBeforeRecovery}): ${ensureError(error).message}`, ); if (!(error instanceof OperationalError)) { this.errorReporter.error(error); } - if (this.consecutiveFailures >= MAX_PING_FAILURES_BEFORE_RECOVERY) { + if (this.consecutiveFailures >= this.databaseConfig.pingMaxFailuresBeforeRecovery) { this.logger.warn( `Triggering database connection recovery after ${this.consecutiveFailures} consecutive ping failures`, ); // Fire-and-forget; recoverDataSource owns its own try/catch/finally and never rejects. - void this.recoverDataSource(); + this.recoveryPromise = this.recoverDataSource(); } } finally { abortController.abort(); @@ -127,7 +175,7 @@ export class DbConnectionMonitor { if (this.recovering || this.stopped) { return; } - this.recovering = true; + this.startRecovery(); try { const recoveryStart = Date.now(); @@ -140,6 +188,12 @@ export class DbConnectionMonitor { try { if (this.dataSource.isInitialized) { + // We deliberately don't bound this drain with a forced teardown. + // `pool.end()` does not interrupt in-flight queries: + // already-acquired clients keep running until their query finishes, + // and only *new* acquisitions are refused + // (those are handled by the acquisition wait in `wrapConnectionAcquisition`). + // So awaiting `destroy()` lets healthy queries drain on their own without us touching pg-pool internals. await this.dataSource.destroy(); } @@ -148,16 +202,14 @@ export class DbConnectionMonitor { } await this.dataSource.initialize(); this.attachPoolErrorHandler(); + this.wrapConnectionAcquisition(); this.setConnected(true); this.consecutiveFailures = 0; recovered = true; } catch (error) { const wrapped = ensureError(error); this.errorReporter.error(wrapped); - const backoff = Math.min( - MIN_RECOVERY_BACKOFF_MS * 2 ** (attempt - 1), - MAX_RECOVERY_BACKOFF_MS, - ); + const backoff = this.computeBackoff(attempt); this.logger.warn( `Recovery attempt ${attempt} failed: ${wrapped.message}. Retrying in ${backoff}ms`, ); @@ -183,23 +235,48 @@ export class DbConnectionMonitor { } catch (error) { this.errorReporter.error(ensureError(error)); } finally { - this.recovering = false; + this.stopRecovery(); } } + /** + * Exponential backoff for the given (1-based) recovery attempt, ramping from + * `minRecoveryBackoffMs` and capped at `maxRecoveryBackoffMs`. + * + * The cap is clamped to never fall below the floor, so a misconfiguration + * (`maxRecoveryBackoffMs < minRecoveryBackoffMs`) degrades to a constant + * `minRecoveryBackoffMs` delay rather than silently collapsing every retry + * onto the smaller max value (which would defeat the floor). The + * misconfiguration is warned about once at `start()`. + */ + private computeBackoff(attempt: number) { + const { minRecoveryBackoffMs, maxRecoveryBackoffMs } = this.databaseConfig; + const ceiling = Math.max(minRecoveryBackoffMs, maxRecoveryBackoffMs); + return Math.min(minRecoveryBackoffMs * 2 ** (attempt - 1), ceiling); + } + + private get isPostgres(): boolean { + return this.dataSource.options.type === 'postgres'; + } + + /** + * Single cast site to the Postgres driver. Only called once `isPostgres` + * is confirmed. Returns a view of the *current* driver, which + * `initialize()` swaps on every recovery. + */ + private get postgresDriver(): PostgresDriver { + return this.dataSource.driver as PostgresDriver; + } + // pg-pool emits 'error' for idle clients that fail (e.g. server-side pg_terminate_backend or RDS failover). // Without a listener Node treats these as unhandled and crashes the process. private attachPoolErrorHandler() { // Postgres-only: the other supported driver (sqlite-pooled) does not expose a pool-level error stream. - if (this.dataSource.options.type !== 'postgres') { + if (!this.isPostgres) { return; } - const driver = this.dataSource.driver as unknown as { - master?: { on?: (event: string, handler: (cause: unknown) => void) => void }; - }; - - const pool = driver.master; + const pool = this.postgresDriver.master; if (!pool || typeof pool.on !== 'function') { // Defensive: TypeORM may have renamed `driver.master` in a future release. this.logger.warn( @@ -209,12 +286,138 @@ export class DbConnectionMonitor { } pool.on('error', (cause: unknown) => { + if (!this.isPostgres || this.postgresDriver.master !== pool) { + this.logger.debug('Ignoring Postgres pool error from a pool replaced by recovery'); + return; + } this.setConnected(false); this.logger.warn(`Postgres pool client error: ${ensureError(cause).message}`); }); this.logger.debug('Attached pool error listener to Postgres driver'); } + /** + * Wraps the driver's `obtainMasterConnection` so connection acquisition waits + * out an in-progress recovery instead of racing the torn-down pool. + * Re-run on every (re)initialize because `initialize()` swaps in a fresh driver instance. + * + * Only master connections are guarded. TypeORM read-replica reads go through a + * separate `obtainSlaveConnection` chokepoint that we don't wrap, because n8n does + * not configure TypeORM replication. + * If it ever does, replica reads would need the same treatment. + */ + private wrapConnectionAcquisition() { + if (!this.isPostgres) { + return; + } + + const driver = this.postgresDriver; + // Capture the unwrapped acquisition fn before we replace it below (bind keeps `this`). + // `bind` widens to `any` here, so we reassert TypeORM's own signature. + const original = driver.obtainMasterConnection.bind(driver) as ObtainMasterConnection; + this.liveObtainMasterConnection = original; + driver.obtainMasterConnection = async () => await this.acquireConnection(original); + } + + /** + * Awaits any in-progress recovery, then acquires a connection. + * If acquisition still loses a race with `destroy()` (recovery began just after this call passed it), + * retry once against the live driver once recovery completes. + */ + private async acquireConnection(original: ObtainMasterConnection) { + await this.awaitRecovery(); + + try { + return await original(); + } catch (error) { + if (!this.isRecoverableConnectionError(error)) { + throw error; + } + + const liveObtainMasterConnection = this.liveObtainMasterConnection; + const isRecoveryRace = + this.recovering || + this.pendingRecovery !== undefined || + (liveObtainMasterConnection !== undefined && liveObtainMasterConnection !== original); + if (!isRecoveryRace) { + throw error; + } + + await this.awaitRecovery(); + // `original` may be bound to the previous (destroyed) driver. + // Prefer the live one refreshed by the latest wrapConnectionAcquisition(). + return await (this.liveObtainMasterConnection ?? original)(); + } + } + + /** + * Waits out an in-progress recovery before a connection is acquired, bounded by `connectionAcquisitionTimeoutMs`. + * Resolves immediately when no recovery is pending. + * + * The bound matters under load: during a long outage every query parks here, so an + * unbounded wait would pile up parked acquirers for the whole outage. Once the timeout + * elapses the query rejects with an `OperationalError` (fail fast) instead of holding + * the request open. `0` disables the timeout (wait indefinitely). + * + * `stop()` resolves `pendingRecovery`, so a parked acquirer is also released by teardown. + */ + private async awaitRecovery() { + const pending = this.pendingRecovery; + if (!pending) { + return; + } + + const timeoutMs = this.databaseConfig.connectionAcquisitionTimeoutMs; + if (timeoutMs <= 0) { + await pending; + return; + } + + // AbortController clears the timeout timer once recovery (or stop) wins the race + const abortController = new AbortController(); + try { + await Promise.race([ + pending, + setTimeoutP(timeoutMs, undefined, { signal: abortController.signal }).then(() => { + throw new OperationalError( + `Timed out after ${timeoutMs}ms waiting for database connection recovery`, + ); + }), + ]); + } finally { + abortController.abort(); + } + } + + private startRecovery() { + this.recovering = true; + this.markRecoveryPending(); + } + + private markRecoveryPending() { + this.pendingRecovery ??= new Promise<void>( + (resolve) => (this.resolvePendingRecovery = resolve), + ); + } + + private stopRecovery() { + this.recovering = false; + this.clearPendingRecovery(); + } + + private clearPendingRecovery() { + this.resolvePendingRecovery?.(); + this.resolvePendingRecovery = undefined; + this.pendingRecovery = undefined; + } + + private isRecoverableConnectionError(error: unknown): boolean { + const { message } = ensureError(error); + return ( + message.includes(POOL_TORN_DOWN_MESSAGE) || message.includes(DRIVER_NOT_CONNECTED_MESSAGE) + ); + } + private setConnected(connected: boolean) { if (this.connected === connected) { return; diff --git a/packages/@n8n/db/src/connection/db-connection.ts b/packages/@n8n/db/src/connection/db-connection.ts index d5dd2d07544..d3295b6f267 100644 --- a/packages/@n8n/db/src/connection/db-connection.ts +++ b/packages/@n8n/db/src/connection/db-connection.ts @@ -89,7 +89,7 @@ export class DbConnection { } async close() { - this.monitor?.stop(); + await this.monitor?.stop(); this.monitor = undefined; if (this.dataSource.isInitialized) { diff --git a/packages/@n8n/db/src/entities/execution-entity.ts b/packages/@n8n/db/src/entities/execution-entity.ts index 41454ac3553..5b95c80a7cc 100644 --- a/packages/@n8n/db/src/entities/execution-entity.ts +++ b/packages/@n8n/db/src/entities/execution-entity.ts @@ -18,9 +18,9 @@ import type { ExecutionAnnotation } from './execution-annotation.ee'; import type { ExecutionData } from './execution-data'; import type { ExecutionMetadata } from './execution-metadata'; import { WorkflowEntity } from './workflow-entity'; -import { idStringifier } from '../utils/transformers'; +import { bigintStringToNumber, idStringifier } from '../utils/transformers'; -export type ExecutionDataStorageLocation = 'db' | 'fs'; +export type ExecutionDataStorageLocation = 'db' | 'fs' | 's3'; @Entity() @Index(['workflowId', 'id']) @@ -28,6 +28,9 @@ export type ExecutionDataStorageLocation = 'db' | 'fs'; @Index(['finished', 'id']) @Index(['workflowId', 'finished', 'id']) @Index(['workflowId', 'waitTill', 'id']) +// Partial index (Postgres only) — supports paginated list queries filtered by +// workflowId + status without full sequential scans. See migration 1784000000029. +@Index(['workflowId', 'status', 'id'], { where: '"deletedAt" IS NULL' }) export class ExecutionEntity { @Generated() @PrimaryColumn({ transformer: idStringifier }) @@ -99,6 +102,31 @@ export class ExecutionEntity { @Column({ type: 'varchar', length: 255, nullable: true }) deduplicationKey: string | null; + /** + * Size in bytes of the serialized execution data bundle (run data, workflow + * snapshot, version id) as last persisted; excludes binary data, stored + * separately. `0` means not yet calculated — a real bundle is always larger. + */ + @Column({ type: 'bigint', default: 0, transformer: bigintStringToNumber }) + jsonSizeBytes: number; + + /** + * Size in bytes of the binary data offloaded to separate storage (db/fs/S3), + * deduplicated by stored blob. Excludes inline binary from legacy in-memory + * executions, which lives in the bundle counted by {@link jsonSizeBytes}, so the + * two are additive. `0` means unknown. + */ + @Column({ type: 'bigint', default: 0, transformer: bigintStringToNumber }) + binaryDataSizeBytes: number; + + /** + * Version id of the workflow this execution ran, denormalized from the data + * bundle so it can be queried without loading the bundle. `null` when the + * workflow had no version (e.g. unsaved manual executions). + */ + @Column({ type: 'varchar', length: 36, nullable: true }) + workflowVersionId: string | null; + @OneToMany('ExecutionMetadata', 'execution') metadata: ExecutionMetadata[]; diff --git a/packages/@n8n/db/src/entities/index.ts b/packages/@n8n/db/src/entities/index.ts index cfe0b556599..8d3df22ad8e 100644 --- a/packages/@n8n/db/src/entities/index.ts +++ b/packages/@n8n/db/src/entities/index.ts @@ -42,8 +42,10 @@ import { WebhookEntity } from './webhook-entity'; import { WorkflowDependency } from './workflow-dependency-entity'; import { WorkflowEntity } from './workflow-entity'; import { WorkflowHistory } from './workflow-history'; -import { WorkflowPublicationOutbox } from './workflow-publication-outbox'; -import type { WorkflowPublicationOutboxStatus } from './workflow-publication-outbox'; +import { + WorkflowPublicationOutbox, + WorkflowPublicationOutboxStatus, +} from './workflow-publication-outbox'; import { WorkflowPublishHistory } from './workflow-publish-history'; import { WorkflowPublishedVersion } from './workflow-published-version'; import { WorkflowStatistics } from './workflow-statistics'; @@ -86,7 +88,7 @@ export { AuthProviderSyncHistory, WorkflowHistory, WorkflowPublicationOutbox, - type WorkflowPublicationOutboxStatus, + WorkflowPublicationOutboxStatus, WorkflowPublishedVersion, WorkflowPublishHistory, ExecutionData, diff --git a/packages/@n8n/db/src/entities/types-db.ts b/packages/@n8n/db/src/entities/types-db.ts index dde08ed9251..e4923d2d2d4 100644 --- a/packages/@n8n/db/src/entities/types-db.ts +++ b/packages/@n8n/db/src/entities/types-db.ts @@ -67,6 +67,9 @@ export interface IExecutionBase { */ tracingContext?: { traceparent: string; tracestate?: string } | null; deduplicationKey?: string | null; // see `ExecutionEntity.deduplicationKey` + jsonSizeBytes?: number; // see `ExecutionEntity.jsonSizeBytes` + binaryDataSizeBytes?: number; // see `ExecutionEntity.binaryDataSizeBytes` + workflowVersionId?: string | null; // see `ExecutionEntity.workflowVersionId` } // Required by PublicUser @@ -166,7 +169,13 @@ export interface WorkflowWithSharingsMetaDataAndCredentials extends Omit<Workflo /** Payload for creating an execution. */ export type CreateExecutionPayload = Omit< IExecutionDb, - 'id' | 'createdAt' | 'startedAt' | 'storedAt' + | 'id' + | 'createdAt' + | 'startedAt' + | 'storedAt' + | 'jsonSizeBytes' + | 'binaryDataSizeBytes' + | 'workflowVersionId' >; // Data in regular format with references diff --git a/packages/@n8n/db/src/entities/workflow-entity.ts b/packages/@n8n/db/src/entities/workflow-entity.ts index 9bf2e89e4fe..91334a6be94 100644 --- a/packages/@n8n/db/src/entities/workflow-entity.ts +++ b/packages/@n8n/db/src/entities/workflow-entity.ts @@ -129,9 +129,8 @@ export class WorkflowEntity extends WithTimestampsAndStringId implements IWorkfl testRuns: TestRun[]; /** - * Workflow id from the source package when this workflow was imported. - * Null for workflows created directly. Used by import to detect re-imports - * of the same source workflow on the target instance. + * Optional lineage id used by package import to match re-imports when it + * differs from this workflow's local id. */ @Index() @Column({ type: 'varchar', nullable: true }) diff --git a/packages/@n8n/db/src/entities/workflow-publication-outbox.ts b/packages/@n8n/db/src/entities/workflow-publication-outbox.ts index a0641c37aaf..427bd608bcc 100644 --- a/packages/@n8n/db/src/entities/workflow-publication-outbox.ts +++ b/packages/@n8n/db/src/entities/workflow-publication-outbox.ts @@ -2,17 +2,21 @@ import { Column, Entity, Index, PrimaryGeneratedColumn } from '@n8n/typeorm'; import { WithTimestamps } from './abstract-entity'; +export const WorkflowPublicationOutboxStatus = { + Pending: 'pending', + InProgress: 'in_progress', + Completed: 'completed', + PartialSuccess: 'partial_success', + Failed: 'failed', +} as const; + export type WorkflowPublicationOutboxStatus = - | 'pending' - | 'in_progress' - | 'completed' - | 'partial_success' - | 'failed'; + (typeof WorkflowPublicationOutboxStatus)[keyof typeof WorkflowPublicationOutboxStatus]; @Entity({ name: 'workflow_publication_outbox' }) -@Index('IDX_workflow_publication_outbox_pending_workflow', ['workflowId'], { +@Index('IDX_workflow_publication_outbox_active_workflow_status', ['workflowId', 'status'], { unique: true, - where: "status = 'pending'", + where: `status IN ('${WorkflowPublicationOutboxStatus.Pending}', '${WorkflowPublicationOutboxStatus.InProgress}')`, }) export class WorkflowPublicationOutbox extends WithTimestamps { @PrimaryGeneratedColumn() diff --git a/packages/@n8n/db/src/index.ts b/packages/@n8n/db/src/index.ts index 5a305f259de..e8f25f05b80 100644 --- a/packages/@n8n/db/src/index.ts +++ b/packages/@n8n/db/src/index.ts @@ -13,6 +13,7 @@ export { export { generateNanoId } from '@n8n/utils'; export { generateHostInstanceId } from './utils/generators'; export { isStringArray } from './utils/is-string-array'; +export { isUniqueConstraintError } from './utils/is-unique-constraint-error'; export { isValidEmail } from './utils/is-valid-email'; export { separate } from './utils/separate'; export { sql } from './utils/sql'; @@ -41,6 +42,6 @@ export { DbConnectionOptions } from './connection/db-connection-options'; export { AuthRolesService } from './services/auth.roles.service'; export { DbLock, DbLockService } from './services/db-lock.service'; -export { In, Like, Not, DataSource } from '@n8n/typeorm'; +export { In, Like, MoreThanOrEqual, Not, DataSource } from '@n8n/typeorm'; export type { FindManyOptions, FindOptionsWhere } from '@n8n/typeorm'; export type { EntityManager } from '@n8n/typeorm'; diff --git a/packages/@n8n/db/src/migrations/common/1690000000030-RemoveResetPasswordColumns.ts b/packages/@n8n/db/src/migrations/common/1690000000030-RemoveResetPasswordColumns.ts index 01843b46aea..fe08b5bb43d 100644 --- a/packages/@n8n/db/src/migrations/common/1690000000030-RemoveResetPasswordColumns.ts +++ b/packages/@n8n/db/src/migrations/common/1690000000030-RemoveResetPasswordColumns.ts @@ -2,13 +2,16 @@ import type { MigrationContext, ReversibleMigration } from '../migration-types'; export class RemoveResetPasswordColumns1690000000030 implements ReversibleMigration { async up({ schemaBuilder: { dropColumns } }: MigrationContext) { - await dropColumns('user', ['resetPasswordToken', 'resetPasswordTokenExpiration']); + await dropColumns('user', ['resetPasswordToken', 'resetPasswordTokenExpiration'], { + recreatesOnSqlite: true, + }); } async down({ schemaBuilder: { addColumns, column } }: MigrationContext) { - await addColumns('user', [ - column('resetPasswordToken').varchar(), - column('resetPasswordTokenExpiration').int, - ]); + await addColumns( + 'user', + [column('resetPasswordToken').varchar(), column('resetPasswordTokenExpiration').int], + { recreatesOnSqlite: true }, + ); } } diff --git a/packages/@n8n/db/src/migrations/common/1690000000040-AddMfaColumns.ts b/packages/@n8n/db/src/migrations/common/1690000000040-AddMfaColumns.ts index eb1e2b609b5..23f71c50972 100644 --- a/packages/@n8n/db/src/migrations/common/1690000000040-AddMfaColumns.ts +++ b/packages/@n8n/db/src/migrations/common/1690000000040-AddMfaColumns.ts @@ -2,14 +2,20 @@ import type { MigrationContext, ReversibleMigration } from '../migration-types'; export class AddMfaColumns1690000000030 implements ReversibleMigration { async up({ schemaBuilder: { addColumns, column } }: MigrationContext) { - await addColumns('user', [ - column('mfaEnabled').bool.notNull.default(false), - column('mfaSecret').text, - column('mfaRecoveryCodes').text, - ]); + await addColumns( + 'user', + [ + column('mfaEnabled').bool.notNull.default(false), + column('mfaSecret').text, + column('mfaRecoveryCodes').text, + ], + { recreatesOnSqlite: true }, + ); } async down({ schemaBuilder: { dropColumns } }: MigrationContext) { - await dropColumns('user', ['mfaEnabled', 'mfaSecret', 'mfaRecoveryCodes']); + await dropColumns('user', ['mfaEnabled', 'mfaSecret', 'mfaRecoveryCodes'], { + recreatesOnSqlite: true, + }); } } diff --git a/packages/@n8n/db/src/migrations/common/1693491613982-ExecutionSoftDelete.ts b/packages/@n8n/db/src/migrations/common/1693491613982-ExecutionSoftDelete.ts index bf6af3c20c7..0436048d3fc 100644 --- a/packages/@n8n/db/src/migrations/common/1693491613982-ExecutionSoftDelete.ts +++ b/packages/@n8n/db/src/migrations/common/1693491613982-ExecutionSoftDelete.ts @@ -6,7 +6,9 @@ import type { MigrationContext, ReversibleMigration } from '../migration-types'; */ export class ExecutionSoftDelete1693491613982 implements ReversibleMigration { async up({ schemaBuilder: { addColumns, column, createIndex } }: MigrationContext) { - await addColumns('execution_entity', [column('deletedAt').timestamp()]); + await addColumns('execution_entity', [column('deletedAt').timestamp()], { + recreatesOnSqlite: true, + }); await createIndex('execution_entity', ['deletedAt']); await createIndex('execution_entity', ['stoppedAt']); } @@ -14,6 +16,6 @@ export class ExecutionSoftDelete1693491613982 implements ReversibleMigration { async down({ schemaBuilder: { dropColumns, dropIndex } }: MigrationContext) { await dropIndex('execution_entity', ['stoppedAt']); await dropIndex('execution_entity', ['deletedAt']); - await dropColumns('execution_entity', ['deletedAt']); + await dropColumns('execution_entity', ['deletedAt'], { recreatesOnSqlite: true }); } } diff --git a/packages/@n8n/db/src/migrations/common/1693554410387-DisallowOrphanExecutions.ts b/packages/@n8n/db/src/migrations/common/1693554410387-DisallowOrphanExecutions.ts index 86bd272a10b..2e5680bbe9c 100644 --- a/packages/@n8n/db/src/migrations/common/1693554410387-DisallowOrphanExecutions.ts +++ b/packages/@n8n/db/src/migrations/common/1693554410387-DisallowOrphanExecutions.ts @@ -10,13 +10,13 @@ export class DisallowOrphanExecutions1693554410387 implements ReversibleMigratio await runQuery(`DELETE FROM ${executionEntity} WHERE ${workflowId} IS NULL;`); - await addNotNull('execution_entity', 'workflowId'); + await addNotNull('execution_entity', 'workflowId', { recreatesOnSqlite: true }); } /** * Reversal excludes restoring deleted rows. */ async down({ schemaBuilder: { dropNotNull } }: MigrationContext) { - await dropNotNull('execution_entity', 'workflowId'); + await dropNotNull('execution_entity', 'workflowId', { recreatesOnSqlite: true }); } } diff --git a/packages/@n8n/db/src/migrations/common/1695128658538-AddWorkflowMetadata.ts b/packages/@n8n/db/src/migrations/common/1695128658538-AddWorkflowMetadata.ts index c742fad8408..6263c29276f 100644 --- a/packages/@n8n/db/src/migrations/common/1695128658538-AddWorkflowMetadata.ts +++ b/packages/@n8n/db/src/migrations/common/1695128658538-AddWorkflowMetadata.ts @@ -2,10 +2,10 @@ import type { MigrationContext, ReversibleMigration } from '../migration-types'; export class AddWorkflowMetadata1695128658538 implements ReversibleMigration { async up({ schemaBuilder: { addColumns, column } }: MigrationContext) { - await addColumns('workflow_entity', [column('meta').json]); + await addColumns('workflow_entity', [column('meta').json], { recreatesOnSqlite: true }); } async down({ schemaBuilder: { dropColumns } }: MigrationContext) { - await dropColumns('workflow_entity', ['meta']); + await dropColumns('workflow_entity', ['meta'], { recreatesOnSqlite: true }); } } diff --git a/packages/@n8n/db/src/migrations/common/1695829275184-ModifyWorkflowHistoryNodesAndConnections.ts b/packages/@n8n/db/src/migrations/common/1695829275184-ModifyWorkflowHistoryNodesAndConnections.ts index d224e42785e..c4a4958622d 100644 --- a/packages/@n8n/db/src/migrations/common/1695829275184-ModifyWorkflowHistoryNodesAndConnections.ts +++ b/packages/@n8n/db/src/migrations/common/1695829275184-ModifyWorkflowHistoryNodesAndConnections.ts @@ -4,12 +4,20 @@ const tableName = 'workflow_history'; export class ModifyWorkflowHistoryNodesAndConnections1695829275184 implements ReversibleMigration { async up({ schemaBuilder: { addColumns, dropColumns, column } }: MigrationContext) { - await dropColumns(tableName, ['nodes', 'connections']); - await addColumns(tableName, [column('nodes').json.notNull, column('connections').json.notNull]); + await dropColumns(tableName, ['nodes', 'connections'], { recreatesOnSqlite: true }); + await addColumns( + tableName, + [column('nodes').json.notNull, column('connections').json.notNull], + { recreatesOnSqlite: true }, + ); } async down({ schemaBuilder: { dropColumns, addColumns, column } }: MigrationContext) { - await dropColumns(tableName, ['nodes', 'connections']); - await addColumns(tableName, [column('nodes').text.notNull, column('connections').text.notNull]); + await dropColumns(tableName, ['nodes', 'connections'], { recreatesOnSqlite: true }); + await addColumns( + tableName, + [column('nodes').text.notNull, column('connections').text.notNull], + { recreatesOnSqlite: true }, + ); } } diff --git a/packages/@n8n/db/src/migrations/common/1705429061930-DropRoleMapping.ts b/packages/@n8n/db/src/migrations/common/1705429061930-DropRoleMapping.ts index 1570e5fbe47..49e651bf93e 100644 --- a/packages/@n8n/db/src/migrations/common/1705429061930-DropRoleMapping.ts +++ b/packages/@n8n/db/src/migrations/common/1705429061930-DropRoleMapping.ts @@ -48,7 +48,7 @@ export class DropRoleMapping1705429061930 implements ReversibleMigration { tablePrefix, }: MigrationContext, ) { - await addColumns(table, [column('role').text]); + await addColumns(table, [column('role').text], { recreatesOnSqlite: true }); const roleTable = escape.tableName('role'); const tableName = escape.tableName(table); @@ -74,7 +74,7 @@ export class DropRoleMapping1705429061930 implements ReversibleMigration { ${where}`; await runQuery(swQuery); - await addNotNull(table, 'role'); + await addNotNull(table, 'role', { recreatesOnSqlite: true }); await dropForeignKey( table, @@ -82,7 +82,7 @@ export class DropRoleMapping1705429061930 implements ReversibleMigration { ['role', 'id'], `FK_${tablePrefix}${foreignKeySuffixes[table]}`, ); - await dropColumns(table, [roleColumnName]); + await dropColumns(table, [roleColumnName], { recreatesOnSqlite: true }); } private async migrateDown( @@ -95,7 +95,7 @@ export class DropRoleMapping1705429061930 implements ReversibleMigration { }: MigrationContext, ) { const roleColumnName = table === 'user' ? 'globalRoleId' : 'roleId'; - await addColumns(table, [column(roleColumnName).int]); + await addColumns(table, [column(roleColumnName).int], { recreatesOnSqlite: true }); const roleTable = escape.tableName('role'); const tableName = escape.tableName(table); @@ -118,7 +118,7 @@ export class DropRoleMapping1705429061930 implements ReversibleMigration { ${where}`; await runQuery(query); - await addNotNull(table, roleColumnName); + await addNotNull(table, roleColumnName, { recreatesOnSqlite: true }); await addForeignKey( table, roleColumnName, @@ -126,6 +126,6 @@ export class DropRoleMapping1705429061930 implements ReversibleMigration { `FK_${tablePrefix}${foreignKeySuffixes[table]}`, ); - await dropColumns(table, ['role']); + await dropColumns(table, ['role'], { recreatesOnSqlite: true }); } } diff --git a/packages/@n8n/db/src/migrations/common/1712044305787-RemoveNodesAccess.ts b/packages/@n8n/db/src/migrations/common/1712044305787-RemoveNodesAccess.ts index 1ffe4fbff2b..c2eeb5fa74c 100644 --- a/packages/@n8n/db/src/migrations/common/1712044305787-RemoveNodesAccess.ts +++ b/packages/@n8n/db/src/migrations/common/1712044305787-RemoveNodesAccess.ts @@ -2,6 +2,6 @@ import type { IrreversibleMigration, MigrationContext } from '../migration-types export class RemoveNodesAccess1712044305787 implements IrreversibleMigration { async up({ schemaBuilder: { dropColumns } }: MigrationContext) { - await dropColumns('credentials_entity', ['nodesAccess']); + await dropColumns('credentials_entity', ['nodesAccess'], { recreatesOnSqlite: true }); } } diff --git a/packages/@n8n/db/src/migrations/common/1714133768519-CreateProject.ts b/packages/@n8n/db/src/migrations/common/1714133768519-CreateProject.ts index f06bdf16fad..f4334583d3d 100644 --- a/packages/@n8n/db/src/migrations/common/1714133768519-CreateProject.ts +++ b/packages/@n8n/db/src/migrations/common/1714133768519-CreateProject.ts @@ -80,7 +80,7 @@ export class CreateProject1714133768519 implements ReversibleMigration { }: MigrationContext, ) { const projectIdColumn = column('projectId').varchar(36).default('NULL'); - await addColumns(relationTableName, [projectIdColumn]); + await addColumns(relationTableName, [projectIdColumn], { recreatesOnSqlite: true }); const relationTable = escape.tableName(relationTableName); const { t, c } = escapeNames(escape); @@ -104,7 +104,7 @@ export class CreateProject1714133768519 implements ReversibleMigration { await addForeignKey(relationTableName, 'projectId', ['project', 'id']); - await addNotNull(relationTableName, 'projectId'); + await addNotNull(relationTableName, 'projectId', { recreatesOnSqlite: true }); // Index the new projectId column await createIndex(relationTableName, ['projectId']); diff --git a/packages/@n8n/db/src/migrations/common/1714133768521-MakeExecutionStatusNonNullable.ts b/packages/@n8n/db/src/migrations/common/1714133768521-MakeExecutionStatusNonNullable.ts index 08e27e27b53..e1759baba6d 100644 --- a/packages/@n8n/db/src/migrations/common/1714133768521-MakeExecutionStatusNonNullable.ts +++ b/packages/@n8n/db/src/migrations/common/1714133768521-MakeExecutionStatusNonNullable.ts @@ -17,6 +17,8 @@ export class MakeExecutionStatusNonNullable1714133768521 implements Irreversible await runQuery(query); - await schemaBuilder.addNotNull('execution_entity', 'status'); + await schemaBuilder.addNotNull('execution_entity', 'status', { + recreatesOnSqlite: true, + }); } } diff --git a/packages/@n8n/db/src/migrations/common/1724951148974-AddApiKeysTable.ts b/packages/@n8n/db/src/migrations/common/1724951148974-AddApiKeysTable.ts index 7a135d41d87..bfe17f6e742 100644 --- a/packages/@n8n/db/src/migrations/common/1724951148974-AddApiKeysTable.ts +++ b/packages/@n8n/db/src/migrations/common/1724951148974-AddApiKeysTable.ts @@ -70,7 +70,7 @@ export class AddApiKeysTable1724951148974 implements ReversibleMigration { const idColumn = escape.columnName('id'); const createdAtColumn = escape.columnName('createdAt'); - await addColumns('user', [column('apiKey').varchar()]); + await addColumns('user', [column('apiKey').varchar()], { recreatesOnSqlite: true }); await createIndex('user', ['apiKey'], true); diff --git a/packages/@n8n/db/src/migrations/common/1727427440136-SeparateExecutionCreationFromStart.ts b/packages/@n8n/db/src/migrations/common/1727427440136-SeparateExecutionCreationFromStart.ts index 568b4b58d83..1bd40c813fd 100644 --- a/packages/@n8n/db/src/migrations/common/1727427440136-SeparateExecutionCreationFromStart.ts +++ b/packages/@n8n/db/src/migrations/common/1727427440136-SeparateExecutionCreationFromStart.ts @@ -6,11 +6,13 @@ export class SeparateExecutionCreationFromStart1727427440136 implements Reversib runQuery, escape, }: MigrationContext) { - await addColumns('execution_entity', [ - column('createdAt').notNull.timestamp().default('NOW()'), - ]); + await addColumns( + 'execution_entity', + [column('createdAt').notNull.timestamp().default('NOW()')], + { recreatesOnSqlite: true }, + ); - await dropNotNull('execution_entity', 'startedAt'); + await dropNotNull('execution_entity', 'startedAt', { recreatesOnSqlite: true }); const executionEntity = escape.tableName('execution_entity'); const createdAt = escape.columnName('createdAt'); @@ -21,7 +23,7 @@ export class SeparateExecutionCreationFromStart1727427440136 implements Reversib } async down({ schemaBuilder: { dropColumns, addNotNull } }: MigrationContext) { - await dropColumns('execution_entity', ['createdAt']); - await addNotNull('execution_entity', 'startedAt'); + await dropColumns('execution_entity', ['createdAt'], { recreatesOnSqlite: true }); + await addNotNull('execution_entity', 'startedAt', { recreatesOnSqlite: true }); } } diff --git a/packages/@n8n/db/src/migrations/common/1729607673464-UpdateProcessedDataValueColumnToText.ts b/packages/@n8n/db/src/migrations/common/1729607673464-UpdateProcessedDataValueColumnToText.ts index 79e2b8e4357..418c9c26f77 100644 --- a/packages/@n8n/db/src/migrations/common/1729607673464-UpdateProcessedDataValueColumnToText.ts +++ b/packages/@n8n/db/src/migrations/common/1729607673464-UpdateProcessedDataValueColumnToText.ts @@ -9,7 +9,7 @@ export class UpdateProcessedDataValueColumnToText1729607673464 implements Revers await runQuery(`ALTER TABLE ${prefixedTableName} DROP COLUMN value;`); await runQuery(`ALTER TABLE ${prefixedTableName} RENAME COLUMN value_temp TO value`); - await addNotNull(processedDataTableName, 'value'); + await addNotNull(processedDataTableName, 'value', { recreatesOnSqlite: true }); } async down({ schemaBuilder: { addNotNull }, runQuery, tablePrefix }: MigrationContext) { @@ -19,6 +19,6 @@ export class UpdateProcessedDataValueColumnToText1729607673464 implements Revers await runQuery(`ALTER TABLE ${prefixedTableName} DROP COLUMN value;`); await runQuery(`ALTER TABLE ${prefixedTableName} RENAME COLUMN value_temp TO value`); - await addNotNull(processedDataTableName, 'value'); + await addNotNull(processedDataTableName, 'value', { recreatesOnSqlite: true }); } } diff --git a/packages/@n8n/db/src/migrations/common/1729607673469-AddProjectIcons.ts b/packages/@n8n/db/src/migrations/common/1729607673469-AddProjectIcons.ts index 41ee3283775..a9afb3a1dbe 100644 --- a/packages/@n8n/db/src/migrations/common/1729607673469-AddProjectIcons.ts +++ b/packages/@n8n/db/src/migrations/common/1729607673469-AddProjectIcons.ts @@ -1,10 +1,10 @@ import type { MigrationContext, ReversibleMigration } from '../migration-types'; export class AddProjectIcons1729607673469 implements ReversibleMigration { async up({ schemaBuilder: { addColumns, column } }: MigrationContext) { - await addColumns('project', [column('icon').json]); + await addColumns('project', [column('icon').json], { recreatesOnSqlite: true }); } async down({ schemaBuilder: { dropColumns } }: MigrationContext) { - await dropColumns('project', ['icon']); + await dropColumns('project', ['icon'], { recreatesOnSqlite: true }); } } diff --git a/packages/@n8n/db/src/migrations/common/1731404028106-AddDescriptionToTestDefinition.ts b/packages/@n8n/db/src/migrations/common/1731404028106-AddDescriptionToTestDefinition.ts index 6165b1ba520..41b7ae447c3 100644 --- a/packages/@n8n/db/src/migrations/common/1731404028106-AddDescriptionToTestDefinition.ts +++ b/packages/@n8n/db/src/migrations/common/1731404028106-AddDescriptionToTestDefinition.ts @@ -2,10 +2,12 @@ import type { MigrationContext, ReversibleMigration } from '../migration-types'; export class AddDescriptionToTestDefinition1731404028106 implements ReversibleMigration { async up({ schemaBuilder: { addColumns, column } }: MigrationContext) { - await addColumns('test_definition', [column('description').text]); + await addColumns('test_definition', [column('description').text], { + recreatesOnSqlite: true, + }); } async down({ schemaBuilder: { dropColumns } }: MigrationContext) { - await dropColumns('test_definition', ['description']); + await dropColumns('test_definition', ['description'], { recreatesOnSqlite: true }); } } diff --git a/packages/@n8n/db/src/migrations/common/1742918400000-AddScopesColumnToApiKeys.ts b/packages/@n8n/db/src/migrations/common/1742918400000-AddScopesColumnToApiKeys.ts index 7455bbf3380..10ca38a0a57 100644 --- a/packages/@n8n/db/src/migrations/common/1742918400000-AddScopesColumnToApiKeys.ts +++ b/packages/@n8n/db/src/migrations/common/1742918400000-AddScopesColumnToApiKeys.ts @@ -14,7 +14,7 @@ export class AddScopesColumnToApiKeys1742918400000 implements ReversibleMigratio queryRunner, schemaBuilder: { addColumns, column }, }: MigrationContext) { - await addColumns('user_api_keys', [column('scopes').json]); + await addColumns('user_api_keys', [column('scopes').json], { recreatesOnSqlite: true }); const userApiKeysTable = escape.tableName('user_api_keys'); const userTable = escape.tableName('user'); @@ -36,6 +36,6 @@ export class AddScopesColumnToApiKeys1742918400000 implements ReversibleMigratio } async down({ schemaBuilder: { dropColumns } }: MigrationContext) { - await dropColumns('user_api_keys', ['scopes']); + await dropColumns('user_api_keys', ['scopes'], { recreatesOnSqlite: true }); } } diff --git a/packages/@n8n/db/src/migrations/common/1750252139168-LinkRoleToUserTable.ts b/packages/@n8n/db/src/migrations/common/1750252139168-LinkRoleToUserTable.ts index b0909a45ad2..1be772c9790 100644 --- a/packages/@n8n/db/src/migrations/common/1750252139168-LinkRoleToUserTable.ts +++ b/packages/@n8n/db/src/migrations/common/1750252139168-LinkRoleToUserTable.ts @@ -36,7 +36,9 @@ export class LinkRoleToUserTable1750252139168 implements ReversibleMigration { }); } - await addColumns('user', [column('roleSlug').varchar(128).default("'global:member'").notNull]); + await addColumns('user', [column('roleSlug').varchar(128).default("'global:member'").notNull], { + recreatesOnSqlite: true, + }); await runQuery( `UPDATE ${userTableName} SET ${roleSlugColumn} = ${roleColumn} WHERE ${roleColumn} != ${roleSlugColumn}`, @@ -54,6 +56,6 @@ export class LinkRoleToUserTable1750252139168 implements ReversibleMigration { async down({ schemaBuilder: { dropForeignKey, dropColumns } }: MigrationContext) { await dropForeignKey('user', 'roleSlug', ['role', 'slug']); - await dropColumns('user', ['roleSlug']); + await dropColumns('user', ['roleSlug'], { recreatesOnSqlite: true }); } } diff --git a/packages/@n8n/db/src/migrations/common/1750252139170-RemoveOldRoleColumn.ts b/packages/@n8n/db/src/migrations/common/1750252139170-RemoveOldRoleColumn.ts index 1e9d9a5f9dd..c69c69a2a69 100644 --- a/packages/@n8n/db/src/migrations/common/1750252139170-RemoveOldRoleColumn.ts +++ b/packages/@n8n/db/src/migrations/common/1750252139170-RemoveOldRoleColumn.ts @@ -26,7 +26,7 @@ export class RemoveOldRoleColumn1750252139170 implements ReversibleMigration { `UPDATE ${userTableName} SET ${roleSlugColumn} = ${roleColumn} WHERE ${roleColumn} != ${roleSlugColumn}`, ); - await dropColumns('user', ['role']); + await dropColumns('user', ['role'], { recreatesOnSqlite: true }); } async down({ schemaBuilder: { addColumns, column }, escape, runQuery }: MigrationContext) { @@ -34,7 +34,9 @@ export class RemoveOldRoleColumn1750252139170 implements ReversibleMigration { const roleColumn = escape.columnName('role'); const roleSlugColumn = escape.columnName('roleSlug'); - await addColumns('user', [column('role').varchar(128).default("'global:member'").notNull]); + await addColumns('user', [column('role').varchar(128).default("'global:member'").notNull], { + recreatesOnSqlite: true, + }); await runQuery( `UPDATE ${userTableName} SET ${roleColumn} = ${roleSlugColumn} WHERE ${roleSlugColumn} != ${roleColumn}`, diff --git a/packages/@n8n/db/src/migrations/common/1752669793000-AddInputsOutputsToTestCaseExecution.ts b/packages/@n8n/db/src/migrations/common/1752669793000-AddInputsOutputsToTestCaseExecution.ts index a622d490468..8cb6c6b0802 100644 --- a/packages/@n8n/db/src/migrations/common/1752669793000-AddInputsOutputsToTestCaseExecution.ts +++ b/packages/@n8n/db/src/migrations/common/1752669793000-AddInputsOutputsToTestCaseExecution.ts @@ -2,10 +2,14 @@ import type { MigrationContext, ReversibleMigration } from '../migration-types'; export class AddInputsOutputsToTestCaseExecution1752669793000 implements ReversibleMigration { async up({ schemaBuilder: { addColumns, column } }: MigrationContext) { - await addColumns('test_case_execution', [column('inputs').json, column('outputs').json]); + await addColumns('test_case_execution', [column('inputs').json, column('outputs').json], { + recreatesOnSqlite: true, + }); } async down({ schemaBuilder: { dropColumns } }: MigrationContext) { - await dropColumns('test_case_execution', ['inputs', 'outputs']); + await dropColumns('test_case_execution', ['inputs', 'outputs'], { + recreatesOnSqlite: true, + }); } } diff --git a/packages/@n8n/db/src/migrations/common/1756906557570-AddTimestampsToRoleAndRoleIndexes.ts b/packages/@n8n/db/src/migrations/common/1756906557570-AddTimestampsToRoleAndRoleIndexes.ts index 4a8e0d44d64..278ce2c6dc4 100644 --- a/packages/@n8n/db/src/migrations/common/1756906557570-AddTimestampsToRoleAndRoleIndexes.ts +++ b/packages/@n8n/db/src/migrations/common/1756906557570-AddTimestampsToRoleAndRoleIndexes.ts @@ -16,10 +16,14 @@ export class AddTimestampsToRoleAndRoleIndexes1756906557570 implements Irreversi // add the columns twice in the same statement. await queryRunner.getTable(`${tablePrefix}${USER_TABLE_NAME}`); - await schemaBuilder.addColumns(ROLE_TABLE_NAME, [ - new Column('createdAt').timestampTimezone().notNull.default('NOW()'), - new Column('updatedAt').timestampTimezone().notNull.default('NOW()'), - ]); + await schemaBuilder.addColumns( + ROLE_TABLE_NAME, + [ + new Column('createdAt').timestampTimezone().notNull.default('NOW()'), + new Column('updatedAt').timestampTimezone().notNull.default('NOW()'), + ], + { recreatesOnSqlite: true }, + ); // This index should allow us to efficiently query project relations by their role // This will be used for counting how many users have a specific project role diff --git a/packages/@n8n/db/src/migrations/common/1758731786132-AddAudienceColumnToApiKey.ts b/packages/@n8n/db/src/migrations/common/1758731786132-AddAudienceColumnToApiKey.ts index 6c52d7735b9..d4fd7c5ce00 100644 --- a/packages/@n8n/db/src/migrations/common/1758731786132-AddAudienceColumnToApiKey.ts +++ b/packages/@n8n/db/src/migrations/common/1758731786132-AddAudienceColumnToApiKey.ts @@ -2,12 +2,14 @@ import type { MigrationContext, ReversibleMigration } from '../migration-types'; export class AddAudienceColumnToApiKeys1758731786132 implements ReversibleMigration { async up({ schemaBuilder: { addColumns, column } }: MigrationContext) { - await addColumns('user_api_keys', [ - column('audience').varchar().notNull.default("'public-api'"), - ]); + await addColumns( + 'user_api_keys', + [column('audience').varchar().notNull.default("'public-api'")], + { recreatesOnSqlite: true }, + ); } async down({ schemaBuilder: { dropColumns } }: MigrationContext) { - await dropColumns('user_api_keys', ['audience']); + await dropColumns('user_api_keys', ['audience'], { recreatesOnSqlite: true }); } } diff --git a/packages/@n8n/db/src/migrations/common/1760020000000-CreateChatHubAgentTable.ts b/packages/@n8n/db/src/migrations/common/1760020000000-CreateChatHubAgentTable.ts index ee919f6a31e..a0aa75818c3 100644 --- a/packages/@n8n/db/src/migrations/common/1760020000000-CreateChatHubAgentTable.ts +++ b/packages/@n8n/db/src/migrations/common/1760020000000-CreateChatHubAgentTable.ts @@ -38,26 +38,34 @@ export class CreateChatHubAgentTable1760020000000 implements ReversibleMigration }).withTimestamps; // Add agentId and agentName to chat_hub_sessions - await addColumns(table.sessions, [ - column('agentId') - .varchar(36) - .comment('ID of the custom agent (if provider is "custom-agent")'), - column('agentName') - .varchar(128) - .comment('Cached name of the custom agent (if provider is "custom-agent")'), - ]); + await addColumns( + table.sessions, + [ + column('agentId') + .varchar(36) + .comment('ID of the custom agent (if provider is "custom-agent")'), + column('agentName') + .varchar(128) + .comment('Cached name of the custom agent (if provider is "custom-agent")'), + ], + { recreatesOnSqlite: true }, + ); // Add agentId to chat_hub_messages - await addColumns(table.messages, [ - column('agentId') - .varchar(36) - .comment('ID of the custom agent (if provider is "custom-agent")'), - ]); + await addColumns( + table.messages, + [ + column('agentId') + .varchar(36) + .comment('ID of the custom agent (if provider is "custom-agent")'), + ], + { recreatesOnSqlite: true }, + ); } async down({ schemaBuilder: { dropTable, dropColumns } }: MigrationContext) { - await dropColumns(table.messages, ['agentId']); - await dropColumns(table.sessions, ['agentId', 'agentName']); + await dropColumns(table.messages, ['agentId'], { recreatesOnSqlite: true }); + await dropColumns(table.sessions, ['agentId', 'agentName'], { recreatesOnSqlite: true }); await dropTable(table.agents); } } diff --git a/packages/@n8n/db/src/migrations/common/1760965142113-DropUnusedChatHubColumns.ts b/packages/@n8n/db/src/migrations/common/1760965142113-DropUnusedChatHubColumns.ts index 2d53ee65305..c1dbd769323 100644 --- a/packages/@n8n/db/src/migrations/common/1760965142113-DropUnusedChatHubColumns.ts +++ b/packages/@n8n/db/src/migrations/common/1760965142113-DropUnusedChatHubColumns.ts @@ -6,31 +6,41 @@ const table = { export class DropUnusedChatHubColumns1760965142113 implements ReversibleMigration { async up({ schemaBuilder: { dropColumns, addColumns, column } }: MigrationContext) { - await dropColumns(table.messages, ['turnId', 'runIndex', 'state']); - await addColumns(table.messages, [ - column('status') - .varchar(16) - .default("'success'") - .notNull.comment( - 'ChatHubMessageStatus enum, eg. "success", "error", "running", "cancelled"', - ), - ]); + await dropColumns(table.messages, ['turnId', 'runIndex', 'state'], { + recreatesOnSqlite: true, + }); + await addColumns( + table.messages, + [ + column('status') + .varchar(16) + .default("'success'") + .notNull.comment( + 'ChatHubMessageStatus enum, eg. "success", "error", "running", "cancelled"', + ), + ], + { recreatesOnSqlite: true }, + ); } async down({ schemaBuilder: { dropColumns, addColumns, column, addForeignKey }, }: MigrationContext) { - await dropColumns(table.messages, ['status']); - await addColumns(table.messages, [ - column('turnId').uuid, - column('runIndex') - .int.notNull.default(0) - .comment('The nth attempt this message has been generated/retried this turn'), - column('state') - .varchar(16) - .default("'active'") - .notNull.comment('ChatHubMessageState enum: "active", "superseded", "hidden", "deleted"'), - ]); + await dropColumns(table.messages, ['status'], { recreatesOnSqlite: true }); + await addColumns( + table.messages, + [ + column('turnId').uuid, + column('runIndex') + .int.notNull.default(0) + .comment('The nth attempt this message has been generated/retried this turn'), + column('state') + .varchar(16) + .default("'active'") + .notNull.comment('ChatHubMessageState enum: "active", "superseded", "hidden", "deleted"'), + ], + { recreatesOnSqlite: true }, + ); await addForeignKey(table.messages, 'turnId', [table.messages, 'id'], undefined, 'CASCADE'); } } diff --git a/packages/@n8n/db/src/migrations/common/1761773155024-AddAttachmentsToChatHubMessages.ts b/packages/@n8n/db/src/migrations/common/1761773155024-AddAttachmentsToChatHubMessages.ts index 732f569d31b..0e557de1a83 100644 --- a/packages/@n8n/db/src/migrations/common/1761773155024-AddAttachmentsToChatHubMessages.ts +++ b/packages/@n8n/db/src/migrations/common/1761773155024-AddAttachmentsToChatHubMessages.ts @@ -6,14 +6,18 @@ const table = { export class AddAttachmentsToChatHubMessages1761773155024 implements ReversibleMigration { async up({ schemaBuilder: { addColumns, column } }: MigrationContext) { - await addColumns(table.messages, [ - column('attachments').json.comment( - 'File attachments for the message (if any), stored as JSON. Files are stored as base64-encoded data URLs.', - ), - ]); + await addColumns( + table.messages, + [ + column('attachments').json.comment( + 'File attachments for the message (if any), stored as JSON. Files are stored as base64-encoded data URLs.', + ), + ], + { recreatesOnSqlite: true }, + ); } async down({ schemaBuilder: { dropColumns } }: MigrationContext) { - await dropColumns(table.messages, ['attachments']); + await dropColumns(table.messages, ['attachments'], { recreatesOnSqlite: true }); } } diff --git a/packages/@n8n/db/src/migrations/common/1761830340990-AddToolsColumnToChatHubTables.ts b/packages/@n8n/db/src/migrations/common/1761830340990-AddToolsColumnToChatHubTables.ts index 6019c8d9228..6543b2b9a3e 100644 --- a/packages/@n8n/db/src/migrations/common/1761830340990-AddToolsColumnToChatHubTables.ts +++ b/packages/@n8n/db/src/migrations/common/1761830340990-AddToolsColumnToChatHubTables.ts @@ -7,20 +7,28 @@ const table = { export class AddToolsColumnToChatHubTables1761830340990 implements ReversibleMigration { async up({ schemaBuilder: { addColumns, column } }: MigrationContext) { - await addColumns(table.sessions, [ - column('tools') - .json.notNull.default("'[]'") - .comment('Tools available to the agent as JSON node definitions'), - ]); - await addColumns(table.agents, [ - column('tools') - .json.notNull.default("'[]'") - .comment('Tools available to the agent as JSON node definitions'), - ]); + await addColumns( + table.sessions, + [ + column('tools') + .json.notNull.default("'[]'") + .comment('Tools available to the agent as JSON node definitions'), + ], + { recreatesOnSqlite: true }, + ); + await addColumns( + table.agents, + [ + column('tools') + .json.notNull.default("'[]'") + .comment('Tools available to the agent as JSON node definitions'), + ], + { recreatesOnSqlite: true }, + ); } async down({ schemaBuilder: { dropColumns } }: MigrationContext) { - await dropColumns(table.sessions, ['tools']); - await dropColumns(table.agents, ['tools']); + await dropColumns(table.sessions, ['tools'], { recreatesOnSqlite: true }); + await dropColumns(table.agents, ['tools'], { recreatesOnSqlite: true }); } } diff --git a/packages/@n8n/db/src/migrations/common/1762177736257-AddWorkflowDescriptionColumn.ts b/packages/@n8n/db/src/migrations/common/1762177736257-AddWorkflowDescriptionColumn.ts index b59338d2bb3..2db064e8631 100644 --- a/packages/@n8n/db/src/migrations/common/1762177736257-AddWorkflowDescriptionColumn.ts +++ b/packages/@n8n/db/src/migrations/common/1762177736257-AddWorkflowDescriptionColumn.ts @@ -2,10 +2,12 @@ import type { MigrationContext, ReversibleMigration } from '../migration-types'; export class AddWorkflowDescriptionColumn1762177736257 implements ReversibleMigration { async up({ schemaBuilder: { addColumns, column } }: MigrationContext) { - await addColumns('workflow_entity', [column('description').text]); + await addColumns('workflow_entity', [column('description').text], { + recreatesOnSqlite: true, + }); } async down({ schemaBuilder: { dropColumns } }: MigrationContext) { - await dropColumns('workflow_entity', ['description']); + await dropColumns('workflow_entity', ['description'], { recreatesOnSqlite: true }); } } diff --git a/packages/@n8n/db/src/migrations/common/1762763704614-BackfillMissingWorkflowHistoryRecords.ts b/packages/@n8n/db/src/migrations/common/1762763704614-BackfillMissingWorkflowHistoryRecords.ts index acb78dfcc45..ba5ee1885bc 100644 --- a/packages/@n8n/db/src/migrations/common/1762763704614-BackfillMissingWorkflowHistoryRecords.ts +++ b/packages/@n8n/db/src/migrations/common/1762763704614-BackfillMissingWorkflowHistoryRecords.ts @@ -94,6 +94,8 @@ export class BackfillMissingWorkflowHistoryRecords1762763704614 implements Irrev ); // Step 3: Make versionId NOT NULL - await schemaBuilder.addNotNull('workflow_entity', 'versionId'); + await schemaBuilder.addNotNull('workflow_entity', 'versionId', { + recreatesOnSqlite: true, + }); } } diff --git a/packages/@n8n/db/src/migrations/common/1762847206508-AddWorkflowHistoryAutoSaveFields.ts b/packages/@n8n/db/src/migrations/common/1762847206508-AddWorkflowHistoryAutoSaveFields.ts index cd689e74687..bb917374d3b 100644 --- a/packages/@n8n/db/src/migrations/common/1762847206508-AddWorkflowHistoryAutoSaveFields.ts +++ b/packages/@n8n/db/src/migrations/common/1762847206508-AddWorkflowHistoryAutoSaveFields.ts @@ -7,14 +7,20 @@ const description = 'description'; export class AddWorkflowHistoryAutoSaveFields1762847206508 implements ReversibleMigration { async up({ schemaBuilder: { addColumns, column } }: MigrationContext) { - await addColumns(tableName, [ - column(name).varchar(128), - column(autosaved).bool.notNull.default(false), - column(description).text, - ]); + await addColumns( + tableName, + [ + column(name).varchar(128), + column(autosaved).bool.notNull.default(false), + column(description).text, + ], + { recreatesOnSqlite: true }, + ); } async down({ schemaBuilder: { dropColumns } }: MigrationContext) { - await dropColumns(tableName, [name, autosaved, description]); + await dropColumns(tableName, [name, autosaved, description], { + recreatesOnSqlite: true, + }); } } diff --git a/packages/@n8n/db/src/migrations/common/1763047800000-AddActiveVersionIdColumn.ts b/packages/@n8n/db/src/migrations/common/1763047800000-AddActiveVersionIdColumn.ts index 89b4189ddc9..4b125d1364a 100644 --- a/packages/@n8n/db/src/migrations/common/1763047800000-AddActiveVersionIdColumn.ts +++ b/packages/@n8n/db/src/migrations/common/1763047800000-AddActiveVersionIdColumn.ts @@ -12,7 +12,9 @@ export class AddActiveVersionIdColumn1763047800000 implements ReversibleMigratio }: MigrationContext) { const workflowsTableName = escape.tableName(WORKFLOWS_TABLE_NAME); - await addColumns(WORKFLOWS_TABLE_NAME, [column('activeVersionId').varchar(36)]); + await addColumns(WORKFLOWS_TABLE_NAME, [column('activeVersionId').varchar(36)], { + recreatesOnSqlite: true, + }); await addForeignKey( WORKFLOWS_TABLE_NAME, @@ -43,7 +45,9 @@ export class AddActiveVersionIdColumn1763047800000 implements ReversibleMigratio WORKFLOW_HISTORY_TABLE_NAME, 'versionId', ]); - await dropColumns(WORKFLOWS_TABLE_NAME, ['activeVersionId']); + await dropColumns(WORKFLOWS_TABLE_NAME, ['activeVersionId'], { + recreatesOnSqlite: true, + }); } // Create workflow_history records for workflows missing them diff --git a/packages/@n8n/db/src/migrations/common/1764276827837-AddCreatorIdToProjectTable.ts b/packages/@n8n/db/src/migrations/common/1764276827837-AddCreatorIdToProjectTable.ts index 0a93a80863c..a09976b0817 100644 --- a/packages/@n8n/db/src/migrations/common/1764276827837-AddCreatorIdToProjectTable.ts +++ b/packages/@n8n/db/src/migrations/common/1764276827837-AddCreatorIdToProjectTable.ts @@ -13,9 +13,11 @@ export class AddCreatorIdToProjectTable1764276827837 implements ReversibleMigrat schemaBuilder: { addColumns, addForeignKey, column }, queryRunner, }: MigrationContext) { - await addColumns(table.project, [ - column('creatorId').uuid.comment('ID of the user who created the project'), - ]); + await addColumns( + table.project, + [column('creatorId').uuid.comment('ID of the user who created the project')], + { recreatesOnSqlite: true }, + ); await addForeignKey(table.project, 'creatorId', ['user', 'id'], FOREIGN_KEY_NAME, 'SET NULL'); @@ -37,6 +39,6 @@ export class AddCreatorIdToProjectTable1764276827837 implements ReversibleMigrat async down({ schemaBuilder: { dropColumns, dropForeignKey } }: MigrationContext) { await dropForeignKey(table.project, 'creatorId', ['user', 'id'], FOREIGN_KEY_NAME); - await dropColumns(table.project, ['creatorId']); + await dropColumns(table.project, ['creatorId'], { recreatesOnSqlite: true }); } } diff --git a/packages/@n8n/db/src/migrations/common/1765459448000-AddResolvableFieldsToCredentials.ts b/packages/@n8n/db/src/migrations/common/1765459448000-AddResolvableFieldsToCredentials.ts index 1feba94db88..668d36f4224 100644 --- a/packages/@n8n/db/src/migrations/common/1765459448000-AddResolvableFieldsToCredentials.ts +++ b/packages/@n8n/db/src/migrations/common/1765459448000-AddResolvableFieldsToCredentials.ts @@ -6,11 +6,15 @@ const FOREIGN_KEY_NAME = 'credentials_entity_resolverId_foreign'; export class AddResolvableFieldsToCredentials1765459448000 implements ReversibleMigration { async up({ schemaBuilder: { addColumns, addForeignKey, column } }: MigrationContext) { - await addColumns(credentialsTableName, [ - column('isResolvable').bool.notNull.default(false), - column('resolvableAllowFallback').bool.notNull.default(false), - column('resolverId').varchar(16), - ]); + await addColumns( + credentialsTableName, + [ + column('isResolvable').bool.notNull.default(false), + column('resolvableAllowFallback').bool.notNull.default(false), + column('resolverId').varchar(16), + ], + { recreatesOnSqlite: true }, + ); await addForeignKey( credentialsTableName, @@ -29,10 +33,10 @@ export class AddResolvableFieldsToCredentials1765459448000 implements Reversible FOREIGN_KEY_NAME, ); - await dropColumns(credentialsTableName, [ - 'isResolvable', - 'resolvableAllowFallback', - 'resolverId', - ]); + await dropColumns( + credentialsTableName, + ['isResolvable', 'resolvableAllowFallback', 'resolverId'], + { recreatesOnSqlite: true }, + ); } } diff --git a/packages/@n8n/db/src/migrations/common/1765788427674-AddIconToAgentTable.ts b/packages/@n8n/db/src/migrations/common/1765788427674-AddIconToAgentTable.ts index 5052ea85c1e..84185f51967 100644 --- a/packages/@n8n/db/src/migrations/common/1765788427674-AddIconToAgentTable.ts +++ b/packages/@n8n/db/src/migrations/common/1765788427674-AddIconToAgentTable.ts @@ -5,11 +5,11 @@ const table = 'chat_hub_agents'; export class AddIconToAgentTable1765788427674 implements ReversibleMigration { async up({ schemaBuilder: { addColumns, column } }: MigrationContext) { // Add icon column to agents table (nullable) - await addColumns(table, [column('icon').json]); + await addColumns(table, [column('icon').json], { recreatesOnSqlite: true }); } async down({ schemaBuilder: { dropColumns } }: MigrationContext) { // Drop icon column - await dropColumns(table, ['icon']); + await dropColumns(table, ['icon'], { recreatesOnSqlite: true }); } } diff --git a/packages/@n8n/db/src/migrations/common/1766068346315-AddChatMessageIndices.ts b/packages/@n8n/db/src/migrations/common/1766068346315-AddChatMessageIndices.ts index a7cfb408744..53259bbf1d2 100644 --- a/packages/@n8n/db/src/migrations/common/1766068346315-AddChatMessageIndices.ts +++ b/packages/@n8n/db/src/migrations/common/1766068346315-AddChatMessageIndices.ts @@ -18,7 +18,7 @@ export class AddChatMessageIndices1766068346315 implements ReversibleMigration { WHERE ${lastMessageAtColumn} IS NULL`, ); - await addNotNull('chat_hub_sessions', 'lastMessageAt'); + await addNotNull('chat_hub_sessions', 'lastMessageAt', { recreatesOnSqlite: true }); // Index intended for faster sessionRepository.getManyByUserId queries await runQuery( @@ -39,6 +39,6 @@ export class AddChatMessageIndices1766068346315 implements ReversibleMigration { ); await runQuery(`DROP INDEX IF EXISTS ${escape.indexName('chat_hub_messages_sessionId')}`); - await dropNotNull('chat_hub_sessions', 'lastMessageAt'); + await dropNotNull('chat_hub_sessions', 'lastMessageAt', { recreatesOnSqlite: true }); } } diff --git a/packages/@n8n/db/src/migrations/common/1769000000000-AddPublishedVersionIdToWorkflowDependency.ts b/packages/@n8n/db/src/migrations/common/1769000000000-AddPublishedVersionIdToWorkflowDependency.ts index b60a598d665..91dceb6552f 100644 --- a/packages/@n8n/db/src/migrations/common/1769000000000-AddPublishedVersionIdToWorkflowDependency.ts +++ b/packages/@n8n/db/src/migrations/common/1769000000000-AddPublishedVersionIdToWorkflowDependency.ts @@ -2,12 +2,16 @@ import type { MigrationContext, ReversibleMigration } from '../migration-types'; export class AddPublishedVersionIdToWorkflowDependency1769000000000 implements ReversibleMigration { async up({ schemaBuilder: { addColumns, column, createIndex } }: MigrationContext) { - await addColumns('workflow_dependency', [column('publishedVersionId').varchar(36)]); + await addColumns('workflow_dependency', [column('publishedVersionId').varchar(36)], { + recreatesOnSqlite: true, + }); await createIndex('workflow_dependency', ['publishedVersionId']); } async down({ schemaBuilder: { dropColumns, dropIndex } }: MigrationContext) { await dropIndex('workflow_dependency', ['publishedVersionId']); - await dropColumns('workflow_dependency', ['publishedVersionId']); + await dropColumns('workflow_dependency', ['publishedVersionId'], { + recreatesOnSqlite: true, + }); } } diff --git a/packages/@n8n/db/src/migrations/common/1770000000000-CreateChatHubToolsTable.ts b/packages/@n8n/db/src/migrations/common/1770000000000-CreateChatHubToolsTable.ts index cf7f699ff7a..233d6f53b31 100644 --- a/packages/@n8n/db/src/migrations/common/1770000000000-CreateChatHubToolsTable.ts +++ b/packages/@n8n/db/src/migrations/common/1770000000000-CreateChatHubToolsTable.ts @@ -198,8 +198,8 @@ export class CreateChatHubToolsTable1770000000000 implements ReversibleMigration ); // Drop the tools columns from chat hub sessions and agents - await dropColumns(table.sessions, ['tools']); - await dropColumns(table.agents, ['tools']); + await dropColumns(table.sessions, ['tools'], { recreatesOnSqlite: true }); + await dropColumns(table.agents, ['tools'], { recreatesOnSqlite: true }); } async down({ schemaBuilder: { addColumns, column, dropTable } }: MigrationContext) { @@ -210,7 +210,11 @@ export class CreateChatHubToolsTable1770000000000 implements ReversibleMigration // This loses data, but we can't really restore it. // Impact of losing the configured tools should be fairly minimal, as credentials remain intact // and users can easily re-add the search tools to chat hub sessions and agents after the rollback if needed. - await addColumns(table.sessions, [column('tools').json.notNull.default("'[]'")]); - await addColumns(table.agents, [column('tools').json.notNull.default("'[]'")]); + await addColumns(table.sessions, [column('tools').json.notNull.default("'[]'")], { + recreatesOnSqlite: true, + }); + await addColumns(table.agents, [column('tools').json.notNull.default("'[]'")], { + recreatesOnSqlite: true, + }); } } diff --git a/packages/@n8n/db/src/migrations/common/1771500000002-AddFilesColumnToChatHubAgents.ts b/packages/@n8n/db/src/migrations/common/1771500000002-AddFilesColumnToChatHubAgents.ts index 4d61a84d891..961ab0c714b 100644 --- a/packages/@n8n/db/src/migrations/common/1771500000002-AddFilesColumnToChatHubAgents.ts +++ b/packages/@n8n/db/src/migrations/common/1771500000002-AddFilesColumnToChatHubAgents.ts @@ -4,10 +4,12 @@ const table = 'chat_hub_agents'; export class AddFilesColumnToChatHubAgents1771500000002 implements ReversibleMigration { async up({ schemaBuilder: { addColumns, column } }: MigrationContext) { - await addColumns(table, [column('files').json.notNull.default("'[]'")]); + await addColumns(table, [column('files').json.notNull.default("'[]'")], { + recreatesOnSqlite: true, + }); } async down({ schemaBuilder: { dropColumns } }: MigrationContext) { - await dropColumns(table, ['files']); + await dropColumns(table, ['files'], { recreatesOnSqlite: true }); } } diff --git a/packages/@n8n/db/src/migrations/common/1772000000000-AddSuggestedPromptsToAgentTable.ts b/packages/@n8n/db/src/migrations/common/1772000000000-AddSuggestedPromptsToAgentTable.ts index 91472b21e48..a994a486dca 100644 --- a/packages/@n8n/db/src/migrations/common/1772000000000-AddSuggestedPromptsToAgentTable.ts +++ b/packages/@n8n/db/src/migrations/common/1772000000000-AddSuggestedPromptsToAgentTable.ts @@ -4,10 +4,12 @@ const table = 'chat_hub_agents'; export class AddSuggestedPromptsToAgentTable1772000000000 implements ReversibleMigration { async up({ schemaBuilder: { addColumns, column } }: MigrationContext) { - await addColumns(table, [column('suggestedPrompts').json.notNull.default("'[]'")]); + await addColumns(table, [column('suggestedPrompts').json.notNull.default("'[]'")], { + recreatesOnSqlite: true, + }); } async down({ schemaBuilder: { dropColumns } }: MigrationContext) { - await dropColumns(table, ['suggestedPrompts']); + await dropColumns(table, ['suggestedPrompts'], { recreatesOnSqlite: true }); } } diff --git a/packages/@n8n/db/src/migrations/common/1772619247761-AddRoleColumnToProjectSecretsProviderAccess.ts b/packages/@n8n/db/src/migrations/common/1772619247761-AddRoleColumnToProjectSecretsProviderAccess.ts index 9e4f4a970b2..d27ef6dd4c1 100644 --- a/packages/@n8n/db/src/migrations/common/1772619247761-AddRoleColumnToProjectSecretsProviderAccess.ts +++ b/packages/@n8n/db/src/migrations/common/1772619247761-AddRoleColumnToProjectSecretsProviderAccess.ts @@ -6,18 +6,22 @@ export class AddRoleColumnToProjectSecretsProviderAccess1772619247761 implements ReversibleMigration { async up({ schemaBuilder: { addColumns, column } }: MigrationContext) { - await addColumns(table, [ - column('role') - .varchar(128) - .notNull.default("'secretsProviderConnection:user'") - .withEnumCheck(['secretsProviderConnection:owner', 'secretsProviderConnection:user']), - ]); + await addColumns( + table, + [ + column('role') + .varchar(128) + .notNull.default("'secretsProviderConnection:user'") + .withEnumCheck(['secretsProviderConnection:owner', 'secretsProviderConnection:user']), + ], + { recreatesOnSqlite: true }, + ); } async down({ schemaBuilder: { dropColumns }, tablePrefix, queryRunner }: MigrationContext) { const fullTableName = `${tablePrefix}${table}`; const checkName = `CHK_${tablePrefix}${table}_role`; await queryRunner.dropCheckConstraint(fullTableName, checkName); - await dropColumns(table, ['role']); + await dropColumns(table, ['role'], { recreatesOnSqlite: true }); } } diff --git a/packages/@n8n/db/src/migrations/common/1772700000000-AddTypeToChatHubSessions.ts b/packages/@n8n/db/src/migrations/common/1772700000000-AddTypeToChatHubSessions.ts index 5fd1c4d0c43..be364838824 100644 --- a/packages/@n8n/db/src/migrations/common/1772700000000-AddTypeToChatHubSessions.ts +++ b/packages/@n8n/db/src/migrations/common/1772700000000-AddTypeToChatHubSessions.ts @@ -2,15 +2,19 @@ import type { MigrationContext, ReversibleMigration } from '../migration-types'; export class AddTypeToChatHubSessions1772700000000 implements ReversibleMigration { async up({ schemaBuilder: { addColumns, column } }: MigrationContext) { - await addColumns('chat_hub_sessions', [ - column('type') - .varchar(16) - .notNull.default("'production'") - .withEnumCheck(['production', 'manual']), - ]); + await addColumns( + 'chat_hub_sessions', + [ + column('type') + .varchar(16) + .notNull.default("'production'") + .withEnumCheck(['production', 'manual']), + ], + { recreatesOnSqlite: true }, + ); } async down({ schemaBuilder: { dropColumns } }: MigrationContext) { - await dropColumns('chat_hub_sessions', ['type']); + await dropColumns('chat_hub_sessions', ['type'], { recreatesOnSqlite: true }); } } diff --git a/packages/@n8n/db/src/migrations/common/1774280963551-AddRestoreFieldsToWorkflowBuilderSession.ts b/packages/@n8n/db/src/migrations/common/1774280963551-AddRestoreFieldsToWorkflowBuilderSession.ts index 837b34af13f..c6cbc32fb96 100644 --- a/packages/@n8n/db/src/migrations/common/1774280963551-AddRestoreFieldsToWorkflowBuilderSession.ts +++ b/packages/@n8n/db/src/migrations/common/1774280963551-AddRestoreFieldsToWorkflowBuilderSession.ts @@ -2,16 +2,21 @@ import type { MigrationContext, ReversibleMigration } from '../migration-types'; export class AddRestoreFieldsToWorkflowBuilderSession1774280963551 implements ReversibleMigration { async up({ schemaBuilder: { addColumns, column } }: MigrationContext) { - await addColumns('workflow_builder_session', [ - column('activeVersionCardId').varchar(255), - column('resumeAfterRestoreMessageId').varchar(255), - ]); + await addColumns( + 'workflow_builder_session', + [ + column('activeVersionCardId').varchar(255), + column('resumeAfterRestoreMessageId').varchar(255), + ], + { recreatesOnSqlite: true }, + ); } async down({ schemaBuilder: { dropColumns } }: MigrationContext) { - await dropColumns('workflow_builder_session', [ - 'activeVersionCardId', - 'resumeAfterRestoreMessageId', - ]); + await dropColumns( + 'workflow_builder_session', + ['activeVersionCardId', 'resumeAfterRestoreMessageId'], + { recreatesOnSqlite: true }, + ); } } diff --git a/packages/@n8n/db/src/migrations/common/1775740765000-ChangeWorkflowPublishHistoryVersionIdToSetNull.ts b/packages/@n8n/db/src/migrations/common/1775740765000-ChangeWorkflowPublishHistoryVersionIdToSetNull.ts index c7a3ace6b4f..ed13de36370 100644 --- a/packages/@n8n/db/src/migrations/common/1775740765000-ChangeWorkflowPublishHistoryVersionIdToSetNull.ts +++ b/packages/@n8n/db/src/migrations/common/1775740765000-ChangeWorkflowPublishHistoryVersionIdToSetNull.ts @@ -15,7 +15,7 @@ export class ChangeWorkflowPublishHistoryVersionIdToSetNull1775740765000 { async up({ schemaBuilder: { dropForeignKey, addForeignKey, dropNotNull } }: MigrationContext) { await dropForeignKey(tableName, columnName, reference); - await dropNotNull(tableName, columnName); + await dropNotNull(tableName, columnName, { recreatesOnSqlite: true }); await addForeignKey(tableName, columnName, reference, undefined, 'SET NULL'); } @@ -26,7 +26,7 @@ export class ChangeWorkflowPublishHistoryVersionIdToSetNull1775740765000 await dropForeignKey(tableName, columnName, reference); await mc.runQuery(`DELETE FROM ${tableName} WHERE ${columnName} IS NULL`); - await addNotNull(tableName, columnName); + await addNotNull(tableName, columnName, { recreatesOnSqlite: true }); await addForeignKey(tableName, columnName, reference, undefined, 'CASCADE'); } } diff --git a/packages/@n8n/db/src/migrations/common/1777045000000-AddTracingContextToExecution.ts b/packages/@n8n/db/src/migrations/common/1777045000000-AddTracingContextToExecution.ts index d839d152bfe..46c77600361 100644 --- a/packages/@n8n/db/src/migrations/common/1777045000000-AddTracingContextToExecution.ts +++ b/packages/@n8n/db/src/migrations/common/1777045000000-AddTracingContextToExecution.ts @@ -2,10 +2,12 @@ import type { MigrationContext, ReversibleMigration } from '../migration-types'; export class AddTracingContextToExecution1777045000000 implements ReversibleMigration { async up({ schemaBuilder: { addColumns, column } }: MigrationContext) { - await addColumns('execution_entity', [column('tracingContext').json]); + await addColumns('execution_entity', [column('tracingContext').json], { + recreatesOnSqlite: true, + }); } async down({ schemaBuilder: { dropColumns } }: MigrationContext) { - await dropColumns('execution_entity', ['tracingContext']); + await dropColumns('execution_entity', ['tracingContext'], { recreatesOnSqlite: true }); } } diff --git a/packages/@n8n/db/src/migrations/common/1777100000000-AddLangsmithIdsToInstanceAiRunSnapshots.ts b/packages/@n8n/db/src/migrations/common/1777100000000-AddLangsmithIdsToInstanceAiRunSnapshots.ts index 7de0daa48df..0a25d0235cc 100644 --- a/packages/@n8n/db/src/migrations/common/1777100000000-AddLangsmithIdsToInstanceAiRunSnapshots.ts +++ b/packages/@n8n/db/src/migrations/common/1777100000000-AddLangsmithIdsToInstanceAiRunSnapshots.ts @@ -2,17 +2,23 @@ import type { MigrationContext, ReversibleMigration } from '../migration-types'; export class AddLangsmithIdsToInstanceAiRunSnapshots1777100000000 implements ReversibleMigration { async up({ schemaBuilder: { addColumns, column } }: MigrationContext) { - await addColumns('instance_ai_run_snapshots', [ - column('langsmithRunId') - .varchar(36) - .comment('LangSmith run ID (UUID v4, e.g. "f47ac10b-58cc-4372-a567-0e02b2c3d479").'), - column('langsmithTraceId') - .varchar(36) - .comment('LangSmith trace ID (UUID v4, e.g. "f47ac10b-58cc-4372-a567-0e02b2c3d479").'), - ]); + await addColumns( + 'instance_ai_run_snapshots', + [ + column('langsmithRunId') + .varchar(36) + .comment('LangSmith run ID (UUID v4, e.g. "f47ac10b-58cc-4372-a567-0e02b2c3d479").'), + column('langsmithTraceId') + .varchar(36) + .comment('LangSmith trace ID (UUID v4, e.g. "f47ac10b-58cc-4372-a567-0e02b2c3d479").'), + ], + { recreatesOnSqlite: true }, + ); } async down({ schemaBuilder: { dropColumns } }: MigrationContext) { - await dropColumns('instance_ai_run_snapshots', ['langsmithRunId', 'langsmithTraceId']); + await dropColumns('instance_ai_run_snapshots', ['langsmithRunId', 'langsmithTraceId'], { + recreatesOnSqlite: true, + }); } } diff --git a/packages/@n8n/db/src/migrations/common/1778000000000-AddExecutionDeduplicationKey.ts b/packages/@n8n/db/src/migrations/common/1778000000000-AddExecutionDeduplicationKey.ts index 6e9ab30359c..7bb519a282d 100644 --- a/packages/@n8n/db/src/migrations/common/1778000000000-AddExecutionDeduplicationKey.ts +++ b/packages/@n8n/db/src/migrations/common/1778000000000-AddExecutionDeduplicationKey.ts @@ -13,7 +13,9 @@ import type { MigrationContext, ReversibleMigration } from '../migration-types'; */ export class AddExecutionDeduplicationKey1778000000000 implements ReversibleMigration { async up({ schemaBuilder: { addColumns, column, createIndex } }: MigrationContext) { - await addColumns('execution_entity', [column('deduplicationKey').varchar(255)]); + await addColumns('execution_entity', [column('deduplicationKey').varchar(255)], { + recreatesOnSqlite: true, + }); // NOTE: partial unique index. Two inserts with the same non-null key race and the // second fails, so duplicates can be detected. Null rows are excluded from the index // entirely — executions without a dedupe key don't occupy index space and aren't @@ -29,6 +31,6 @@ export class AddExecutionDeduplicationKey1778000000000 implements ReversibleMigr async down({ schemaBuilder: { dropIndex, dropColumns } }: MigrationContext) { await dropIndex('execution_entity', ['deduplicationKey']); - await dropColumns('execution_entity', ['deduplicationKey']); + await dropColumns('execution_entity', ['deduplicationKey'], { recreatesOnSqlite: true }); } } diff --git a/packages/@n8n/db/src/migrations/common/1778100002000-AddEvaluationConfigColumnsToTestRun.ts b/packages/@n8n/db/src/migrations/common/1778100002000-AddEvaluationConfigColumnsToTestRun.ts index aaf486e1fd7..08f1d3b26b3 100644 --- a/packages/@n8n/db/src/migrations/common/1778100002000-AddEvaluationConfigColumnsToTestRun.ts +++ b/packages/@n8n/db/src/migrations/common/1778100002000-AddEvaluationConfigColumnsToTestRun.ts @@ -11,7 +11,9 @@ export class AddEvaluationConfigColumnsToTestRun1778100002000 implements Reversi runQuery, dbType, }: MigrationContext) { - await addColumns(TEST_RUN_TABLE, [column('evaluationConfigId').varchar(36)]); + await addColumns(TEST_RUN_TABLE, [column('evaluationConfigId').varchar(36)], { + recreatesOnSqlite: true, + }); await addForeignKey( TEST_RUN_TABLE, @@ -31,7 +33,9 @@ export class AddEvaluationConfigColumnsToTestRun1778100002000 implements Reversi } async down({ schemaBuilder: { dropColumns, dropForeignKey, dropIndex } }: MigrationContext) { - await dropColumns(TEST_RUN_TABLE, ['evaluationConfigSnapshot']); + await dropColumns(TEST_RUN_TABLE, ['evaluationConfigSnapshot'], { + recreatesOnSqlite: true, + }); await dropIndex(TEST_RUN_TABLE, ['evaluationConfigId']); await dropForeignKey( TEST_RUN_TABLE, @@ -39,6 +43,6 @@ export class AddEvaluationConfigColumnsToTestRun1778100002000 implements Reversi [EVALUATION_CONFIG_TABLE, 'id'], FK_NAME, ); - await dropColumns(TEST_RUN_TABLE, ['evaluationConfigId']); + await dropColumns(TEST_RUN_TABLE, ['evaluationConfigId'], { recreatesOnSqlite: true }); } } diff --git a/packages/@n8n/db/src/migrations/common/1778496086558-CreateEvaluationCollection.ts b/packages/@n8n/db/src/migrations/common/1778496086558-CreateEvaluationCollection.ts index 191d42369dd..0400f262f25 100644 --- a/packages/@n8n/db/src/migrations/common/1778496086558-CreateEvaluationCollection.ts +++ b/packages/@n8n/db/src/migrations/common/1778496086558-CreateEvaluationCollection.ts @@ -56,7 +56,9 @@ export class CreateEvaluationCollection1778496086558 implements ReversibleMigrat await queryRunner.getTable(TEST_RUN_TABLE); } - await addColumns(TEST_RUN_TABLE, [column('collectionId').varchar(36)]); + await addColumns(TEST_RUN_TABLE, [column('collectionId').varchar(36)], { + recreatesOnSqlite: true, + }); await addForeignKey( TEST_RUN_TABLE, @@ -79,7 +81,7 @@ export class CreateEvaluationCollection1778496086558 implements ReversibleMigrat [EVALUATION_COLLECTION_TABLE, 'id'], FK_TEST_RUN_COLLECTION, ); - await dropColumns(TEST_RUN_TABLE, ['collectionId']); + await dropColumns(TEST_RUN_TABLE, ['collectionId'], { recreatesOnSqlite: true }); await dropTable(EVALUATION_COLLECTION_TABLE); } } diff --git a/packages/@n8n/db/src/migrations/common/1784000000002-DropAgentExecutionWorkingMemory.ts b/packages/@n8n/db/src/migrations/common/1784000000002-DropAgentExecutionWorkingMemory.ts index ac8aa4d575d..51286cdad65 100644 --- a/packages/@n8n/db/src/migrations/common/1784000000002-DropAgentExecutionWorkingMemory.ts +++ b/packages/@n8n/db/src/migrations/common/1784000000002-DropAgentExecutionWorkingMemory.ts @@ -2,10 +2,12 @@ import type { MigrationContext, ReversibleMigration } from '../migration-types'; export class DropAgentExecutionWorkingMemory1784000000002 implements ReversibleMigration { async up({ schemaBuilder: { dropColumns } }: MigrationContext) { - await dropColumns('agent_execution', ['workingMemory']); + await dropColumns('agent_execution', ['workingMemory'], { recreatesOnSqlite: true }); } async down({ schemaBuilder: { addColumns, column } }: MigrationContext) { - await addColumns('agent_execution', [column('workingMemory').text]); + await addColumns('agent_execution', [column('workingMemory').text], { + recreatesOnSqlite: true, + }); } } diff --git a/packages/@n8n/db/src/migrations/common/1784000000006-AddNodeGroupsColumnToWorkflowAndHistory.ts b/packages/@n8n/db/src/migrations/common/1784000000006-AddNodeGroupsColumnToWorkflowAndHistory.ts index cad077e86e7..7148ef3fe8f 100644 --- a/packages/@n8n/db/src/migrations/common/1784000000006-AddNodeGroupsColumnToWorkflowAndHistory.ts +++ b/packages/@n8n/db/src/migrations/common/1784000000006-AddNodeGroupsColumnToWorkflowAndHistory.ts @@ -2,12 +2,16 @@ import type { MigrationContext, ReversibleMigration } from '../migration-types'; export class AddNodeGroupsColumnToWorkflowAndHistory1784000000006 implements ReversibleMigration { async up({ schemaBuilder: { addColumns, column } }: MigrationContext) { - await addColumns('workflow_entity', [column('nodeGroups').json.notNull.default("'[]'")]); - await addColumns('workflow_history', [column('nodeGroups').json.notNull.default("'[]'")]); + await addColumns('workflow_entity', [column('nodeGroups').json.notNull.default("'[]'")], { + recreatesOnSqlite: true, + }); + await addColumns('workflow_history', [column('nodeGroups').json.notNull.default("'[]'")], { + recreatesOnSqlite: true, + }); } async down({ schemaBuilder: { dropColumns } }: MigrationContext) { - await dropColumns('workflow_entity', ['nodeGroups']); - await dropColumns('workflow_history', ['nodeGroups']); + await dropColumns('workflow_entity', ['nodeGroups'], { recreatesOnSqlite: true }); + await dropColumns('workflow_history', ['nodeGroups'], { recreatesOnSqlite: true }); } } diff --git a/packages/@n8n/db/src/migrations/common/1784000000007-CreateInstanceAiCheckpointTable.ts b/packages/@n8n/db/src/migrations/common/1784000000007-CreateInstanceAiCheckpointTable.ts index 2fc6b06a82f..9092f5fc6a1 100644 --- a/packages/@n8n/db/src/migrations/common/1784000000007-CreateInstanceAiCheckpointTable.ts +++ b/packages/@n8n/db/src/migrations/common/1784000000007-CreateInstanceAiCheckpointTable.ts @@ -5,10 +5,16 @@ const runSnapshotsTable = 'instance_ai_run_snapshots'; export class CreateInstanceAiCheckpointTable1784000000007 implements ReversibleMigration { async up({ schemaBuilder: { createTable, addColumns, column } }: MigrationContext) { - await addColumns(runSnapshotsTable, [ - column('traceId').varchar(64).comment('OpenTelemetry trace ID for the root Instance AI run.'), - column('spanId').varchar(64).comment('OpenTelemetry span ID for the root Instance AI run.'), - ]); + await addColumns( + runSnapshotsTable, + [ + column('traceId') + .varchar(64) + .comment('OpenTelemetry trace ID for the root Instance AI run.'), + column('spanId').varchar(64).comment('OpenTelemetry span ID for the root Instance AI run.'), + ], + { recreatesOnSqlite: true }, + ); await createTable(checkpointTable) .withColumns( @@ -34,6 +40,6 @@ export class CreateInstanceAiCheckpointTable1784000000007 implements ReversibleM async down({ schemaBuilder: { dropTable, dropColumns } }: MigrationContext) { await dropTable(checkpointTable); - await dropColumns(runSnapshotsTable, ['traceId', 'spanId']); + await dropColumns(runSnapshotsTable, ['traceId', 'spanId'], { recreatesOnSqlite: true }); } } diff --git a/packages/@n8n/db/src/migrations/common/1784000000011-CreateAgentHistoryTable.ts b/packages/@n8n/db/src/migrations/common/1784000000011-CreateAgentHistoryTable.ts index b0a8eeda0b4..51771b7d5c3 100644 --- a/packages/@n8n/db/src/migrations/common/1784000000011-CreateAgentHistoryTable.ts +++ b/packages/@n8n/db/src/migrations/common/1784000000011-CreateAgentHistoryTable.ts @@ -43,7 +43,9 @@ export class CreateAgentHistoryTable1784000000011 implements ReversibleMigration onDelete: 'SET NULL', }).withTimestamps; - await addColumns('agents', [column('activeVersionId').varchar(36)]); + await addColumns('agents', [column('activeVersionId').varchar(36)], { + recreatesOnSqlite: true, + }); await addForeignKey( 'agents', 'activeVersionId', @@ -59,7 +61,9 @@ export class CreateAgentHistoryTable1784000000011 implements ReversibleMigration await dropTable('agent_published_version'); // These columns were left from previous refactors and never actually used in the live system - await dropColumns('agents', ['credentialId', 'provider', 'model']); + await dropColumns('agents', ['credentialId', 'provider', 'model'], { + recreatesOnSqlite: true, + }); } async down(ctx: MigrationContext) { @@ -67,11 +71,15 @@ export class CreateAgentHistoryTable1784000000011 implements ReversibleMigration const { createTable, addColumns, dropForeignKey, dropColumns, dropTable, column } = schemaBuilder; - await addColumns('agents', [ - column('credentialId').varchar(255), - column('provider').varchar(128), - column('model').varchar(128), - ]); + await addColumns( + 'agents', + [ + column('credentialId').varchar(255), + column('provider').varchar(128), + column('model').varchar(128), + ], + { recreatesOnSqlite: true }, + ); await createTable('agent_published_version') .withColumns( @@ -99,7 +107,7 @@ export class CreateAgentHistoryTable1784000000011 implements ReversibleMigration await this.restoreActiveHistoryToPublishedVersion(ctx); await dropForeignKey('agents', 'activeVersionId', ['agent_history', 'versionId']); - await dropColumns('agents', ['activeVersionId']); + await dropColumns('agents', ['activeVersionId'], { recreatesOnSqlite: true }); await dropTable('agent_history'); } diff --git a/packages/@n8n/db/src/migrations/common/1784000000014-PersistInstanceAiPendingConfirmations.ts b/packages/@n8n/db/src/migrations/common/1784000000014-PersistInstanceAiPendingConfirmations.ts index 3acd9345c73..a0780240596 100644 --- a/packages/@n8n/db/src/migrations/common/1784000000014-PersistInstanceAiPendingConfirmations.ts +++ b/packages/@n8n/db/src/migrations/common/1784000000014-PersistInstanceAiPendingConfirmations.ts @@ -34,16 +34,24 @@ export class PersistInstanceAiPendingConfirmations1784000000014 implements Rever // Reshape `instance_ai_checkpoints` first, then create the table that // FKs into it. SQLite's `dropNotNull` recreates the table; doing that // while a FK already points at it would force a more fragile rebuild. - await schemaBuilder.addColumns(checkpointsTable, [ - schemaBuilder - .column('expiredAt') - .timestampTimezone() - .comment('Soft-delete timestamp: null means live; non-null marks the row as a tombstone.'), - ]); + await schemaBuilder.addColumns( + checkpointsTable, + [ + schemaBuilder + .column('expiredAt') + .timestampTimezone() + .comment( + 'Soft-delete timestamp: null means live; non-null marks the row as a tombstone.', + ), + ], + { recreatesOnSqlite: true }, + ); // Soft-delete sets `state = null` on consumed/pruned snapshots, so the // column must be nullable. Created NOT NULL in `1784000000007`. - await schemaBuilder.dropNotNull(checkpointsTable, 'state'); + await schemaBuilder.dropNotNull(checkpointsTable, 'state', { + recreatesOnSqlite: true, + }); // Enforce the soft-delete invariant at the DB level: a tombstoned row // (`expiredAt` set) must have released its `state` blob. @@ -80,8 +88,8 @@ export class PersistInstanceAiPendingConfirmations1784000000014 implements Rever const stateCol = escape.columnName('state'); await runQuery(`DELETE FROM ${table} WHERE ${stateCol} IS NULL`); - await addNotNull(checkpointsTable, 'state'); - await dropColumns(checkpointsTable, ['expiredAt']); + await addNotNull(checkpointsTable, 'state', { recreatesOnSqlite: true }); + await dropColumns(checkpointsTable, ['expiredAt'], { recreatesOnSqlite: true }); } private async createPendingConfirmationsTable({ diff --git a/packages/@n8n/db/src/migrations/common/1784000000015-AddSourceWorkflowIdToWorkflow.ts b/packages/@n8n/db/src/migrations/common/1784000000015-AddSourceWorkflowIdToWorkflow.ts index 8fdbd294eb1..71ccaca7bb7 100644 --- a/packages/@n8n/db/src/migrations/common/1784000000015-AddSourceWorkflowIdToWorkflow.ts +++ b/packages/@n8n/db/src/migrations/common/1784000000015-AddSourceWorkflowIdToWorkflow.ts @@ -2,7 +2,9 @@ import type { MigrationContext, ReversibleMigration } from '../migration-types'; export class AddSourceWorkflowIdToWorkflow1784000000015 implements ReversibleMigration { async up({ schemaBuilder: { addColumns, column, createIndex } }: MigrationContext) { - await addColumns('workflow_entity', [column('sourceWorkflowId').varchar()]); + await addColumns('workflow_entity', [column('sourceWorkflowId').varchar()], { + recreatesOnSqlite: true, + }); await createIndex( 'workflow_entity', @@ -15,6 +17,8 @@ export class AddSourceWorkflowIdToWorkflow1784000000015 implements ReversibleMig async down({ schemaBuilder: { dropColumns, dropIndex } }: MigrationContext) { await dropIndex('workflow_entity', ['sourceWorkflowId']); - await dropColumns('workflow_entity', ['sourceWorkflowId']); + await dropColumns('workflow_entity', ['sourceWorkflowId'], { + recreatesOnSqlite: true, + }); } } diff --git a/packages/@n8n/db/src/migrations/common/1784000000017-AddLastUsedAtToApiKey.ts b/packages/@n8n/db/src/migrations/common/1784000000017-AddLastUsedAtToApiKey.ts index f58da86718b..a919cd1e087 100644 --- a/packages/@n8n/db/src/migrations/common/1784000000017-AddLastUsedAtToApiKey.ts +++ b/packages/@n8n/db/src/migrations/common/1784000000017-AddLastUsedAtToApiKey.ts @@ -2,10 +2,12 @@ import type { MigrationContext, ReversibleMigration } from '../migration-types'; export class AddLastUsedAtToApiKey1784000000017 implements ReversibleMigration { async up({ schemaBuilder: { addColumns, column } }: MigrationContext) { - await addColumns('user_api_keys', [column('lastUsedAt').timestampTimezone()]); + await addColumns('user_api_keys', [column('lastUsedAt').timestampTimezone()], { + recreatesOnSqlite: true, + }); } async down({ schemaBuilder: { dropColumns } }: MigrationContext) { - await dropColumns('user_api_keys', ['lastUsedAt']); + await dropColumns('user_api_keys', ['lastUsedAt'], { recreatesOnSqlite: true }); } } diff --git a/packages/@n8n/db/src/migrations/common/1784000000018-CreateAgentFilesTable.ts b/packages/@n8n/db/src/migrations/common/1784000000018-CreateAgentFilesTable.ts index 250b6c3a3ac..f47a783ce9b 100644 --- a/packages/@n8n/db/src/migrations/common/1784000000018-CreateAgentFilesTable.ts +++ b/packages/@n8n/db/src/migrations/common/1784000000018-CreateAgentFilesTable.ts @@ -46,7 +46,9 @@ export class CreateAgentFilesTable1784000000018 implements ReversibleMigration { { schemaBuilder: { addEnumCheck, dropEnumCheck } }: MigrationContext, sourceTypes: string[], ) { - await dropEnumCheck(binaryDataTableName, sourceTypeColumn); - await addEnumCheck(binaryDataTableName, sourceTypeColumn, sourceTypes); + await dropEnumCheck(binaryDataTableName, sourceTypeColumn, { recreatesOnSqlite: true }); + await addEnumCheck(binaryDataTableName, sourceTypeColumn, sourceTypes, { + recreatesOnSqlite: true, + }); } } diff --git a/packages/@n8n/db/src/migrations/common/1784000000019-AddCustomTelemetryTagsToProject.ts b/packages/@n8n/db/src/migrations/common/1784000000019-AddCustomTelemetryTagsToProject.ts index 048d1a87d48..7472f3319ca 100644 --- a/packages/@n8n/db/src/migrations/common/1784000000019-AddCustomTelemetryTagsToProject.ts +++ b/packages/@n8n/db/src/migrations/common/1784000000019-AddCustomTelemetryTagsToProject.ts @@ -2,12 +2,14 @@ import type { MigrationContext, ReversibleMigration } from '../migration-types'; export class AddCustomTelemetryTagsToProject1784000000019 implements ReversibleMigration { async up({ schemaBuilder: { addColumns, column, createIndex } }: MigrationContext) { - await addColumns('project', [column('customTelemetryTags').json.notNull.default("'[]'")]); + await addColumns('project', [column('customTelemetryTags').json.notNull.default("'[]'")], { + recreatesOnSqlite: true, + }); await createIndex('shared_workflow', ['projectId']); } async down({ schemaBuilder: { dropColumns, dropIndex } }: MigrationContext) { await dropIndex('shared_workflow', ['projectId']); - await dropColumns('project', ['customTelemetryTags']); + await dropColumns('project', ['customTelemetryTags'], { recreatesOnSqlite: true }); } } diff --git a/packages/@n8n/db/src/migrations/common/1784000000021-CreateAgentTaskDefinitionTable.ts b/packages/@n8n/db/src/migrations/common/1784000000021-CreateAgentTaskDefinitionTable.ts index a03300eb1b1..2c7d985bfda 100644 --- a/packages/@n8n/db/src/migrations/common/1784000000021-CreateAgentTaskDefinitionTable.ts +++ b/packages/@n8n/db/src/migrations/common/1784000000021-CreateAgentTaskDefinitionTable.ts @@ -82,16 +82,20 @@ export class CreateAgentTaskDefinitionTable1784000000021 implements ReversibleMi onDelete: 'CASCADE', }).withTimestamps; - await addColumns('agent_execution_threads', [ - column('taskId') - .varchar(32) - .comment( - 'Published task ID that triggered this session; not an FK because published runs can outlive draft task definition rows', - ), - column('taskVersionId') - .varchar(36) - .comment('Published agent_history version that supplied the task snapshot'), - ]); + await addColumns( + 'agent_execution_threads', + [ + column('taskId') + .varchar(32) + .comment( + 'Published task ID that triggered this session; not an FK because published runs can outlive draft task definition rows', + ), + column('taskVersionId') + .varchar(36) + .comment('Published agent_history version that supplied the task snapshot'), + ], + { recreatesOnSqlite: true }, + ); await addForeignKey( 'agent_execution_threads', 'taskVersionId', @@ -110,7 +114,9 @@ export class CreateAgentTaskDefinitionTable1784000000021 implements ReversibleMi 'agent_history', 'versionId', ]); - await dropColumns('agent_execution_threads', ['taskId', 'taskVersionId']); + await dropColumns('agent_execution_threads', ['taskId', 'taskVersionId'], { + recreatesOnSqlite: true, + }); await dropTable('agent_task_run_lock'); await dropTable('agent_task_snapshot'); await dropTable('agent_task_definition'); diff --git a/packages/@n8n/db/src/migrations/common/1784000000022-AddSubAgentLinkageToAgentExecutionThreads.ts b/packages/@n8n/db/src/migrations/common/1784000000022-AddSubAgentLinkageToAgentExecutionThreads.ts index 5daa7194ccf..385c90906b9 100644 --- a/packages/@n8n/db/src/migrations/common/1784000000022-AddSubAgentLinkageToAgentExecutionThreads.ts +++ b/packages/@n8n/db/src/migrations/common/1784000000022-AddSubAgentLinkageToAgentExecutionThreads.ts @@ -45,14 +45,18 @@ export class AddSubAgentLinkageToAgentExecutionThreads1784000000022 escape, tablePrefix, }: MigrationContext) { - await addColumns('agent_execution_threads', [ - column('parentThreadId') - .varchar(128) - .comment('Parent session thread id that delegated this subagent run.'), - column('parentAgentId') - .varchar(36) - .comment('Saved agent id of the parent that delegated this subagent run.'), - ]); + await addColumns( + 'agent_execution_threads', + [ + column('parentThreadId') + .varchar(128) + .comment('Parent session thread id that delegated this subagent run.'), + column('parentAgentId') + .varchar(36) + .comment('Saved agent id of the parent that delegated this subagent run.'), + ], + { recreatesOnSqlite: true }, + ); if (isPostgres) { for (const { table, column: columnName } of COLUMNS_TO_WIDEN) { diff --git a/packages/@n8n/db/src/migrations/common/1784000000024-AddResourceToOAuthAuthorizationCodes.ts b/packages/@n8n/db/src/migrations/common/1784000000024-AddResourceToOAuthAuthorizationCodes.ts index 02798315f62..1e84fa49236 100644 --- a/packages/@n8n/db/src/migrations/common/1784000000024-AddResourceToOAuthAuthorizationCodes.ts +++ b/packages/@n8n/db/src/migrations/common/1784000000024-AddResourceToOAuthAuthorizationCodes.ts @@ -7,17 +7,21 @@ const COLUMN_NAME = 'resource'; // instance's canonical MCP resource URL when consuming the code. export class AddResourceToOAuthAuthorizationCodes1784000000024 implements ReversibleMigration { async up({ schemaBuilder: { addColumns, column } }: MigrationContext) { - await addColumns(TABLE_NAME, [ - column(COLUMN_NAME) - .varchar() - .comment( - 'RFC 8707 resource indicator URI (e.g. https://n8n.example.com/mcp-server/http). ' + - 'NULL = legacy flow predating resource indicator support; defaults to the instance canonical MCP resource URL.', - ), - ]); + await addColumns( + TABLE_NAME, + [ + column(COLUMN_NAME) + .varchar() + .comment( + 'RFC 8707 resource indicator URI (e.g. https://n8n.example.com/mcp-server/http). ' + + 'NULL = legacy flow predating resource indicator support; defaults to the instance canonical MCP resource URL.', + ), + ], + { recreatesOnSqlite: true }, + ); } async down({ schemaBuilder: { dropColumns } }: MigrationContext) { - await dropColumns(TABLE_NAME, [COLUMN_NAME]); + await dropColumns(TABLE_NAME, [COLUMN_NAME], { recreatesOnSqlite: true }); } } diff --git a/packages/@n8n/db/src/migrations/common/1784000000026-AddScopeColumnToOAuthTables.ts b/packages/@n8n/db/src/migrations/common/1784000000026-AddScopeColumnToOAuthTables.ts new file mode 100644 index 00000000000..0c6bb1b930c --- /dev/null +++ b/packages/@n8n/db/src/migrations/common/1784000000026-AddScopeColumnToOAuthTables.ts @@ -0,0 +1,35 @@ +import type { MigrationContext, ReversibleMigration } from '../migration-types'; + +// Default scopes applied to OAuth grants that predate the scope column, and to +// any grant created before a scope is written explicitly. Inlined because +// migrations are snapshots and must not import runtime code. +const LEGACY_SCOPES = ['tool:listWorkflows', 'tool:getWorkflowDetails']; +const DEFAULT_SCOPE = `'${JSON.stringify(LEGACY_SCOPES)}'`; + +export class AddScopeColumnToOAuthTables1784000000026 implements ReversibleMigration { + async up({ schemaBuilder: { addColumns, column } }: MigrationContext) { + await addColumns( + 'oauth_authorization_codes', + [ + column('scope') + .json.notNull.default(DEFAULT_SCOPE) + .comment('OAuth scopes granted for this authorization code'), + ], + { recreatesOnSqlite: true }, + ); + await addColumns( + 'oauth_refresh_tokens', + [ + column('scope') + .json.notNull.default(DEFAULT_SCOPE) + .comment('OAuth scopes granted for this refresh token'), + ], + { recreatesOnSqlite: true }, + ); + } + + async down({ schemaBuilder: { dropColumns } }: MigrationContext) { + await dropColumns('oauth_refresh_tokens', ['scope'], { recreatesOnSqlite: true }); + await dropColumns('oauth_authorization_codes', ['scope'], { recreatesOnSqlite: true }); + } +} diff --git a/packages/@n8n/db/src/migrations/common/1784000000020-CreateWorkflowPublicationOutboxTable.ts b/packages/@n8n/db/src/migrations/common/1784000000027-CreateWorkflowPublicationOutboxTable.ts similarity index 74% rename from packages/@n8n/db/src/migrations/common/1784000000020-CreateWorkflowPublicationOutboxTable.ts rename to packages/@n8n/db/src/migrations/common/1784000000027-CreateWorkflowPublicationOutboxTable.ts index e9b1a15e470..b8d05af2c07 100644 --- a/packages/@n8n/db/src/migrations/common/1784000000020-CreateWorkflowPublicationOutboxTable.ts +++ b/packages/@n8n/db/src/migrations/common/1784000000027-CreateWorkflowPublicationOutboxTable.ts @@ -5,7 +5,7 @@ import type { MigrationContext, ReversibleMigration } from '../migration-types'; * pattern. Each row represents a pending (or in-progress / completed) * publication request that the outbox consumer will process asynchronously. */ -export class CreateWorkflowPublicationOutboxTable1784000000020 implements ReversibleMigration { +export class CreateWorkflowPublicationOutboxTable1784000000027 implements ReversibleMigration { async up({ schemaBuilder: { createTable, createIndex, column } }: MigrationContext) { await createTable('workflow_publication_outbox').withColumns( column('id').int.primary.autoGenerate2, @@ -35,14 +35,17 @@ export class CreateWorkflowPublicationOutboxTable1784000000020 implements Revers ), ).withTimestamps; - // At most one pending record per workflow: enqueueing a newer version - // while one is still pending supersedes the older publishedVersionId. + // Uniqueness on (workflowId, status) for active statuses gives us two + // invariants in one index: at most one pending record per workflow (a + // newer version supersedes the older) and at most one in-progress record + // per workflow (never published concurrently). A pending and an in-progress + // record can still coexist, since their (workflowId, status) tuples differ. await createIndex( 'workflow_publication_outbox', - ['workflowId'], + ['workflowId', 'status'], true, - 'IDX_workflow_publication_outbox_pending_workflow', - "status = 'pending'", + 'IDX_workflow_publication_outbox_active_workflow_status', + "status IN ('pending', 'in_progress')", ); } diff --git a/packages/@n8n/db/src/migrations/common/1784000000029-AddJsonSizeBytesAndWorkflowVersionIdToExecutionEntity.ts b/packages/@n8n/db/src/migrations/common/1784000000029-AddJsonSizeBytesAndWorkflowVersionIdToExecutionEntity.ts new file mode 100644 index 00000000000..3fa01427c1a --- /dev/null +++ b/packages/@n8n/db/src/migrations/common/1784000000029-AddJsonSizeBytesAndWorkflowVersionIdToExecutionEntity.ts @@ -0,0 +1,39 @@ +import type { MigrationContext, ReversibleMigration } from '../migration-types'; + +export class AddJsonSizeBytesAndWorkflowVersionIdToExecutionEntity1784000000029 + implements ReversibleMigration +{ + async up({ escape, runQuery, isPostgres }: MigrationContext) { + const tableName = escape.tableName('execution_entity'); + const jsonSizeBytes = escape.columnName('jsonSizeBytes'); + const workflowVersionId = escape.columnName('workflowVersionId'); + + // Not using addColumn DSL to avoid recreating this large table in SQLite. + // See: https://github.com/n8n-io/n8n/blob/05c554dad53397f735003917f29eac5a5d62bdb4/.claude/plugins/n8n/skills/db-migrations/SKILL.md#sqlite-table-recreation-risk + await runQuery( + `ALTER TABLE ${tableName} ADD COLUMN ${jsonSizeBytes} BIGINT NOT NULL DEFAULT 0`, + ); + await runQuery( + `ALTER TABLE ${tableName} ADD COLUMN ${workflowVersionId} VARCHAR(36) DEFAULT NULL`, + ); + + // SQLite has no column comments, so annotate only on Postgres. + if (isPostgres) { + await runQuery( + `COMMENT ON COLUMN ${tableName}.${jsonSizeBytes} IS 'Byte size of the JSON execution data bundle (run data, workflow snapshot, version id); excludes binary data. 0 means unknown.'`, + ); + await runQuery( + `COMMENT ON COLUMN ${tableName}.${workflowVersionId} IS 'Version id of the workflow run by this execution; denormalized from the data bundle.'`, + ); + } + } + + async down({ escape, runQuery }: MigrationContext) { + const tableName = escape.tableName('execution_entity'); + const jsonSizeBytes = escape.columnName('jsonSizeBytes'); + const workflowVersionId = escape.columnName('workflowVersionId'); + + await runQuery(`ALTER TABLE ${tableName} DROP COLUMN ${workflowVersionId}`); + await runQuery(`ALTER TABLE ${tableName} DROP COLUMN ${jsonSizeBytes}`); + } +} diff --git a/packages/@n8n/db/src/migrations/common/1784000000030-CreateAgentChatSubscriptions.ts b/packages/@n8n/db/src/migrations/common/1784000000030-CreateAgentChatSubscriptions.ts new file mode 100644 index 00000000000..bf1fb2b3e8a --- /dev/null +++ b/packages/@n8n/db/src/migrations/common/1784000000030-CreateAgentChatSubscriptions.ts @@ -0,0 +1,31 @@ +import type { MigrationContext, ReversibleMigration } from '../migration-types'; + +const AGENT_CHAT_INTEGRATION_TYPES = ['telegram', 'slack', 'linear']; + +export class CreateAgentChatSubscriptions1784000000030 implements ReversibleMigration { + async up({ schemaBuilder: { createTable, column } }: MigrationContext) { + await createTable('agent_chat_subscriptions') + .withColumns( + column('agentId').varchar(36).primary.comment('Agent that owns this subscription'), + column('integrationType') + .varchar(64) + .primary.withEnumCheck(AGENT_CHAT_INTEGRATION_TYPES) + .comment('Chat integration platform for this subscription'), + column('credentialId') + .varchar(255) + .primary.comment('Credential connection that owns this subscription'), + column('threadId') + .varchar(255) + .primary.comment('Platform thread ID the agent is subscribed to'), + ) + .withForeignKey('agentId', { + tableName: 'agents', + columnName: 'id', + onDelete: 'CASCADE', + }).withTimestamps; + } + + async down({ schemaBuilder: { dropTable } }: MigrationContext) { + await dropTable('agent_chat_subscriptions'); + } +} diff --git a/packages/@n8n/db/src/migrations/common/1784000000033-AddBinaryDataSizeBytesToExecutionEntity.ts b/packages/@n8n/db/src/migrations/common/1784000000033-AddBinaryDataSizeBytesToExecutionEntity.ts new file mode 100644 index 00000000000..7433b5c52e6 --- /dev/null +++ b/packages/@n8n/db/src/migrations/common/1784000000033-AddBinaryDataSizeBytesToExecutionEntity.ts @@ -0,0 +1,28 @@ +import type { MigrationContext, ReversibleMigration } from '../migration-types'; + +export class AddBinaryDataSizeBytesToExecutionEntity1784000000033 implements ReversibleMigration { + async up({ escape, runQuery, isPostgres }: MigrationContext) { + const tableName = escape.tableName('execution_entity'); + const binaryDataSizeBytes = escape.columnName('binaryDataSizeBytes'); + + // Not using addColumn DSL to avoid recreating this large table in SQLite. + // See: https://github.com/n8n-io/n8n/blob/05c554dad53397f735003917f29eac5a5d62bdb4/.claude/plugins/n8n/skills/db-migrations/SKILL.md#sqlite-table-recreation-risk + await runQuery( + `ALTER TABLE ${tableName} ADD COLUMN ${binaryDataSizeBytes} BIGINT NOT NULL DEFAULT 0`, + ); + + // SQLite has no column comments, so annotate only on Postgres. + if (isPostgres) { + await runQuery( + `COMMENT ON COLUMN ${tableName}.${binaryDataSizeBytes} IS 'Byte size of binary data offloaded to separate storage (db/fs/S3), deduplicated by blob; excludes inline binary counted in jsonSizeBytes. 0 means unknown.'`, + ); + } + } + + async down({ escape, runQuery }: MigrationContext) { + const tableName = escape.tableName('execution_entity'); + const binaryDataSizeBytes = escape.columnName('binaryDataSizeBytes'); + + await runQuery(`ALTER TABLE ${tableName} DROP COLUMN ${binaryDataSizeBytes}`); + } +} diff --git a/packages/@n8n/db/src/migrations/common/AddProjectIdToInstanceAiThreadBase.ts b/packages/@n8n/db/src/migrations/common/AddProjectIdToInstanceAiThreadBase.ts new file mode 100644 index 00000000000..94d48c670be --- /dev/null +++ b/packages/@n8n/db/src/migrations/common/AddProjectIdToInstanceAiThreadBase.ts @@ -0,0 +1,140 @@ +import type { MigrationContext } from '../migration-types'; + +export const FK_NAME = 'FK_instance_ai_threads_projectId'; +export const THREADS_TABLE = 'instance_ai_threads'; +export const PROJECT_ID_COLUMN = 'projectId'; +export const PROJECT_ID_COMMENT = 'Project this thread is scoped to'; +const SUB_AGENT_PREFIX = 'instance-ai-subagent'; + +/** + * Shared backfill for the per-database `AddProjectIdToInstanceAiThread1784000000028` + * migrations. The backfill SQL is identical on Postgres and SQLite, so it lives + * here and each engine migration (postgresdb/ and sqlite/) extends this base and + * implements only its own `up()` / `down()`. + * + * Existing threads are scoped so none is left unset: user threads take their + * owner's personal project, sub-agent threads inherit their parent thread's + * project, and any remaining thread (deleted user/parent) falls back to the + * instance owner's personal project. A final safety net deletes any thread still + * unscoped — only reachable when no instance owner exists (e.g. a corrupted or + * half-set-up database) — so the NOT NULL column can always be populated. + * + * This is not a migration itself: it has no timestamp and is not registered in + * any index; it is only extended by the two engine migrations. + */ +export abstract class AddProjectIdToInstanceAiThreadBase { + /** + * A user thread's `resourceId` is its owner's user id, so bind each to that + * user's personal project. `project:personalOwner` is the relation role used + * only for personal projects. `project_relation.userId` is a uuid on Postgres + * while `resourceId` is varchar (no implicit cast), so cast the uuid to text — + * not `resourceId` to uuid, since sub-agent resourceIds are not valid uuids + * (the cast is a no-op on SQLite). + */ + protected async backfillUserThreads({ runQuery, escape }: MigrationContext) { + const threads = escape.tableName(THREADS_TABLE); + const relation = escape.tableName('project_relation'); + const projectId = escape.columnName(PROJECT_ID_COLUMN); + const resourceId = escape.columnName('resourceId'); + const userId = escape.columnName('userId'); + const role = escape.columnName('role'); + + await runQuery( + `UPDATE ${threads} + SET ${projectId} = ( + SELECT pr.${projectId} + FROM ${relation} pr + WHERE CAST(pr.${userId} AS TEXT) = ${threads}.${resourceId} + AND pr.${role} = 'project:personalOwner' + LIMIT 1 + ) + WHERE ${projectId} IS NULL + AND ${resourceId} IN ( + SELECT CAST(${userId} AS TEXT) FROM ${relation} WHERE ${role} = 'project:personalOwner' + )`, + ); + } + + /** + * Sub-agent threads (`instance-ai-subagent:<parentThreadId>:<kind>`) inherit the + * parent thread's project. The parent id is embedded in the resourceId, so match + * it by concatenation (works on both Postgres and SQLite) rather than parsing. + * Runs after the user backfill so parent projects are already populated. + */ + protected async backfillSubAgentThreads({ runQuery, escape }: MigrationContext) { + const threads = escape.tableName(THREADS_TABLE); + const projectId = escape.columnName(PROJECT_ID_COLUMN); + const resourceId = escape.columnName('resourceId'); + const id = escape.columnName('id'); + + await runQuery( + `UPDATE ${threads} + SET ${projectId} = ( + SELECT parent.${projectId} + FROM ${threads} parent + WHERE ${threads}.${resourceId} LIKE ('${SUB_AGENT_PREFIX}:' || parent.${id} || ':%') + AND parent.${projectId} IS NOT NULL + LIMIT 1 + ) + WHERE ${projectId} IS NULL + AND ${resourceId} LIKE '${SUB_AGENT_PREFIX}:%'`, + ); + } + + /** + * Safety net for threads whose user or parent no longer exists: bind them to the + * instance owner's personal project so no row is left null before the column + * becomes NOT NULL. We never delete rows that can be scoped. + */ + protected async backfillRemainingToInstanceOwner({ runQuery, escape }: MigrationContext) { + const threads = escape.tableName(THREADS_TABLE); + const relation = escape.tableName('project_relation'); + const user = escape.tableName('user'); + const projectId = escape.columnName(PROJECT_ID_COLUMN); + const userId = escape.columnName('userId'); + const role = escape.columnName('role'); + const id = escape.columnName('id'); + const roleSlug = escape.columnName('roleSlug'); + + await runQuery( + `UPDATE ${threads} + SET ${projectId} = ( + SELECT pr.${projectId} + FROM ${relation} pr + INNER JOIN ${user} u ON u.${id} = pr.${userId} + WHERE u.${roleSlug} = 'global:owner' + AND pr.${role} = 'project:personalOwner' + LIMIT 1 + ) + WHERE ${projectId} IS NULL`, + ); + } + + /** + * Final safety net: drop any thread still unscoped after every backfill so the + * NOT NULL column can always be populated. This only matches rows when no + * instance owner exists (e.g. a half-set-up or hand-edited database); in normal + * operation the instance-owner backfill catches everything and this is a no-op. + * The alternative — a failed migration — would brick startup, and these rows are + * unmappable orphans whose owning user and parent thread are already gone. + */ + protected async deleteUnmappableThreads({ + runQuery, + escape, + logger, + migrationName, + }: MigrationContext) { + const threads = escape.tableName(THREADS_TABLE); + const projectId = escape.columnName(PROJECT_ID_COLUMN); + + const [{ unmappable }] = await runQuery<Array<{ unmappable: number }>>( + `SELECT COUNT(*) AS unmappable FROM ${threads} WHERE ${projectId} IS NULL`, + ); + if (Number(unmappable) === 0) return; + + logger.warn( + `[${migrationName}] Deleting ${unmappable} Instance AI thread(s) that could not be scoped to any project (no owning user, parent thread, or instance owner); their NOT NULL projectId cannot be satisfied.`, + ); + await runQuery(`DELETE FROM ${threads} WHERE ${projectId} IS NULL`); + } +} diff --git a/packages/@n8n/db/src/migrations/dsl/index.ts b/packages/@n8n/db/src/migrations/dsl/index.ts index 1e349172143..307e9e41607 100644 --- a/packages/@n8n/db/src/migrations/dsl/index.ts +++ b/packages/@n8n/db/src/migrations/dsl/index.ts @@ -15,6 +15,14 @@ import { DropTable, } from './table'; +/** + * Marks an operation that recreates the entire table on SQLite. + * Adding this option is an explicit acknowledgment of that risk. + * + * @see {@link BaseMigration.withFKsDisabled} + */ +type RecreatesOnSqliteAck = { recreatesOnSqlite: true }; + export const createSchemaBuilder = (tablePrefix: string, queryRunner: QueryRunner) => ({ column: (name: string) => new Column(name), /* eslint-disable @typescript-eslint/promise-function-async */ @@ -23,9 +31,41 @@ export const createSchemaBuilder = (tablePrefix: string, queryRunner: QueryRunne dropTable: (tableName: string) => new DropTable(tableName, tablePrefix, queryRunner), - addColumns: (tableName: string, columns: Column[]) => + /** + * Adds columns to an existing table. + * + * **WARNING — SQLite table recreation:** On SQLite, TypeORM implements this by + * recreating the entire table (create temp → copy data → drop original → rename). + * If other tables have incoming FK constraints with CASCADE on the target table, + * the DROP triggers cascading deletes and **wipes data from those tables**. + * + * **Mitigation:** On SQLite migrations, set `withFKsDisabled = true as const` + * when the target table has incoming FKs. For common migrations, add a + * SQLite-only subclass with the flag instead of setting it on the common class. + * + * **Safer alternative:** When all new columns are nullable or have defaults, + * raw `ALTER TABLE ADD COLUMN` avoids table recreation entirely. + * + * @see {@link BaseMigration.withFKsDisabled} + */ + addColumns: (tableName: string, columns: Column[], _opts: RecreatesOnSqliteAck) => new AddColumns(tableName, columns, tablePrefix, queryRunner), - dropColumns: (tableName: string, columnNames: string[]) => + + /** + * Drops columns from an existing table. + * + * **WARNING — SQLite table recreation:** On SQLite, TypeORM implements this by + * recreating the entire table. If other tables have incoming FK constraints with + * CASCADE on the target table, the DROP triggers cascading deletes and **wipes + * data from those tables**. + * + * **Mitigation:** On SQLite migrations, set `withFKsDisabled = true as const` + * when the target table has incoming FKs. For common migrations, add a + * SQLite-only subclass with the flag instead of setting it on the common class. + * + * @see {@link BaseMigration.withFKsDisabled} + */ + dropColumns: (tableName: string, columnNames: string[], _opts: RecreatesOnSqliteAck) => new DropColumns(tableName, columnNames, tablePrefix, queryRunner), /** @@ -91,16 +131,76 @@ export const createSchemaBuilder = (tablePrefix: string, queryRunner: QueryRunne customConstraintName, ), - addNotNull: (tableName: string, columnName: string) => + /** + * Adds a NOT NULL constraint to an existing column. + * + * **WARNING — SQLite table recreation:** On SQLite, TypeORM implements + * `changeColumn` by recreating the entire table. If other tables have incoming + * FK constraints with CASCADE on the target table, the DROP triggers cascading + * deletes and **wipes data from those tables**. + * + * **Mitigation:** On SQLite migrations, set `withFKsDisabled = true as const` + * when the target table has incoming FKs. For common migrations, add a + * SQLite-only subclass with the flag instead of setting it on the common class. + * + * @see {@link BaseMigration.withFKsDisabled} + */ + addNotNull: (tableName: string, columnName: string, _opts: RecreatesOnSqliteAck) => new AddNotNull(tableName, columnName, tablePrefix, queryRunner), - dropNotNull: (tableName: string, columnName: string) => + + /** + * Drops the NOT NULL constraint from an existing column. + * + * **WARNING — SQLite table recreation:** On SQLite, TypeORM implements + * `changeColumn` by recreating the entire table. If other tables have incoming + * FK constraints with CASCADE on the target table, the DROP triggers cascading + * deletes and **wipes data from those tables**. + * + * **Mitigation:** On SQLite migrations, set `withFKsDisabled = true as const` + * when the target table has incoming FKs. For common migrations, add a + * SQLite-only subclass with the flag instead of setting it on the common class. + * + * @see {@link BaseMigration.withFKsDisabled} + */ + dropNotNull: (tableName: string, columnName: string, _opts: RecreatesOnSqliteAck) => new DropNotNull(tableName, columnName, tablePrefix, queryRunner), - /** WARNING: This recreates the entire table on SQLite. */ - addEnumCheck: (tableName: string, columnName: string, values: string[]) => - new AddEnumCheck(tableName, columnName, values, tablePrefix, queryRunner), - /** WARNING: This recreates the entire table on SQLite. */ - dropEnumCheck: (tableName: string, columnName: string) => + /** + * Adds a CHECK constraint that emulates an enum on the given column. + * + * **WARNING — SQLite table recreation:** On SQLite, TypeORM implements this by + * recreating the entire table. If other tables have incoming FK constraints with + * CASCADE on the target table, the DROP triggers cascading deletes and **wipes + * data from those tables**. + * + * **Mitigation:** On SQLite migrations, set `withFKsDisabled = true as const` + * when the target table has incoming FKs. For common migrations, add a + * SQLite-only subclass with the flag instead of setting it on the common class. + * + * @see {@link BaseMigration.withFKsDisabled} + */ + addEnumCheck: ( + tableName: string, + columnName: string, + values: string[], + _opts: RecreatesOnSqliteAck, + ) => new AddEnumCheck(tableName, columnName, values, tablePrefix, queryRunner), + + /** + * Drops a CHECK constraint that emulates an enum on the given column. + * + * **WARNING — SQLite table recreation:** On SQLite, TypeORM implements this by + * recreating the entire table. If other tables have incoming FK constraints with + * CASCADE on the target table, the DROP triggers cascading deletes and **wipes + * data from those tables**. + * + * **Mitigation:** On SQLite migrations, set `withFKsDisabled = true as const` + * when the target table has incoming FKs. For common migrations, add a + * SQLite-only subclass with the flag instead of setting it on the common class. + * + * @see {@link BaseMigration.withFKsDisabled} + */ + dropEnumCheck: (tableName: string, columnName: string, _opts: RecreatesOnSqliteAck) => new DropEnumCheck(tableName, columnName, tablePrefix, queryRunner), /* eslint-enable */ diff --git a/packages/@n8n/db/src/migrations/dsl/table.ts b/packages/@n8n/db/src/migrations/dsl/table.ts index 1ca54fc292c..ad85d0bf3f5 100644 --- a/packages/@n8n/db/src/migrations/dsl/table.ts +++ b/packages/@n8n/db/src/migrations/dsl/table.ts @@ -152,6 +152,7 @@ export class DropTable extends TableOperation { } } +/** SQLite: TypeORM recreates the table internally — beware CASCADE FK data loss. */ export class AddColumns extends TableOperation { constructor( tableName: string, @@ -179,6 +180,7 @@ export class AddColumns extends TableOperation { } } +/** SQLite: TypeORM recreates the table internally — beware CASCADE FK data loss. */ export class DropColumns extends TableOperation { constructor( tableName: string, @@ -233,6 +235,7 @@ export class DropForeignKey extends ForeignKeyOperation { } } +/** SQLite: TypeORM recreates the table internally via changeColumn — beware CASCADE FK data loss. */ class ModifyNotNull extends TableOperation { constructor( tableName: string, diff --git a/packages/@n8n/db/src/migrations/postgresdb/1758794506893-AddProjectIdToVariableTable.ts b/packages/@n8n/db/src/migrations/postgresdb/1758794506893-AddProjectIdToVariableTable.ts index 01b50b83776..cccb608a09a 100644 --- a/packages/@n8n/db/src/migrations/postgresdb/1758794506893-AddProjectIdToVariableTable.ts +++ b/packages/@n8n/db/src/migrations/postgresdb/1758794506893-AddProjectIdToVariableTable.ts @@ -26,7 +26,9 @@ export class AddProjectIdToVariableTable1758794506893 implements ReversibleMigra `ALTER TABLE ${variablesTableName} DROP CONSTRAINT ${tablePrefix}variables_key_key;`, ); - await addColumns(VARIABLES_TABLE_NAME, [column('projectId').varchar(36)]); + await addColumns(VARIABLES_TABLE_NAME, [column('projectId').varchar(36)], { + recreatesOnSqlite: true, + }); await addForeignKey(VARIABLES_TABLE_NAME, 'projectId', ['project', 'id'], undefined, 'CASCADE'); // Create index for unique project key (projectId not null) @@ -65,7 +67,7 @@ export class AddProjectIdToVariableTable1758794506893 implements ReversibleMigra // Remove foreign key constraints and drop the projectId column await dropForeignKey(VARIABLES_TABLE_NAME, 'projectId', ['project', 'id']); - await dropColumns(VARIABLES_TABLE_NAME, ['projectId']); + await dropColumns(VARIABLES_TABLE_NAME, ['projectId'], { recreatesOnSqlite: true }); // Recreate the original unique index on key await queryRunner.query(` diff --git a/packages/@n8n/db/src/migrations/postgresdb/1784000000028-AddProjectIdToInstanceAiThread.ts b/packages/@n8n/db/src/migrations/postgresdb/1784000000028-AddProjectIdToInstanceAiThread.ts new file mode 100644 index 00000000000..e6cb7c7b670 --- /dev/null +++ b/packages/@n8n/db/src/migrations/postgresdb/1784000000028-AddProjectIdToInstanceAiThread.ts @@ -0,0 +1,54 @@ +import { + AddProjectIdToInstanceAiThreadBase, + FK_NAME, + PROJECT_ID_COLUMN, + PROJECT_ID_COMMENT, + THREADS_TABLE, +} from '../common/AddProjectIdToInstanceAiThreadBase'; +import type { MigrationContext, ReversibleMigration } from '../migration-types'; + +/** + * Adds a non-null project foreign key to Instance AI threads (Postgres). + * + * Postgres applies the column, NOT NULL, foreign key, and index in place via the + * DSL (cheap ALTERs). The SQLite variant (sqlite/1784000000028) instead rebuilds + * the table once by hand, because there each operation would recreate the whole + * table. The shared backfill lives in {@link AddProjectIdToInstanceAiThreadBase}. + * The schema change is reversible via `down()`. + */ +export class AddProjectIdToInstanceAiThread1784000000028 + extends AddProjectIdToInstanceAiThreadBase + implements ReversibleMigration +{ + async up(ctx: MigrationContext) { + const { + schemaBuilder: { addColumns, column, addNotNull, addForeignKey, createIndex }, + } = ctx; + + await addColumns( + THREADS_TABLE, + [column(PROJECT_ID_COLUMN).varchar(36).comment(PROJECT_ID_COMMENT)], + { recreatesOnSqlite: true }, + ); + + // Scope every existing row before the column becomes NOT NULL. + await this.backfillUserThreads(ctx); + await this.backfillSubAgentThreads(ctx); + await this.backfillRemainingToInstanceOwner(ctx); + await this.deleteUnmappableThreads(ctx); + + await addNotNull(THREADS_TABLE, PROJECT_ID_COLUMN, { recreatesOnSqlite: true }); + await addForeignKey(THREADS_TABLE, PROJECT_ID_COLUMN, ['project', 'id'], FK_NAME, 'CASCADE'); + await createIndex(THREADS_TABLE, [PROJECT_ID_COLUMN]); + } + + async down(ctx: MigrationContext) { + const { + schemaBuilder: { dropIndex, dropForeignKey, dropColumns }, + } = ctx; + + await dropIndex(THREADS_TABLE, [PROJECT_ID_COLUMN]); + await dropForeignKey(THREADS_TABLE, PROJECT_ID_COLUMN, ['project', 'id'], FK_NAME); + await dropColumns(THREADS_TABLE, [PROJECT_ID_COLUMN], { recreatesOnSqlite: true }); + } +} diff --git a/packages/@n8n/db/src/migrations/postgresdb/1784000000031-AddExecutionEntityWorkflowStatusIndex.ts b/packages/@n8n/db/src/migrations/postgresdb/1784000000031-AddExecutionEntityWorkflowStatusIndex.ts new file mode 100644 index 00000000000..c2243b9bd3d --- /dev/null +++ b/packages/@n8n/db/src/migrations/postgresdb/1784000000031-AddExecutionEntityWorkflowStatusIndex.ts @@ -0,0 +1,39 @@ +import type { MigrationContext, ReversibleMigration } from '../migration-types'; + +/** + * Adds a partial composite index on execution_entity(workflowId, status, id DESC) + * filtered to non-deleted rows (deletedAt IS NULL). + * + * Without this index Postgres performs a parallel sequential scan of the full + * execution_entity table for every paginated executions-list request, because + * the CASE-based ORDER BY and the access-control IN/EXISTS subquery prevent the + * planner from using any narrower path. + * + * With this index the planner can do per-workflowId range scans (one index seek + * per accessible workflow) and merge them into the top-N result without touching + * irrelevant rows, dropping the query from a full-table sequential scan to a + * bounded index walk. + * + * Partial (WHERE deletedAt IS NULL) keeps the index small: pruned executions are + * excluded and never appear in list queries. + * + * Postgres-only migration: partial functional indexes are a Postgres feature; + * SQLite is not affected by this performance class of issue at n8n scale. + */ +export class AddExecutionEntityWorkflowStatusIndex1784000000031 implements ReversibleMigration { + async up({ schemaBuilder: { createIndex }, escape }: MigrationContext) { + const col = (c: string) => escape.columnName(c); + + await createIndex( + 'execution_entity', + ['workflowId', 'status', 'id'], + false, + undefined, + `${col('deletedAt')} IS NULL`, + ); + } + + async down({ schemaBuilder: { dropIndex } }: MigrationContext) { + await dropIndex('execution_entity', ['workflowId', 'status', 'id'], { skipIfMissing: true }); + } +} diff --git a/packages/@n8n/db/src/migrations/postgresdb/index.ts b/packages/@n8n/db/src/migrations/postgresdb/index.ts index d40d108ac75..b0e37513a5c 100644 --- a/packages/@n8n/db/src/migrations/postgresdb/index.ts +++ b/packages/@n8n/db/src/migrations/postgresdb/index.ts @@ -51,6 +51,8 @@ import { ExpandInsightsWorkflowIdLength1766500000000 } from './1766500000000-Exp import { ChangeWorkflowStatisticsFKToNoAction1767018516000 } from './1767018516000-ChangeWorkflowStatisticsFKToNoAction'; import { ExpandVariablesValueColumnToText1777420800000 } from './1777420800000-ExpandVariablesValueColumnToText'; import { LimitWorkflowVersionTriggerToContent1784000000003 } from './1784000000003-LimitWorkflowVersionTriggerToContent'; +import { AddProjectIdToInstanceAiThread1784000000028 } from './1784000000028-AddProjectIdToInstanceAiThread'; +import { AddExecutionEntityWorkflowStatusIndex1784000000031 } from './1784000000031-AddExecutionEntityWorkflowStatusIndex'; import { CreateLdapEntities1674509946020 } from '../common/1674509946020-CreateLdapEntities'; import { PurgeInvalidWorkflowConnections1675940580449 } from '../common/1675940580449-PurgeInvalidWorkflowConnections'; import { RemoveResetPasswordColumns1690000000030 } from '../common/1690000000030-RemoveResetPasswordColumns'; @@ -195,12 +197,16 @@ import { UseSlugAsPrimaryKeyInMcpRegistryServer1784000000016 } from '../common/1 import { AddLastUsedAtToApiKey1784000000017 } from '../common/1784000000017-AddLastUsedAtToApiKey'; import { CreateAgentFilesTable1784000000018 } from '../common/1784000000018-CreateAgentFilesTable'; import { AddCustomTelemetryTagsToProject1784000000019 } from '../common/1784000000019-AddCustomTelemetryTagsToProject'; -import { CreateWorkflowPublicationOutboxTable1784000000020 } from '../common/1784000000020-CreateWorkflowPublicationOutboxTable'; import { CreateAgentTaskDefinitionTable1784000000021 } from '../common/1784000000021-CreateAgentTaskDefinitionTable'; import { AddSubAgentLinkageToAgentExecutionThreads1784000000022 } from '../common/1784000000022-AddSubAgentLinkageToAgentExecutionThreads'; import { CreateInstanceAiMcpRegistryConnectionTable1784000000023 } from '../common/1784000000023-CreateInstanceAiMcpRegistryConnectionTable'; import { AddResourceToOAuthAuthorizationCodes1784000000024 } from '../common/1784000000024-AddResourceToOAuthAuthorizationCodes'; import { MigrateRedactionEnforcementToFloor1784000000025 } from '../common/1784000000025-MigrateRedactionEnforcementToFloor'; +import { AddScopeColumnToOAuthTables1784000000026 } from '../common/1784000000026-AddScopeColumnToOAuthTables'; +import { CreateWorkflowPublicationOutboxTable1784000000027 } from '../common/1784000000027-CreateWorkflowPublicationOutboxTable'; +import { AddJsonSizeBytesAndWorkflowVersionIdToExecutionEntity1784000000029 } from '../common/1784000000029-AddJsonSizeBytesAndWorkflowVersionIdToExecutionEntity'; +import { CreateAgentChatSubscriptions1784000000030 } from '../common/1784000000030-CreateAgentChatSubscriptions'; +import { AddBinaryDataSizeBytesToExecutionEntity1784000000033 } from '../common/1784000000033-AddBinaryDataSizeBytesToExecutionEntity'; import type { Migration } from '../migration-types'; export const postgresMigrations: Migration[] = [ @@ -401,10 +407,16 @@ export const postgresMigrations: Migration[] = [ AddLastUsedAtToApiKey1784000000017, CreateAgentFilesTable1784000000018, AddCustomTelemetryTagsToProject1784000000019, - CreateWorkflowPublicationOutboxTable1784000000020, CreateAgentTaskDefinitionTable1784000000021, AddSubAgentLinkageToAgentExecutionThreads1784000000022, CreateInstanceAiMcpRegistryConnectionTable1784000000023, AddResourceToOAuthAuthorizationCodes1784000000024, MigrateRedactionEnforcementToFloor1784000000025, + AddScopeColumnToOAuthTables1784000000026, + CreateWorkflowPublicationOutboxTable1784000000027, + AddProjectIdToInstanceAiThread1784000000028, + AddJsonSizeBytesAndWorkflowVersionIdToExecutionEntity1784000000029, + CreateAgentChatSubscriptions1784000000030, + AddExecutionEntityWorkflowStatusIndex1784000000031, + AddBinaryDataSizeBytesToExecutionEntity1784000000033, ]; diff --git a/packages/@n8n/db/src/migrations/sqlite/1764276827837-AddCreatorIdToProjectTable.ts b/packages/@n8n/db/src/migrations/sqlite/1764276827837-AddCreatorIdToProjectTable.ts index 87154ce34e0..5d8e319fda8 100644 --- a/packages/@n8n/db/src/migrations/sqlite/1764276827837-AddCreatorIdToProjectTable.ts +++ b/packages/@n8n/db/src/migrations/sqlite/1764276827837-AddCreatorIdToProjectTable.ts @@ -15,9 +15,11 @@ export class AddCreatorIdToProjectTable1764276827837 implements ReversibleMigrat schemaBuilder: { addColumns, addForeignKey, column }, queryRunner, }: MigrationContext) { - await addColumns(table.project, [ - column('creatorId').uuid.comment('ID of the user who created the project'), - ]); + await addColumns( + table.project, + [column('creatorId').uuid.comment('ID of the user who created the project')], + { recreatesOnSqlite: true }, + ); await addForeignKey(table.project, 'creatorId', ['user', 'id'], FOREIGN_KEY_NAME, 'SET NULL'); @@ -38,6 +40,6 @@ export class AddCreatorIdToProjectTable1764276827837 implements ReversibleMigrat } async down({ schemaBuilder: { dropColumns } }: MigrationContext) { - await dropColumns(table.project, ['creatorId']); + await dropColumns(table.project, ['creatorId'], { recreatesOnSqlite: true }); } } diff --git a/packages/@n8n/db/src/migrations/sqlite/1764689448000-AddResolvableFieldsToCredentials.ts b/packages/@n8n/db/src/migrations/sqlite/1764689448000-AddResolvableFieldsToCredentials.ts index 2fa97444f4c..aa956ca9e0c 100644 --- a/packages/@n8n/db/src/migrations/sqlite/1764689448000-AddResolvableFieldsToCredentials.ts +++ b/packages/@n8n/db/src/migrations/sqlite/1764689448000-AddResolvableFieldsToCredentials.ts @@ -8,11 +8,15 @@ export class AddResolvableFieldsToCredentials1764689448000 implements Reversible withFKsDisabled = true as const; async up({ schemaBuilder: { addColumns, addForeignKey, column } }: MigrationContext) { - await addColumns(credentialsTableName, [ - column('isResolvable').bool.notNull.default(false), - column('resolvableAllowFallback').bool.notNull.default(false), - column('resolverId').varchar(16), - ]); + await addColumns( + credentialsTableName, + [ + column('isResolvable').bool.notNull.default(false), + column('resolvableAllowFallback').bool.notNull.default(false), + column('resolverId').varchar(16), + ], + { recreatesOnSqlite: true }, + ); await addForeignKey( credentialsTableName, @@ -24,10 +28,10 @@ export class AddResolvableFieldsToCredentials1764689448000 implements Reversible } async down({ schemaBuilder: { dropColumns } }: MigrationContext) { - await dropColumns(credentialsTableName, [ - 'isResolvable', - 'resolvableAllowFallback', - 'resolverId', - ]); + await dropColumns( + credentialsTableName, + ['isResolvable', 'resolvableAllowFallback', 'resolverId'], + { recreatesOnSqlite: true }, + ); } } diff --git a/packages/@n8n/db/src/migrations/sqlite/1784000000026-AddScopeColumnToOAuthTables.ts b/packages/@n8n/db/src/migrations/sqlite/1784000000026-AddScopeColumnToOAuthTables.ts new file mode 100644 index 00000000000..bd25f95617e --- /dev/null +++ b/packages/@n8n/db/src/migrations/sqlite/1784000000026-AddScopeColumnToOAuthTables.ts @@ -0,0 +1,5 @@ +import { AddScopeColumnToOAuthTables1784000000026 as BaseMigration } from '../common/1784000000026-AddScopeColumnToOAuthTables'; + +export class AddScopeColumnToOAuthTables1784000000026 extends BaseMigration { + withFKsDisabled = true as const; +} diff --git a/packages/@n8n/db/src/migrations/sqlite/1784000000028-AddProjectIdToInstanceAiThread.ts b/packages/@n8n/db/src/migrations/sqlite/1784000000028-AddProjectIdToInstanceAiThread.ts new file mode 100644 index 00000000000..12d9cf803ec --- /dev/null +++ b/packages/@n8n/db/src/migrations/sqlite/1784000000028-AddProjectIdToInstanceAiThread.ts @@ -0,0 +1,109 @@ +import { + AddProjectIdToInstanceAiThreadBase, + FK_NAME, + PROJECT_ID_COLUMN, + PROJECT_ID_COMMENT, + THREADS_TABLE, +} from '../common/AddProjectIdToInstanceAiThreadBase'; +import type { MigrationContext, ReversibleMigration } from '../migration-types'; + +const THREADS_TABLE_TMP = 'instance_ai_threads_tmp'; + +/** + * Adds a non-null project foreign key to Instance AI threads (SQLite). + * + * On SQLite each of ADD COLUMN / SET NOT NULL / ADD FOREIGN KEY recreates the + * whole table, and `instance_ai_threads` is referenced by many tables with + * ON DELETE CASCADE. So rather than three recreations, the column is added, + * backfilled (see {@link AddProjectIdToInstanceAiThreadBase}), and the table is + * then rebuilt once (create → copy → drop → rename) with foreign keys disabled + * (`withFKsDisabled`) so the drop does not cascade into the referencing tables. + * The Postgres variant (postgresdb/1784000000028) uses the DSL directly. The + * schema change is reversible via `down()`. + */ +export class AddProjectIdToInstanceAiThread1784000000028 + extends AddProjectIdToInstanceAiThreadBase + implements ReversibleMigration +{ + withFKsDisabled = true as const; + + async up(ctx: MigrationContext) { + // Native ADD COLUMN is metadata-only on SQLite (no recreation), so the + // column can be backfilled before the single table rebuild materializes it + // as NOT NULL with its foreign key. + const { runQuery, escape } = ctx; + await runQuery( + `ALTER TABLE ${escape.tableName(THREADS_TABLE)} ADD COLUMN ${escape.columnName( + PROJECT_ID_COLUMN, + )} varchar(36)`, + ); + + await this.backfillUserThreads(ctx); + await this.backfillSubAgentThreads(ctx); + await this.backfillRemainingToInstanceOwner(ctx); + await this.deleteUnmappableThreads(ctx); + + await this.rebuildTable(ctx, { withProjectId: true }); + } + + async down(ctx: MigrationContext) { + await this.rebuildTable(ctx, { withProjectId: false }); + } + + /** + * Single-pass rebuild: create the target shape, copy the rows, drop the + * original, rename. Foreign keys are disabled for the migration, so dropping + * the old table does not cascade into the tables that reference it. Indexes are + * created on the final table after the rename so their generated names derive + * from `instance_ai_threads` (matching the original schema) and the dropped + * original frees those names — creating them on the temp table would leave a + * name that collides when the table is rebuilt again (e.g. down). + */ + private async rebuildTable( + { + schemaBuilder: { createTable, column, createIndex, dropTable }, + runQuery, + escape, + copyTable, + }: MigrationContext, + { withProjectId }: { withProjectId: boolean }, + ) { + let builder = createTable(THREADS_TABLE_TMP).withColumns( + column('id').uuid.primary.notNull, + column('resourceId').varchar(255).notNull, + ...(withProjectId + ? [column(PROJECT_ID_COLUMN).varchar(36).notNull.comment(PROJECT_ID_COMMENT)] + : []), + column('title').text.default("''").notNull, + column('metadata').json, + ); + if (withProjectId) { + builder = builder.withForeignKey(PROJECT_ID_COLUMN, { + tableName: 'project', + columnName: 'id', + onDelete: 'CASCADE', + name: FK_NAME, + }); + } + await builder.withTimestamps; + + const fields = ['id', 'resourceId', ...(withProjectId ? [PROJECT_ID_COLUMN] : [])].concat( + 'title', + 'metadata', + 'createdAt', + 'updatedAt', + ); + await copyTable(THREADS_TABLE, THREADS_TABLE_TMP, fields, fields); + await dropTable(THREADS_TABLE); + await runQuery( + `ALTER TABLE ${escape.tableName(THREADS_TABLE_TMP)} RENAME TO ${escape.tableName( + THREADS_TABLE, + )}`, + ); + + await createIndex(THREADS_TABLE, ['resourceId']); + if (withProjectId) { + await createIndex(THREADS_TABLE, [PROJECT_ID_COLUMN]); + } + } +} diff --git a/packages/@n8n/db/src/migrations/sqlite/index.ts b/packages/@n8n/db/src/migrations/sqlite/index.ts index 34a132ed0d9..409b4cdb99f 100644 --- a/packages/@n8n/db/src/migrations/sqlite/index.ts +++ b/packages/@n8n/db/src/migrations/sqlite/index.ts @@ -53,6 +53,8 @@ import { AddChatMessageIndices1766068346315 } from './1766068346315-AddChatMessa import { ChangeWorkflowStatisticsFKToNoAction1767018516000 } from './1767018516000-ChangeWorkflowStatisticsFKToNoAction'; import { LimitWorkflowVersionTriggerToContent1784000000003 } from './1784000000003-LimitWorkflowVersionTriggerToContent'; import { CreateAgentHistoryTable1784000000011 } from './1784000000011-CreateAgentHistoryTable'; +import { AddScopeColumnToOAuthTables1784000000026 } from './1784000000026-AddScopeColumnToOAuthTables'; +import { AddProjectIdToInstanceAiThread1784000000028 } from './1784000000028-AddProjectIdToInstanceAiThread'; import { UniqueWorkflowNames1620821879465 } from '../common/1620821879465-UniqueWorkflowNames'; import { UpdateWorkflowCredentials1630330987096 } from '../common/1630330987096-UpdateWorkflowCredentials'; import { AddNodeIds1658930531669 } from '../common/1658930531669-AddNodeIds'; @@ -188,13 +190,16 @@ import { UseSlugAsPrimaryKeyInMcpRegistryServer1784000000016 } from '../common/1 import { AddLastUsedAtToApiKey1784000000017 } from '../common/1784000000017-AddLastUsedAtToApiKey'; import { CreateAgentFilesTable1784000000018 } from '../common/1784000000018-CreateAgentFilesTable'; import { AddCustomTelemetryTagsToProject1784000000019 } from '../common/1784000000019-AddCustomTelemetryTagsToProject'; -import { CreateWorkflowPublicationOutboxTable1784000000020 } from '../common/1784000000020-CreateWorkflowPublicationOutboxTable'; import { AddSubAgentLinkageToAgentExecutionThreads1784000000022 } from '../common/1784000000022-AddSubAgentLinkageToAgentExecutionThreads'; import { CreateInstanceAiMcpRegistryConnectionTable1784000000023 } from '../common/1784000000023-CreateInstanceAiMcpRegistryConnectionTable'; import { AddResourceToOAuthAuthorizationCodes1784000000024 } from '../common/1784000000024-AddResourceToOAuthAuthorizationCodes'; +import { CreateWorkflowPublicationOutboxTable1784000000027 } from '../common/1784000000027-CreateWorkflowPublicationOutboxTable'; +import { CreateAgentChatSubscriptions1784000000030 } from '../common/1784000000030-CreateAgentChatSubscriptions'; import type { Migration } from '../migration-types'; import { CreateAgentTaskDefinitionTable1784000000021 } from './1784000000021-CreateAgentTaskDefinitionTable'; import { MigrateRedactionEnforcementToFloor1784000000025 } from '../common/1784000000025-MigrateRedactionEnforcementToFloor'; +import { AddJsonSizeBytesAndWorkflowVersionIdToExecutionEntity1784000000029 } from '../common/1784000000029-AddJsonSizeBytesAndWorkflowVersionIdToExecutionEntity'; +import { AddBinaryDataSizeBytesToExecutionEntity1784000000033 } from '../common/1784000000033-AddBinaryDataSizeBytesToExecutionEntity'; const sqliteMigrations: Migration[] = [ InitialMigration1588102412422, @@ -387,12 +392,17 @@ const sqliteMigrations: Migration[] = [ AddLastUsedAtToApiKey1784000000017, CreateAgentFilesTable1784000000018, AddCustomTelemetryTagsToProject1784000000019, - CreateWorkflowPublicationOutboxTable1784000000020, CreateAgentTaskDefinitionTable1784000000021, AddSubAgentLinkageToAgentExecutionThreads1784000000022, CreateInstanceAiMcpRegistryConnectionTable1784000000023, AddResourceToOAuthAuthorizationCodes1784000000024, MigrateRedactionEnforcementToFloor1784000000025, + AddScopeColumnToOAuthTables1784000000026, + CreateWorkflowPublicationOutboxTable1784000000027, + AddProjectIdToInstanceAiThread1784000000028, + AddJsonSizeBytesAndWorkflowVersionIdToExecutionEntity1784000000029, + CreateAgentChatSubscriptions1784000000030, + AddBinaryDataSizeBytesToExecutionEntity1784000000033, ]; export { sqliteMigrations }; diff --git a/packages/@n8n/db/src/repositories/__tests__/execution.repository.test.ts b/packages/@n8n/db/src/repositories/__tests__/execution.repository.test.ts index 9574edd205f..6895d656b05 100644 --- a/packages/@n8n/db/src/repositories/__tests__/execution.repository.test.ts +++ b/packages/@n8n/db/src/repositories/__tests__/execution.repository.test.ts @@ -32,201 +32,6 @@ describe('ExecutionRepository', () => { vi.resetAllMocks(); }); - describe('getExecutionsForPublicApi', () => { - const defaultLimit = 10; - const defaultQuery = { - select: [ - 'id', - 'mode', - 'retryOf', - 'retrySuccessId', - 'startedAt', - 'stoppedAt', - 'workflowId', - 'waitTill', - 'finished', - 'status', - ], - where: {}, - order: { id: 'DESC' }, - take: defaultLimit, - }; - - test('should get executions matching all filter parameters', async () => { - const params = { - limit: defaultLimit, - lastId: '3', - workflowIds: ['3', '4'], - }; - const mockEntities = [{ id: '1' }, { id: '2' }]; - - entityManager.find.mockResolvedValueOnce(mockEntities); - const result = await executionRepository.getExecutionsForPublicApi(params); - - expect(entityManager.find).toHaveBeenCalledWith(ExecutionEntity, { - ...defaultQuery, - where: { - id: LessThan(params.lastId), - workflowId: In(params.workflowIds), - }, - }); - expect(result.length).toBe(mockEntities.length); - expect(result[0].id).toEqual(mockEntities[0].id); - }); - - test('should get executions matching the workflowIds filter', async () => { - const params = { - limit: 10, - workflowIds: ['3', '4'], - }; - const mockEntities = [{ id: '1' }, { id: '2' }]; - - entityManager.find.mockResolvedValueOnce(mockEntities); - const result = await executionRepository.getExecutionsForPublicApi(params); - - expect(entityManager.find).toHaveBeenCalledWith(ExecutionEntity, { - ...defaultQuery, - where: { - workflowId: In(params.workflowIds), - }, - }); - expect(result.length).toBe(mockEntities.length); - expect(result[0].id).toEqual(mockEntities[0].id); - }); - - describe('with id filters', () => { - test.each` - lastId | excludedExecutionsIds | expectedIdCondition - ${'5'} | ${['2', '3']} | ${And(LessThan('5'), Not(In(['2', '3'])))} - ${'5'} | ${[]} | ${LessThan('5')} - ${'5'} | ${undefined} | ${LessThan('5')} - ${undefined} | ${['2', '3']} | ${Not(In(['2', '3']))} - ${undefined} | ${[]} | ${undefined} - ${undefined} | ${undefined} | ${undefined} - `( - 'should find with id less than "$lastId" and not in "$excludedExecutionsIds"', - async ({ lastId, excludedExecutionsIds, expectedIdCondition }) => { - const params = { - limit: defaultLimit, - ...(lastId ? { lastId } : {}), - ...(excludedExecutionsIds ? { excludedExecutionsIds } : {}), - }; - const mockEntities = [{ id: '1' }, { id: '2' }]; - entityManager.find.mockResolvedValueOnce(mockEntities); - const result = await executionRepository.getExecutionsForPublicApi(params); - - expect(entityManager.find).toHaveBeenCalledWith(ExecutionEntity, { - ...defaultQuery, - where: { - ...(expectedIdCondition ? { id: expectedIdCondition } : {}), - }, - }); - expect(result.length).toBe(mockEntities.length); - expect(result[0].id).toEqual(mockEntities[0].id); - }, - ); - }); - - describe('with status filter', () => { - test.each` - filterStatus | entityStatus - ${'canceled'} | ${'canceled'} - ${'error'} | ${In(['error', 'crashed'])} - ${'running'} | ${'running'} - ${'success'} | ${'success'} - ${'waiting'} | ${'waiting'} - `('should find all "$filterStatus" executions', async ({ filterStatus, entityStatus }) => { - const mockEntities = [{ id: '1' }, { id: '2' }]; - - entityManager.find.mockResolvedValueOnce(mockEntities); - const result = await executionRepository.getExecutionsForPublicApi({ - limit: defaultLimit, - status: filterStatus, - }); - - expect(entityManager.find).toHaveBeenCalledWith(ExecutionEntity, { - ...defaultQuery, - where: { status: entityStatus }, - }); - expect(result.length).toBe(mockEntities.length); - expect(result[0].id).toEqual(mockEntities[0].id); - }); - - test.each` - filterStatus - ${'crashed'} - ${'new'} - ${'unknown'} - `( - 'should find all executions and ignore status filter "$filterStatus"', - async ({ filterStatus }) => { - const mockEntities = [{ id: '1' }, { id: '2' }]; - - entityManager.find.mockResolvedValueOnce(mockEntities); - const result = await executionRepository.getExecutionsForPublicApi({ - limit: defaultLimit, - status: filterStatus, - }); - - expect(entityManager.find).toHaveBeenCalledWith(ExecutionEntity, { - ...defaultQuery, - where: {}, - }); - expect(result.length).toBe(mockEntities.length); - expect(result[0].id).toEqual(mockEntities[0].id); - }, - ); - }); - - describe('with includeData parameter', () => { - test('should not fetch executionData and metadata relations when includeData is false', async () => { - const params = { - limit: defaultLimit, - includeData: false, - }; - const mockEntities = [{ id: '1' }, { id: '2' }]; - - entityManager.find.mockResolvedValueOnce(mockEntities); - const result = await executionRepository.getExecutionsForPublicApi(params); - - expect(entityManager.find).toHaveBeenCalledWith(ExecutionEntity, { - ...defaultQuery, - where: {}, - }); - expect(result.length).toBe(mockEntities.length); - }); - - test('should fetch executionData and metadata relations when includeData is true', async () => { - const params = { - limit: defaultLimit, - includeData: true, - }; - const mockEntities = [ - { - id: '1', - executionData: { data: '[]' }, - metadata: [], - }, - { - id: '2', - executionData: { data: '[]' }, - metadata: [], - }, - ]; - - entityManager.find.mockResolvedValueOnce(mockEntities); - const result = await executionRepository.getExecutionsForPublicApi(params); - - expect(entityManager.find).toHaveBeenCalledWith(ExecutionEntity, { - ...defaultQuery, - where: {}, - relations: ['executionData', 'metadata'], - }); - expect(result.length).toBe(mockEntities.length); - }); - }); - }); - describe('getExecutionsCountForPublicApi', () => { test('should get executions matching all filter parameters', async () => { const mockCount = 20; @@ -386,50 +191,12 @@ describe('ExecutionRepository', () => { expect(entityManager.update).toHaveBeenCalledWith( ExecutionEntity, - { id: In(executionIds) }, + { id: In(executionIds), status: In(['new', 'running', 'unknown']) }, expect.objectContaining({ status: 'crashed', waitTill: null }), ); }); }); - describe('stopDuringRun', () => { - test('should update execution with ManualExecutionCancelledError', async () => { - const mockExecution = { - id: '123', - data: { - resultData: { - runData: {}, - }, - }, - } as unknown; - - const updateSpy = vi.spyOn(executionRepository, 'updateExistingExecution'); - - const result = await executionRepository.stopDuringRun(mockExecution as IExecutionResponse); - - // Verify updateExistingExecution was called with the execution - expect(updateSpy).toHaveBeenCalledWith( - '123', - expect.objectContaining({ - status: 'canceled', - stoppedAt: expect.any(Date), - waitTill: null, - data: expect.objectContaining({ - resultData: expect.objectContaining({ - error: expect.objectContaining({ - message: 'The execution was cancelled manually', - }), - }), - }), - }), - ); - - // Verify the execution was marked as canceled - expect(result.status).toBe('canceled'); - expect(result.data.resultData.error?.message).toBe('The execution was cancelled manually'); - }); - }); - describe('setRunning', () => { beforeEach(() => { entityManager.transaction.mockImplementation(async (fn: unknown) => { diff --git a/packages/@n8n/db/src/repositories/execution-data.repository.ts b/packages/@n8n/db/src/repositories/execution-data.repository.ts index 9e6a99651e1..cf88879e23f 100644 --- a/packages/@n8n/db/src/repositories/execution-data.repository.ts +++ b/packages/@n8n/db/src/repositories/execution-data.repository.ts @@ -2,7 +2,6 @@ import { Service } from '@n8n/di'; import { DataSource, In, Repository } from '@n8n/typeorm'; import type { EntityManager } from '@n8n/typeorm'; import type { QueryDeepPartialEntity } from '@n8n/typeorm/query-builder/QueryPartialEntity'; -import { DateUtils } from '@n8n/typeorm/util/DateUtils'; import chunk from 'lodash/chunk'; import { ExecutionData } from '../entities'; @@ -22,17 +21,6 @@ export class ExecutionDataRepository extends Repository<ExecutionData> { return await transactionManager.insert(ExecutionData, data); } - async getWorkflowsExecutedSince(date: Date) { - return await this.createQueryBuilder('executionData') - .select('executionData.workflowData') - .innerJoin('executionData.execution', 'execution') - .where('execution.startedAt >= :date', { - date: DateUtils.mixedDateToUtcDatetimeString(date), - }) - .getMany() - .then((results) => results.map(({ workflowData }) => workflowData)); - } - async deleteMany(executionIds: string[]) { if (executionIds.length === 0) return; diff --git a/packages/@n8n/db/src/repositories/execution.repository.ts b/packages/@n8n/db/src/repositories/execution.repository.ts index ecf8763331b..af4e8d06d51 100644 --- a/packages/@n8n/db/src/repositories/execution.repository.ts +++ b/packages/@n8n/db/src/repositories/execution.repository.ts @@ -33,8 +33,7 @@ import type { IRunExecutionDataAll, } from 'n8n-workflow'; import { - createEmptyRunExecutionData, - ManualExecutionCancelledError, + CRASHABLE_EXECUTION_STATUSES, migrateRunExecutionData, UnexpectedError, } from 'n8n-workflow'; @@ -359,7 +358,10 @@ export class ExecutionRepository extends Repository<ExecutionEntity> { // NOTE: if a slice goes past the end of the array, it just returns up til the end. const batch: string[] = executionIds.slice(processed, processed + MAX_UPDATE_BATCH_SIZE); await this.update( - { id: In(batch) }, + // Guard against overwriting executions that have since moved to a `waiting` or + // terminal status: recovery can race a `running` -> `waiting` transition and flag a + // healthy execution as dangling, but only genuinely in-progress rows should be crashed + { id: In(batch), status: In(CRASHABLE_EXECUTION_STATUSES) }, { status: 'crashed', stoppedAt: new Date(), @@ -417,6 +419,8 @@ export class ExecutionRepository extends Repository<ExecutionEntity> { createdAt, // must never change startedAt, // must never change customData, + jsonSizeBytes, // computed by ExecutionPersistence on write; never set from a caller here + binaryDataSizeBytes, // computed by ExecutionPersistence on write; never set from a caller here ...executionInformation } = execution; @@ -675,7 +679,7 @@ export class ExecutionRepository extends Repository<ExecutionEntity> { return condition; } - private getFindExecutionsForPublicApiCondition(params: { + getFindExecutionsForPublicApiCondition(params: { lastId?: string; workflowIds?: string[]; status?: ExecutionStatus; @@ -693,77 +697,6 @@ export class ExecutionRepository extends Repository<ExecutionEntity> { return where; } - async getExecutionsForPublicApi(params: { - limit: number; - includeData?: boolean; - lastId?: string; - workflowIds?: string[]; - status?: ExecutionStatus; - excludedExecutionsIds?: string[]; - }): Promise<IExecutionBase[]> { - const where = this.getFindExecutionsForPublicApiCondition(params); - - return await this.findMultipleExecutions( - { - select: [ - 'id', - 'mode', - 'retryOf', - 'retrySuccessId', - 'startedAt', - 'stoppedAt', - 'workflowId', - 'waitTill', - 'finished', - 'status', - ], - where, - order: { id: 'DESC' }, - take: params.limit, - }, - { - includeData: params.includeData, - unflattenData: true, - }, - ); - } - - async getExecutionInWorkflowsForPublicApi( - id: string, - workflowIds: string[], - includeData?: boolean, - ): Promise<IExecutionBase | undefined> { - return await this.findSingleExecution(id, { - where: { - workflowId: In(workflowIds), - }, - includeData, - unflattenData: true, - }); - } - - async findWithUnflattenedData(executionId: string, accessibleWorkflowIds: string[]) { - return await this.findSingleExecution(executionId, { - where: { - workflowId: In(accessibleWorkflowIds), - }, - includeData: true, - unflattenData: true, - includeAnnotation: true, - }); - } - - async findIfSharedUnflatten(executionId: string, sharedWorkflowIds: string[]) { - return await this.findSingleExecution(executionId, { - where: { - workflowId: In(sharedWorkflowIds), - }, - includeData: true, - unflattenData: true, - includeAnnotation: true, - }); - } - async findIfShared(executionId: string, sharedWorkflowIds: string[]) { return await this.findSingleExecution(executionId, { where: { @@ -794,26 +727,6 @@ export class ExecutionRepository extends Repository<ExecutionEntity> { return execution; } - async stopDuringRun(execution: IExecutionResponse) { - const error = new ManualExecutionCancelledError(execution.id); - - execution.data = execution.data || createEmptyRunExecutionData(); - - execution.data.resultData.error = { - ...error, - message: error.message, - stack: error.stack, - }; - - execution.stoppedAt = new Date(); - execution.waitTill = null; - execution.status = 'canceled'; - - await this.updateExistingExecution(execution.id, execution); - - return execution; - } - async cancelMany(executionIds: string[]) { await this.update( { id: In(executionIds) }, @@ -831,6 +744,9 @@ export class ExecutionRepository extends Repository<ExecutionEntity> { private summaryFields = { id: true, workflowId: true, + workflowVersionId: true, + jsonSizeBytes: true, + binaryDataSizeBytes: true, mode: true, retryOf: true, status: true, @@ -915,9 +831,21 @@ export class ExecutionRepository extends Repository<ExecutionEntity> { startedAt: Date | string | null; stoppedAt?: Date | string; waitTill?: Date | string | null; + jsonSizeBytes?: number | string; + binaryDataSizeBytes?: number | string; }): ExecutionSummary { execution.id = execution.id.toString(); + if (execution.jsonSizeBytes !== undefined && typeof execution.jsonSizeBytes === 'string') { + // Raw query bypasses the entity transformer, so Postgres hands bigint back as a string. + execution.jsonSizeBytes = Number(execution.jsonSizeBytes); + } + + if (typeof execution.binaryDataSizeBytes === 'string') { + // Raw query bypasses the entity transformer, so Postgres hands bigint back as a string. + execution.binaryDataSizeBytes = Number(execution.binaryDataSizeBytes); + } + const normalizeDateString = (date: string) => { if (date.includes(' ')) return date.replace(' ', 'T') + 'Z'; return date; diff --git a/packages/@n8n/db/src/repositories/shared-credentials.repository.ts b/packages/@n8n/db/src/repositories/shared-credentials.repository.ts index 96448003c43..61dae64c6a3 100644 --- a/packages/@n8n/db/src/repositories/shared-credentials.repository.ts +++ b/packages/@n8n/db/src/repositories/shared-credentials.repository.ts @@ -146,6 +146,42 @@ export class SharedCredentialsRepository extends Repository<SharedCredentials> { }); } + /** + * Given a list of `(credentialId, userId)` pairs, returns the subset that + * still retains `scope` on the credential through a project membership path: + * + * SharedCredentials (credential ↔ project) + * ← ProjectRelation (project ↔ user, project role must grant `scope`) + */ + async findPairsWithCredentialAccess( + pairs: Array<{ credentialId: string; userId: string }>, + scope: Scope, + credentialRoles: string[], + trx?: EntityManager, + ): Promise<Array<{ credentialId: string; userId: string }>> { + if (pairs.length === 0 || credentialRoles.length === 0) return []; + + const manager = trx ?? this.manager; + const credentialIds = [...new Set(pairs.map((p) => p.credentialId))]; + const userIds = [...new Set(pairs.map((p) => p.userId))]; + + const rows = await manager + .createQueryBuilder(SharedCredentials, 'sc') + .select(['sc.credentialsId AS "credentialId"', 'pr.userId AS "userId"']) + .distinct(true) + .innerJoin(ProjectRelation, 'pr', 'pr.projectId = sc.projectId') + .innerJoin('pr.role', 'pr_role') + .innerJoin('pr_role.scopes', 'pr_scope') + .where('sc.credentialsId IN (:...credentialIds)', { credentialIds }) + .andWhere('pr.userId IN (:...userIds)', { userIds }) + .andWhere('pr_scope.slug = :scope', { scope }) + .andWhere('sc.role IN (:...credentialRoles)', { credentialRoles }) + .getRawMany<{ credentialId: string; userId: string }>(); + + const requested = new Set(pairs.map((p) => `${p.credentialId}|${p.userId}`)); + return rows.filter((r) => requested.has(`${r.credentialId}|${r.userId}`)); + } + /** * Build a subquery that returns credential IDs based on sharing permissions. * This replicates the logic from CredentialsFinderService but as a subquery. diff --git a/packages/@n8n/db/src/repositories/workflow-publication-outbox.repository.ts b/packages/@n8n/db/src/repositories/workflow-publication-outbox.repository.ts index c66610e0909..b0e67cc3cfa 100644 --- a/packages/@n8n/db/src/repositories/workflow-publication-outbox.repository.ts +++ b/packages/@n8n/db/src/repositories/workflow-publication-outbox.repository.ts @@ -1,11 +1,256 @@ +import { GlobalConfig } from '@n8n/config'; import { Service } from '@n8n/di'; import { DataSource, Repository } from '@n8n/typeorm'; +import type { EntityManager } from '@n8n/typeorm'; +import { UnexpectedError } from 'n8n-workflow'; -import { WorkflowPublicationOutbox } from '../entities/workflow-publication-outbox'; +import { + WorkflowPublicationOutbox, + WorkflowPublicationOutboxStatus as Status, +} from '../entities/workflow-publication-outbox'; @Service() export class WorkflowPublicationOutboxRepository extends Repository<WorkflowPublicationOutbox> { - constructor(dataSource: DataSource) { + constructor( + dataSource: DataSource, + private readonly globalConfig: GlobalConfig, + ) { super(WorkflowPublicationOutbox, dataSource.manager); } + + /** + * Enqueue a publication for `workflowId`. If a pending record is already in + * place for the same workflow, its `publishedVersionId` is updated in place, + * superseding the previous requested version. + * + * A single atomic UPSERT on the partial unique index + * (`workflowId` where `status = 'pending'`) guarantees at most one pending + * record per workflow without an explicit transaction. Callers only need to + * know the enqueue succeeded, so no row is returned. + * + * Pass `trx` to run the UPSERT inside an existing transaction, e.g. to make + * the enqueue atomic with a `workflow_entity` update. + */ + async enqueue( + workflowId: string, + publishedVersionId: string, + trx?: EntityManager, + ): Promise<void> { + if (this.globalConfig.database.type === 'postgresdb') { + await this.enqueueWithPostgresUpsert(workflowId, publishedVersionId, trx ?? this.manager); + return; + } + + await this.enqueueWithSqliteUpsert(workflowId, publishedVersionId, trx ?? this.manager); + } + + private async enqueueWithPostgresUpsert( + workflowId: string, + publishedVersionId: string, + trx: EntityManager, + ): Promise<void> { + const tableName = this.getTableName('workflow_publication_outbox'); + + // `createdAt`/`updatedAt` carry DB-level defaults, so the insert omits + // them; the conflict path bumps `updatedAt` explicitly. + await trx.query( + `INSERT INTO ${tableName} ("workflowId", "publishedVersionId", "status") + VALUES ($1, $2, '${Status.Pending}') + ON CONFLICT ("workflowId", "status") WHERE "status" IN ('${Status.Pending}', '${Status.InProgress}') + DO UPDATE SET "publishedVersionId" = EXCLUDED."publishedVersionId", "updatedAt" = CURRENT_TIMESTAMP(3)`, + [workflowId, publishedVersionId], + ); + } + + private async enqueueWithSqliteUpsert( + workflowId: string, + publishedVersionId: string, + trx: EntityManager, + ): Promise<void> { + const tableName = this.getTableName('workflow_publication_outbox'); + + await trx.query( + `INSERT INTO ${tableName} ("workflowId", "publishedVersionId", "status") + VALUES (?, ?, '${Status.Pending}') + ON CONFLICT ("workflowId", "status") WHERE "status" IN ('${Status.Pending}', '${Status.InProgress}') + DO UPDATE SET "publishedVersionId" = excluded."publishedVersionId", "updatedAt" = STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW')`, + [workflowId, publishedVersionId], + ); + } + + /** + * Enqueue a pending publication record for every active, non-archived workflow + * at its current active version, in a single statement. Idempotent via the same + * partial-unique-index upsert as {@link enqueue}. + */ + async enqueueAllActiveWorkflows(): Promise<void> { + if (this.globalConfig.database.type === 'postgresdb') { + await this.enqueueAllActiveWithPostgresUpsert(); + return; + } + + await this.enqueueAllActiveWithSqliteUpsert(); + } + + private async enqueueAllActiveWithPostgresUpsert(): Promise<void> { + const tableName = this.getTableName('workflow_publication_outbox'); + const workflowTableName = this.getTableName('workflow_entity'); + + await this.query( + `INSERT INTO ${tableName} ("workflowId", "publishedVersionId", "status") + SELECT w."id", w."activeVersionId", '${Status.Pending}' + FROM ${workflowTableName} w + WHERE w."activeVersionId" IS NOT NULL AND w."isArchived" = false + ON CONFLICT ("workflowId", "status") WHERE "status" IN ('${Status.Pending}', '${Status.InProgress}') + DO UPDATE SET "publishedVersionId" = EXCLUDED."publishedVersionId", "updatedAt" = CURRENT_TIMESTAMP(3)`, + ); + } + + private async enqueueAllActiveWithSqliteUpsert(): Promise<void> { + const tableName = this.getTableName('workflow_publication_outbox'); + const workflowTableName = this.getTableName('workflow_entity'); + + await this.query( + `INSERT INTO ${tableName} ("workflowId", "publishedVersionId", "status") + SELECT w."id", w."activeVersionId", '${Status.Pending}' + FROM ${workflowTableName} w + WHERE w."activeVersionId" IS NOT NULL AND w."isArchived" = 0 + ON CONFLICT ("workflowId", "status") WHERE "status" IN ('${Status.Pending}', '${Status.InProgress}') + DO UPDATE SET "publishedVersionId" = excluded."publishedVersionId", "updatedAt" = STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW')`, + ); + } + + /** + * Atomically claim the oldest pending record by transitioning its status to + * `in_progress`. Postgres uses `FOR UPDATE SKIP LOCKED` so concurrent + * consumers never receive the same row; SQLite serializes the find-then-update + * via the sqlite-pooled driver's `BEGIN IMMEDIATE` transactions, so + * concurrent claimers can't both see the same pending row. + * + * Returns the claimed record, or `null` when nothing is pending. + */ + async claimNextPendingRecord(): Promise<WorkflowPublicationOutbox | null> { + if (this.globalConfig.database.type === 'postgresdb') { + return await this.claimWithPostgresLocking(); + } + + return await this.claimWithSqliteTransaction(); + } + + private async claimWithPostgresLocking(): Promise<WorkflowPublicationOutbox | null> { + const tableName = this.getTableName('workflow_publication_outbox'); + + // TypeORM's Postgres driver returns `[rows, affectedCount]` from a raw + // UPDATE ... RETURNING (unlike INSERT, which returns the rows directly). + const [rows]: [WorkflowPublicationOutbox[], number] = await this.query( + // Claim the oldest pending row whose workflow has no in-progress row, + // so a workflow is never published concurrently. Ordering by id gives + // FIFO: ids are monotonically assigned, so the oldest is processed first. + `UPDATE ${tableName} + SET "status" = '${Status.InProgress}', "updatedAt" = CURRENT_TIMESTAMP(3) + WHERE "id" = ( + SELECT o."id" FROM ${tableName} o + WHERE o."status" = '${Status.Pending}' + AND NOT EXISTS ( + SELECT 1 FROM ${tableName} ip + WHERE ip."workflowId" = o."workflowId" AND ip."status" = '${Status.InProgress}' + ) + ORDER BY o."id" ASC + LIMIT 1 + FOR UPDATE SKIP LOCKED + ) + RETURNING *`, + ); + + return rows[0] ?? null; + } + + // Two statements rather than one because `update` doesn't return the claimed + // row. The `BEGIN IMMEDIATE` transaction serializes claimers. + private async claimWithSqliteTransaction(): Promise<WorkflowPublicationOutbox | null> { + return await this.manager.transaction(async (tx) => { + // Claim the oldest pending row whose workflow has no in-progress row, + // so a workflow is never published concurrently. Ordering by id gives + // FIFO: ids are monotonically assigned, so the oldest is processed first. + const record = await tx + .createQueryBuilder(WorkflowPublicationOutbox, 'o') + .where('o.status = :pending', { pending: Status.Pending }) + .andWhere((qb) => { + const sub = qb + .subQuery() + .select('1') + .from(WorkflowPublicationOutbox, 'ip') + .where('ip.workflowId = o.workflowId') + .andWhere('ip.status = :inProgress') + .getQuery(); + return `NOT EXISTS ${sub}`; + }) + .setParameter('inProgress', Status.InProgress) + .orderBy('o.id', 'ASC') + .getOne(); + + if (!record) return null; + + await tx.update( + WorkflowPublicationOutbox, + { id: record.id, status: Status.Pending }, + { status: Status.InProgress }, + ); + record.status = Status.InProgress; + return record; + }); + } + + /** Mark a claimed record as successfully processed. */ + async markCompleted(id: number): Promise<void> { + const result = await this.update( + { id, status: Status.InProgress }, + { status: Status.Completed, errorMessage: null }, + ); + this.assertSingleRowAffected(result.affected, id, Status.Completed); + } + + /** Mark a claimed record as failed and record the error for diagnostics. */ + async markFailed(id: number, errorMessage: string): Promise<void> { + const result = await this.update( + { id, status: Status.InProgress }, + { status: Status.Failed, errorMessage }, + ); + this.assertSingleRowAffected(result.affected, id, Status.Failed); + } + + /** + * Mark a claimed record as partially successful: the published version advanced + * and some triggers are running, but others failed to (de)register. The message + * carries per-node detail for diagnostics. The workflow stays published. + */ + async markPartialSuccess(id: number, errorMessage: string): Promise<void> { + const result = await this.update( + { id, status: Status.InProgress }, + { status: Status.PartialSuccess, errorMessage }, + ); + this.assertSingleRowAffected(result.affected, id, Status.PartialSuccess); + } + + /** + * Guards against transitioning a record that is no longer the in-progress row + * we expect (e.g. it was already resolved or never claimed): such a transition + * affects zero rows and would otherwise be lost silently. + */ + private assertSingleRowAffected( + affected: number | null | undefined, + id: number, + target: Status, + ): void { + if (affected !== 1) { + throw new UnexpectedError( + `Expected to transition outbox record ${id} to '${target}', but ${affected ?? 0} rows were affected. The record may not be in progress.`, + ); + } + } + + private getTableName(name: string): string { + const { tablePrefix } = this.globalConfig.database; + return this.manager.connection.driver.escape(`${tablePrefix}${name}`); + } } diff --git a/packages/@n8n/db/src/repositories/workflow-publish-history.repository.ts b/packages/@n8n/db/src/repositories/workflow-publish-history.repository.ts index b03857ee7e3..6a62561bb2b 100644 --- a/packages/@n8n/db/src/repositories/workflow-publish-history.repository.ts +++ b/packages/@n8n/db/src/repositories/workflow-publish-history.repository.ts @@ -1,5 +1,6 @@ import { Service } from '@n8n/di'; import { DataSource, Repository } from '@n8n/typeorm'; +import type { EntityManager } from '@n8n/typeorm'; import { WorkflowPublishHistory } from '../entities'; @@ -9,13 +10,17 @@ export class WorkflowPublishHistoryRepository extends Repository<WorkflowPublish super(WorkflowPublishHistory, dataSource.manager); } - async addRecord({ - workflowId, - versionId, - event, - userId, - }: Pick<WorkflowPublishHistory, 'event' | 'workflowId' | 'versionId' | 'userId'>) { - await this.insert({ + async addRecord( + { + workflowId, + versionId, + event, + userId, + }: Pick<WorkflowPublishHistory, 'event' | 'workflowId' | 'versionId' | 'userId'>, + trx?: EntityManager, + ) { + const repository = trx ? trx.getRepository(WorkflowPublishHistory) : this; + await repository.insert({ workflowId, versionId, event, diff --git a/packages/@n8n/db/src/repositories/workflow.repository.ts b/packages/@n8n/db/src/repositories/workflow.repository.ts index 575e87a7158..81022f40377 100644 --- a/packages/@n8n/db/src/repositories/workflow.repository.ts +++ b/packages/@n8n/db/src/repositories/workflow.repository.ts @@ -30,7 +30,6 @@ import type { ListQuery, } from '../entities/types-db'; import { applyWorkflowBooleanSettingFilter } from '../utils/apply-workflow-boolean-setting-filter'; -import { buildWorkflowsByNodesQuery } from '../utils/build-workflows-by-nodes-query'; import { isStringArray } from '../utils/is-string-array'; import { TimedQuery } from '../utils/timed-query'; @@ -207,6 +206,19 @@ export class WorkflowRepository extends Repository<WorkflowEntity> { return await this.find(options); } + async findPreExistingWorkflows(workflowIds: string[]): Promise<WorkflowEntity[]> { + if (workflowIds.length === 0) { + return []; + } + + return await this.createQueryBuilder('workflow') + .select(['workflow.id', 'workflow.name', 'workflow.isArchived']) + .leftJoin('workflow.shared', 'shared', 'shared.role = :role', { role: 'workflow:owner' }) + .addSelect(['shared.workflowId', 'shared.projectId', 'shared.role']) + .where('workflow.id IN (:...workflowIds)', { workflowIds }) + .getMany(); + } + async getActiveTriggerCount() { const totalTriggerCount = await this.sum('triggerCount', { activeVersionId: Not(IsNull()), @@ -1087,12 +1099,19 @@ export class WorkflowRepository extends Repository<WorkflowEntity> { if (!nodeTypes.length) return; - const { whereClause, parameters } = buildWorkflowsByNodesQuery( - nodeTypes, - this.globalConfig.database.type, - ); + const subQuery = this.buildWorkflowIdsByNodeTypesSubQuery(nodeTypes); + qb.andWhere(`workflow.id IN (${subQuery.getQuery()})`); + qb.setParameters(subQuery.getParameters()); + } - qb.andWhere(whereClause, parameters); + private buildWorkflowIdsByNodeTypesSubQuery(nodeTypes: string[]) { + return this.manager + .createQueryBuilder(WorkflowDependency, 'dep') + .select('dep.workflowId') + .distinct(true) + .where('dep.dependencyType = :depType', { depType: 'nodeType' }) + .andWhere('dep.dependencyKey IN (:...nodeTypes)', { nodeTypes }) + .andWhere('dep.publishedVersionId IS NULL'); } private applyOwnedByRelation(qb: SelectQueryBuilder<WorkflowEntity>): void { @@ -1364,11 +1383,7 @@ export class WorkflowRepository extends Repository<WorkflowEntity> { if (!nodeTypes?.length) return []; const qb = this.createQueryBuilder('workflow'); - - const { whereClause, parameters } = buildWorkflowsByNodesQuery( - nodeTypes, - this.globalConfig.database.type, - ); + const subQuery = this.buildWorkflowIdsByNodeTypesSubQuery(nodeTypes); const workflows: Array< Pick<WorkflowEntity, 'id' | 'name' | 'active' | 'activeVersionId'> & @@ -1381,7 +1396,8 @@ export class WorkflowRepository extends Repository<WorkflowEntity> { 'workflow.activeVersionId', ...(includeNodes ? ['workflow.nodes'] : []), ]) - .where(whereClause, parameters) + .where(`workflow.id IN (${subQuery.getQuery()})`) + .setParameters(subQuery.getParameters()) .getMany(); return workflows; @@ -1496,7 +1512,7 @@ export class WorkflowRepository extends Repository<WorkflowEntity> { /** * Returns if the workflow is stored as `active`. * - * @important Do not confuse with `ActiveWorkflows.isActive()`, + * @important Do not confuse with `ActiveWorkflowTriggers.isActive()`, * which checks if the workflow is active in memory. */ async isActive(workflowId: string) { diff --git a/packages/@n8n/db/src/utils/__tests__/build-workflows-by-nodes-query.test.ts b/packages/@n8n/db/src/utils/__tests__/build-workflows-by-nodes-query.test.ts deleted file mode 100644 index ddcb1e4fae4..00000000000 --- a/packages/@n8n/db/src/utils/__tests__/build-workflows-by-nodes-query.test.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { buildWorkflowsByNodesQuery } from '../build-workflows-by-nodes-query'; - -describe('WorkflowRepository', () => { - describe('filterWorkflowsByNodesConstructWhereClause', () => { - it('should return the correct WHERE clause and parameters for sqlite', () => { - const nodeTypes = ['HTTP Request', 'Set']; - const expectedInQuery = - "FROM json_each(workflow.nodes) WHERE json_extract(json_each.value, '$.type')"; - const expectedParameters = { - nodeType0: 'HTTP Request', - nodeType1: 'Set', - nodeTypes, - }; - - const { whereClause, parameters } = buildWorkflowsByNodesQuery(nodeTypes, 'sqlite'); - - expect(whereClause).toContain(expectedInQuery); - expect(parameters).toEqual(expectedParameters); - }); - - it('should return the correct WHERE clause and parameters for postgresdb', () => { - const nodeTypes = ['HTTP Request', 'Set']; - const expectedInQuery = 'FROM jsonb_array_elements(workflow.nodes::jsonb) AS node'; - const expectedParameters = { nodeTypes }; - - const { whereClause, parameters } = buildWorkflowsByNodesQuery(nodeTypes, 'postgresdb'); - - expect(whereClause).toContain(expectedInQuery); - expect(parameters).toEqual(expectedParameters); - }); - }); -}); diff --git a/packages/@n8n/db/src/utils/__tests__/is-unique-constraint-error.test.ts b/packages/@n8n/db/src/utils/__tests__/is-unique-constraint-error.test.ts new file mode 100644 index 00000000000..0f851fc7ade --- /dev/null +++ b/packages/@n8n/db/src/utils/__tests__/is-unique-constraint-error.test.ts @@ -0,0 +1,71 @@ +import { QueryFailedError } from '@n8n/typeorm'; + +import { isUniqueConstraintError } from '../is-unique-constraint-error'; + +describe('isUniqueConstraintError', () => { + const makeQueryFailedError = ( + message: string, + driverError: { code?: string } = {}, + ): QueryFailedError => { + return new QueryFailedError('Query', [], Object.assign(new Error(message), driverError)); + }; + + describe('returns true for actual database unique-constraint violations', () => { + it('SQLite extended code SQLITE_CONSTRAINT_UNIQUE', () => { + const error = makeQueryFailedError('UNIQUE constraint failed: workflow_entity.name', { + code: 'SQLITE_CONSTRAINT_UNIQUE', + }); + expect(isUniqueConstraintError(error)).toBe(true); + }); + + it('SQLite base code SQLITE_CONSTRAINT when message mentions UNIQUE constraint', () => { + const error = makeQueryFailedError( + 'SQLITE_CONSTRAINT: UNIQUE constraint failed: workflow_entity.name', + { code: 'SQLITE_CONSTRAINT' }, + ); + expect(isUniqueConstraintError(error)).toBe(true); + }); + + it('PostgreSQL unique_violation (code 23505)', () => { + const error = makeQueryFailedError( + 'duplicate key value violates unique constraint "users_email_key"', + { code: '23505' }, + ); + expect(isUniqueConstraintError(error)).toBe(true); + }); + }); + + describe('returns false for non-QueryFailedError values', () => { + it('plain Error whose message mentions "unique" and "duplicate"', () => { + const error = new Error('Unique identifier duplicate found in configuration'); + expect(isUniqueConstraintError(error)).toBe(false); + }); + + it('non-error values', () => { + expect(isUniqueConstraintError(null)).toBe(false); + expect(isUniqueConstraintError(undefined)).toBe(false); + expect(isUniqueConstraintError('UNIQUE constraint failed')).toBe(false); + }); + }); + + describe('returns false for unrelated database errors', () => { + it('SQLite base code SQLITE_CONSTRAINT for a NOT NULL violation', () => { + const error = makeQueryFailedError('NOT NULL constraint failed: workflow_entity.name', { + code: 'SQLITE_CONSTRAINT', + }); + expect(isUniqueConstraintError(error)).toBe(false); + }); + + it('PostgreSQL not_null_violation (code 23502)', () => { + const error = makeQueryFailedError('null value in column violates not-null constraint', { + code: '23502', + }); + expect(isUniqueConstraintError(error)).toBe(false); + }); + + it('QueryFailedError with no driver code', () => { + const error = makeQueryFailedError('Connection timeout after 30000ms'); + expect(isUniqueConstraintError(error)).toBe(false); + }); + }); +}); diff --git a/packages/@n8n/db/src/utils/build-workflows-by-nodes-query.ts b/packages/@n8n/db/src/utils/build-workflows-by-nodes-query.ts deleted file mode 100644 index f69a7cf3a64..00000000000 --- a/packages/@n8n/db/src/utils/build-workflows-by-nodes-query.ts +++ /dev/null @@ -1,37 +0,0 @@ -/** - * Builds the WHERE clause and parameters for a query to find workflows by node types - */ -export function buildWorkflowsByNodesQuery(nodeTypes: string[], dbType: 'postgresdb' | 'sqlite') { - let whereClause: string; - - const parameters: Record<string, string | string[]> = { nodeTypes }; - - switch (dbType) { - case 'postgresdb': - whereClause = `EXISTS ( - SELECT 1 - FROM jsonb_array_elements(workflow.nodes::jsonb) AS node - WHERE node->>'type' = ANY(:nodeTypes) - )`; - break; - case 'sqlite': { - const conditions = nodeTypes - .map( - (_, i) => - `EXISTS (SELECT 1 FROM json_each(workflow.nodes) WHERE json_extract(json_each.value, '$.type') = :nodeType${i})`, - ) - .join(' OR '); - - whereClause = `(${conditions})`; - - nodeTypes.forEach((nodeType, index) => { - parameters[`nodeType${index}`] = nodeType; - }); - break; - } - default: - throw new Error('Unsupported database type'); - } - - return { whereClause, parameters }; -} diff --git a/packages/@n8n/db/src/utils/is-unique-constraint-error.ts b/packages/@n8n/db/src/utils/is-unique-constraint-error.ts new file mode 100644 index 00000000000..4147bdce714 --- /dev/null +++ b/packages/@n8n/db/src/utils/is-unique-constraint-error.ts @@ -0,0 +1,26 @@ +import { QueryFailedError } from '@n8n/typeorm'; + +/** + * Whether `error` is a unique-constraint violation, across PostgreSQL and SQLite. + */ +export function isUniqueConstraintError(error: unknown): boolean { + if (!(error instanceof QueryFailedError)) return false; + + // TypeORM types `driverError` as `any`; narrow it via `unknown` so the + // property checks below stay type-safe without an `as` cast. + const driverError: unknown = error.driverError; + if (typeof driverError !== 'object' || driverError === null) return false; + + const code = + 'code' in driverError && typeof driverError.code === 'string' ? driverError.code : undefined; + + // PostgreSQL: 23505 = unique_violation. + if (code === '23505') return true; + + // SQLite: the extended code is unambiguous; the base code covers all constraint + // kinds (NOT NULL, FK, CHECK, UNIQUE), so disambiguate via the message. + if (code === 'SQLITE_CONSTRAINT_UNIQUE') return true; + if (code === 'SQLITE_CONSTRAINT' && /UNIQUE constraint/i.test(error.message)) return true; + + return false; +} diff --git a/packages/@n8n/db/tsconfig.build.json b/packages/@n8n/db/tsconfig.build.json index c45aa087e59..6b02cf562de 100644 --- a/packages/@n8n/db/tsconfig.build.json +++ b/packages/@n8n/db/tsconfig.build.json @@ -3,8 +3,7 @@ "compilerOptions": { "composite": true, "rootDir": "src", - "outDir": "dist", - "tsBuildInfoFile": "dist/build.tsbuildinfo" + "outDir": "dist" }, "include": ["src/**/*.ts"], "exclude": ["src/**/__tests__/**", "src/**/*.test.ts", "src/**/*.spec.ts"] diff --git a/packages/@n8n/db/tsconfig.json b/packages/@n8n/db/tsconfig.json index 43e4621d711..16de2b4c1c4 100644 --- a/packages/@n8n/db/tsconfig.json +++ b/packages/@n8n/db/tsconfig.json @@ -2,7 +2,6 @@ "extends": "@n8n/typescript-config/tsconfig.common.json", "compilerOptions": { "types": ["node", "vitest/globals"], - "tsBuildInfoFile": "dist/typecheck.tsbuildinfo", "experimentalDecorators": true, "emitDecoratorMetadata": true, diff --git a/packages/@n8n/decorators/package.json b/packages/@n8n/decorators/package.json index fbb025e07a5..ec280520590 100644 --- a/packages/@n8n/decorators/package.json +++ b/packages/@n8n/decorators/package.json @@ -1,6 +1,6 @@ { "name": "@n8n/decorators", - "version": "1.25.0", + "version": "1.27.0", "scripts": { "clean": "rimraf dist .turbo", "dev": "pnpm watch", @@ -37,5 +37,6 @@ "@n8n/permissions": "workspace:*", "lodash": "catalog:", "n8n-workflow": "workspace:*" - } + }, + "license": "LicenseRef-n8n-sustainable-use" } diff --git a/packages/@n8n/decorators/src/controller/__tests__/rate-limit.test.ts b/packages/@n8n/decorators/src/controller/__tests__/rate-limit.test.ts new file mode 100644 index 00000000000..5a0bd62b40e --- /dev/null +++ b/packages/@n8n/decorators/src/controller/__tests__/rate-limit.test.ts @@ -0,0 +1,16 @@ +import { createIpRateLimit } from '../rate-limit'; + +describe('createIpRateLimit', () => { + it('returns the limit config for a positive limit', () => { + expect(createIpRateLimit(100)).toEqual({ limit: 100 }); + }); + + it('includes windowMs when provided', () => { + expect(createIpRateLimit(50, 60000)).toEqual({ limit: 50, windowMs: 60000 }); + }); + + it('returns false for a limit of 0 to disable rate limiting', () => { + expect(createIpRateLimit(0)).toBe(false); + expect(createIpRateLimit(0, 60000)).toBe(false); + }); +}); diff --git a/packages/@n8n/decorators/src/controller/index.ts b/packages/@n8n/decorators/src/controller/index.ts index bd4670baeb8..dab397c1cdc 100644 --- a/packages/@n8n/decorators/src/controller/index.ts +++ b/packages/@n8n/decorators/src/controller/index.ts @@ -20,4 +20,5 @@ export { type KeyedRateLimiterConfig, createBodyKeyedRateLimiter, createUserKeyedRateLimiter, + createIpRateLimit, } from './rate-limit'; diff --git a/packages/@n8n/decorators/src/controller/rate-limit.ts b/packages/@n8n/decorators/src/controller/rate-limit.ts index dd45c7e927a..e03e5552129 100644 --- a/packages/@n8n/decorators/src/controller/rate-limit.ts +++ b/packages/@n8n/decorators/src/controller/rate-limit.ts @@ -31,6 +31,22 @@ export interface UserKeyedRateLimiterConfig extends RateLimiterLimits { export type KeyedRateLimiterConfig = BodyKeyedRateLimiterConfig | UserKeyedRateLimiterConfig; +/** + * Build an IP-based rate limit option from a configured limit. A limit of `0` + * (or any non-positive value) returns `false`, which leaves the route without + * IP rate limiting. A positive limit returns the matching `RateLimiterLimits` + * config. + * + * @example + * createIpRateLimit(100); // { limit: 100 } + * createIpRateLimit(50, 60000); // { limit: 50, windowMs: 60000 } + * createIpRateLimit(0); // false + */ +export const createIpRateLimit = (limit: number, windowMs?: number): false | RateLimiterLimits => { + if (limit <= 0) return false; + return windowMs === undefined ? { limit } : { limit, windowMs }; +}; + /** * Create a body keyed rate limiter configuration. This ends up creating * a rate limiter that is keyed by the value of the specified field in the diff --git a/packages/@n8n/decorators/src/pubsub/pubsub-metadata.ts b/packages/@n8n/decorators/src/pubsub/pubsub-metadata.ts index f5525a6d0ae..0ae6c8b4461 100644 --- a/packages/@n8n/decorators/src/pubsub/pubsub-metadata.ts +++ b/packages/@n8n/decorators/src/pubsub/pubsub-metadata.ts @@ -14,6 +14,7 @@ export type PubSubEventName = | 'community-package-uninstall' | 'community-package-update' | 'get-worker-status' + | 'stop-execution' | 'reload-external-secrets-providers' | 'reload-license' | 'reload-oidc-config' @@ -28,11 +29,14 @@ export type PubSubEventName = | 'reload-sso-provisioning-configuration' | 'reload-source-control-config' | 'reload-mcp-registry' + | 'reload-otel-config' | 'cancel-test-run' | 'cancel-collection' | 'agent-chat-integration-changed' + | 'agent-chat-subscription-changed' | 'agent-config-changed' - | 'agent-tasks-changed'; + | 'agent-tasks-changed' + | 'redaction-floor-changed'; export type PubSubEventFilter = | { diff --git a/packages/@n8n/decorators/tsconfig.build.json b/packages/@n8n/decorators/tsconfig.build.json index ee0e3e20fda..e08cb937d03 100644 --- a/packages/@n8n/decorators/tsconfig.build.json +++ b/packages/@n8n/decorators/tsconfig.build.json @@ -3,8 +3,7 @@ "compilerOptions": { "composite": true, "rootDir": "src", - "outDir": "dist", - "tsBuildInfoFile": "dist/build.tsbuildinfo" + "outDir": "dist" }, "include": ["src/**/*.ts"], "exclude": ["src/**/__tests__/**"] diff --git a/packages/@n8n/decorators/tsconfig.json b/packages/@n8n/decorators/tsconfig.json index 931de862507..d21152245e7 100644 --- a/packages/@n8n/decorators/tsconfig.json +++ b/packages/@n8n/decorators/tsconfig.json @@ -2,7 +2,6 @@ "extends": "@n8n/typescript-config/tsconfig.common.json", "compilerOptions": { "types": ["node", "vitest/globals"], - "tsBuildInfoFile": "dist/typecheck.tsbuildinfo", "experimentalDecorators": true, "emitDecoratorMetadata": true }, diff --git a/packages/@n8n/di/package.json b/packages/@n8n/di/package.json index fb65447aa80..d9046df62b8 100644 --- a/packages/@n8n/di/package.json +++ b/packages/@n8n/di/package.json @@ -1,6 +1,6 @@ { "name": "@n8n/di", - "version": "0.12.0", + "version": "0.14.0", "scripts": { "clean": "rimraf dist .turbo", "dev": "pnpm watch", @@ -31,5 +31,6 @@ "vitest": "catalog:", "vitest-mock-extended": "catalog:", "@n8n/typescript-config": "workspace:*" - } + }, + "license": "LicenseRef-n8n-sustainable-use" } diff --git a/packages/@n8n/di/tsconfig.build.json b/packages/@n8n/di/tsconfig.build.json index ee0e3e20fda..e08cb937d03 100644 --- a/packages/@n8n/di/tsconfig.build.json +++ b/packages/@n8n/di/tsconfig.build.json @@ -3,8 +3,7 @@ "compilerOptions": { "composite": true, "rootDir": "src", - "outDir": "dist", - "tsBuildInfoFile": "dist/build.tsbuildinfo" + "outDir": "dist" }, "include": ["src/**/*.ts"], "exclude": ["src/**/__tests__/**"] diff --git a/packages/@n8n/di/tsconfig.json b/packages/@n8n/di/tsconfig.json index 919d86d3724..6a4394d802a 100644 --- a/packages/@n8n/di/tsconfig.json +++ b/packages/@n8n/di/tsconfig.json @@ -2,7 +2,6 @@ "extends": "@n8n/typescript-config/tsconfig.common.json", "compilerOptions": { "types": ["node", "vitest/globals"], - "tsBuildInfoFile": "dist/typecheck.tsbuildinfo", "experimentalDecorators": true, "emitDecoratorMetadata": true }, diff --git a/packages/@n8n/engine/package.json b/packages/@n8n/engine/package.json index 1f2a47bf1f5..d2955b086e4 100644 --- a/packages/@n8n/engine/package.json +++ b/packages/@n8n/engine/package.json @@ -1,6 +1,6 @@ { "name": "@n8n/engine", - "version": "0.5.0", + "version": "0.7.0", "description": "n8n workflow execution engine (v2)", "scripts": { "clean": "rimraf dist .turbo compiled", @@ -36,5 +36,6 @@ "@types/supertest": "^6.0.3", "supertest": "^7.1.1", "vitest": "catalog:" - } + }, + "license": "LicenseRef-n8n-sustainable-use" } diff --git a/packages/@n8n/engine/tsconfig.build.json b/packages/@n8n/engine/tsconfig.build.json index ab3f5caec86..01a568888e9 100644 --- a/packages/@n8n/engine/tsconfig.build.json +++ b/packages/@n8n/engine/tsconfig.build.json @@ -3,8 +3,7 @@ "compilerOptions": { "composite": true, "rootDir": "src", - "outDir": "dist", - "tsBuildInfoFile": "dist/build.tsbuildinfo" + "outDir": "dist" }, "include": ["src/**/*.ts"], "exclude": ["src/**/__tests__/**", "**/*.test.ts"] diff --git a/packages/@n8n/engine/tsconfig.json b/packages/@n8n/engine/tsconfig.json index e54b3d13fa4..5c0b6966267 100644 --- a/packages/@n8n/engine/tsconfig.json +++ b/packages/@n8n/engine/tsconfig.json @@ -7,7 +7,6 @@ "target": "es2023", "lib": ["es2023"], "types": ["node"], - "tsBuildInfoFile": "dist/typecheck.tsbuildinfo", "experimentalDecorators": true, "emitDecoratorMetadata": true }, diff --git a/packages/@n8n/errors/package.json b/packages/@n8n/errors/package.json index 63179fff041..0654c45bef0 100644 --- a/packages/@n8n/errors/package.json +++ b/packages/@n8n/errors/package.json @@ -1,6 +1,6 @@ { "name": "@n8n/errors", - "version": "0.8.0", + "version": "0.10.0", "scripts": { "clean": "rimraf dist .turbo", "dev": "pnpm watch", @@ -27,5 +27,6 @@ }, "dependencies": { "callsites": "catalog:" - } + }, + "license": "LicenseRef-n8n-sustainable-use" } diff --git a/packages/@n8n/errors/tsconfig.build.json b/packages/@n8n/errors/tsconfig.build.json index ee0e3e20fda..e08cb937d03 100644 --- a/packages/@n8n/errors/tsconfig.build.json +++ b/packages/@n8n/errors/tsconfig.build.json @@ -3,8 +3,7 @@ "compilerOptions": { "composite": true, "rootDir": "src", - "outDir": "dist", - "tsBuildInfoFile": "dist/build.tsbuildinfo" + "outDir": "dist" }, "include": ["src/**/*.ts"], "exclude": ["src/**/__tests__/**"] diff --git a/packages/@n8n/errors/tsconfig.json b/packages/@n8n/errors/tsconfig.json index 5fe436c08a3..3a807ec1f86 100644 --- a/packages/@n8n/errors/tsconfig.json +++ b/packages/@n8n/errors/tsconfig.json @@ -2,7 +2,6 @@ "extends": "@n8n/typescript-config/tsconfig.common.json", "compilerOptions": { "types": ["node", "jest"], - "tsBuildInfoFile": "dist/typecheck.tsbuildinfo", "experimentalDecorators": true, "emitDecoratorMetadata": true }, diff --git a/packages/@n8n/eslint-config/package.json b/packages/@n8n/eslint-config/package.json index 323a01ccb71..0b3be880cca 100644 --- a/packages/@n8n/eslint-config/package.json +++ b/packages/@n8n/eslint-config/package.json @@ -55,5 +55,6 @@ }, "peerDependencies": { "eslint": "catalog:" - } + }, + "license": "LicenseRef-n8n-sustainable-use" } diff --git a/packages/@n8n/eslint-config/src/configs/base.ts b/packages/@n8n/eslint-config/src/configs/base.ts index 51c408fede7..c0234de803b 100644 --- a/packages/@n8n/eslint-config/src/configs/base.ts +++ b/packages/@n8n/eslint-config/src/configs/base.ts @@ -334,6 +334,27 @@ export const baseConfig = tseslint.config( 'import-x/no-named-as-default-member': 'off', 'import-x/no-unresolved': 'off', + 'import-x/no-extraneous-dependencies': [ + 'error', + { + devDependencies: [ + '**/test/**', + '**/__tests__/**', + '**/*.test.ts', + '**/*.test.utils.ts', + '**/*.spec.ts', + '**/integration-tests/**', + '**/test-utils/**', + '**/*.config.ts', + '**/*.config.js', + '**/scripts/*.ts', + '**/scripts/*.js', + ], + optionalDependencies: false, + peerDependencies: false, + }, + ], + // ****************************************************************** // overrides to base ruleset // ****************************************************************** diff --git a/packages/@n8n/eslint-plugin-community-nodes/README.md b/packages/@n8n/eslint-plugin-community-nodes/README.md index c3a0da178be..bf24090e269 100644 --- a/packages/@n8n/eslint-plugin-community-nodes/README.md +++ b/packages/@n8n/eslint-plugin-community-nodes/README.md @@ -51,15 +51,19 @@ export default [ | [cred-class-name-field-conventions](docs/rules/cred-class-name-field-conventions.md) | Credential `name` field must end with `Api` and start with a lowercase letter | ✅ ☑️ | | 🔧 | | | | [cred-class-name-suffix](docs/rules/cred-class-name-suffix.md) | Credential class names must be suffixed with `Api` | ✅ ☑️ | | 🔧 | | | | [cred-class-oauth2-naming](docs/rules/cred-class-oauth2-naming.md) | OAuth2 credentials must include `OAuth2` in the class name, `name`, and `displayName` | ✅ ☑️ | | 🔧 | | | +| [cred-filename-against-convention](docs/rules/cred-filename-against-convention.md) | Credential filename must match the credential class name | ✅ ☑️ | | | | | | [credential-documentation-url](docs/rules/credential-documentation-url.md) | Enforce valid credential documentationUrl format (URL or lowercase alphanumeric slug) | ✅ ☑️ | | 🔧 | | | | [credential-password-field](docs/rules/credential-password-field.md) | Ensure credential fields with sensitive names have typeOptions.password = true | ✅ ☑️ | | 🔧 | | | | [credential-test-required](docs/rules/credential-test-required.md) | Ensure credentials have a credential test | ✅ ☑️ | | | 💡 | | -| [icon-validation](docs/rules/icon-validation.md) | Validate node and credential icon files exist, are SVG format, and light/dark icons are different | ✅ ☑️ | | | 💡 | | +| [icon-prefer-themed-variants](docs/rules/icon-prefer-themed-variants.md) | Encourage node and credential icons to provide light/dark variants instead of a single icon file | | ✅ ☑️ | | | | +| [icon-validation](docs/rules/icon-validation.md) | Validate node and credential icon files exist, use the file: protocol, and that light/dark icons are different | ✅ ☑️ | | | 💡 | | | [missing-paired-item](docs/rules/missing-paired-item.md) | Require pairedItem on INodeExecutionData objects in execute() methods to preserve item linking. | ✅ ☑️ | | | | | | [n8n-object-validation](docs/rules/n8n-object-validation.md) | Validate the structure of the "n8n" object in community node package.json (required keys, types, and dist/ paths) | ✅ ☑️ | | | | | | [no-builder-hint-leakage](docs/rules/no-builder-hint-leakage.md) | Disallow wire-format expression syntax (={{...}}) and NodeConnectionType string literals in builderHint texts and AI-builder prompts. Use expr() and SDK-canonical references instead. | ✅ ☑️ | | | | | | [no-credential-reuse](docs/rules/no-credential-reuse.md) | Prevent credential re-use security issues by ensuring nodes only reference credentials from the same package | ✅ ☑️ | | | 💡 | | +| [no-dangerous-functions](docs/rules/no-dangerous-functions.md) | Disallow `eval`, the `Function` constructor, and `child_process` process-spawning functions (`exec`, `spawn`, etc.) in community nodes. | ✅ ☑️ | | | | | | [no-deprecated-workflow-functions](docs/rules/no-deprecated-workflow-functions.md) | Disallow usage of deprecated functions and types from n8n-workflow package | ✅ ☑️ | | | 💡 | | +| [no-emoji-in-options](docs/rules/no-emoji-in-options.md) | Disallow emoji characters in node option name and displayName values | ✅ ☑️ | | | | | | [no-forbidden-lifecycle-scripts](docs/rules/no-forbidden-lifecycle-scripts.md) | Ban lifecycle scripts (prepare, preinstall, postinstall, etc.) in community node packages | ✅ ☑️ | | | | | | [no-http-request-with-manual-auth](docs/rules/no-http-request-with-manual-auth.md) | Disallow this.helpers.httpRequest() in functions that call this.getCredentials(). Use this.helpers.httpRequestWithAuthentication() instead. | ✅ ☑️ | | | | | | [no-overrides-field](docs/rules/no-overrides-field.md) | Ban the "overrides" field in community node package.json | ✅ ☑️ | | | | | @@ -69,7 +73,9 @@ export default [ | [no-template-placeholders](docs/rules/no-template-placeholders.md) | Disallow unresolved template placeholders in package.json | ✅ ☑️ | | | | | | [node-class-description-icon-missing](docs/rules/node-class-description-icon-missing.md) | Node class description must have an `icon` property defined. Deprecated: use `require-node-description-fields` instead. | | | | 💡 | ❌ | | [node-connection-type-literal](docs/rules/node-connection-type-literal.md) | Disallow string literals in node description `inputs`/`outputs` — use `NodeConnectionTypes` enum instead | ✅ ☑️ | | 🔧 | | | +| [node-filename-against-convention](docs/rules/node-filename-against-convention.md) | Node filename must match the node `description.name` | ✅ ☑️ | | | | | | [node-operation-error-itemindex](docs/rules/node-operation-error-itemindex.md) | Require { itemIndex } in NodeOperationError / NodeApiError options inside item loops | ✅ ☑️ | | | | | +| [node-registration-complete](docs/rules/node-registration-complete.md) | Ensure every `.node.ts` file in the `nodes/` directory is registered in the "n8n.nodes" array of package.json | | ✅ ☑️ | | | | | [node-usable-as-tool](docs/rules/node-usable-as-tool.md) | Ensure node classes have usableAsTool property | ✅ ☑️ | | 🔧 | | | | [options-sorted-alphabetically](docs/rules/options-sorted-alphabetically.md) | Enforce alphabetical ordering of options arrays in n8n node properties | | ✅ ☑️ | | | | | [package-name-convention](docs/rules/package-name-convention.md) | Enforce correct package naming convention for n8n community nodes | ✅ ☑️ | | | 💡 | | @@ -77,7 +83,9 @@ export default [ | [require-continue-on-fail](docs/rules/require-continue-on-fail.md) | Require continueOnFail() handling in execute() methods of node classes | ✅ ☑️ | | | | | | [require-node-api-error](docs/rules/require-node-api-error.md) | Require NodeApiError or NodeOperationError for error wrapping in catch blocks. Raw errors lose HTTP context in the n8n UI. | ✅ ☑️ | | | | | | [require-node-description-fields](docs/rules/require-node-description-fields.md) | Node class description must define all required fields: icon, subtitle | ✅ ☑️ | | | | | +| [require-version](docs/rules/require-version.md) | Require a valid "version" field in community node package.json | ✅ ☑️ | | | | | | [resource-operation-pattern](docs/rules/resource-operation-pattern.md) | Enforce proper resource/operation pattern for better UX in n8n nodes | | ✅ ☑️ | | | | +| [valid-author](docs/rules/valid-author.md) | Require a non-empty author name and email in package.json | ✅ ☑️ | | | | | | [valid-credential-references](docs/rules/valid-credential-references.md) | Ensure credentials referenced in node descriptions exist as credential classes in the package | ✅ ☑️ | | | 💡 | | | [valid-description](docs/rules/valid-description.md) | Require a non-empty "description" field in community node package.json | ✅ ☑️ | | | | | | [valid-peer-dependencies](docs/rules/valid-peer-dependencies.md) | Require community node package.json peerDependencies to contain only "n8n-workflow": "*" (and optionally "ai-node-sdk") | ✅ ☑️ | | 🔧 | | | diff --git a/packages/@n8n/eslint-plugin-community-nodes/docs/rules/cred-filename-against-convention.md b/packages/@n8n/eslint-plugin-community-nodes/docs/rules/cred-filename-against-convention.md new file mode 100644 index 00000000000..160fbd0a1c3 --- /dev/null +++ b/packages/@n8n/eslint-plugin-community-nodes/docs/rules/cred-filename-against-convention.md @@ -0,0 +1,42 @@ +# Credential filename must match the credential class name (`@n8n/community-nodes/cred-filename-against-convention`) + +💼 This rule is enabled in the following configs: ✅ `recommended`, ☑️ `recommendedWithoutN8nCloudSupport`. + +<!-- end auto-generated rule header --> + +## Rule Details + +This rule enforces that the basename of a `*.credentials.ts` file (without the +`.credentials.ts` extension) matches the name of the credential class it +contains. The class name is the source of truth. + +Keeping filenames in sync with class names makes credentials predictable to +locate and matches the convention used throughout n8n's built-in credentials. + +## Examples + +### Incorrect + +```typescript +// File: GithubApi.credentials.ts +import type { ICredentialType, INodeProperties } from 'n8n-workflow'; + +export class GitlabApi implements ICredentialType { + name = 'gitlabApi'; + displayName = 'GitLab API'; + properties: INodeProperties[] = []; +} +``` + +### Correct + +```typescript +// File: GithubApi.credentials.ts +import type { ICredentialType, INodeProperties } from 'n8n-workflow'; + +export class GithubApi implements ICredentialType { + name = 'githubApi'; + displayName = 'GitHub API'; + properties: INodeProperties[] = []; +} +``` diff --git a/packages/@n8n/eslint-plugin-community-nodes/docs/rules/icon-prefer-themed-variants.md b/packages/@n8n/eslint-plugin-community-nodes/docs/rules/icon-prefer-themed-variants.md new file mode 100644 index 00000000000..486f71bd45b --- /dev/null +++ b/packages/@n8n/eslint-plugin-community-nodes/docs/rules/icon-prefer-themed-variants.md @@ -0,0 +1,71 @@ +# Encourage node and credential icons to provide light/dark variants instead of a single icon file (`@n8n/community-nodes/icon-prefer-themed-variants`) + +⚠️ This rule _warns_ in the following configs: ✅ `recommended`, ☑️ `recommendedWithoutN8nCloudSupport`. + +<!-- end auto-generated rule header --> + +## Rule Details + +n8n supports themed icons via the `{ light, dark }` object form, and the +marketplace/preview UI renders both variants for nodes that aren't installed yet. +A single icon file often renders poorly on one of the two themes (for example, a +dark glyph on a dark background). + +This rule warns when a node or credential defines its icon as a single file +string instead of the themed `{ light, dark }` object. It is a **warning**, not +an error: most existing nodes ship a single icon, so this nudges authors toward +themed variants without failing verification. + +The companion `icon-validation` rule still validates that the referenced files +exist, use the `file:` protocol, and that the light and dark variants point to +different files. + +## Examples + +### ❌ Incorrect + +```typescript +export class MyNode implements INodeType { + description: INodeTypeDescription = { + displayName: 'My Node', + name: 'myNode', + icon: 'file:icons/my-icon.svg', // Single file — renders poorly on one theme + // ... + }; +} +``` + +```typescript +export class MyApi implements ICredentialType { + name = 'myApi'; + displayName = 'My API'; + icon = 'file:icons/my-icon.svg'; // Single file +} +``` + +### ✅ Correct + +```typescript +export class MyNode implements INodeType { + description: INodeTypeDescription = { + displayName: 'My Node', + name: 'myNode', + icon: { + light: 'file:icons/my-icon.light.svg', + dark: 'file:icons/my-icon.dark.svg', + }, + // ... + }; +} +``` + +```typescript +export class MyApi implements ICredentialType { + name = 'myApi'; + displayName = 'My API'; + icon = { + light: 'file:icons/my-icon.light.svg', + dark: 'file:icons/my-icon.dark.svg', + }; +} +``` diff --git a/packages/@n8n/eslint-plugin-community-nodes/docs/rules/icon-validation.md b/packages/@n8n/eslint-plugin-community-nodes/docs/rules/icon-validation.md index 66be5ea225f..e10858b3212 100644 --- a/packages/@n8n/eslint-plugin-community-nodes/docs/rules/icon-validation.md +++ b/packages/@n8n/eslint-plugin-community-nodes/docs/rules/icon-validation.md @@ -1,4 +1,4 @@ -# Validate node and credential icon files exist, are SVG format, and light/dark icons are different (`@n8n/community-nodes/icon-validation`) +# Validate node and credential icon files exist, use the file: protocol, and that light/dark icons are different (`@n8n/community-nodes/icon-validation`) 💼 This rule is enabled in the following configs: ✅ `recommended`, ☑️ `recommendedWithoutN8nCloudSupport`. @@ -8,7 +8,9 @@ ## Rule Details -Validates that your node and credential icon files exist, are in SVG format, and use the correct `file:` protocol. Icons must be different files when providing light/dark theme variants. +Validates that your node and credential icon files exist and use the correct `file:` protocol. Icons must be different files when providing light/dark theme variants. + +Both SVG and PNG icons are accepted. SVG is recommended (it scales cleanly and supports theming), but PNG is allowed — see the `icon-prefer-themed-variants` rule for the related light/dark nudge. ## Examples @@ -19,7 +21,7 @@ export class MyNode implements INodeType { description: INodeTypeDescription = { displayName: 'My Node', name: 'myNode', - icon: 'icons/my-icon.png', // Missing 'file:' prefix, wrong format + icon: 'icons/my-icon.svg', // Missing 'file:' prefix // ... }; } diff --git a/packages/@n8n/eslint-plugin-community-nodes/docs/rules/no-dangerous-functions.md b/packages/@n8n/eslint-plugin-community-nodes/docs/rules/no-dangerous-functions.md new file mode 100644 index 00000000000..aedecb34e1d --- /dev/null +++ b/packages/@n8n/eslint-plugin-community-nodes/docs/rules/no-dangerous-functions.md @@ -0,0 +1,41 @@ +# Disallow `eval`, the `Function` constructor, and `child_process` process-spawning functions (`exec`, `spawn`, etc.) in community nodes (`@n8n/community-nodes/no-dangerous-functions`) + +💼 This rule is enabled in the following configs: ✅ `recommended`, ☑️ `recommendedWithoutN8nCloudSupport`. + +<!-- end auto-generated rule header --> + +## Rule Details + +Community nodes run inside the n8n runtime, often on shared infrastructure. Functions that execute arbitrary code from strings or spawn operating-system processes are a primary vector for remote code execution and command injection, and have no legitimate use in a community node. This rule bans them outright: + +- **`eval(...)`** — executes arbitrary code from a string. +- **`Function(...)` / `new Function(...)`** — the `Function` constructor is an `eval` equivalent that builds a callable from a string body. +- **`child_process` process spawners** — `exec`, `execSync`, `execFile`, `execFileSync`, `spawn`, `spawnSync`, and `fork`. + +The `child_process` functions are detected only when they originate from the `child_process` / `node:child_process` module (via `import` or `require`), so unrelated methods such as `RegExp.prototype.exec` are not affected. + +This complements [`no-restricted-imports`](no-restricted-imports.md) (which blocks the `child_process` module entirely on n8n Cloud) and [`no-restricted-globals`](no-restricted-globals.md), providing a clear, specific error and defense-in-depth that also applies when the import restrictions are relaxed. + +## Examples + +### ❌ Incorrect + +```typescript +import { exec } from 'child_process'; + +eval(userProvidedCode); + +const compiled = new Function('return ' + expression); + +exec(`rm -rf ${userInput}`); +``` + +### ✅ Correct + +```typescript +// Parse data instead of evaluating it. +const value = JSON.parse(rawJson); + +// Use n8n helpers and well-scoped library APIs instead of spawning processes. +const response = await this.helpers.httpRequest({ url }); +``` diff --git a/packages/@n8n/eslint-plugin-community-nodes/docs/rules/no-emoji-in-options.md b/packages/@n8n/eslint-plugin-community-nodes/docs/rules/no-emoji-in-options.md new file mode 100644 index 00000000000..842504d6a50 --- /dev/null +++ b/packages/@n8n/eslint-plugin-community-nodes/docs/rules/no-emoji-in-options.md @@ -0,0 +1,60 @@ +# Disallow emoji characters in node option name and displayName values (`@n8n/community-nodes/no-emoji-in-options`) + +💼 This rule is enabled in the following configs: ✅ `recommended`, ☑️ `recommendedWithoutN8nCloudSupport`. + +<!-- end auto-generated rule header --> + +## Rule Details + +User-facing labels in a node — the node's `displayName`, each property's +`displayName`, and the `name` of entries in `options` arrays — are rendered +directly in the n8n editor. Emoji in these labels render inconsistently across +platforms, break alphabetical sorting and search, and clash with the editor's +visual language. This rule flags any emoji character (pictographs such as 🚀 or +✅, and regional-indicator flag emoji such as 🇺🇸) found in a `name` or +`displayName` string within a node's `description`. + +Accented and non-Latin characters (e.g. `Café`, `日本語`) are allowed — only +emoji are reported. + +## Examples + +### Incorrect + +```typescript +export class MyNode implements INodeType { + description: INodeTypeDescription = { + displayName: '🚀 My Node', + name: 'myNode', + properties: [ + { + displayName: 'Operation', + name: 'operation', + type: 'options', + options: [{ name: '✅ Create', value: 'create' }], + default: 'create', + }, + ], + }; +} +``` + +### Correct + +```typescript +export class MyNode implements INodeType { + description: INodeTypeDescription = { + displayName: 'My Node', + name: 'myNode', + properties: [ + { + displayName: 'Operation', + name: 'operation', + type: 'options', + options: [{ name: 'Create', value: 'create' }], + default: 'create', + }, + ], + }; +} +``` diff --git a/packages/@n8n/eslint-plugin-community-nodes/docs/rules/node-filename-against-convention.md b/packages/@n8n/eslint-plugin-community-nodes/docs/rules/node-filename-against-convention.md new file mode 100644 index 00000000000..31469b594a4 --- /dev/null +++ b/packages/@n8n/eslint-plugin-community-nodes/docs/rules/node-filename-against-convention.md @@ -0,0 +1,50 @@ +# Node filename must match the node `description.name` (`@n8n/community-nodes/node-filename-against-convention`) + +💼 This rule is enabled in the following configs: ✅ `recommended`, ☑️ `recommendedWithoutN8nCloudSupport`. + +<!-- end auto-generated rule header --> + +## Rule Details + +Every `*.node.ts` file must be named after its node's `description.name`, with the +first character upper-cased. The source of truth is `description.name` — **not** +the class name. Keeping the filename in sync with the registered node name makes +nodes predictable to locate and matches the convention n8n tooling expects. + +A trailing version suffix (`V2`, `V3`, …) is allowed, so versioned implementations +such as `GithubV2.node.ts` are accepted for a node whose `description.name` is +`github`. + +The comparison is case-sensitive: a node named `github` must live in +`Github.node.ts`, not `github.node.ts` or `GitHub.node.ts`. + +This rule is not auto-fixable because ESLint cannot rename files. Rename the file +to the reported name. + +## Examples + +### ❌ Incorrect + +```typescript +// File: Gitlab.node.ts +export class Github implements INodeType { + description: INodeTypeDescription = { + displayName: 'GitHub', + name: 'github', // expected file to be named "Github.node.ts" + // ... + }; +} +``` + +### ✅ Correct + +```typescript +// File: Github.node.ts (or GithubV2.node.ts) +export class Github implements INodeType { + description: INodeTypeDescription = { + displayName: 'GitHub', + name: 'github', + // ... + }; +} +``` diff --git a/packages/@n8n/eslint-plugin-community-nodes/docs/rules/node-registration-complete.md b/packages/@n8n/eslint-plugin-community-nodes/docs/rules/node-registration-complete.md new file mode 100644 index 00000000000..818999526ef --- /dev/null +++ b/packages/@n8n/eslint-plugin-community-nodes/docs/rules/node-registration-complete.md @@ -0,0 +1,46 @@ +# Ensure every `.node.ts` file in the `nodes/` directory is registered in the "n8n.nodes" array of package.json (`@n8n/community-nodes/node-registration-complete`) + +⚠️ This rule _warns_ in the following configs: ✅ `recommended`, ☑️ `recommendedWithoutN8nCloudSupport`. + +<!-- end auto-generated rule header --> + +## Rule Details + +n8n discovers the nodes in a community package from the `n8n.nodes` array in `package.json`. Any `.node.ts` file that exists in the package's `nodes/` directory but is missing from that array will be silently excluded from the published package — the node simply won't show up in n8n. + +This rule cross-references the `.node.ts` files found in the `nodes/` directory against the entries in `n8n.nodes` and flags every node file that is not registered, so missing registrations are caught at lint time rather than after publishing. + +## Examples + +Given a package with these files on disk: + +``` +nodes/Foo/Foo.node.ts +nodes/Bar/Bar.node.ts +``` + +### ❌ Incorrect + +`Bar.node.ts` exists but is not registered: + +```json +{ + "name": "n8n-nodes-my-service", + "n8n": { + "nodes": ["dist/nodes/Foo/Foo.node.js"] + } +} +``` + +### ✅ Correct + +Every node file is registered: + +```json +{ + "name": "n8n-nodes-my-service", + "n8n": { + "nodes": ["dist/nodes/Foo/Foo.node.js", "dist/nodes/Bar/Bar.node.js"] + } +} +``` diff --git a/packages/@n8n/eslint-plugin-community-nodes/docs/rules/require-version.md b/packages/@n8n/eslint-plugin-community-nodes/docs/rules/require-version.md new file mode 100644 index 00000000000..40a7e1effb5 --- /dev/null +++ b/packages/@n8n/eslint-plugin-community-nodes/docs/rules/require-version.md @@ -0,0 +1,51 @@ +# Require a valid "version" field in community node package.json (`@n8n/community-nodes/require-version`) + +💼 This rule is enabled in the following configs: ✅ `recommended`, ☑️ `recommendedWithoutN8nCloudSupport`. + +<!-- end auto-generated rule header --> + +## Rule Details + +Every community node package must declare a `version` field in its `package.json`. npm refuses to publish a package without a valid [semantic version](https://semver.org/), and n8n relies on the version to track and update installed community packages. + +This rule reports a missing `version` key as well as a value that is not a valid semantic version string (for example `"1.0"`, `"v1.0.0"`, a range like `"^1.0.0"`, an empty string, or a non-string value). + +## Examples + +### ❌ Incorrect + +```json +{ + "name": "n8n-nodes-acme" +} +``` + +```json +{ + "name": "n8n-nodes-acme", + "version": "1.0" +} +``` + +```json +{ + "name": "n8n-nodes-acme", + "version": "v1.0.0" +} +``` + +### ✅ Correct + +```json +{ + "name": "n8n-nodes-acme", + "version": "1.0.0" +} +``` + +```json +{ + "name": "n8n-nodes-acme", + "version": "0.1.0-beta.1" +} +``` diff --git a/packages/@n8n/eslint-plugin-community-nodes/docs/rules/valid-author.md b/packages/@n8n/eslint-plugin-community-nodes/docs/rules/valid-author.md new file mode 100644 index 00000000000..04eea06c471 --- /dev/null +++ b/packages/@n8n/eslint-plugin-community-nodes/docs/rules/valid-author.md @@ -0,0 +1,60 @@ +# Require a non-empty author name and email in package.json (`@n8n/community-nodes/valid-author`) + +💼 This rule is enabled in the following configs: ✅ `recommended`, ☑️ `recommendedWithoutN8nCloudSupport`. + +<!-- end auto-generated rule header --> + +## Rule Details + +A published community node package should identify its author. This rule +requires the `package.json` to declare an `author` with at minimum a non-empty +`name` and `email`, so users and n8n can reach the maintainer. + +Both npm `author` forms are supported: + +- the object form `{ "name": "...", "email": "..." }` +- the shorthand string form `"Name <email> (url)"` + +Whitespace-only values count as empty. The literal `<...>` placeholder pattern +left over from the node starter template is handled separately by the +[`no-template-placeholders`](./no-template-placeholders.md) rule. + +## Examples + +### ❌ Incorrect + +```json +{ + "name": "n8n-nodes-my-service" +} +``` + +```json +{ + "name": "n8n-nodes-my-service", + "author": { "name": "Jane Doe" } +} +``` + +```json +{ + "name": "n8n-nodes-my-service", + "author": "Jane Doe" +} +``` + +### ✅ Correct + +```json +{ + "name": "n8n-nodes-my-service", + "author": { "name": "Jane Doe", "email": "jane@example.com" } +} +``` + +```json +{ + "name": "n8n-nodes-my-service", + "author": "Jane Doe <jane@example.com> (https://example.com)" +} +``` diff --git a/packages/@n8n/eslint-plugin-community-nodes/package.json b/packages/@n8n/eslint-plugin-community-nodes/package.json index d07c88e9c9c..583141af27f 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.19.0", + "version": "0.21.0", "main": "./dist/plugin.js", "types": "./dist/plugin.d.ts", "exports": { @@ -59,5 +59,6 @@ "☑️" ] ] - } + }, + "license": "LicenseRef-n8n-sustainable-use" } diff --git a/packages/@n8n/eslint-plugin-community-nodes/src/plugin.ts b/packages/@n8n/eslint-plugin-community-nodes/src/plugin.ts index 88dde6751cc..2df17b50130 100644 --- a/packages/@n8n/eslint-plugin-community-nodes/src/plugin.ts +++ b/packages/@n8n/eslint-plugin-community-nodes/src/plugin.ts @@ -26,16 +26,19 @@ const configs = { '@n8n/community-nodes/credential-password-field': 'error', '@n8n/community-nodes/n8n-object-validation': 'error', '@n8n/community-nodes/no-deprecated-workflow-functions': 'error', + '@n8n/community-nodes/no-emoji-in-options': 'error', '@n8n/community-nodes/node-usable-as-tool': 'error', '@n8n/community-nodes/package-name-convention': 'error', '@n8n/community-nodes/credential-test-required': 'error', '@n8n/community-nodes/no-credential-reuse': 'error', + '@n8n/community-nodes/no-dangerous-functions': 'error', '@n8n/community-nodes/no-forbidden-lifecycle-scripts': 'error', '@n8n/community-nodes/no-http-request-with-manual-auth': 'error', '@n8n/community-nodes/no-overrides-field': 'error', '@n8n/community-nodes/no-runtime-dependencies': 'error', '@n8n/community-nodes/no-template-placeholders': 'error', '@n8n/community-nodes/icon-validation': 'error', + '@n8n/community-nodes/icon-prefer-themed-variants': 'warn', '@n8n/community-nodes/options-sorted-alphabetically': 'warn', '@n8n/community-nodes/resource-operation-pattern': 'warn', '@n8n/community-nodes/credential-documentation-url': 'error', @@ -43,14 +46,19 @@ const configs = { '@n8n/community-nodes/cred-class-name-field-conventions': 'error', '@n8n/community-nodes/cred-class-name-suffix': 'error', '@n8n/community-nodes/cred-class-oauth2-naming': 'error', + '@n8n/community-nodes/cred-filename-against-convention': 'error', '@n8n/community-nodes/node-connection-type-literal': 'error', + '@n8n/community-nodes/node-filename-against-convention': 'error', '@n8n/community-nodes/missing-paired-item': 'error', '@n8n/community-nodes/no-builder-hint-leakage': 'error', '@n8n/community-nodes/node-operation-error-itemindex': 'error', + '@n8n/community-nodes/node-registration-complete': 'warn', '@n8n/community-nodes/require-community-node-keyword': 'warn', '@n8n/community-nodes/require-continue-on-fail': 'error', '@n8n/community-nodes/require-node-api-error': 'error', '@n8n/community-nodes/require-node-description-fields': 'error', + '@n8n/community-nodes/require-version': 'error', + '@n8n/community-nodes/valid-author': 'error', '@n8n/community-nodes/valid-credential-references': 'error', '@n8n/community-nodes/valid-description': 'error', '@n8n/community-nodes/valid-peer-dependencies': 'error', @@ -67,16 +75,19 @@ const configs = { '@n8n/community-nodes/credential-password-field': 'error', '@n8n/community-nodes/n8n-object-validation': 'error', '@n8n/community-nodes/no-deprecated-workflow-functions': 'error', + '@n8n/community-nodes/no-emoji-in-options': 'error', '@n8n/community-nodes/node-usable-as-tool': 'error', '@n8n/community-nodes/package-name-convention': 'error', '@n8n/community-nodes/credential-test-required': 'error', '@n8n/community-nodes/no-credential-reuse': 'error', + '@n8n/community-nodes/no-dangerous-functions': 'error', '@n8n/community-nodes/no-forbidden-lifecycle-scripts': 'error', '@n8n/community-nodes/no-http-request-with-manual-auth': 'error', '@n8n/community-nodes/no-overrides-field': 'error', '@n8n/community-nodes/no-runtime-dependencies': 'error', '@n8n/community-nodes/no-template-placeholders': 'error', '@n8n/community-nodes/icon-validation': 'error', + '@n8n/community-nodes/icon-prefer-themed-variants': 'warn', '@n8n/community-nodes/options-sorted-alphabetically': 'warn', '@n8n/community-nodes/credential-documentation-url': 'error', '@n8n/community-nodes/resource-operation-pattern': 'warn', @@ -84,14 +95,19 @@ const configs = { '@n8n/community-nodes/cred-class-name-field-conventions': 'error', '@n8n/community-nodes/cred-class-name-suffix': 'error', '@n8n/community-nodes/cred-class-oauth2-naming': 'error', + '@n8n/community-nodes/cred-filename-against-convention': 'error', '@n8n/community-nodes/node-connection-type-literal': 'error', + '@n8n/community-nodes/node-filename-against-convention': 'error', '@n8n/community-nodes/missing-paired-item': 'error', '@n8n/community-nodes/no-builder-hint-leakage': 'error', '@n8n/community-nodes/node-operation-error-itemindex': 'error', + '@n8n/community-nodes/node-registration-complete': 'warn', '@n8n/community-nodes/require-community-node-keyword': 'warn', '@n8n/community-nodes/require-continue-on-fail': 'error', '@n8n/community-nodes/require-node-api-error': 'error', '@n8n/community-nodes/require-node-description-fields': 'error', + '@n8n/community-nodes/require-version': 'error', + '@n8n/community-nodes/valid-author': 'error', '@n8n/community-nodes/valid-credential-references': 'error', '@n8n/community-nodes/valid-description': 'error', '@n8n/community-nodes/valid-peer-dependencies': 'error', diff --git a/packages/@n8n/eslint-plugin-community-nodes/src/rules/cred-filename-against-convention.test.ts b/packages/@n8n/eslint-plugin-community-nodes/src/rules/cred-filename-against-convention.test.ts new file mode 100644 index 00000000000..8d71fd65cff --- /dev/null +++ b/packages/@n8n/eslint-plugin-community-nodes/src/rules/cred-filename-against-convention.test.ts @@ -0,0 +1,72 @@ +import { RuleTester } from '@typescript-eslint/rule-tester'; + +import { CredFilenameAgainstConventionRule } from './cred-filename-against-convention.js'; + +const ruleTester = new RuleTester(); + +function createCredentialCode(className: string): string { + return ` +import type { ICredentialType, INodeProperties } from 'n8n-workflow'; + +export class ${className} implements ICredentialType { + name = '${className.charAt(0).toLowerCase() + className.slice(1)}'; + displayName = '${className}'; + properties: INodeProperties[] = []; +}`; +} + +function createRegularClass(): string { + return ` +export class SomeHelper { + name = 'githubApi'; +}`; +} + +ruleTester.run('cred-filename-against-convention', CredFilenameAgainstConventionRule, { + valid: [ + { + name: 'filename matches credential class name', + filename: '/tmp/GithubApi.credentials.ts', + code: createCredentialCode('GithubApi'), + }, + { + name: 'multi-word class name matches filename', + filename: '/tmp/GoogleSheetsOAuth2Api.credentials.ts', + code: createCredentialCode('GoogleSheetsOAuth2Api'), + }, + { + name: 'class not implementing ICredentialType is ignored', + filename: '/tmp/Github.credentials.ts', + code: createRegularClass(), + }, + { + name: 'non-.credentials.ts file is ignored', + filename: '/tmp/GithubApi.ts', + code: createCredentialCode('Mismatch'), + }, + ], + invalid: [ + { + name: 'filename does not match class name', + filename: '/tmp/GithubApi.credentials.ts', + code: createCredentialCode('GitlabApi'), + errors: [ + { + messageId: 'renameFile', + data: { className: 'GitlabApi', expected: 'GitlabApi.credentials.ts' }, + }, + ], + }, + { + name: 'filename has wrong casing', + filename: '/tmp/githubApi.credentials.ts', + code: createCredentialCode('GithubApi'), + errors: [ + { + messageId: 'renameFile', + data: { className: 'GithubApi', expected: 'GithubApi.credentials.ts' }, + }, + ], + }, + ], +}); diff --git a/packages/@n8n/eslint-plugin-community-nodes/src/rules/cred-filename-against-convention.ts b/packages/@n8n/eslint-plugin-community-nodes/src/rules/cred-filename-against-convention.ts new file mode 100644 index 00000000000..751ebb93a20 --- /dev/null +++ b/packages/@n8n/eslint-plugin-community-nodes/src/rules/cred-filename-against-convention.ts @@ -0,0 +1,48 @@ +import * as path from 'node:path'; + +import { isCredentialTypeClass, isFileType, createRule } from '../utils/index.js'; + +export const CredFilenameAgainstConventionRule = createRule({ + name: 'cred-filename-against-convention', + meta: { + type: 'problem', + docs: { + description: 'Credential filename must match the credential class name', + }, + messages: { + renameFile: + 'Credential filename must match the class name "{{className}}". Rename file to "{{expected}}".', + }, + schema: [], + }, + defaultOptions: [], + create(context) { + if (!isFileType(context.filename, '.credentials.ts')) { + return {}; + } + + return { + ClassDeclaration(node) { + if (!isCredentialTypeClass(node)) { + return; + } + + const classNameNode = node.id; + if (!classNameNode) { + return; + } + + const className = classNameNode.name; + const actualBaseName = path.basename(context.filename, '.credentials.ts'); + + if (actualBaseName !== className) { + context.report({ + node: classNameNode, + messageId: 'renameFile', + data: { className, expected: `${className}.credentials.ts` }, + }); + } + }, + }; + }, +}); diff --git a/packages/@n8n/eslint-plugin-community-nodes/src/rules/icon-prefer-themed-variants.test.ts b/packages/@n8n/eslint-plugin-community-nodes/src/rules/icon-prefer-themed-variants.test.ts new file mode 100644 index 00000000000..69c1420e43f --- /dev/null +++ b/packages/@n8n/eslint-plugin-community-nodes/src/rules/icon-prefer-themed-variants.test.ts @@ -0,0 +1,128 @@ +import { RuleTester } from '@typescript-eslint/rule-tester'; + +import { IconPreferThemedVariantsRule } from './icon-prefer-themed-variants.js'; + +const ruleTester = new RuleTester(); + +const nodeFilePath = '/tmp/TestNode.node.ts'; +const credentialFilePath = '/tmp/TestCredential.credentials.ts'; + +function createNodeCode(icon?: string | { light: string; dark: string }): string { + let iconProperty = ''; + if (icon) { + if (typeof icon === 'string') { + iconProperty = `icon: '${icon}',`; + } else { + iconProperty = `icon: { + light: '${icon.light}', + dark: '${icon.dark}' + },`; + } + } + + return ` +import type { INodeType, INodeTypeDescription } from 'n8n-workflow'; + +export class TestNode implements INodeType { + description: INodeTypeDescription = { + displayName: 'Test Node', + name: 'testNode', + ${iconProperty} + group: ['input'], + version: 1, + description: 'A test node', + defaults: { + name: 'Test Node', + }, + inputs: ['main'], + outputs: ['main'], + properties: [], + }; +}`; +} + +function createCredentialCode(icon?: string | { light: string; dark: string }): string { + let iconProperty = ''; + if (icon) { + if (typeof icon === 'string') { + iconProperty = `icon = '${icon}';`; + } else { + iconProperty = `icon = { + light: '${icon.light}', + dark: '${icon.dark}' + };`; + } + } + + return ` +import type { ICredentialType, INodeProperties } from 'n8n-workflow'; + +export class TestCredential implements ICredentialType { + name = 'testApi'; + displayName = 'Test API'; + ${iconProperty} + properties: INodeProperties[] = []; +}`; +} + +function createNonNodeClass(icon: string): string { + return ` +export class NotANode { + icon = '${icon}'; +}`; +} + +ruleTester.run('icon-prefer-themed-variants', IconPreferThemedVariantsRule, { + valid: [ + { + name: 'non-node class ignored', + filename: nodeFilePath, + code: createNonNodeClass('file:icon.svg'), + }, + { + name: 'non-node file ignored', + filename: '/tmp/regular-file.ts', + code: createNodeCode('file:icon.svg'), + }, + { + name: 'node with no icon property ignored', + filename: nodeFilePath, + code: createNodeCode(), + }, + { + name: 'node with themed light/dark icons', + filename: nodeFilePath, + code: createNodeCode({ + light: 'file:icons/icon.light.svg', + dark: 'file:icons/icon.dark.svg', + }), + }, + { + name: 'credential with no icon property ignored', + filename: credentialFilePath, + code: createCredentialCode(), + }, + { + name: 'credential with themed light/dark icons', + filename: credentialFilePath, + code: createCredentialCode({ + light: 'file:icons/icon.light.svg', + dark: 'file:icons/icon.dark.svg', + }), + }, + ], + invalid: [ + { + name: 'node with single string icon', + filename: nodeFilePath, + code: createNodeCode('file:icons/icon.svg'), + errors: [{ messageId: 'missingThemedVariants' }], + }, + { + name: 'credential with single string icon', + filename: credentialFilePath, + code: createCredentialCode('file:icons/icon.svg'), + errors: [{ messageId: 'missingThemedVariants' }], + }, + ], +}); diff --git a/packages/@n8n/eslint-plugin-community-nodes/src/rules/icon-prefer-themed-variants.ts b/packages/@n8n/eslint-plugin-community-nodes/src/rules/icon-prefer-themed-variants.ts new file mode 100644 index 00000000000..8dbadbfd2a2 --- /dev/null +++ b/packages/@n8n/eslint-plugin-community-nodes/src/rules/icon-prefer-themed-variants.ts @@ -0,0 +1,70 @@ +import { TSESTree } from '@typescript-eslint/utils'; + +import { + isNodeTypeClass, + isCredentialTypeClass, + findClassProperty, + findObjectProperty, + isFileType, + createRule, +} from '../utils/index.js'; + +const messages = { + missingThemedVariants: + 'Icon is defined as a single file. Provide both light and dark variants using the `{ light, dark }` form so the icon renders well on both themes.', +} as const; + +export const IconPreferThemedVariantsRule = createRule({ + name: 'icon-prefer-themed-variants', + meta: { + type: 'suggestion', + docs: { + description: + 'Encourage node and credential icons to provide light/dark variants instead of a single icon file', + }, + messages, + schema: [], + }, + defaultOptions: [], + create(context) { + if ( + !isFileType(context.filename, '.node.ts') && + !isFileType(context.filename, '.credentials.ts') + ) { + return {}; + } + + const checkIconValue = (iconValue: TSESTree.Node) => { + if ( + iconValue.type === TSESTree.AST_NODE_TYPES.Literal && + typeof iconValue.value === 'string' + ) { + context.report({ + node: iconValue, + messageId: 'missingThemedVariants', + }); + } + }; + + return { + ClassDeclaration(node) { + if (isNodeTypeClass(node)) { + const descriptionProperty = findClassProperty(node, 'description'); + if (descriptionProperty?.value?.type !== TSESTree.AST_NODE_TYPES.ObjectExpression) { + return; + } + + const iconProperty = findObjectProperty(descriptionProperty.value, 'icon'); + if (iconProperty) { + checkIconValue(iconProperty.value); + } + } else if (isCredentialTypeClass(node)) { + const iconProperty = findClassProperty(node, 'icon'); + if (iconProperty?.value) { + checkIconValue(iconProperty.value); + } + } + }, + }; + }, +}); diff --git a/packages/@n8n/eslint-plugin-community-nodes/src/rules/icon-validation.test.ts b/packages/@n8n/eslint-plugin-community-nodes/src/rules/icon-validation.test.ts index f2f23b33281..dcf228342ce 100644 --- a/packages/@n8n/eslint-plugin-community-nodes/src/rules/icon-validation.test.ts +++ b/packages/@n8n/eslint-plugin-community-nodes/src/rules/icon-validation.test.ts @@ -146,6 +146,11 @@ ruleTester.run('icon-validation', IconValidationRule, { filename: nodeFilePath, code: createNodeCode('file:icons/TestNode.svg', true), }, + { + name: 'node with valid PNG string icon in description', + filename: nodeFilePath, + code: createNodeCode('file:icons/NotSvg.png', true), + }, { name: 'node with valid light/dark icons in description', filename: nodeFilePath, @@ -162,6 +167,11 @@ ruleTester.run('icon-validation', IconValidationRule, { filename: credentialFilePath, code: createCredentialCode('file:icons/TestNode.svg'), }, + { + name: 'credential with valid PNG string icon', + filename: credentialFilePath, + code: createCredentialCode('file:icons/NotSvg.png'), + }, { name: 'credential with valid light/dark icons', filename: credentialFilePath, diff --git a/packages/@n8n/eslint-plugin-community-nodes/src/rules/icon-validation.ts b/packages/@n8n/eslint-plugin-community-nodes/src/rules/icon-validation.ts index 480ed3b0bfa..675f65cc4bd 100644 --- a/packages/@n8n/eslint-plugin-community-nodes/src/rules/icon-validation.ts +++ b/packages/@n8n/eslint-plugin-community-nodes/src/rules/icon-validation.ts @@ -9,20 +9,18 @@ import { findObjectProperty, getStringLiteralValue, validateIconPath, - findSimilarSvgFiles, + findSimilarIconFiles, isFileType, createRule, } from '../utils/index.js'; const messages = { iconFileNotFound: 'Icon file "{{ iconPath }}" does not exist', - iconNotSvg: 'Icon file "{{ iconPath }}" must be an SVG file (end with .svg)', lightDarkSame: 'Light and dark icons cannot be the same file. Both point to "{{ iconPath }}"', invalidIconPath: 'Icon path "{{ iconPath }}" must use file: protocol and be a string', missingIcon: 'Node/Credential class must have an icon property defined', addPlaceholder: 'Add icon property with placeholder', addFileProtocol: "Add 'file:' protocol to icon path", - changeExtension: "Change icon extension to '.svg'", similarIcon: "Use existing icon '{{ suggestedName }}'", } as const; @@ -32,7 +30,7 @@ export const IconValidationRule = createRule({ type: 'problem', docs: { description: - 'Validate node and credential icon files exist, are SVG format, and light/dark icons are different', + 'Validate node and credential icon files exist, use the file: protocol, and that light/dark icons are different', }, messages, schema: [], @@ -80,34 +78,12 @@ export const IconValidationRule = createRule({ return false; } - if (!validation.isSvg) { - const relativePath = iconPath.replace(/^file:/, ''); - const suggestions: ReportSuggestionArray<keyof typeof messages> = []; - - const pathWithoutExt = relativePath.replace(/\.[^/.]+$/, ''); - const svgPath = `${pathWithoutExt}.svg`; - suggestions.push({ - messageId: 'changeExtension', - fix(fixer) { - return fixer.replaceText(node, `"file:${svgPath}"`); - }, - }); - - context.report({ - node, - messageId: 'iconNotSvg', - data: { iconPath: relativePath }, - suggest: suggestions, - }); - return false; - } - if (!validation.exists) { const relativePath = iconPath.replace(/^file:/, ''); const suggestions: ReportSuggestionArray<keyof typeof messages> = []; - // Find similar SVG files in the same directory - const similarFiles = findSimilarSvgFiles(relativePath, currentDir); + // Find similar icon files in the same directory + const similarFiles = findSimilarIconFiles(relativePath, currentDir); for (const similarFile of similarFiles) { suggestions.push({ messageId: 'similarIcon', diff --git a/packages/@n8n/eslint-plugin-community-nodes/src/rules/index.ts b/packages/@n8n/eslint-plugin-community-nodes/src/rules/index.ts index ea9069e64a7..cf031eb1419 100644 --- a/packages/@n8n/eslint-plugin-community-nodes/src/rules/index.ts +++ b/packages/@n8n/eslint-plugin-community-nodes/src/rules/index.ts @@ -5,15 +5,19 @@ import { CredClassFieldIconMissingRule } from './cred-class-field-icon-missing.j import { CredClassNameFieldConventionsRule } from './cred-class-name-field-conventions.js'; import { CredClassNameSuffixRule } from './cred-class-name-suffix.js'; import { CredClassOAuth2NamingRule } from './cred-class-oauth2-naming.js'; +import { CredFilenameAgainstConventionRule } from './cred-filename-against-convention.js'; import { CredentialDocumentationUrlRule } from './credential-documentation-url.js'; import { CredentialPasswordFieldRule } from './credential-password-field.js'; import { CredentialTestRequiredRule } from './credential-test-required.js'; +import { IconPreferThemedVariantsRule } from './icon-prefer-themed-variants.js'; import { IconValidationRule } from './icon-validation.js'; import { MissingPairedItemRule } from './missing-paired-item.js'; import { N8nObjectValidationRule } from './n8n-object-validation.js'; import { NoBuilderHintLeakageRule } from './no-builder-hint-leakage.js'; import { NoCredentialReuseRule } from './no-credential-reuse.js'; +import { NoDangerousFunctionsRule } from './no-dangerous-functions.js'; import { NoDeprecatedWorkflowFunctionsRule } from './no-deprecated-workflow-functions.js'; +import { NoEmojiInOptionsRule } from './no-emoji-in-options.js'; import { NoForbiddenLifecycleScriptsRule } from './no-forbidden-lifecycle-scripts.js'; import { NoHttpRequestWithManualAuthRule } from './no-http-request-with-manual-auth.js'; import { NoOverridesFieldRule } from './no-overrides-field.js'; @@ -23,7 +27,9 @@ import { NoRuntimeDependenciesRule } from './no-runtime-dependencies.js'; import { NoTemplatePlaceholdersRule } from './no-template-placeholders.js'; import { NodeClassDescriptionIconMissingRule } from './node-class-description-icon-missing.js'; import { NodeConnectionTypeLiteralRule } from './node-connection-type-literal.js'; +import { NodeFilenameAgainstConventionRule } from './node-filename-against-convention.js'; import { NodeOperationErrorItemIndexRule } from './node-operation-error-itemindex.js'; +import { NodeRegistrationCompleteRule } from './node-registration-complete.js'; import { NodeUsableAsToolRule } from './node-usable-as-tool.js'; import { OptionsSortedAlphabeticallyRule } from './options-sorted-alphabetically.js'; import { PackageNameConventionRule } from './package-name-convention.js'; @@ -31,7 +37,9 @@ import { RequireCommunityNodeKeywordRule } from './require-community-node-keywor import { RequireContinueOnFailRule } from './require-continue-on-fail.js'; import { RequireNodeApiErrorRule } from './require-node-api-error.js'; import { RequireNodeDescriptionFieldsRule } from './require-node-description-fields.js'; +import { RequireVersionRule } from './require-version.js'; import { ResourceOperationPatternRule } from './resource-operation-pattern.js'; +import { ValidAuthorRule } from './valid-author.js'; import { ValidCredentialReferencesRule } from './valid-credential-references.js'; import { ValidDescriptionRule } from './valid-description.js'; import { ValidPeerDependenciesRule } from './valid-peer-dependencies.js'; @@ -43,17 +51,20 @@ export const rules = { 'no-restricted-imports': NoRestrictedImportsRule, 'credential-password-field': CredentialPasswordFieldRule, 'no-deprecated-workflow-functions': NoDeprecatedWorkflowFunctionsRule, + 'no-emoji-in-options': NoEmojiInOptionsRule, 'node-usable-as-tool': NodeUsableAsToolRule, 'options-sorted-alphabetically': OptionsSortedAlphabeticallyRule, 'package-name-convention': PackageNameConventionRule, 'credential-test-required': CredentialTestRequiredRule, 'no-credential-reuse': NoCredentialReuseRule, + 'no-dangerous-functions': NoDangerousFunctionsRule, 'no-forbidden-lifecycle-scripts': NoForbiddenLifecycleScriptsRule, 'no-http-request-with-manual-auth': NoHttpRequestWithManualAuthRule, 'no-overrides-field': NoOverridesFieldRule, 'no-runtime-dependencies': NoRuntimeDependenciesRule, 'no-template-placeholders': NoTemplatePlaceholdersRule, 'icon-validation': IconValidationRule, + 'icon-prefer-themed-variants': IconPreferThemedVariantsRule, 'resource-operation-pattern': ResourceOperationPatternRule, 'credential-documentation-url': CredentialDocumentationUrlRule, 'node-class-description-icon-missing': NodeClassDescriptionIconMissingRule, @@ -61,8 +72,11 @@ export const rules = { 'cred-class-name-field-conventions': CredClassNameFieldConventionsRule, 'cred-class-name-suffix': CredClassNameSuffixRule, 'cred-class-oauth2-naming': CredClassOAuth2NamingRule, + 'cred-filename-against-convention': CredFilenameAgainstConventionRule, 'node-connection-type-literal': NodeConnectionTypeLiteralRule, + 'node-filename-against-convention': NodeFilenameAgainstConventionRule, 'node-operation-error-itemindex': NodeOperationErrorItemIndexRule, + 'node-registration-complete': NodeRegistrationCompleteRule, 'missing-paired-item': MissingPairedItemRule, 'no-builder-hint-leakage': NoBuilderHintLeakageRule, 'n8n-object-validation': N8nObjectValidationRule, @@ -70,6 +84,8 @@ export const rules = { 'require-continue-on-fail': RequireContinueOnFailRule, 'require-node-api-error': RequireNodeApiErrorRule, 'require-node-description-fields': RequireNodeDescriptionFieldsRule, + 'require-version': RequireVersionRule, + 'valid-author': ValidAuthorRule, 'valid-credential-references': ValidCredentialReferencesRule, 'valid-description': ValidDescriptionRule, 'valid-peer-dependencies': ValidPeerDependenciesRule, diff --git a/packages/@n8n/eslint-plugin-community-nodes/src/rules/no-dangerous-functions.test.ts b/packages/@n8n/eslint-plugin-community-nodes/src/rules/no-dangerous-functions.test.ts new file mode 100644 index 00000000000..1fd7813d388 --- /dev/null +++ b/packages/@n8n/eslint-plugin-community-nodes/src/rules/no-dangerous-functions.test.ts @@ -0,0 +1,83 @@ +import { RuleTester } from '@typescript-eslint/rule-tester'; + +import { NoDangerousFunctionsRule } from './no-dangerous-functions.js'; + +const ruleTester = new RuleTester(); + +ruleTester.run('no-dangerous-functions', NoDangerousFunctionsRule, { + valid: [ + // `exec`/`spawn` not originating from `child_process` must not be flagged. + { name: 'regex exec', code: 'const match = /foo/.exec(input);' }, + { name: 'regex exec via variable', code: 'regex.exec(input);' }, + { name: 'unrelated exec member', code: 'db.exec("SELECT 1");' }, + { name: 'unrelated spawn member', code: 'queue.spawn(job);' }, + { name: 'locally declared exec', code: 'function exec() {} exec();' }, + // Importing without calling is fine. + { name: 'import without call', code: "import { exec } from 'child_process';" }, + // Non-dangerous members of the namespace import are fine. + { + name: 'non-dangerous namespace member', + code: "import * as cp from 'child_process'; const p = cp.execPath;", + }, + // `eval`/`Function` as identifier references (not calls) are fine. + { name: 'eval reference only', code: 'const f = eval;' }, + { name: 'Function reference only', code: 'const F = Function;' }, + // Non-child_process module is irrelevant. + { + name: 'spawn from unrelated module', + code: "import { spawn } from 'some-lib'; spawn('x');", + }, + ], + invalid: [ + { + name: 'SECURITY: eval call', + code: "eval('1 + 1');", + errors: [{ messageId: 'noEval' }], + }, + { + name: 'SECURITY: Function constructor with new', + code: "const fn = new Function('return process');", + errors: [{ messageId: 'noFunctionConstructor' }], + }, + { + name: 'SECURITY: Function constructor without new', + code: "const fn = Function('return 1');", + errors: [{ messageId: 'noFunctionConstructor' }], + }, + { + name: 'SECURITY: exec from child_process', + code: "import { exec } from 'child_process'; exec('ls');", + errors: [{ messageId: 'noChildProcess', data: { name: 'exec' } }], + }, + { + name: 'SECURITY: aliased exec from node:child_process', + code: "import { exec as run } from 'node:child_process'; run('ls');", + errors: [{ messageId: 'noChildProcess', data: { name: 'exec' } }], + }, + { + name: 'SECURITY: spawn from child_process', + code: "import { spawn } from 'child_process'; spawn('ls', ['-la']);", + errors: [{ messageId: 'noChildProcess', data: { name: 'spawn' } }], + }, + { + name: 'SECURITY: namespace execSync', + code: "import * as cp from 'child_process'; cp.execSync('ls');", + errors: [{ messageId: 'noChildProcess', data: { name: 'execSync' } }], + }, + { + name: 'SECURITY: default import spawnSync', + code: "import childProcess from 'node:child_process'; childProcess.spawnSync('ls');", + errors: [{ messageId: 'noChildProcess', data: { name: 'spawnSync' } }], + }, + { + name: 'SECURITY: destructured require execFile', + code: "const { execFile } = require('child_process'); execFile('ls');", + errors: [{ messageId: 'noChildProcess', data: { name: 'execFile' } }], + }, + { + name: 'SECURITY: namespace require fork', + code: "const cp = require('node:child_process'); cp.fork('./worker.js');", + errors: [{ messageId: 'noChildProcess', data: { name: 'fork' } }], + }, + ], +}); diff --git a/packages/@n8n/eslint-plugin-community-nodes/src/rules/no-dangerous-functions.ts b/packages/@n8n/eslint-plugin-community-nodes/src/rules/no-dangerous-functions.ts new file mode 100644 index 00000000000..edc96caf924 --- /dev/null +++ b/packages/@n8n/eslint-plugin-community-nodes/src/rules/no-dangerous-functions.ts @@ -0,0 +1,155 @@ +import { TSESTree } from '@typescript-eslint/utils'; + +import { + createRule, + getModulePath, + isDirectRequireCall, + isRequireMemberCall, +} from '../utils/index.js'; + +const { AST_NODE_TYPES } = TSESTree; + +const CHILD_PROCESS_MODULES = new Set(['child_process', 'node:child_process']); + +/** + * `child_process` functions that spawn OS processes and are therefore + * vulnerable to command injection when fed untrusted input. + */ +const DANGEROUS_CHILD_PROCESS_FUNCTIONS = new Set([ + 'exec', + 'execSync', + 'execFile', + 'execFileSync', + 'spawn', + 'spawnSync', + 'fork', +]); + +const isChildProcessModule = (node: TSESTree.Node | null): boolean => { + const modulePath = getModulePath(node); + return modulePath !== null && CHILD_PROCESS_MODULES.has(modulePath); +}; + +export const NoDangerousFunctionsRule = createRule({ + name: 'no-dangerous-functions', + meta: { + type: 'problem', + docs: { + description: + 'Disallow `eval`, the `Function` constructor, and `child_process` process-spawning functions (`exec`, `spawn`, etc.) in community nodes.', + }, + messages: { + noEval: + 'Use of `eval` is not allowed. It executes arbitrary code and is a common source of remote code execution vulnerabilities.', + noFunctionConstructor: + 'Use of the `Function` constructor is not allowed. Like `eval`, it executes arbitrary code from strings.', + noChildProcess: + 'Use of `{{ name }}` from `child_process` is not allowed. Spawning OS processes is not permitted in community nodes and can lead to command injection.', + }, + schema: [], + }, + defaultOptions: [], + create(context) { + // Local names bound to dangerous named imports, e.g. `import { exec as run }` -> `run`. + const dangerousLocalNames = new Map<string, string>(); + // Local names bound to the whole module, e.g. `import * as cp` or `const cp = require(...)`. + const namespaceNames = new Set<string>(); + + const recordDestructuredModule = (pattern: TSESTree.ObjectPattern) => { + for (const property of pattern.properties) { + if ( + property.type !== AST_NODE_TYPES.Property || + property.key.type !== AST_NODE_TYPES.Identifier || + !DANGEROUS_CHILD_PROCESS_FUNCTIONS.has(property.key.name) + ) { + continue; + } + + if (property.value.type === AST_NODE_TYPES.Identifier) { + dangerousLocalNames.set(property.value.name, property.key.name); + } + } + }; + + return { + ImportDeclaration(node) { + if (!CHILD_PROCESS_MODULES.has(node.source.value)) return; + + for (const specifier of node.specifiers) { + if ( + specifier.type === AST_NODE_TYPES.ImportSpecifier && + specifier.imported.type === AST_NODE_TYPES.Identifier && + DANGEROUS_CHILD_PROCESS_FUNCTIONS.has(specifier.imported.name) + ) { + dangerousLocalNames.set(specifier.local.name, specifier.imported.name); + } else if ( + specifier.type === AST_NODE_TYPES.ImportNamespaceSpecifier || + specifier.type === AST_NODE_TYPES.ImportDefaultSpecifier + ) { + namespaceNames.add(specifier.local.name); + } + } + }, + + VariableDeclarator(node) { + if ( + node.init?.type !== AST_NODE_TYPES.CallExpression || + !(isDirectRequireCall(node.init) || isRequireMemberCall(node.init)) || + !isChildProcessModule(node.init.arguments[0] ?? null) + ) { + return; + } + + if (node.id.type === AST_NODE_TYPES.ObjectPattern) { + recordDestructuredModule(node.id); + } else if (node.id.type === AST_NODE_TYPES.Identifier) { + namespaceNames.add(node.id.name); + } + }, + + NewExpression(node) { + if (node.callee.type === AST_NODE_TYPES.Identifier && node.callee.name === 'Function') { + context.report({ node, messageId: 'noFunctionConstructor' }); + } + }, + + CallExpression(node) { + const { callee } = node; + + if (callee.type === AST_NODE_TYPES.Identifier) { + if (callee.name === 'eval') { + context.report({ node, messageId: 'noEval' }); + return; + } + + if (callee.name === 'Function') { + context.report({ node, messageId: 'noFunctionConstructor' }); + return; + } + + const originalName = dangerousLocalNames.get(callee.name); + if (originalName) { + context.report({ node, messageId: 'noChildProcess', data: { name: originalName } }); + } + + return; + } + + if ( + callee.type === AST_NODE_TYPES.MemberExpression && + !callee.computed && + callee.object.type === AST_NODE_TYPES.Identifier && + namespaceNames.has(callee.object.name) && + callee.property.type === AST_NODE_TYPES.Identifier && + DANGEROUS_CHILD_PROCESS_FUNCTIONS.has(callee.property.name) + ) { + context.report({ + node, + messageId: 'noChildProcess', + data: { name: callee.property.name }, + }); + } + }, + }; + }, +}); diff --git a/packages/@n8n/eslint-plugin-community-nodes/src/rules/no-emoji-in-options.test.ts b/packages/@n8n/eslint-plugin-community-nodes/src/rules/no-emoji-in-options.test.ts new file mode 100644 index 00000000000..cccbfc3470c --- /dev/null +++ b/packages/@n8n/eslint-plugin-community-nodes/src/rules/no-emoji-in-options.test.ts @@ -0,0 +1,157 @@ +import { RuleTester } from '@typescript-eslint/rule-tester'; + +import { NoEmojiInOptionsRule } from './no-emoji-in-options.js'; + +const ruleTester = new RuleTester(); + +function createNodeCode(body: string): string { + return ` + import type { INodeType, INodeTypeDescription } from 'n8n-workflow'; + + export class TestNode implements INodeType { + description: INodeTypeDescription = { + ${body} + }; + } + `; +} + +ruleTester.run('no-emoji-in-options', NoEmojiInOptionsRule, { + valid: [ + { + name: 'class that does not implement INodeType', + filename: '/tmp/TestNode.node.ts', + code: ` + export class NotANode { + description = { displayName: '🚀 Rocket' }; + } + `, + }, + { + name: 'non .node.ts file is ignored', + filename: '/tmp/helper.ts', + code: ` + export class TestNode { + description = { displayName: '🚀 Rocket' }; + } + `, + }, + { + name: 'node and option labels without emoji', + filename: '/tmp/TestNode.node.ts', + code: createNodeCode(` + displayName: 'Test Node', + name: 'testNode', + defaults: { name: 'Test Node' }, + properties: [ + { + displayName: 'Operation', + name: 'operation', + type: 'options', + options: [ + { name: 'Create', value: 'create' }, + { name: 'Delete', value: 'delete' }, + ], + default: 'create', + }, + ], + `), + }, + { + name: 'accented and non-latin characters are allowed', + filename: '/tmp/TestNode.node.ts', + code: createNodeCode(` + displayName: 'Créer un café', + name: 'testNode', + properties: [ + { + displayName: '日本語', + name: 'field', + type: 'string', + default: '', + }, + ], + `), + }, + ], + invalid: [ + { + name: 'emoji in node displayName', + filename: '/tmp/TestNode.node.ts', + code: createNodeCode(` + displayName: '🚀 Rocket Node', + name: 'testNode', + properties: [], + `), + errors: [{ messageId: 'emojiInOption', data: { key: 'displayName', emoji: '🚀' } }], + }, + { + name: 'emoji in option name within options array', + filename: '/tmp/TestNode.node.ts', + code: createNodeCode(` + displayName: 'Test Node', + name: 'testNode', + properties: [ + { + displayName: 'Operation', + name: 'operation', + type: 'options', + options: [ + { name: '✅ Create', value: 'create' }, + { name: 'Delete', value: 'delete' }, + ], + default: 'create', + }, + ], + `), + errors: [{ messageId: 'emojiInOption', data: { key: 'name', emoji: '✅' } }], + }, + { + name: 'emoji in property displayName', + filename: '/tmp/TestNode.node.ts', + code: createNodeCode(` + displayName: 'Test Node', + name: 'testNode', + properties: [ + { + displayName: 'First Name 🙂', + name: 'firstName', + type: 'string', + default: '', + }, + ], + `), + errors: [{ messageId: 'emojiInOption', data: { key: 'displayName', emoji: '🙂' } }], + }, + { + name: 'flag emoji built from regional indicators', + filename: '/tmp/TestNode.node.ts', + code: createNodeCode(` + displayName: 'Region 🇺🇸', + name: 'testNode', + properties: [], + `), + errors: [{ messageId: 'emojiInOption', data: { key: 'displayName', emoji: '🇺 🇸' } }], + }, + { + name: 'multiple emoji values reported separately', + filename: '/tmp/TestNode.node.ts', + code: createNodeCode(` + displayName: '🚀 Node', + name: 'testNode', + properties: [ + { + displayName: 'Field 🎉', + name: 'field', + type: 'string', + default: '', + }, + ], + `), + errors: [ + { messageId: 'emojiInOption', data: { key: 'displayName', emoji: '🚀' } }, + { messageId: 'emojiInOption', data: { key: 'displayName', emoji: '🎉' } }, + ], + }, + ], +}); diff --git a/packages/@n8n/eslint-plugin-community-nodes/src/rules/no-emoji-in-options.ts b/packages/@n8n/eslint-plugin-community-nodes/src/rules/no-emoji-in-options.ts new file mode 100644 index 00000000000..ff9631f20e2 --- /dev/null +++ b/packages/@n8n/eslint-plugin-community-nodes/src/rules/no-emoji-in-options.ts @@ -0,0 +1,105 @@ +import type { TSESTree } from '@typescript-eslint/utils'; +import { AST_NODE_TYPES } from '@typescript-eslint/utils'; + +import { + isNodeTypeClass, + findClassProperty, + getStringLiteralValue, + isFileType, + createRule, +} from '../utils/index.js'; + +/** + * Matches emoji characters: pictographs (😀, 🚀, ✉️, etc.) and regional + * indicator symbols that compose flag emoji (🇺🇸). + */ +const EMOJI_REGEX = /(\p{Extended_Pictographic}|\p{Regional_Indicator})/gu; + +/** Keys whose string values are surfaced to users as labels. */ +const LABEL_KEYS = new Set(['name', 'displayName']); + +export const NoEmojiInOptionsRule = createRule({ + name: 'no-emoji-in-options', + meta: { + type: 'problem', + docs: { + description: 'Disallow emoji characters in node option name and displayName values', + }, + messages: { + emojiInOption: 'Emoji characters are not allowed in "{{ key }}" values. Found: {{ emoji }}.', + }, + schema: [], + }, + defaultOptions: [], + create(context) { + if (!isFileType(context.filename, '.node.ts')) { + return {}; + } + + const checkLabelValue = (key: string, valueNode: TSESTree.Node): void => { + const value = getStringLiteralValue(valueNode); + if (value === null) { + return; + } + + const matches = value.match(EMOJI_REGEX); + if (!matches) { + return; + } + + context.report({ + node: valueNode, + messageId: 'emojiInOption', + data: { + key, + emoji: [...new Set(matches)].join(' '), + }, + }); + }; + + const traverse = (node: TSESTree.Node): void => { + if (node.type === AST_NODE_TYPES.ObjectExpression) { + for (const property of node.properties) { + if ( + property.type === AST_NODE_TYPES.Property && + property.key.type === AST_NODE_TYPES.Identifier && + LABEL_KEYS.has(property.key.name) + ) { + checkLabelValue(property.key.name, property.value); + } + } + } + + for (const key in node) { + if (key === 'parent') { + continue; + } + const child = node[key as keyof TSESTree.Node] as unknown; + if (Array.isArray(child)) { + for (const item of child) { + if (item && typeof item === 'object' && 'type' in item) { + traverse(item as TSESTree.Node); + } + } + } else if (child && typeof child === 'object' && 'type' in child) { + traverse(child as TSESTree.Node); + } + } + }; + + return { + ClassDeclaration(node) { + if (!isNodeTypeClass(node)) { + return; + } + + const descriptionProperty = findClassProperty(node, 'description'); + if (!descriptionProperty?.value) { + return; + } + + traverse(descriptionProperty.value); + }, + }; + }, +}); diff --git a/packages/@n8n/eslint-plugin-community-nodes/src/rules/node-filename-against-convention.test.ts b/packages/@n8n/eslint-plugin-community-nodes/src/rules/node-filename-against-convention.test.ts new file mode 100644 index 00000000000..8ed785ef49a --- /dev/null +++ b/packages/@n8n/eslint-plugin-community-nodes/src/rules/node-filename-against-convention.test.ts @@ -0,0 +1,115 @@ +import { RuleTester } from '@typescript-eslint/rule-tester'; + +import { NodeFilenameAgainstConventionRule } from './node-filename-against-convention.js'; + +const ruleTester = new RuleTester(); + +function createNodeCode(name: string): string { + return ` +import type { INodeType, INodeTypeDescription } from 'n8n-workflow'; + +export class TestNode implements INodeType { + description: INodeTypeDescription = { + displayName: 'Test Node', + name: '${name}', + group: ['input'], + version: 1, + description: 'A test node', + defaults: { name: 'Test Node' }, + inputs: [], + outputs: [], + properties: [], + }; +}`; +} + +function createNodeCodeWithoutName(): string { + return ` +import type { INodeType, INodeTypeDescription } from 'n8n-workflow'; + +export class TestNode implements INodeType { + description: INodeTypeDescription = { + displayName: 'Test Node', + group: ['input'], + version: 1, + description: 'A test node', + defaults: { name: 'Test Node' }, + inputs: [], + outputs: [], + properties: [], + }; +}`; +} + +function createRegularClass(): string { + return ` +export class SomeHelper { + name = 'github'; +}`; +} + +ruleTester.run('node-filename-against-convention', NodeFilenameAgainstConventionRule, { + valid: [ + { + name: 'filename matches PascalCased description.name', + filename: '/tmp/Github.node.ts', + code: createNodeCode('github'), + }, + { + name: 'filename with version suffix is accepted', + filename: '/tmp/GithubV2.node.ts', + code: createNodeCode('github'), + }, + { + name: 'filename with multi-digit version suffix is accepted', + filename: '/tmp/GithubV10.node.ts', + code: createNodeCode('github'), + }, + { + name: 'multi-word camelCase name maps to PascalCase filename', + filename: '/tmp/GoogleSheets.node.ts', + code: createNodeCode('googleSheets'), + }, + { + name: 'class not implementing INodeType is ignored', + filename: '/tmp/Github.node.ts', + code: createRegularClass(), + }, + { + name: 'non-.node.ts file is ignored', + filename: '/tmp/Github.ts', + code: createNodeCode('mismatch'), + }, + { + name: 'missing description.name is ignored', + filename: '/tmp/Github.node.ts', + code: createNodeCodeWithoutName(), + }, + ], + invalid: [ + { + name: 'filename does not match description.name', + filename: '/tmp/Github.node.ts', + code: createNodeCode('gitlab'), + errors: [{ messageId: 'renameFile', data: { expected: 'Gitlab.node.ts' } }], + }, + { + name: 'filename is lowercased', + filename: '/tmp/github.node.ts', + code: createNodeCode('github'), + errors: [{ messageId: 'renameFile', data: { expected: 'Github.node.ts' } }], + }, + { + name: 'filename has wrong internal casing', + filename: '/tmp/GitHub.node.ts', + code: createNodeCode('github'), + errors: [{ messageId: 'renameFile', data: { expected: 'Github.node.ts' } }], + }, + { + name: 'version suffix does not excuse a mismatched base name', + filename: '/tmp/GitlabV2.node.ts', + code: createNodeCode('github'), + errors: [{ messageId: 'renameFile', data: { expected: 'Github.node.ts' } }], + }, + ], +}); diff --git a/packages/@n8n/eslint-plugin-community-nodes/src/rules/node-filename-against-convention.ts b/packages/@n8n/eslint-plugin-community-nodes/src/rules/node-filename-against-convention.ts new file mode 100644 index 00000000000..a70179b76a9 --- /dev/null +++ b/packages/@n8n/eslint-plugin-community-nodes/src/rules/node-filename-against-convention.ts @@ -0,0 +1,76 @@ +import { TSESTree } from '@typescript-eslint/utils'; +import * as path from 'node:path'; + +import { + isNodeTypeClass, + findClassProperty, + findObjectProperty, + getStringLiteralValue, + isFileType, + createRule, +} from '../utils/index.js'; + +/** + * Converts a `description.name` to the expected node file basename by + * upper-casing the first character. The source of truth is `description.name`, + * not the class name. Example: `github` -> `Github`. + */ +function toExpectedBaseName(name: string): string { + return name.charAt(0).toUpperCase() + name.slice(1); +} + +export const NodeFilenameAgainstConventionRule = createRule({ + name: 'node-filename-against-convention', + meta: { + type: 'problem', + docs: { + description: 'Node filename must match the node `description.name`', + }, + messages: { + renameFile: 'Node filename must match `description.name`. Rename file to "{{expected}}".', + }, + schema: [], + }, + defaultOptions: [], + create(context) { + if (!isFileType(context.filename, '.node.ts')) { + return {}; + } + + return { + ClassDeclaration(node) { + if (!isNodeTypeClass(node)) { + return; + } + + const descriptionProperty = findClassProperty(node, 'description'); + if (descriptionProperty?.value?.type !== TSESTree.AST_NODE_TYPES.ObjectExpression) { + return; + } + + const nameProperty = findObjectProperty(descriptionProperty.value, 'name'); + if (!nameProperty) { + return; + } + + const name = getStringLiteralValue(nameProperty.value); + if (!name) { + return; + } + + const expectedBaseName = toExpectedBaseName(name); + // Strip the `.node.ts` extension and any trailing `V<digits>` version + // suffix so versioned files (e.g. `GithubV2.node.ts`) are accepted. + const actualBaseName = path.basename(context.filename, '.node.ts').replace(/V\d+$/, ''); + + if (actualBaseName !== expectedBaseName) { + context.report({ + node: nameProperty.value, + messageId: 'renameFile', + data: { expected: `${expectedBaseName}.node.ts` }, + }); + } + }, + }; + }, +}); diff --git a/packages/@n8n/eslint-plugin-community-nodes/src/rules/node-registration-complete.test.ts b/packages/@n8n/eslint-plugin-community-nodes/src/rules/node-registration-complete.test.ts new file mode 100644 index 00000000000..9d963ed7faf --- /dev/null +++ b/packages/@n8n/eslint-plugin-community-nodes/src/rules/node-registration-complete.test.ts @@ -0,0 +1,87 @@ +import { RuleTester } from '@typescript-eslint/rule-tester'; +import { afterEach, vi } from 'vitest'; + +import { NodeRegistrationCompleteRule } from './node-registration-complete.js'; +import * as fileUtils from '../utils/file-utils.js'; + +vi.mock('../utils/file-utils.js', async () => { + const actual = await vi.importActual('../utils/file-utils.js'); + return { + ...actual, + findNodeSourceFilesOnDisk: vi.fn(), + readPackageJsonNodes: vi.fn(), + }; +}); + +const mockFindNodeSourceFilesOnDisk = vi.mocked(fileUtils.findNodeSourceFilesOnDisk); +const mockReadPackageJsonNodes = vi.mocked(fileUtils.readPackageJsonNodes); + +const packageJsonPath = '/tmp/package.json'; +const fooNode = '/tmp/nodes/Foo/Foo.node.ts'; +const barNode = '/tmp/nodes/Bar/Bar.node.ts'; + +const ruleTester = new RuleTester(); + +function setup(onDisk: string[], registered: string[]): void { + mockFindNodeSourceFilesOnDisk.mockReturnValue(onDisk); + mockReadPackageJsonNodes.mockReturnValue(registered); +} + +afterEach(() => { + vi.clearAllMocks(); +}); + +// Default: both node files exist on disk and both are registered. +setup([fooNode, barNode], [fooNode, barNode]); + +ruleTester.run('node-registration-complete', NodeRegistrationCompleteRule, { + valid: [ + { + name: 'all node files are registered', + filename: packageJsonPath, + code: '{ "name": "n8n-nodes-example", "n8n": { "nodes": ["dist/nodes/Foo/Foo.node.js", "dist/nodes/Bar/Bar.node.js"] } }', + }, + { + name: 'non-package.json file is ignored', + filename: 'some-config.json', + code: '{ "name": "n8n-nodes-example" }', + }, + ], + invalid: [ + { + name: 'one node file is not registered', + filename: packageJsonPath, + code: '{ "name": "n8n-nodes-example", "n8n": { "nodes": ["dist/nodes/Foo/Foo.node.js"] } }', + before() { + setup([fooNode, barNode], [fooNode]); + }, + errors: [ + { + messageId: 'nodeNotRegistered', + data: { nodeFile: 'nodes/Bar/Bar.node.ts' }, + }, + ], + }, + { + name: 'multiple node files are not registered', + filename: packageJsonPath, + code: '{ "name": "n8n-nodes-example", "n8n": { "nodes": [] } }', + before() { + setup([fooNode, barNode], []); + }, + errors: [ + { messageId: 'nodeNotRegistered', data: { nodeFile: 'nodes/Foo/Foo.node.ts' } }, + { messageId: 'nodeNotRegistered', data: { nodeFile: 'nodes/Bar/Bar.node.ts' } }, + ], + }, + { + name: 'node files exist on disk but there is no n8n object', + filename: packageJsonPath, + code: '{ "name": "n8n-nodes-example" }', + before() { + setup([fooNode], []); + }, + errors: [{ messageId: 'nodeNotRegistered', data: { nodeFile: 'nodes/Foo/Foo.node.ts' } }], + }, + ], +}); diff --git a/packages/@n8n/eslint-plugin-community-nodes/src/rules/node-registration-complete.ts b/packages/@n8n/eslint-plugin-community-nodes/src/rules/node-registration-complete.ts new file mode 100644 index 00000000000..2c0bf0f11de --- /dev/null +++ b/packages/@n8n/eslint-plugin-community-nodes/src/rules/node-registration-complete.ts @@ -0,0 +1,79 @@ +import type { TSESTree } from '@typescript-eslint/utils'; +import { AST_NODE_TYPES } from '@typescript-eslint/utils'; +import * as path from 'node:path'; + +import { + createRule, + findJsonProperty, + findNodeSourceFilesOnDisk, + readPackageJsonNodes, +} from '../utils/index.js'; + +export const NodeRegistrationCompleteRule = createRule({ + name: 'node-registration-complete', + meta: { + type: 'problem', + docs: { + description: + 'Ensure every `.node.ts` file in the `nodes/` directory is registered in the "n8n.nodes" array of package.json', + }, + messages: { + nodeNotRegistered: + 'The node file "{{ nodeFile }}" is not registered in the "n8n.nodes" array of package.json. Add it so n8n can discover the node.', + }, + schema: [], + }, + defaultOptions: [], + create(context) { + if (!context.filename.endsWith('package.json')) { + return {}; + } + + return { + ObjectExpression(node: TSESTree.ObjectExpression) { + // Only inspect the root object of the package.json file. + if (node.parent?.type !== AST_NODE_TYPES.ExpressionStatement) { + return; + } + + const nodeFilesOnDisk = findNodeSourceFilesOnDisk(context.filename); + if (nodeFilesOnDisk.length === 0) { + return; + } + + const registered = new Set( + readPackageJsonNodes(context.filename).map((filePath) => path.resolve(filePath)), + ); + + const packageDir = path.dirname(context.filename); + const reportTarget = resolveReportTarget(node); + + for (const nodeFile of nodeFilesOnDisk) { + if (registered.has(path.resolve(nodeFile))) { + continue; + } + + context.report({ + node: reportTarget, + messageId: 'nodeNotRegistered', + data: { nodeFile: path.relative(packageDir, nodeFile) }, + }); + } + }, + }; + }, +}); + +/** + * Reports against the most specific available node: the `n8n.nodes` array, the + * `n8n` object, or the package.json root object as a fallback. + */ +function resolveReportTarget(root: TSESTree.ObjectExpression): TSESTree.Node { + const n8nProperty = findJsonProperty(root, 'n8n'); + if (n8nProperty?.value.type !== AST_NODE_TYPES.ObjectExpression) { + return n8nProperty ?? root; + } + + const nodesProperty = findJsonProperty(n8nProperty.value, 'nodes'); + return nodesProperty ?? n8nProperty; +} diff --git a/packages/@n8n/eslint-plugin-community-nodes/src/rules/require-version.test.ts b/packages/@n8n/eslint-plugin-community-nodes/src/rules/require-version.test.ts new file mode 100644 index 00000000000..9d8746dbfea --- /dev/null +++ b/packages/@n8n/eslint-plugin-community-nodes/src/rules/require-version.test.ts @@ -0,0 +1,90 @@ +import { RuleTester } from '@typescript-eslint/rule-tester'; + +import { RequireVersionRule } from './require-version.js'; + +const ruleTester = new RuleTester(); + +ruleTester.run('require-version', RequireVersionRule, { + valid: [ + { + name: 'version is a valid semver string', + filename: 'package.json', + code: '{ "name": "n8n-nodes-example", "version": "1.0.0" }', + }, + { + name: 'version with pre-release and build metadata', + filename: 'package.json', + code: '{ "name": "n8n-nodes-example", "version": "1.2.3-beta.1+build.5" }', + }, + { + name: 'zero version is valid', + filename: 'package.json', + code: '{ "name": "n8n-nodes-example", "version": "0.1.0" }', + }, + { + name: 'non-package.json file is ignored', + filename: 'some-config.json', + code: '{ "name": "n8n-nodes-example" }', + }, + { + name: 'nested objects with missing version are not checked', + filename: 'package.json', + code: '{ "name": "n8n-nodes-example", "version": "1.0.0", "config": { "nested": "value" } }', + }, + { + name: 'objects inside arrays (e.g. contributors) are not flagged', + filename: 'package.json', + code: `{ + "name": "n8n-nodes-example", + "version": "1.0.0", + "contributors": [ + { "name": "Alice", "email": "alice@example.com" } + ] + }`, + }, + ], + invalid: [ + { + name: 'version field is missing entirely', + filename: 'package.json', + code: '{ "name": "n8n-nodes-example", "description": "Example" }', + errors: [{ messageId: 'missingVersion' }], + }, + { + name: 'empty package.json object', + filename: 'package.json', + code: '{}', + errors: [{ messageId: 'missingVersion' }], + }, + { + name: 'version is an empty string', + filename: 'package.json', + code: '{ "name": "n8n-nodes-example", "version": "" }', + errors: [{ messageId: 'invalidVersion' }], + }, + { + name: 'version is not a valid semver', + filename: 'package.json', + code: '{ "name": "n8n-nodes-example", "version": "1.0" }', + errors: [{ messageId: 'invalidVersion' }], + }, + { + name: 'version has a leading "v"', + filename: 'package.json', + code: '{ "name": "n8n-nodes-example", "version": "v1.0.0" }', + errors: [{ messageId: 'invalidVersion' }], + }, + { + name: 'version is a range, not an exact version', + filename: 'package.json', + code: '{ "name": "n8n-nodes-example", "version": "^1.0.0" }', + errors: [{ messageId: 'invalidVersion' }], + }, + { + name: 'version is a number, not a string', + filename: 'package.json', + code: '{ "name": "n8n-nodes-example", "version": 1 }', + errors: [{ messageId: 'invalidVersion' }], + }, + ], +}); diff --git a/packages/@n8n/eslint-plugin-community-nodes/src/rules/require-version.ts b/packages/@n8n/eslint-plugin-community-nodes/src/rules/require-version.ts new file mode 100644 index 00000000000..2666a53d1a5 --- /dev/null +++ b/packages/@n8n/eslint-plugin-community-nodes/src/rules/require-version.ts @@ -0,0 +1,62 @@ +import type { TSESTree } from '@typescript-eslint/utils'; +import { AST_NODE_TYPES } from '@typescript-eslint/utils'; + +import { createRule, findJsonProperty } from '../utils/index.js'; + +// Official SemVer 2.0.0 regex (https://semver.org/), anchored. +const SEMVER_REGEX = + /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/; + +export const RequireVersionRule = createRule({ + name: 'require-version', + meta: { + type: 'problem', + docs: { + description: 'Require a valid "version" field in community node package.json', + }, + messages: { + missingVersion: + 'The package.json must have a "version" field. npm requires a valid semantic version (e.g. "1.0.0") to publish the package.', + invalidVersion: + 'The "version" field must be a valid semantic version string (e.g. "1.0.0"), got {{ value }}.', + }, + schema: [], + }, + defaultOptions: [], + create(context) { + if (!context.filename.endsWith('package.json')) { + return {}; + } + + return { + ObjectExpression(node: TSESTree.ObjectExpression) { + if (node.parent?.type !== AST_NODE_TYPES.ExpressionStatement) { + return; + } + + const versionProp = findJsonProperty(node, 'version'); + + if (!versionProp) { + context.report({ + node, + messageId: 'missingVersion', + }); + return; + } + + const valueNode = versionProp.value; + const value = valueNode.type === AST_NODE_TYPES.Literal ? valueNode.value : null; + + if (typeof value !== 'string' || !SEMVER_REGEX.test(value)) { + const rawValue = + valueNode.type === AST_NODE_TYPES.Literal ? String(valueNode.raw) : 'non-literal'; + context.report({ + node: versionProp, + messageId: 'invalidVersion', + data: { value: rawValue }, + }); + } + }, + }; + }, +}); diff --git a/packages/@n8n/eslint-plugin-community-nodes/src/rules/valid-author.test.ts b/packages/@n8n/eslint-plugin-community-nodes/src/rules/valid-author.test.ts new file mode 100644 index 00000000000..60d1cddfb20 --- /dev/null +++ b/packages/@n8n/eslint-plugin-community-nodes/src/rules/valid-author.test.ts @@ -0,0 +1,108 @@ +import { RuleTester } from '@typescript-eslint/rule-tester'; + +import { ValidAuthorRule } from './valid-author.js'; + +const ruleTester = new RuleTester(); + +ruleTester.run('valid-author', ValidAuthorRule, { + valid: [ + { + name: 'author object with non-empty name and email', + filename: 'package.json', + code: '{ "name": "n8n-nodes-example", "author": { "name": "Jane Doe", "email": "jane@example.com" } }', + }, + { + name: 'author object with extra fields', + filename: 'package.json', + code: '{ "author": { "name": "Jane Doe", "email": "jane@example.com", "url": "https://example.com" } }', + }, + { + name: 'author shorthand string with name and email', + filename: 'package.json', + code: '{ "author": "Jane Doe <jane@example.com>" }', + }, + { + name: 'author shorthand string with name, email and url', + filename: 'package.json', + code: '{ "author": "Jane Doe <jane@example.com> (https://example.com)" }', + }, + { + name: 'non-package.json file is ignored', + filename: 'some-config.json', + code: '{ "name": "n8n-nodes-example" }', + }, + { + name: 'nested objects are not checked', + filename: 'package.json', + code: '{ "author": { "name": "Jane Doe", "email": "jane@example.com" }, "config": { "nested": "value" } }', + }, + ], + invalid: [ + { + name: 'missing author field entirely', + filename: 'package.json', + code: '{ "name": "n8n-nodes-example", "version": "1.0.0" }', + errors: [{ messageId: 'authorMissing' }], + }, + { + name: 'empty package.json object', + filename: 'package.json', + code: '{}', + errors: [{ messageId: 'authorMissing' }], + }, + { + name: 'author object missing email', + filename: 'package.json', + code: '{ "author": { "name": "Jane Doe" } }', + errors: [{ messageId: 'authorEmailMissing' }], + }, + { + name: 'author object missing name', + filename: 'package.json', + code: '{ "author": { "email": "jane@example.com" } }', + errors: [{ messageId: 'authorNameMissing' }], + }, + { + name: 'author object with empty name and email strings', + filename: 'package.json', + code: '{ "author": { "name": "", "email": " " } }', + errors: [{ messageId: 'authorNameMissing' }, { messageId: 'authorEmailMissing' }], + }, + { + name: 'author object with non-string name', + filename: 'package.json', + code: '{ "author": { "name": 123, "email": "jane@example.com" } }', + errors: [{ messageId: 'authorNameMissing' }], + }, + { + name: 'author shorthand string with name only', + filename: 'package.json', + code: '{ "author": "Jane Doe" }', + errors: [{ messageId: 'authorEmailMissing' }], + }, + { + name: 'author shorthand string with email only', + filename: 'package.json', + code: '{ "author": "<jane@example.com>" }', + errors: [{ messageId: 'authorNameMissing' }], + }, + { + name: 'author shorthand string with empty email angle brackets', + filename: 'package.json', + code: '{ "author": "Jane Doe <>" }', + errors: [{ messageId: 'authorEmailMissing' }], + }, + { + name: 'empty author string', + filename: 'package.json', + code: '{ "author": "" }', + errors: [{ messageId: 'authorNameMissing' }, { messageId: 'authorEmailMissing' }], + }, + { + name: 'author as empty array', + filename: 'package.json', + code: '{ "author": [] }', + errors: [{ messageId: 'authorMissing' }], + }, + ], +}); diff --git a/packages/@n8n/eslint-plugin-community-nodes/src/rules/valid-author.ts b/packages/@n8n/eslint-plugin-community-nodes/src/rules/valid-author.ts new file mode 100644 index 00000000000..4113bf0487d --- /dev/null +++ b/packages/@n8n/eslint-plugin-community-nodes/src/rules/valid-author.ts @@ -0,0 +1,100 @@ +import type { TSESTree } from '@typescript-eslint/utils'; +import { AST_NODE_TYPES } from '@typescript-eslint/utils'; + +import { createRule, findJsonProperty, getTopLevelObjectInJson } from '../utils/index.js'; + +/** + * Parses an npm "person" shorthand string of the form + * `Name <email> (url)` into its name and email parts. Any part may be absent. + */ +function parsePersonString(value: string): { name: string; email: string } { + const emailMatch = /<([^>]*)>/.exec(value); + const email = (emailMatch?.[1] ?? '').trim(); + + const ltIndex = value.indexOf('<'); + const parenIndex = value.indexOf('('); + let nameEnd = value.length; + if (ltIndex !== -1) nameEnd = Math.min(nameEnd, ltIndex); + if (parenIndex !== -1) nameEnd = Math.min(nameEnd, parenIndex); + const name = value.slice(0, nameEnd).trim(); + + return { name, email }; +} + +function isNonEmptyStringLiteral(node: TSESTree.Property | null): boolean { + if (!node || node.value.type !== AST_NODE_TYPES.Literal) { + return false; + } + const { value } = node.value; + return typeof value === 'string' && value.trim().length > 0; +} + +export const ValidAuthorRule = createRule({ + name: 'valid-author', + meta: { + type: 'problem', + docs: { + description: 'Require a non-empty author name and email in package.json', + }, + messages: { + authorMissing: 'package.json must have an "author" field with a non-empty name and email.', + authorNameMissing: 'The "author" field must include a non-empty name.', + authorEmailMissing: 'The "author" field must include a non-empty email.', + }, + schema: [], + }, + defaultOptions: [], + create(context) { + if (!context.filename.endsWith('package.json')) { + return {}; + } + + return { + ObjectExpression(node: TSESTree.ObjectExpression) { + const root = getTopLevelObjectInJson(node); + if (!root) { + return; + } + + const authorProp = findJsonProperty(root, 'author'); + if (!authorProp) { + context.report({ node: root, messageId: 'authorMissing' }); + return; + } + + const authorValue = authorProp.value; + + // Shorthand string form: "Name <email> (url)" + if (authorValue.type === AST_NODE_TYPES.Literal) { + if (typeof authorValue.value !== 'string') { + context.report({ node: authorProp, messageId: 'authorMissing' }); + return; + } + + const { name, email } = parsePersonString(authorValue.value); + if (name.length === 0) { + context.report({ node: authorProp, messageId: 'authorNameMissing' }); + } + if (email.length === 0) { + context.report({ node: authorProp, messageId: 'authorEmailMissing' }); + } + return; + } + + // Object form: { "name": "...", "email": "..." } + if (authorValue.type === AST_NODE_TYPES.ObjectExpression) { + if (!isNonEmptyStringLiteral(findJsonProperty(authorValue, 'name'))) { + context.report({ node: authorProp, messageId: 'authorNameMissing' }); + } + if (!isNonEmptyStringLiteral(findJsonProperty(authorValue, 'email'))) { + context.report({ node: authorProp, messageId: 'authorEmailMissing' }); + } + return; + } + + // Any other shape (e.g. array, null) cannot carry a name and email. + context.report({ node: authorProp, messageId: 'authorMissing' }); + }, + }; + }, +}); diff --git a/packages/@n8n/eslint-plugin-community-nodes/src/utils/file-utils.ts b/packages/@n8n/eslint-plugin-community-nodes/src/utils/file-utils.ts index f855db9d704..6240d4f4848 100644 --- a/packages/@n8n/eslint-plugin-community-nodes/src/utils/file-utils.ts +++ b/packages/@n8n/eslint-plugin-community-nodes/src/utils/file-utils.ts @@ -158,20 +158,17 @@ export function validateIconPath( ): { isValid: boolean; isFile: boolean; - isSvg: boolean; exists: boolean; } { const isFile = iconPath.startsWith('file:'); const relativePath = iconPath.replace(/^file:/, ''); - const isSvg = relativePath.endsWith('.svg'); // Should not use safeJoinPath here because iconPath can be outside of the node class folder const fullPath = path.join(baseDir, relativePath); const exists = fileExistsWithCaseSync(fullPath); return { - isValid: isFile && isSvg && exists, + isValid: isFile && exists, isFile, - isSvg, exists, }; } @@ -182,6 +179,44 @@ export function readPackageJsonNodes(packageJsonPath: string): string[] { return resolveN8nFilePaths(packageJsonPath, nodePaths); } +function findFilesRecursively(dir: string, matches: (fileName: string) => boolean): string[] { + const results: string[] = []; + + let entries; + try { + entries = readdirSync(dir, { withFileTypes: true }); + } catch { + return results; + } + + for (const entry of entries) { + const fullPath = path.join(dir, entry.name); + if (entry.isDirectory()) { + results.push(...findFilesRecursively(fullPath, matches)); + } else if (entry.isFile() && matches(entry.name)) { + results.push(fullPath); + } + } + + return results; +} + +/** + * Finds all `*.node.ts` source files in the package's `nodes/` directory, + * returning their absolute paths. Returns an empty array if there is no + * `nodes/` directory. + */ +export function findNodeSourceFilesOnDisk(packageJsonPath: string): string[] { + const packageDir = dirname(packageJsonPath); + const nodesDir = safeJoinPath(packageDir, 'nodes'); + + if (!existsSync(nodesDir)) { + return []; + } + + return findFilesRecursively(nodesDir, (fileName) => fileName.endsWith('.node.ts')); +} + export function areAllCredentialUsagesTestedByNodes( credentialName: string, packageDir: string, @@ -268,7 +303,9 @@ function fileExistsWithCaseSync(filePath: string): boolean { } } -export function findSimilarSvgFiles(targetPath: string, baseDir: string): string[] { +const ICON_EXTENSIONS = ['.svg', '.png']; + +export function findSimilarIconFiles(targetPath: string, baseDir: string): string[] { try { const targetFileName = path.basename(targetPath, path.extname(targetPath)); const targetDir = path.dirname(targetPath); @@ -279,15 +316,25 @@ export function findSimilarSvgFiles(targetPath: string, baseDir: string): string return []; } - const files = readdirSync(searchDir); - const svgFileNames = files - .filter((file) => file.endsWith('.svg')) - .map((file) => path.basename(file, '.svg')); + const files = readdirSync(searchDir).filter((file) => + ICON_EXTENSIONS.includes(path.extname(file).toLowerCase()), + ); - const candidateNames = new Set(svgFileNames); + // Map icon base names to their actual filenames so suggestions keep their extension. + const baseNameToFiles = new Map<string, string[]>(); + for (const file of files) { + const baseName = path.basename(file, path.extname(file)); + const existing = baseNameToFiles.get(baseName) ?? []; + existing.push(file); + baseNameToFiles.set(baseName, existing); + } + + const candidateNames = new Set(baseNameToFiles.keys()); const similarNames = findSimilarStrings(targetFileName, candidateNames); - return similarNames.map((name) => path.join(targetDir, `${name}.svg`)); + return similarNames.flatMap((name) => + (baseNameToFiles.get(name) ?? []).map((file) => path.join(targetDir, file)), + ); } catch { return []; } diff --git a/packages/@n8n/expression-runtime/package.json b/packages/@n8n/expression-runtime/package.json index 00ff82bbcd3..eeaa1151200 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.16.0", + "version": "0.18.0", "description": "Secure, isolated expression evaluation runtime for n8n", "main": "dist/cjs/index.js", "module": "dist/esm/index.js", @@ -31,7 +31,7 @@ "web-worker", "security" ], - "license": "SEE LICENSE IN LICENSE.md", + "license": "LicenseRef-n8n-sustainable-use", "dependencies": { "@n8n/errors": "workspace:*", "@n8n/tournament": "workspace:*", diff --git a/packages/@n8n/expression-runtime/src/extensions/__tests__/string-extensions.test.ts b/packages/@n8n/expression-runtime/src/extensions/__tests__/string-extensions.test.ts index be23609f9fb..c52bc1c1614 100644 --- a/packages/@n8n/expression-runtime/src/extensions/__tests__/string-extensions.test.ts +++ b/packages/@n8n/expression-runtime/src/extensions/__tests__/string-extensions.test.ts @@ -5,6 +5,8 @@ const extractUrlPath = stringExtensions.functions.extractUrlPath as ( value: string, ) => string | undefined; +const toSentenceCase = stringExtensions.functions.toSentenceCase as (value: string) => string; + describe('extractUrlPath (imperative parser, no URL constructor)', () => { it.each([ ['https://example.com/path', '/path'], @@ -33,3 +35,32 @@ describe('extractUrlPath (imperative parser, no URL constructor)', () => { expect(extractUrlPath(input)).toBeUndefined(); }); }); + +describe('toSentenceCase', () => { + it.each([ + [ + 'i am a test! i have multiple types of Punctuation. or do i?', + 'I am a test! I have multiple types of punctuation. Or do i?', + ], + ['i am a test!', 'I am a test!'], + ['i am a test', 'I am a test'], + ['quick! brown FOX', 'Quick! Brown fox'], + ])('should sentence-case %s', (input, expected) => { + expect(toSentenceCase(input)).toBe(expected); + }); + + it.each([ + ['hello world. 123', 'Hello world. 123'], + ['end with punc. 42!', 'End with punc. 42!'], + ['growth is high. 50%', 'Growth is high. 50%'], + ])('should preserve trailing letter-less text in %s', (input, expected) => { + expect(toSentenceCase(input)).toBe(expected); + }); + + it.each([ + ['42', '42'], + ['', ''], + ])('should return letter-free input %p unchanged', (input, expected) => { + expect(toSentenceCase(input)).toBe(expected); + }); +}); diff --git a/packages/@n8n/expression-runtime/src/extensions/string-extensions.ts b/packages/@n8n/expression-runtime/src/extensions/string-extensions.ts index 08ea90a489b..d49c6e9be8f 100644 --- a/packages/@n8n/expression-runtime/src/extensions/string-extensions.ts +++ b/packages/@n8n/expression-runtime/src/extensions/string-extensions.ts @@ -323,7 +323,7 @@ function toSentenceCase(value: string) { current = current.slice(puncIndex + 1); } - return buffer; + return buffer + current; } function toSnakeCase(value: string) { diff --git a/packages/@n8n/expression-runtime/src/runtime/jmespath.ts b/packages/@n8n/expression-runtime/src/runtime/jmespath.ts index 0c726f4206b..dff32f7d7ee 100644 --- a/packages/@n8n/expression-runtime/src/runtime/jmespath.ts +++ b/packages/@n8n/expression-runtime/src/runtime/jmespath.ts @@ -36,18 +36,26 @@ const unsafeJmespathPropertyPattern = new RegExp( /** * In-isolate `$jmespath` / `$jmesPath` implementation. * - * Mirrors the host-side wrapper in `packages/workflow/src/workflow-data-proxy.ts` - * so that expressions resolve `$jmespath` from the in-isolate runtime via - * Tournament's polyfill. `$jmespath` is a pure utility — it takes its - * data as an argument and runs a query on it, with no need for host - * context. Keeping it in-isolate means it does not appear as a - * host-callable on the bridge, which shrinks the host-callable surface - * the isolate can reach. + * In-isolate counterpart of the host-side wrapper in + * `packages/workflow/src/workflow-data-proxy.ts`, so that expressions + * resolve `$jmespath` from the in-isolate runtime via Tournament's + * polyfill. `$jmespath` is a pure utility — it takes its data as an + * argument and runs a query on it, with no need for host context. + * Keeping it in-isolate means it does not appear as a host-callable on + * the bridge, which shrinks the host-callable surface the isolate can + * reach. * - * Behavioural parity with the host wrapper: + * Relationship to the host wrapper — same observable contract, + * deliberately different internals: * - Throws `ExpressionError` (same name) when args are wrong. * - Rejects queries that contain unsafe property tokens. - * - Spreads non-array, non-null objects to drop proxies at the top level. + * - Does NOT spread `data` before querying. Host-side, the top-level + * spread exists to strip proxies off the data before handing it to + * jmespath; in-isolate that is a no-op (nested values stay lazy + * proxies either way, and the isolate boundary already prevents + * host-object leakage), while spreading a lazy proxy (e.g. `$json`) + * would cost one synchronous host roundtrip per top-level key + * before the query even runs. * * Note on lazy proxies: when `data` is a lazy proxy (e.g. `$json`), each * property access during `jmespath.search` triggers a synchronous host @@ -69,10 +77,5 @@ export function jmesPath(data: unknown, query: string): unknown { ); } - if (data !== null && !Array.isArray(data) && typeof data === 'object') { - return jmespath.search({ ...(data as Record<string, unknown>) }, query); - } - - // Array or null — pass through to jmespath which accepts both return jmespath.search(data as never, query); } diff --git a/packages/@n8n/expression-runtime/tsconfig.build.cjs.json b/packages/@n8n/expression-runtime/tsconfig.build.cjs.json index 8fb48a61234..7fd749690f0 100644 --- a/packages/@n8n/expression-runtime/tsconfig.build.cjs.json +++ b/packages/@n8n/expression-runtime/tsconfig.build.cjs.json @@ -2,8 +2,7 @@ "extends": ["./tsconfig.json", "@n8n/typescript-config/modern/tsconfig.cjs.json"], "compilerOptions": { "rootDir": "src", - "outDir": "dist/cjs", - "tsBuildInfoFile": "dist/cjs/build.tsbuildinfo" + "outDir": "dist/cjs" }, "include": ["src/**/*.ts"], "exclude": ["node_modules", "dist", "src/**/__tests__/**"] diff --git a/packages/@n8n/extension-sdk/package.json b/packages/@n8n/extension-sdk/package.json index 60f1d1ae530..e90db20e272 100644 --- a/packages/@n8n/extension-sdk/package.json +++ b/packages/@n8n/extension-sdk/package.json @@ -1,6 +1,6 @@ { "name": "@n8n/extension-sdk", - "version": "0.10.0", + "version": "0.12.0", "type": "module", "files": [ "dist", @@ -39,7 +39,7 @@ "build:unchecked": "pnpm run build", "create-json-schema": "tsx scripts/create-json-schema.ts", "preview": "vite preview", - "test": "jest" + "test": "jest --passWithNoTests" }, "peerDependencies": { "vue": "catalog:frontend", @@ -49,6 +49,7 @@ "@n8n/typescript-config": "workspace:*", "@vitejs/plugin-vue": "catalog:frontend", "@vue/tsconfig": "catalog:frontend", + "prettier": "catalog:", "tsdown": "catalog:", "rimraf": "catalog:", "vite": "catalog:", @@ -58,7 +59,7 @@ "zod-to-json-schema": "catalog:", "tsx": "catalog:" }, - "license": "https://docs.n8n.io/sustainable-use-license/", + "license": "LicenseRef-n8n-sustainable-use", "dependencies": { "zod": "catalog:" } diff --git a/packages/@n8n/extension-sdk/tsconfig.backend.json b/packages/@n8n/extension-sdk/tsconfig.backend.json index 0fb2a1a200c..a7ee6a6615b 100644 --- a/packages/@n8n/extension-sdk/tsconfig.backend.json +++ b/packages/@n8n/extension-sdk/tsconfig.backend.json @@ -3,7 +3,7 @@ "compilerOptions": { "composite": true, "declaration": true, - "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.backend.tsbuildinfo" + "tsBuildInfoFile": "${configDir}/dist/backend.tsbuildinfo" }, "include": ["src/backend/**/*.ts"] } diff --git a/packages/@n8n/extension-sdk/tsconfig.common.json b/packages/@n8n/extension-sdk/tsconfig.common.json index c96e32876d4..65fb354d3b0 100644 --- a/packages/@n8n/extension-sdk/tsconfig.common.json +++ b/packages/@n8n/extension-sdk/tsconfig.common.json @@ -3,7 +3,7 @@ "compilerOptions": { "composite": true, "declaration": true, - "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.backend.tsbuildinfo" + "tsBuildInfoFile": "${configDir}/dist/common.tsbuildinfo" }, "include": ["src/*.ts"] } diff --git a/packages/@n8n/extension-sdk/tsconfig.frontend.json b/packages/@n8n/extension-sdk/tsconfig.frontend.json index b57b4d95f7f..41406d348ee 100644 --- a/packages/@n8n/extension-sdk/tsconfig.frontend.json +++ b/packages/@n8n/extension-sdk/tsconfig.frontend.json @@ -3,7 +3,7 @@ "compilerOptions": { "composite": true, "declaration": true, - "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.frontend.tsbuildinfo" + "tsBuildInfoFile": "${configDir}/dist/frontend.tsbuildinfo" }, "include": ["src/frontend/**/*.ts", "src/frontend/**/*.vue"] } diff --git a/packages/@n8n/imap/package.json b/packages/@n8n/imap/package.json index 1b3952e7bc0..07cd662ec23 100644 --- a/packages/@n8n/imap/package.json +++ b/packages/@n8n/imap/package.json @@ -1,6 +1,6 @@ { "name": "@n8n/imap", - "version": "0.20.0", + "version": "0.22.0", "scripts": { "clean": "rimraf dist .turbo", "dev": "pnpm watch", @@ -35,5 +35,6 @@ "@types/quoted-printable": "^1.0.2", "@types/utf8": "^3.0.3", "vitest-mock-extended": "catalog:" - } + }, + "license": "LicenseRef-n8n-sustainable-use" } diff --git a/packages/@n8n/imap/tsconfig.build.json b/packages/@n8n/imap/tsconfig.build.json index 8f1e58acad7..ca7b8fc5268 100644 --- a/packages/@n8n/imap/tsconfig.build.json +++ b/packages/@n8n/imap/tsconfig.build.json @@ -3,8 +3,7 @@ "compilerOptions": { "composite": true, "rootDir": "src", - "outDir": "dist", - "tsBuildInfoFile": "dist/build.tsbuildinfo" + "outDir": "dist" }, "include": ["src/**/*.ts"], "exclude": ["src/**/*.test.ts"] diff --git a/packages/@n8n/imap/tsconfig.json b/packages/@n8n/imap/tsconfig.json index d0823e2290a..60db8a9593b 100644 --- a/packages/@n8n/imap/tsconfig.json +++ b/packages/@n8n/imap/tsconfig.json @@ -1,8 +1,7 @@ { "extends": "@n8n/typescript-config/tsconfig.common.json", "compilerOptions": { - "types": ["node", "vite/client", "vitest/globals"], - "tsBuildInfoFile": "dist/typecheck.tsbuildinfo" + "types": ["node", "vite/client", "vitest/globals"] }, "include": ["src/**/*.ts"] } diff --git a/packages/@n8n/instance-ai/docs/ENGINEERING.md b/packages/@n8n/instance-ai/docs/ENGINEERING.md index 4ad23154f78..5ada43f5f22 100644 --- a/packages/@n8n/instance-ai/docs/ENGINEERING.md +++ b/packages/@n8n/instance-ai/docs/ENGINEERING.md @@ -30,7 +30,7 @@ const data: ExecutionResult = parseExecutionResult(response); ### Zod schemas are the source of truth Every tool has an input schema (what the LLM sends) and an output schema -(what the tool returns). Mastra uses these schemas to generate tool +(what the tool returns). `@n8n/agents` uses these schemas to generate tool descriptions for the LLM, validate inputs at runtime, and type-check the execute function. If the TypeScript type and the Zod schema are defined separately, they drift — the LLM sees one contract, the code enforces @@ -120,7 +120,7 @@ it('should stream tool-call event when agent uses a tool', async () => { The clean interface boundary (ADR-002) makes each layer testable in isolation. Verify the contract at each boundary — not the wiring between -them. Tools can be tested without Mastra, the reducer without SSE, adapters +them. Tools can be tested without `@n8n/agents`, the reducer without SSE, adapters without the agent. For each tool, test: @@ -203,15 +203,15 @@ When backend and frontend both switch on event types with duplicated logic, a change to the format requires updating both in lockstep. Extract the shared part into `@n8n/api-types` or a shared utility. -## Mastra Patterns +## Agent SDK Patterns ### Tool definitions -Mastra uses Zod schemas for both runtime validation and LLM tool +`@n8n/agents` uses Zod schemas for both runtime validation and LLM tool descriptions. The `.describe()` strings on schema fields become the parameter descriptions the LLM sees when deciding how to call a tool. Missing or vague descriptions lead to bad tool calls. The `outputSchema` -lets Mastra validate return values and gives the LLM structured expectations. +lets `@n8n/agents` validate return values and gives the LLM structured expectations. - Always define both `inputSchema` and `outputSchema` - Use `.describe()` on Zod fields — these are the LLM's parameter docs diff --git a/packages/@n8n/instance-ai/docs/architecture.md b/packages/@n8n/instance-ai/docs/architecture.md index 9c1b1665cbf..d2d7bde0f41 100644 --- a/packages/@n8n/instance-ai/docs/architecture.md +++ b/packages/@n8n/instance-ai/docs/architecture.md @@ -95,10 +95,13 @@ The system implements the four pillars of the deep agent pattern: ### 1. Explicit Planning -The orchestrator uses a `plan` tool to externalize its execution strategy. -Between phases of the autonomous loop, the orchestrator reviews and updates the -plan. This serves as a context engineering mechanism — writing the plan forces -structured reasoning, and reading it back prevents goal drift over long loops. +The orchestrator loads the `planning` skill to externalize its execution +strategy for work that needs dependency coordination: multiple workflows, shared +artifacts, cross-workflow data contracts, or ambiguous business process design. +After normal discovery, it calls `create-tasks` to persist the task graph for +user approval. Clear single-workflow builds, including new and one-off +workflows, go directly to the builder and do not create a plan merely to obtain +verification. Plans are stored in thread-scoped storage (see ADR-017). @@ -116,7 +119,7 @@ directly to the event bus (ADR-014). They cannot spawn their own sub-agents. ### 3. Observational Memory -Mastra's observational memory compresses old messages into dense observations via +`@n8n/agents` observational memory compresses old messages into dense observations via background Observer and Reflector agents. Tool-heavy workloads (workflow definitions, execution results) get 5–40x compression. This prevents context degradation over 50+ step autonomous loops (see ADR-016). @@ -132,11 +135,11 @@ prompts written by the orchestrator. ```mermaid graph TD O[Orchestrator Agent] -->|delegate| S1[Sub-Agent: role A] - O -->|plan| S3[Planned Tasks] + O -->|planning skill + create-tasks| S3[Planned Tasks] O -->|direct| T1[list-workflows] O -->|direct| T2[run-workflow] O -->|direct| T3[get-execution] - O -->|direct| T4[plan] + O -->|direct| T4[create-tasks] O -->|direct| T5[data-tables] S3 -->|kind: build-workflow| S4[Orchestrator Follow-Up] @@ -157,17 +160,19 @@ graph TD **Orchestrator** handles directly: - Read-only queries (list-workflows, get-execution, list-credentials) - Execution triggers (run-workflow) -- Planning (plan tool — always direct) +- Planning (`planning` skill + `create-tasks` — always direct) - Verification and credential application (verify-built-workflow, apply-workflow-credentials) **Single-task delegation** (`delegate`): - Complex multi-step operations that are not handled by a planned build follow-up - Tasks that benefit from clean context (no accumulated noise) -**Multi-task plans** (`plan` tool): +**Multi-task plans** (`planning` skill + `create-tasks`): - Dependency-aware task graphs with parallel execution - Each task dispatched to a preconfigured executor (build-workflow, checkpoint, or delegate) - User approves the plan before execution starts +- Workflow runtime verification is tracked separately as a workflow-loop + obligation, so routine "verify workflow" checkpoints are not required The orchestrator decides what to delegate based on complexity — simple reads stay direct, complex operations go to focused sub-agents. @@ -180,7 +185,7 @@ The agent package — framework-agnostic business logic. - **Agent factory** (`agent/`) — creates orchestrator instances with tools, memory, MCP, and tool search - **Sub-agent factory** (`agent/`) — creates stateless sub-agents with mandatory protocol and tool subsets -- **Orchestration tools** (`tools/orchestration/`) — `plan`, `delegate`, `update-tasks`, `cancel-background-task`, `correct-background-task`, `verify-built-workflow`, `report-verification-verdict`, `apply-workflow-credentials` +- **Orchestration tools** (`tools/orchestration/`) — `create-tasks`, `delegate`, `update-tasks`, `cancel-background-task`, `correct-background-task`, `verify-built-workflow`, `report-verification-verdict`, `apply-workflow-credentials` - **Domain tools** (`tools/`) — native tools across workflows, executions, credentials, nodes, data tables, workspace, and web research - **Knowledge base** (`knowledge-base/`, `workspace/`) — best-practices guides and curated templates materialized in the builder sandbox for workspace tools to read - **Runtime** (`runtime/`) — stream execution engine, resumable streams with HITL suspension, background task manager, run state registry @@ -192,7 +197,7 @@ The agent package — framework-agnostic business logic. - **Storage** (`storage/`) — iteration logs, task storage, planned task storage, workflow loop storage, agent tree snapshots - **MCP client** (`mcp/`) — manages connections to external MCP servers, schema sanitization for Anthropic compatibility - **Domain access** (`domain-access/`) — domain gating and access tracking for external URL approval -- **Stream mapping** (`stream/`) — Mastra chunk → canonical event translation, HITL consumption +- **Stream mapping** (`stream/`) — agent chunk → canonical event translation, HITL consumption - **Event bus interface** (`event-bus/`) — publishing agent events to the thread channel - **Tracing** (`tracing/`) — LangSmith integration for step-level observability - **System prompt** (`agent/`) — dynamic context-aware prompt based on instance configuration @@ -287,19 +292,19 @@ Instance AI uses n8n's module system (`@BackendModule`). This means: ## Runtime & Streaming -The agent runtime is built on Mastra's streaming primitives with added +The agent runtime is built on `@n8n/agents` streaming primitives with added resumability, HITL suspension, and background task management. ### Stream Execution ``` streamAgentRun() → agent.stream() → executeResumableStream() - ├─ for each chunk: mapMastraChunkToEvent() → eventBus.publish() + ├─ for each chunk: mapAgentChunkToEvent() → eventBus.publish() ├─ on suspension: wait for confirmation → agent.resumeStream() → loop - └─ return StreamRunResult {status, mastraRunId, text} + └─ return StreamRunResult {status, agentRunId, text} ``` -The `executeResumableStream()` loop consumes Mastra chunks, translates them to +The `executeResumableStream()` loop consumes agent chunks, translates them to canonical `InstanceAiEvent` schema, publishes to the event bus, and handles HITL suspension/resume cycles. Two control modes: @@ -331,23 +336,25 @@ In-memory registry of active, suspended, and pending runs per thread. Manages: ### Planned Task System -The `plan` tool creates dependency-aware task graphs for multi-step work. Each -task has a `kind` that determines its executor: +The `planning` skill guides discovery and `create-tasks` creates +dependency-aware task graphs for multi-step work. Each task has a `kind` that +determines its executor: | Kind | Executor | Tools | |------|----------|-------| | `build-workflow` | Builder agent | search-nodes, build-workflow, get-node-type-definition, etc. | | `delegate` | Custom sub-agent | Orchestrator-specified subset | -| `checkpoint` | Orchestrator follow-up | verify-built-workflow, executions | +| `checkpoint` | Orchestrator follow-up | Semantic or cross-workflow validation that standard runtime verification cannot cover | Standalone data-table work bypasses planned tasks: the orchestrator loads the -`data-table-manager` skill and uses `data-tables` / `parse-file` directly. +`data-table-manager` skill and uses `data-tables` / `parse-file` directly. A +single workflow with a workflow-local table can use the direct builder path; +planning is reserved for shared schema work or real dependency coordination. -Build and delegate tasks run detached as background agents. Checkpoint -tasks run as orchestrator follow-ups so they can inspect the latest workflow -state before verifying. Dependencies are respected — a task only starts when all -its `deps` have succeeded. The plan is shown to the user for approval before -execution begins. +Build and delegate tasks run detached as background agents. Checkpoint tasks run +as orchestrator follow-ups when the plan includes an exceptional semantic check. +Dependencies are respected — a task only starts when all its `deps` have +succeeded. The plan is shown to the user for approval before execution begins. ### Workflow Loop State Machine @@ -362,7 +369,17 @@ build → submit → verify → (success | needs_patch | needs_rebuild | failed_ verify verify ``` -The `report-verification-verdict` tool feeds results into this state machine, +Workflow-loop storage also derives a `WorkflowVerificationObligation` from each +builder outcome. The service uses this obligation as the completion gate for both +direct and planned workflow builds: + +- `ready_to_verify` schedules an internal workflow-verification follow-up. +- `verified` reuses structured `verify-built-workflow` evidence. +- `needs_setup` routes to `workflows(action="setup")`. +- `not_verifiable` is a warning/manual-test completion state, not "verified". +- `blocked` carries the build or verification blocker. + +The `report-verification-verdict` tool feeds results into the state machine, which returns guidance for the next action. Same failure signature twice triggers a terminal state to prevent infinite loops. @@ -370,7 +387,7 @@ a terminal state to prevent infinite loops. To keep the orchestrator's context lean, tools are stratified into two tiers: -- **Core tools** (always-loaded): `plan`, `delegate`, `ask-user`, `web-search`, +- **Core tools** (always-loaded): `create-tasks`, `delegate`, `ask-user`, `web-search`, `fetch-url` — these are directly available to the LLM - **Deferred tools** (behind ToolSearchProcessor): all other domain tools — discovered on-demand via `search_tools` and activated via `load_tool` diff --git a/packages/@n8n/instance-ai/docs/configuration.md b/packages/@n8n/instance-ai/docs/configuration.md index d54c05da0e9..46d52e482c8 100644 --- a/packages/@n8n/instance-ai/docs/configuration.md +++ b/packages/@n8n/instance-ai/docs/configuration.md @@ -14,8 +14,6 @@ All Instance AI configuration is done via environment variables. | `N8N_INSTANCE_AI_MCP_SERVERS` | string | `''` | Comma-separated MCP server configs. Format: `name=url,name=url` | | `N8N_INSTANCE_AI_SUB_AGENT_MAX_STEPS` | number | `100` | Maximum LLM reasoning steps for sub-agents spawned via delegate tool | | `N8N_INSTANCE_AI_LOCAL_GATEWAY_DISABLED` | boolean | `false` | Disable the local gateway (filesystem, shell, browser) for all users | -| `N8N_INSTANCE_AI_ENFORCE_CREATE_TASKS_REPLAN` | boolean | `true` | Reject `create-tasks` outside replan contexts unless the request explicitly bypasses planner discovery. | -| `N8N_INSTANCE_AI_ENFORCE_BUILD_VIA_PLAN` | boolean | `true` | Reject direct `build-workflow` calls unless they run from an approved plan or explicitly allowed build context. | ### Tracing @@ -26,6 +24,12 @@ All Instance AI configuration is done via environment variables. | `LANGSMITH_ENDPOINT` / `LANGCHAIN_ENDPOINT` | string | unset | Optional direct LangSmith endpoint override. | | `LANGSMITH_TRACING` / `LANGCHAIN_TRACING_V2` | boolean | unset | LangSmith SDK tracing flags. `false` disables tracing; `true` enables direct tracing when direct LangSmith credentials or endpoints are configured. | +### Debugging + +| Variable | Type | Default | Description | +|----------|------|---------|-------------| +| `N8N_INSTANCE_AI_RUN_DEBUG_ENABLED` | boolean | `false` | Capture orchestrator LLM steps and workflow code snapshots for the dev debug panel and eval LLM debug reports. | + ### Memory | Variable | Type | Default | Description | @@ -67,6 +71,10 @@ When no search provider is available, the `web-search` action is disabled. `fetc | `N8N_INSTANCE_AI_SANDBOX_IMAGE` | string | `daytonaio/sandbox:0.5.0` | Docker image for the Daytona sandbox. | | `N8N_INSTANCE_AI_SANDBOX_TIMEOUT` | number | `300000` | Default command timeout in the sandbox (milliseconds). | | `N8N_INSTANCE_AI_SANDBOX_NAME_PREFIX` | string | `''` | Prefix prepended to every Daytona sandbox name (e.g. `eval-baseline-daily`). Also surfaced as a `name_prefix` label. Empty in production. | +| `N8N_INSTANCE_AI_SANDBOX_EPHEMERAL` | boolean | `false` | When true, Daytona sandboxes are created ephemeral (auto-deleted on stop) instead of lingering stopped. Intended for throwaway eval instances so sandboxes don't accumulate. | +| `N8N_INSTANCE_AI_SANDBOX_AUTO_STOP_MINUTES` | number | `15` | Minutes an idle Daytona sandbox waits before being stopped. `0` disables auto-stop. | +| `N8N_INSTANCE_AI_SANDBOX_AUTO_ARCHIVE_MINUTES` | number | `10080` (7 days) | Minutes a stopped Daytona sandbox waits before being archived to cold storage. `0` uses Daytona's maximum interval. | +| `N8N_INSTANCE_AI_SANDBOX_AUTO_DELETE_MINUTES` | number | `43200` (30 days) | Minutes a stopped Daytona sandbox waits before being deleted. Negative disables auto-delete; `0` deletes on stop. Ignored when `N8N_INSTANCE_AI_SANDBOX_EPHEMERAL` is true. | When sandbox is enabled, the builder agent writes TypeScript to `~/workspace/src/workflow.ts`, runs `tsc` for validation, and uses @@ -93,6 +101,26 @@ Observer and Reflector use the same model as the orchestrator agent (see `@n8n/a | `N8N_INSTANCE_AI_SNAPSHOT_RETENTION` | number | `86400000` | Retention period in ms for orphaned workflow snapshots before pruning. | | `N8N_INSTANCE_AI_CONFIRMATION_TIMEOUT` | number | `86400000` | Timeout in ms for HITL confirmation requests. 0 = no timeout. | +### Output Filtering + +Agent output is scanned for secrets/PII and redacted before it reaches the user. +The scan covers streamed assistant text, reasoning, and tool results/errors, for +both the orchestrator and delegated sub-agents. A filtering event (categories +and counts only — never the values) is logged whenever a redaction occurs. + +| Variable | Type | Default | Description | +|----------|------|---------|-------------| +| `N8N_INSTANCE_AI_OUTPUT_REDACTION_ENABLED` | boolean | `true` | Master switch. When `false`, output passes through untouched. | +| `N8N_INSTANCE_AI_OUTPUT_REDACTION_SECRETS` | boolean | `true` | Redact credential/secret patterns (API keys, tokens, auth headers, `key=value` pairs). | +| `N8N_INSTANCE_AI_OUTPUT_REDACTION_PII` | string | `credit-card` | Comma-separated PII categories to redact. Available: `email`, `credit-card` (Luhn-validated), `ssn-us` (US Social Security Number, dashed `123-45-6789` form). Defaults to `credit-card` only; `email`/`ssn-us` are implemented but off by default pending review of false-positive rates. Empty = no PII scanning. Unrecognized values are ignored. Per-country national IDs each use their own `ssn-<cc>` category (e.g. a future `ssn-uk`). | +| `N8N_INSTANCE_AI_OUTPUT_REDACTION_PLACEHOLDER` | string | `[REDACTED]` | Replacement text substituted for each redacted match. | + +Secret detection is conservative by design — it matches well-known token shapes +and explicit `key=value`/JSON secret fields, not arbitrary opaque strings, to +avoid mangling normal output. The `PiiDetectionType` API also reserves `phone` +and `address`, but those have no detection pattern yet — setting them has no +effect (they were deferred as too false-positive-prone for free-form prose). + ## Enabling / Disabling The module is **enabled** when `N8N_INSTANCE_AI_MODEL` is set to a non-empty value. @@ -153,47 +181,40 @@ Runtime behavior: N8N_INSTANCE_AI_MODEL=anthropic/claude-opus-4-8 # With MCP servers -N8N_INSTANCE_AI_MODEL=anthropic/claude-opus-4-8 N8N_INSTANCE_AI_MCP_SERVERS="my-tools=https://mcp.example.com/sse" # With SearXNG (free, self-hosted search) -N8N_INSTANCE_AI_MODEL=anthropic/claude-opus-4-8 N8N_INSTANCE_AI_SEARXNG_URL=http://searxng:8080 # With Brave Search (paid API, takes priority over SearXNG) -N8N_INSTANCE_AI_MODEL=anthropic/claude-opus-4-8 INSTANCE_AI_BRAVE_SEARCH_API_KEY=BSA-xxx # With sandbox (n8n sandbox service) # CI can start it with: # pnpm tsx packages/testing/containers/start-sandbox.ts --network n8n-eval-net -N8N_INSTANCE_AI_MODEL=anthropic/claude-sonnet-4-5 N8N_INSTANCE_AI_SANDBOX_ENABLED=true N8N_INSTANCE_AI_SANDBOX_PROVIDER=n8n-sandbox N8N_SANDBOX_SERVICE_URL=https://sandbox.example.com N8N_SANDBOX_SERVICE_API_KEY=sandbox-key # With sandbox (Daytona — explicit provider) -N8N_INSTANCE_AI_MODEL=anthropic/claude-opus-4-8 N8N_INSTANCE_AI_SANDBOX_ENABLED=true N8N_INSTANCE_AI_SANDBOX_PROVIDER=daytona DAYTONA_API_URL=https://app.daytona.io/api DAYTONA_API_KEY=dtn_xxx # With filesystem gateway (user runs daemon on their machine) -N8N_INSTANCE_AI_MODEL=anthropic/claude-opus-4-8 N8N_INSTANCE_AI_GATEWAY_API_KEY=my-secret-key # User runs: npx @n8n/computer-use # With custom OpenAI-compatible endpoint (e.g. LM Studio, Ollama) -N8N_INSTANCE_AI_MODEL=custom/llama-3.1-70b N8N_INSTANCE_AI_MODEL_URL=http://localhost:1234/v1 -# Full configuration with observational memory tuning -N8N_INSTANCE_AI_MODEL=anthropic/claude-opus-4-8 -N8N_INSTANCE_AI_MCP_SERVERS="github=https://mcp.github.com/sse" -N8N_INSTANCE_AI_MAX_STEPS=50 -N8N_INSTANCE_AI_MAX_LOOP_ITERATIONS=10 +# Output filtering — secrets + email only, with a custom placeholder +N8N_INSTANCE_AI_OUTPUT_REDACTION_PII=email +N8N_INSTANCE_AI_OUTPUT_REDACTION_PLACEHOLDER=‹redacted› + +# Observational memory tuning N8N_INSTANCE_AI_OBSERVER_MESSAGE_TOKENS=30000 ``` diff --git a/packages/@n8n/instance-ai/docs/e2e-tests.md b/packages/@n8n/instance-ai/docs/e2e-tests.md index 837f049b557..c4aa761d3b9 100644 --- a/packages/@n8n/instance-ai/docs/e2e-tests.md +++ b/packages/@n8n/instance-ai/docs/e2e-tests.md @@ -168,7 +168,7 @@ Some tools pass through without wrapping: | Tool | Why | |------|-----| -| `plan` | Pure text orchestration, no IDs | +| `create-tasks` | Pure text orchestration, no IDs | | `delegate` | Must spawn real sub-agent (which gets its own wrapping) | | `update-tasks` | Orchestration bookkeeping | diff --git a/packages/@n8n/instance-ai/docs/memory.md b/packages/@n8n/instance-ai/docs/memory.md index b06d899ef87..a1c1cbf8123 100644 --- a/packages/@n8n/instance-ai/docs/memory.md +++ b/packages/@n8n/instance-ai/docs/memory.md @@ -77,10 +77,9 @@ of the current task. ### Tier 4: Plan Storage -The `plan` tool stores execution plans in thread-scoped storage. Plans are -structured data (goal, current phase, iteration count, step statuses) that -persist across reconnects within a conversation. See the [tools](./tools.md) -documentation for the plan tool schema. +The `create-tasks` tool stores execution plans in thread-scoped storage. Plans +are structured task graphs that persist across reconnects within a conversation. +See the [tools](./tools.md) documentation for the task graph schema. ## Scoping Model diff --git a/packages/@n8n/instance-ai/docs/sandboxing.md b/packages/@n8n/instance-ai/docs/sandboxing.md index 4fa92b17c9e..702de708f3e 100644 --- a/packages/@n8n/instance-ai/docs/sandboxing.md +++ b/packages/@n8n/instance-ai/docs/sandboxing.md @@ -6,15 +6,15 @@ Today the main consumer is the workflow builder. The agent writes TypeScript fil ## How the Pieces Fit Together -There are three layers between the agent and actual code execution: a workspace abstraction from Mastra, a sandbox provider (n8n sandbox service or Daytona), and the execution runtime inside the sandbox. Here is how they relate: +There are three layers between the agent and actual code execution: a workspace abstraction from `@n8n/agents`, a sandbox provider (n8n sandbox service or Daytona), and the execution runtime inside the sandbox. Here is how they relate: ```mermaid graph TB subgraph Agent ["Agent Layer"] - LLM[LLM] --> AgentRuntime["Agent Runtime (Mastra)"] + LLM[LLM] --> AgentRuntime["Agent Runtime (@n8n/agents)"] end - subgraph WorkspaceLayer ["Workspace Abstraction (Mastra)"] + subgraph WorkspaceLayer ["Workspace Abstraction (@n8n/agents)"] AgentRuntime --> Workspace["Workspace"] Workspace --> FS["Filesystem Interface<br/>(read, write, list, edit files)"] Workspace --> Sandbox["Sandbox Interface<br/>(execute shell commands)"] @@ -42,14 +42,14 @@ graph TB The agent never talks to Daytona, the n8n sandbox service, or the host filesystem directly. It only sees the Workspace, which exposes two capabilities: a filesystem (read/write/list files) and a sandbox (run shell commands). The Workspace routes those operations to whichever provider is configured. -## Mastra Workspaces +## Workspaces -Mastra is the agent framework that Instance AI uses. A Mastra **Workspace** is a pairing of two things: +`@n8n/agents` is the agent SDK that Instance AI uses. A **Workspace** is a pairing of two things: 1. **A Sandbox** — an interface for executing shell commands. It accepts a command string and returns stdout, stderr, and an exit code. Think of it as a remote terminal. 2. **A Filesystem** — an interface for file operations: read, write, list, delete, copy, move. Think of it as a remote disk. -When a Workspace is attached to an agent, Mastra automatically exposes built-in tools to the LLM: `read_file`, `write_file`, `edit_file`, `list_files`, `grep`, `execute_command`, and others. The agent uses these tools naturally in its reasoning loop — it writes a file, runs a command, reads the output, and decides what to do next. +When a Workspace is attached to an agent, `@n8n/agents` automatically exposes built-in tools to the LLM: `read_file`, `write_file`, `edit_file`, `list_files`, `grep`, `execute_command`, and others. The agent uses these tools naturally in its reasoning loop — it writes a file, runs a command, reads the output, and decides what to do next. The key design property is that the Workspace abstraction is provider-agnostic. The agent's code and prompts are identical regardless of whether the workspace is backed by n8n sandbox service or Daytona. The provider choice is purely an infrastructure decision. @@ -106,7 +106,7 @@ sequenceDiagram D-->>n8n: Sandbox ID n8n->>S: Write node-types catalog via filesystem API - n8n->>n8n: Wrap sandbox as Mastra Workspace + n8n->>n8n: Wrap sandbox as Workspace n8n->>n8n: Inject Workspace into builder agent Note over S: Agent works inside sandbox @@ -124,7 +124,7 @@ The process starts with a **pre-warmed image**. On first use, n8n builds a Dayto One thing that cannot be baked into the image is the **node-types catalog** (a searchable index of all available n8n nodes). It is too large for the image build API, so it is written to each sandbox after creation via the filesystem API. -Once the sandbox is provisioned and the catalog is written, n8n wraps it in a Mastra Workspace and hands it to the builder agent. From that point, the agent works autonomously inside the sandbox — writing files, running the compiler, fixing errors, iterating — until it produces a valid workflow. +Once the sandbox is provisioned and the catalog is written, n8n wraps it in a Workspace and hands it to the builder agent. From that point, the agent works autonomously inside the sandbox — writing files, running the compiler, fixing errors, iterating — until it produces a valid workflow. ### What is inside a Daytona sandbox @@ -139,7 +139,7 @@ Once the sandbox is provisioned and the catalog is written, n8n wraps it in a Ma ## n8n Sandbox Service: Default Provider -The n8n sandbox service exposes a simple HTTP API for creating sandboxes, executing shell commands, and manipulating files. Instance AI uses it through a custom Mastra sandbox and filesystem adapter. +The n8n sandbox service exposes a simple HTTP API for creating sandboxes, executing shell commands, and manipulating files. Instance AI uses it through a custom `@n8n/agents` sandbox and filesystem adapter. This provider supports the builder's file and command workflow, but it does not expose interactive process handles. That means `execute_command` works, while process-manager-backed features such as long-lived spawned subprocesses are out of scope for this provider. @@ -247,3 +247,7 @@ If any step fails, the agent reads the error output, fixes the code, and retries | `N8N_INSTANCE_AI_SANDBOX_IMAGE` | `daytonaio/sandbox:0.5.0` | Base container image for Daytona | | `N8N_INSTANCE_AI_SANDBOX_TIMEOUT` | `300000` | Command timeout in milliseconds | | `N8N_INSTANCE_AI_SANDBOX_NAME_PREFIX` | — | Prefix for every Daytona sandbox name (e.g. `eval-baseline-daily`). Also added as a `name_prefix` label. Empty in production. | +| `N8N_INSTANCE_AI_SANDBOX_EPHEMERAL` | `false` | Create Daytona sandboxes ephemeral (auto-deleted on stop) instead of lingering stopped. Intended for throwaway eval instances so sandboxes don't accumulate. | +| `N8N_INSTANCE_AI_SANDBOX_AUTO_STOP_MINUTES` | `15` | Minutes an idle sandbox waits before Daytona stops it. `0` = disabled (stays running). | +| `N8N_INSTANCE_AI_SANDBOX_AUTO_ARCHIVE_MINUTES` | `10080` (7 days) | Minutes a stopped sandbox waits before Daytona archives it to cold storage. `0` = Daytona's max interval. | +| `N8N_INSTANCE_AI_SANDBOX_AUTO_DELETE_MINUTES` | `43200` (30 days) | Minutes a stopped sandbox waits before Daytona deletes it. Negative = disabled; `0` = on stop. Ignored when `N8N_INSTANCE_AI_SANDBOX_EPHEMERAL` is true. | diff --git a/packages/@n8n/instance-ai/docs/streaming-protocol.md b/packages/@n8n/instance-ai/docs/streaming-protocol.md index bdaf439a75b..223a9b9ae02 100644 --- a/packages/@n8n/instance-ai/docs/streaming-protocol.md +++ b/packages/@n8n/instance-ai/docs/streaming-protocol.md @@ -339,7 +339,7 @@ When a run errors: ``` ← run-start {runId: "r1", agentId: "a1", payload: {messageId: "m1"}} -← tool-call {runId: "r1", agentId: "a1", payload: {toolName: "plan", ...}} +← tool-call {runId: "r1", agentId: "a1", payload: {toolName: "create-tasks", ...}} ← tool-result {runId: "r1", agentId: "a1", payload: {result: {goal: "Weather to Slack"}}} ← tool-call {runId: "r1", agentId: "a1", payload: {toolName: "delegate", toolCallId: "tc2"}} ← agent-spawned {runId: "r1", agentId: "a2", payload: {parentId: "a1", role: "workflow builder"}} @@ -357,7 +357,7 @@ When a run errors: ← reasoning-delta {runId: "r1", agentId: "a3", payload: {text: "The HTTP node returned 401..."}} ← agent-completed {runId: "r1", agentId: "a3", payload: {result: "Missing API key header"}} ← tool-result {runId: "r1", agentId: "a1", payload: {toolCallId: "tc5", result: "Missing API key"}} -← tool-call {runId: "r1", agentId: "a1", payload: {toolName: "plan", args: {action: "update"}}} +← tool-call {runId: "r1", agentId: "a1", payload: {toolName: "create-tasks", args: {planningContext: {source: "replan"}}}} ← ...loop continues... ← text-delta {runId: "r1", agentId: "a1", payload: {text: "Done! I created a workflow..."}} ← run-finish {runId: "r1", agentId: "a1", payload: {status: "completed"}} @@ -434,7 +434,7 @@ The frontend renders events as a collapsible tree grouped by `agentId`: 🤖 Orchestrator ├── 💭 "Let me check what credentials are available..." ├── 🔧 list-credentials → [slack-bot, weather-api] -├── 📋 plan: build → execute → inspect +├── 📋 create-tasks: build → execute → inspect │ ├── 🤖 Sub-Agent A (workflow builder) │ ├── 🔧 list-nodes → [scheduleTrigger, httpRequest, slack] @@ -482,14 +482,14 @@ replaying all SSE events. ### How It Works -1. **Mastra V2 messages** — Mastra persists tool invocations, reasoning, and - text in its V2 message format. The backend parses these into rich +1. **Persisted messages** — `@n8n/agents` persists tool invocations, reasoning, and + text in its message format. The backend parses these into rich `InstanceAiMessage[]` objects with tool calls and flat agent trees. 2. **Agent tree snapshots** — after each `run-finish`, the backend replays events through `buildAgentTreeFromEvents()` and stores the resulting tree in thread metadata. This preserves the full sub-agent hierarchy (tool - calls, text, reasoning) that the V2 message format alone cannot capture. + calls, text, reasoning) that the message format alone cannot capture. 3. **SSE cursor** — the messages response includes `nextEventId`. The frontend sets its SSE cursor to `nextEventId - 1` so the SSE connection only receives diff --git a/packages/@n8n/instance-ai/docs/tools.md b/packages/@n8n/instance-ai/docs/tools.md index f223885597c..61e1133f246 100644 --- a/packages/@n8n/instance-ai/docs/tools.md +++ b/packages/@n8n/instance-ai/docs/tools.md @@ -10,15 +10,22 @@ its input/output schema via Zod. These tools are exclusive to the orchestrator agent. Sub-agents do not receive them. Some are conditional on context availability. -### `plan` +### `create-tasks` -Persist a dependency-aware task plan for detached multi-step execution. Use only -when the work requires 2+ tasks with dependencies. The plan is shown to the user -for approval before execution starts. +Persist a dependency-aware task plan for detached multi-step execution. For +initial plan-worthy work, the orchestrator loads the `planning` skill, performs +discovery with normal domain tools, then calls `create-tasks` with +`planningContext.source: "planning-skill"`. For +`<planned-task-follow-up type="replan">` turns, use +`planningContext.source: "replan"` when multiple dependent tasks still need +scheduling. Clear single-workflow builds, including new and one-off workflows, +use `workflow-builder` plus `build-workflow` directly. The plan is shown to the +user for approval before execution starts. | Field | Type | Required | Description | |-------|------|----------|-------------| | `tasks` | array | yes | Dependency-aware execution plan (see schema below) | +| `planningContext` | object | yes | `{ source: "planning-skill" \| "replan", summary: string, assumptions?: string[] }` | **Task schema**: @@ -31,6 +38,7 @@ for approval before execution starts. deps: string[]; // Task IDs that must succeed before this task can start tools?: string[]; // Required tool subset for delegate tasks workflowId?: string; // Existing workflow ID to modify (build-workflow tasks only) + isSupportingWorkflow?: boolean; // Build task completes after saving a supporting sub-workflow } ``` @@ -40,15 +48,19 @@ for approval before execution starts. - First call persists the plan, publishes `tasks-update` event, and **suspends** for user approval - On approval: calls `schedulePlannedTasks()` to start detached execution -- On denial: returns feedback for the LLM to revise the plan +- On rejection: returns feedback for the LLM to revise the plan +- On denial: cancels the graph and blocks same-turn resubmission **Task kinds** map to executors: - `build-workflow` → orchestrator follow-up run using the workflow-builder skill - `delegate` → custom sub-agent with orchestrator-specified tool subset -- `checkpoint` → orchestrator-executed verification step +- `checkpoint` → exceptional orchestrator-executed semantic or cross-workflow check Standalone data-table work is handled directly by the orchestrator with the -`data-table-manager` skill and the `data-tables` / `parse-file` tools. +`data-table-manager` skill and the `data-tables` / `parse-file` tools. Single +workflow-local table requirements belong in the builder task spec; plan only +when the table schema is shared, independently durable, or creates real +dependency coordination. ### `delegate` @@ -69,7 +81,7 @@ fixed taxonomy of sub-agent types. **Behavior**: - Validates `tools` against registered native domain tool names -- Forbids orchestration tools (`plan`, `delegate`) and MCP tools +- Forbids orchestration tools (`create-tasks`, `delegate`) and MCP tools - Creates a fresh agent with specified tools and low `maxSteps` (default 10) - Sub-agent publishes events directly to the event bus - Sub-agent has no memory — receives context only via the briefing @@ -82,7 +94,7 @@ tracking during synchronous work. | Field | Type | Required | Description | |-------|------|----------|-------------| -| `tasks` | array | yes | List of `{id, description, status}` items | +| `tasks` | array | yes | List of `{id, description, status, detail?}` items | **Returns**: `{ result: string }` @@ -120,7 +132,20 @@ Send a course correction to a running background task. ### `verify-built-workflow` *(conditional)* -Run a built workflow with sidecar pin data for verification (never persisted). +Run a built workflow with per-execution pin data for verification (never +persisted to the workflow). Destructive and user-action nodes — write +operations, nodes with mocked credentials, mid-workflow Form pages, Wait +nodes — are **simulated**: the build outcome carries a per-node +execute-vs-simulate plan (`nodeSimulationPlan`, produced by a deterministic +classifier plus an LLM pass at submit time) and LLM-generated mock output +(`simulationFixtures`). Simulated nodes are pinned with their fixture, so +verification never sends messages, writes rows, deletes data, or parks in +`waiting`. The tool output marks simulated nodes (`simulatedNodes`, +`nodePreviews[].simulated`, `simulationNote`), and the saved execution +carries `resultData.simulation` so the editor can label simulated outputs. +For build outcomes that carry a plan, a `waiting` result is a failure (an +unsimulated user-action node); only legacy plan-less outcomes keep the +waiting-with-output-as-success fallback. | Field | Type | Required | Description | |-------|------|----------|-------------| @@ -138,7 +163,10 @@ Run a built workflow with sidecar pin data for verification (never persisted). | Chat Trigger | `{chatInput: "..."}` | `{ sessionId, action, chatInput }` | | Schedule | omit | synthetic timestamp fields | -**Writes on success/failure**: the tool persists a structured `verification` record (`{ attempted, success, executionId, status, evidence, verifiedAt }`) onto the build outcome so subsequent checkpoint turns can reuse it without re-running verify. +**Writes on success/failure**: the tool persists a structured `verification` +record (`{ attempted, success, executionId, status, evidence, verifiedAt }`) onto +the build outcome so workflow-verification follow-ups and exceptional checkpoint +turns can reuse it without re-running verify. **Returns**: `{ executionId?, success, status?, data?, error? }` @@ -672,7 +700,7 @@ everything; sub-agents receive only what they need. | Tool Category | Orchestrator | Sub-Agents (delegate) | Background Agents | |---------------|:---:|:---:|:---:| -| Orchestration tools (`plan`, `delegate`, etc.) | ✅ | ❌ | ❌ | +| Orchestration tools (`create-tasks`, `delegate`, etc.) | ✅ | ❌ | ❌ | | Workflow tools | ✅ | ✅ (via delegate) | ✅ (builder) | | Execution tools | ✅ (direct use) | ✅ (via delegate) | ❌ | | Credential tools | ✅ | ✅ (via delegate) | ✅ (builder — setup only) | @@ -692,11 +720,11 @@ everything; sub-agents receive only what they need. 1. Create a file in `src/tools/<domain>/` following the naming convention `<verb>-<noun>.tool.ts` 2. Define input/output schemas with Zod (`.describe()` on fields — these are the LLM's parameter docs) -3. Export a factory function that takes the service context and returns a Mastra tool +3. Export a factory function that takes the service context and returns an `@n8n/agents` tool 4. Register the tool in `src/tools/index.ts` (in `createAllTools` or `createOrchestrationTools`) 5. If the tool requires a new service method, add it to the interface in `src/types.ts` and implement it in the backend adapter 6. New native domain tools are automatically available for delegation — the orchestrator can include them in sub-agent tool subsets via `delegate` -7. For HITL tools, define `suspendSchema` and `resumeSchema` — Mastra handles +7. For HITL tools, define `suspendSchema` and `resumeSchema` — `@n8n/agents` handles the suspension/resume lifecycle automatically diff --git a/packages/@n8n/instance-ai/evaluations/README.md b/packages/@n8n/instance-ai/evaluations/README.md index c2faf78a7c8..3e3819e0983 100644 --- a/packages/@n8n/instance-ai/evaluations/README.md +++ b/packages/@n8n/instance-ai/evaluations/README.md @@ -52,7 +52,8 @@ You need an n8n instance running with Instance AI enabled, a seeded owner accoun 1. **Create `.env.local`** at the repo root with at minimum: ```env - N8N_INSTANCE_AI_MODEL_API_KEY=sk-ant-... + N8N_INSTANCE_AI_MODEL=openai/gpt-5.5 + OPENAI_API_KEY=sk-proj-... N8N_EVAL_EMAIL=nathan@n8n.io N8N_EVAL_PASSWORD=PlaywrightTest123 # Optional — see "Environment variables" for the full list @@ -132,6 +133,7 @@ dotenvx run -f ../../../.env.local -- pnpm eval:instance-ai --iterations 3 | `--exclude` | — | Skip test cases whose filename matches any of the substrings. Same comma-separated shape as `--filter`; applied after `--filter` | | `--prebuilt-workflows` | — | Path to a JSON manifest mapping test-case slugs to existing workflow IDs. Skips the orchestrator build for matched test cases — see [Running evals against pre-built workflows](#running-evals-against-pre-built-workflows) | | `--keep-workflows` | `false` | Don't delete built workflows after the run. Pair with the HTML report's "view in n8n" links to inspect each scenario's canvas execution | +| `--delete-prebuilt-workflows` | `false` | With `--prebuilt-workflows`, delete successfully used manifest workflows after the eval run. Mutually exclusive with `--keep-workflows` | | `--base-url` | `http://localhost:5678` | n8n instance URL | | `--email` | E2E test owner | Override login email (or `N8N_EVAL_EMAIL`) | | `--password` | E2E test owner | Override login password (or `N8N_EVAL_PASSWORD`) | @@ -164,7 +166,7 @@ Every run produces: - **Console** — live progress, per-scenario pass/fail with `[failure_category]` tag, and a grouped summary. - **`eval-results.json`** — structured results in `--output-dir` (or cwd). Consumed by the CI PR comment. -- **`.data/workflow-eval-report.html`** — self-contained debugging view with per-node execution traces, intercepted requests, mock responses, Phase 1 hints, verifier reasoning, and the per-built-workflow check rubric (see below). +- **`.data/workflow-eval-report.html`** — self-contained debugging view with a green/red stage review for prompt, planner, builder, and verifier behavior, generalized prompt-improvement suggestions for failures, per-node execution traces, intercepted requests, mock responses, Phase 1 hints, verifier reasoning, and the per-built-workflow check rubric (see below). - **LangSmith experiment** — only when `LANGSMITH_API_KEY` is set. See the caveat in [Environment variables](#environment-variables). ### Workflow checks (per built workflow) @@ -195,11 +197,42 @@ Operational details: - 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_matches_workflow_changes`) reuse the same Sonnet model as the verifier — auto-skipped (N/A) when no Anthropic key is set. +### Build expectations (per test case) + +A test case can declare optional natural-language assertions about *how the build went* — `buildExpectations: string[]` in its JSON. Each is graded by a separate Sonnet judge (`build-expectations/verifier.ts`) against the **conversation transcript + final workflow + conversation metrics**, and **counts as a unit in the pass rate**: evaluated expectations fold into the per-case and headline pass@k/pass^k alongside execution scenarios. It doesn't flip an individual scenario's pass/fail (it's its own unit), and a judge `incomplete` verdict is excluded from the count. + +Use it for things the binary checks and `successCriteria` don't cover: + +- **Process / conversational** — `"Before building, the agent asked which Slack channel to use."` (judged from the transcript) +- **Outcome tied to the conversation** — `"The final workflow reflects the user's follow-up to split the records envelope before posting."` (judged from the workflow) + +```json +"buildExpectations": [ + "Before building, the agent asked which Airtable table and which Slack channel to use.", + "The agent honored the user's instruction to fetch via an HTTP Request node, not the Airtable node." +] +``` + +The signal surfaces in: + +- **HTML report** — a "Build expectations" disclosure on the test case: per-expectation ✓/✗ with a one-line judge reason. +- **`eval-results.json`** — `buildExpectations` (aggregated per-expectation pass rate) plus `buildExpectationResultsPerRun` (per-iteration verdicts). + +Operational details: + +- Judged **once per build** (not per scenario), fired concurrently with the scenario batch — ~0 added wall-clock in the common case. +- Runs on both eval paths (direct loop + LangSmith). Requires a build transcript, so it's judged even when the build fails, and skipped only when no transcript was captured. +- The judge retries on failure, has a per-attempt timeout, and falls back to an all-fail verdict — a judge failure can't break a run. +- Absent the field, it's a complete no-op. + ## Environment variables | Variable | Required | Description | |----------|----------|-------------| -| `N8N_INSTANCE_AI_MODEL_API_KEY` | Yes | Anthropic API key for the agent, mock generation, and verification | +| `N8N_INSTANCE_AI_MODEL` | Yes | Model used by Instance AI and, by default, the eval helper calls for mock generation and verification | +| `N8N_INSTANCE_AI_MODEL_API_KEY` | No | Generic eval-model API key override | +| `OPENAI_API_KEY` | No | Provider-specific key used automatically when `N8N_INSTANCE_AI_MODEL` starts with `openai/` | +| `ANTHROPIC_API_KEY` | No | Provider-specific key used automatically when `N8N_INSTANCE_AI_MODEL` starts with `anthropic/` | | `N8N_EVAL_EMAIL` | No | n8n login email (defaults to E2E test owner) | | `N8N_EVAL_PASSWORD` | No | n8n login password (defaults to E2E test owner) | | `LANGSMITH_API_KEY` | No | Enables experiment tracking + tracing. **See caveat below.** | @@ -208,6 +241,7 @@ Operational details: | `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 | +| `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. | **LangSmith caveat:** if `LANGSMITH_API_KEY` is set in `.env.local`, local runs also land in the shared `instance-ai-workflow-evals` dataset. Unset it (or run without `dotenvx`) to keep exploratory runs out of team results. @@ -279,7 +313,7 @@ dotenvx run -f ../../../.env.local -- pnpm eval:instance-ai \ --experiment-name mcp-cohort ``` -The harness leaves prebuilt workflows alone after the run (no auto-delete), so the manifest can be re-used across multiple eval runs. +The harness leaves prebuilt workflows alone after the run (no auto-delete), so the manifest can be re-used across multiple eval runs. If the workflows were created only for this eval cohort, pass `--delete-prebuilt-workflows` with `--prebuilt-workflows` to delete every successfully used manifest workflow once after the run. This is destructive: the manifest will still contain the deleted IDs and should not be re-used afterward. ### Producing a manifest @@ -321,8 +355,8 @@ pnpm eval:discovery --filter data-table-skill-loading --trials 3 --verbose --fai Verbose output lists each trial's completed tool calls with argument previews. For data-table routing, look for `load_skill(skillId="data-table-manager")` -and `data-tables(action="list")`, and verify there are no planner, -workflow-builder, or delegate sub-agent entries in the spawned-agent section. +and `data-tables(action="list")`, and verify there are no planning, +workflow-builder, or delegate entries in the spawned-agent section. ## Pairwise evals @@ -420,7 +454,7 @@ The agent is stubbed for non-interactive use. The summary tracks divergence from this assumption — investigate any non-zero count: - `askUserCount` — `ask-user` tool was invoked (eval responds with `{ approved: false }`) -- `planToolCount` — `plan` tool was invoked (single-prompt dataset shouldn't trigger planning) +- `planToolCount` — `create-tasks` was invoked (single-prompt dataset shouldn't trigger planning) - `autoApprovedSuspensions` — HITL-gated tool fired (e.g., `data-tables` create); auto-approved - `mockedCredentialTypes` — credential types the agent referenced (auto-mocked since `credentialService.list()` returns `[]`) @@ -483,31 +517,52 @@ When `LANGSMITH_API_KEY` is set, each run is recorded as a LangSmith experiment ## Adding test cases -Test cases live in `evaluations/data/workflows/*.json`. Drop a file in, the CLI and LangSmith sync picks it up — no registration step. +Test cases live in `evaluations/data/workflows/*.json`. Drop a file in — the CLI and LangSmith sync pick it up, no registration step. Every case is validated against `data/workflows/schema.ts`. ```json { - "prompt": "Create a workflow that...", + "description": "Optional note on what this case checks.", + "conversation": [ + { "role": "user", "text": "Every morning, post a summary of yesterday's signups to Slack #growth." } + ], "complexity": "medium", - "tags": ["build", "webhook", "gmail"], - "triggerType": "webhook", - "scenarios": [ + "tags": ["build", "schedule", "slack"], + "triggerType": "schedule", + "executionScenarios": [ { "name": "happy-path", "description": "Normal operation", - "dataSetup": "The webhook receives a submission from Jane (jane@example.com)...", - "successCriteria": "The workflow executes without errors. An email is sent to jane@example.com..." + "dataSetup": "The signups source returns 3 rows for yesterday: Ana, Ben, Cara.", + "successCriteria": "The workflow runs without errors and posts a summary of the 3 signups to Slack #growth." } ] } ``` -**One JSON file = one LangSmith split.** Scenarios in the same file share a split; split names derive from the filename slug. Pick a slug you're happy to also use as a `--filter` target. +`conversation` (≥1 turn, first must be `user`) and `executionScenarios` (≥1), plus `complexity` and `tags`, are required. `description`, `triggerType`, `messageBudget`, `buildExpectations`, and `datasets` (default `["full"]`) are optional. A turn's `text` may be a string or an array of strings joined with newlines — handy for long stage directions. -**Prompt tips** +**One JSON file = one LangSmith split**, named from the filename slug. Pick a slug you're happy to also use as a `--filter` target. -- Be specific about node configuration — document IDs, sheet names, channel names, chat IDs. The agent won't ask for these in eval mode (no multi-turn yet). -- Add "Configure all nodes as completely as possible and don't ask me for credentials, I'll set them up later." +### Conversations & stage directions + +`conversation` replaces the old single `prompt`; its mode is chosen automatically: + +- **Single-prompt (auto-approve):** one `user` turn, no `assistant` turns — the prompt is sent and every confirmation is auto-approved. Use for plain build cases. +- **Multi-turn:** anything else. A user-proxy LLM plays the user — it answers questions, audits the agent's plan against the script, and sends follow-ups (capped by `messageBudget`). `assistant` turns are *reference* for the proxy (the expected flow); they're never sent to the builder. + +Write the turns as a screenplay of what the user wants, keeping concrete values (channel IDs, schedules) verbatim. Inside a `user` turn, text in `[square brackets]` is a **stage direction** for the proxy — behaviour, not dialogue, never spoken to the builder. It overrides the proxy's defaults (e.g. "always answer"): + +| To make the user… | Direction | +|---|---| +| Withhold a value until asked | `[Don't bring up the channel unless the agent asks where to post; then say 'Slack #growth.']` | +| Refuse and hold firm on re-ask | `[The user has no channel and won't provide one. If asked — question or setup card, even repeatedly — skip it; never invent one.]` | +| Keep the conversation going | `[After each change lands, send the next one from the list, one at a time, until done.]` | + +A direction governs only what it covers; otherwise the proxy answers every question (inventing plausible placeholders) and never sets credentials. Setup cards (the "configure your workflow" card) are filled via the wizard — or dismissed when a direction withholds the value — not answered as questions. + +**Prompt / conversation tips** + +- Be specific about node configuration (IDs, sheet names, channel names). In single-prompt mode the agent won't ask; in multi-turn the proxy supplies or withholds per the script. - If a built-in node doesn't expose a field you need (e.g. the Linear node doesn't query `creator.email`), tell the agent to use HTTP Request instead. **Scenario tips** @@ -525,7 +580,7 @@ Test cases live in `evaluations/data/workflows/*.json`. Drop a file in, the CLI ### Adding a new credential type -`credentials/seeder.ts` seeds generic creds (HTTP Header, HTTP Basic) on every run, plus env-gated creds (GitHub, Gmail, Teams, Linear…) when the matching env var is set. If your scenario needs a credential type that isn't there, add it to the appropriate list in `seeder.ts` — env-gated if it requires a real token, generic if a placeholder is fine. +`credentials/seeder.ts` seeds every credential with a placeholder token on every run — execution is mocked at the wire level, so the value is never used. Set the matching `EVAL_*_ACCESS_TOKEN` to override a service with a real token for a live run. If your scenario needs a credential type that isn't seeded, add it to `seeder.ts`. ## Failure categories diff --git a/packages/@n8n/instance-ai/evaluations/__tests__/args.test.ts b/packages/@n8n/instance-ai/evaluations/__tests__/args.test.ts index 4de259f7512..0d1b84213a7 100644 --- a/packages/@n8n/instance-ai/evaluations/__tests__/args.test.ts +++ b/packages/@n8n/instance-ai/evaluations/__tests__/args.test.ts @@ -41,6 +41,7 @@ describe('parseCliArgs --base-url', () => { describe('parseCliArgs --prebuilt-workflows', () => { it('is undefined by default', () => { expect(parseCliArgs([]).prebuiltWorkflows).toBeUndefined(); + expect(parseCliArgs([]).deletePrebuiltWorkflows).toBe(false); }); it('accepts a path argument', () => { @@ -51,6 +52,32 @@ describe('parseCliArgs --prebuilt-workflows', () => { it('throws when no value is provided', () => { expect(() => parseCliArgs(['--prebuilt-workflows'])).toThrow(/Missing value/); }); + + it('accepts deleting prebuilt workflows when a manifest is provided', () => { + const args = parseCliArgs([ + '--prebuilt-workflows', + './mcp-manifest.json', + '--delete-prebuilt-workflows', + ]); + expect(args.deletePrebuiltWorkflows).toBe(true); + }); + + it('rejects deleting prebuilt workflows without a manifest', () => { + expect(() => parseCliArgs(['--delete-prebuilt-workflows'])).toThrow( + /--delete-prebuilt-workflows requires --prebuilt-workflows/, + ); + }); + + it('rejects deleting and keeping workflows at the same time', () => { + expect(() => + parseCliArgs([ + '--prebuilt-workflows', + './mcp-manifest.json', + '--delete-prebuilt-workflows', + '--keep-workflows', + ]), + ).toThrow(/--delete-prebuilt-workflows cannot be used with --keep-workflows/); + }); }); describe('parseCliArgs --exclude', () => { 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 new file mode 100644 index 00000000000..1ccb8b462f5 --- /dev/null +++ b/packages/@n8n/instance-ai/evaluations/__tests__/build-expectations-verifier.test.ts @@ -0,0 +1,151 @@ +import type { Mock, MockedFunction } from 'vitest'; +import { vi } from 'vitest'; + +vi.mock('../../src/utils/eval-agents', () => ({ + createEvalAgent: vi.fn(), + EPHEMERAL_CACHE: {}, + SONNET_MODEL: 'test-sonnet-model', +})); + +import { createEvalAgent } from '../../src/utils/eval-agents'; +import { verifyBuildExpectations } from '../build-expectations/verifier'; +import type { ConversationMetrics, TranscriptTurn } from '../types'; + +const mockCreateEvalAgent = createEvalAgent as MockedFunction<typeof createEvalAgent>; + +type JudgeResponse = { + structuredOutput?: { results: Array<{ index: number; pass: boolean; reason: string }> }; +}; +type GenerateFn = (messages: unknown, opts: unknown) => Promise<JudgeResponse>; +type GenerateMock = Mock<GenerateFn>; + +/** Wire createEvalAgent().structuredOutput().generate() to the given generate mock. */ +function mockJudge(generate: GenerateMock): void { + const structuredOutput = vi.fn().mockReturnValue({ generate }); + mockCreateEvalAgent.mockReturnValue({ structuredOutput } as unknown as ReturnType< + typeof createEvalAgent + >); +} + +const TRANSCRIPT: TranscriptTurn[] = [ + { + userMessage: 'Build a Slack notifier', + steps: [{ kind: 'agent-text', text: 'Which channel?' }], + }, + { userMessage: '#general', steps: [{ kind: 'agent-text', text: 'Done.' }] }, +]; + +describe('verifyBuildExpectations', () => { + beforeEach(() => { + vi.clearAllMocks(); + vi.spyOn(console, 'warn').mockImplementation(() => undefined); + }); + + it('returns empty and never calls the agent when there are no expectations', async () => { + const results = await verifyBuildExpectations([], { transcript: TRANSCRIPT }); + expect(results).toEqual([]); + expect(mockCreateEvalAgent).not.toHaveBeenCalled(); + }); + + it('maps verdicts back to the original expectation strings by index', async () => { + const generate: GenerateMock = vi.fn<GenerateFn>().mockResolvedValue({ + structuredOutput: { + results: [ + { index: 1, pass: false, reason: 'no Slack node' }, + { index: 0, pass: true, reason: 'asked first' }, + ], + }, + }); + mockJudge(generate); + + const results = await verifyBuildExpectations( + ['agent asked which channel', 'workflow posts to Slack'], + { transcript: TRANSCRIPT }, + ); + + expect(results).toEqual([ + { expectation: 'agent asked which channel', pass: true, reason: 'asked first' }, + { expectation: 'workflow posts to Slack', pass: false, reason: 'no Slack node' }, + ]); + }); + + it('synthesizes a fail for any expectation the judge omits', async () => { + const generate: GenerateMock = vi.fn<GenerateFn>().mockResolvedValue({ + structuredOutput: { results: [{ index: 0, pass: true, reason: 'ok' }] }, + }); + mockJudge(generate); + + const results = await verifyBuildExpectations(['first', 'second'], { + transcript: TRANSCRIPT, + }); + + expect(results).toEqual([ + { expectation: 'first', pass: true, reason: 'ok' }, + { expectation: 'second', pass: false, reason: 'no verdict returned', incomplete: true }, + ]); + }); + + it('ignores out-of-range indices returned by the judge', async () => { + const generate: GenerateMock = vi.fn<GenerateFn>().mockResolvedValue({ + structuredOutput: { + results: [ + { index: 0, pass: true, reason: 'ok' }, + { index: 7, pass: true, reason: 'phantom' }, + ], + }, + }); + mockJudge(generate); + + const results = await verifyBuildExpectations(['only one'], { transcript: TRANSCRIPT }); + + expect(results).toEqual([{ expectation: 'only one', pass: true, reason: 'ok' }]); + }); + + it('retries on an unparseable attempt then succeeds', async () => { + const generate: GenerateMock = vi + .fn<GenerateFn>() + .mockResolvedValueOnce({}) + .mockResolvedValueOnce({ + structuredOutput: { results: [{ index: 0, pass: true, reason: 'ok' }] }, + }); + mockJudge(generate); + + const results = await verifyBuildExpectations(['only'], { transcript: TRANSCRIPT }); + + expect(generate).toHaveBeenCalledTimes(2); + expect(results).toEqual([{ expectation: 'only', pass: true, reason: 'ok' }]); + }); + + it('returns an all-fail verdict (never throws) when every attempt fails', async () => { + const generate: GenerateMock = vi.fn<GenerateFn>().mockRejectedValue(new Error('API down')); + mockJudge(generate); + + const results = await verifyBuildExpectations(['a', 'b'], { transcript: TRANSCRIPT }); + + expect(results).toEqual([ + { expectation: 'a', pass: false, reason: 'judge produced no result', incomplete: true }, + { expectation: 'b', pass: false, reason: 'judge produced no result', incomplete: true }, + ]); + }); + + it('passes the metrics ground-truth block and numbered expectations to the judge', async () => { + const generate: GenerateMock = vi.fn<GenerateFn>().mockResolvedValue({ + structuredOutput: { results: [{ index: 0, pass: true, reason: 'ok' }] }, + }); + mockJudge(generate); + + const metrics: ConversationMetrics = { + turnCount: 2, + perTurn: [], + confirmationAskedTotal: 0, + confirmationAskedByKind: {}, + reachedRunFinishCleanly: true, + }; + await verifyBuildExpectations(['expectation zero'], { transcript: TRANSCRIPT, metrics }); + + const sentMessages = JSON.stringify(generate.mock.calls[0]?.[0]); + expect(sentMessages).toContain('ground truth'); + expect(sentMessages).toContain('0. expectation zero'); + expect(sentMessages).toContain('turnCount'); + }); +}); diff --git a/packages/@n8n/instance-ai/evaluations/__tests__/capture-run-debug.test.ts b/packages/@n8n/instance-ai/evaluations/__tests__/capture-run-debug.test.ts new file mode 100644 index 00000000000..e58476b3463 --- /dev/null +++ b/packages/@n8n/instance-ai/evaluations/__tests__/capture-run-debug.test.ts @@ -0,0 +1,50 @@ +import { describe, expect, it, vi } from 'vitest'; + +import type { N8nClient } from '../clients/n8n-client'; +import { captureThreadRunDebug } from '../harness/capture-run-debug'; + +describe('captureThreadRunDebug', () => { + it('fetches full run records for each summary', async () => { + const client = { + listThreadDebugRuns: vi.fn().mockResolvedValue({ + threadId: 'thread-1', + runs: [ + { + runId: 'run-1', + threadId: 'thread-1', + startedAt: 1, + stepCount: 1, + workflowCodeCount: 0, + label: 'Build workflow', + }, + ], + }), + getRunDebug: vi.fn().mockResolvedValue({ + threadId: 'thread-1', + runId: 'run-1', + startedAt: 1, + steps: [{ stepNumber: 0, input: { system: 'prompt' } }], + workflowCode: [], + }), + } as unknown as N8nClient; + + const records = await captureThreadRunDebug(client, 'thread-1'); + + expect(records).toHaveLength(1); + expect(records[0]?.label).toBe('Build workflow'); + expect(records[0]?.steps).toHaveLength(1); + expect(client.getRunDebug).toHaveBeenCalledWith('run-1'); + }); + + it('returns an empty array when the debug API is unavailable', async () => { + const client = { + listThreadDebugRuns: vi + .fn() + .mockRejectedValue( + new Error('n8n API GET /rest/instance-ai/debug/threads/t/runs failed (404): not found'), + ), + } as unknown as N8nClient; + + await expect(captureThreadRunDebug(client, 'thread-1')).resolves.toEqual([]); + }); +}); diff --git a/packages/@n8n/instance-ai/evaluations/__tests__/case-files-schema.test.ts b/packages/@n8n/instance-ai/evaluations/__tests__/case-files-schema.test.ts new file mode 100644 index 00000000000..700747add6a --- /dev/null +++ b/packages/@n8n/instance-ai/evaluations/__tests__/case-files-schema.test.ts @@ -0,0 +1,25 @@ +import { jsonParse } from 'n8n-workflow'; +import { readdirSync, readFileSync } from 'node:fs'; +import { join } from 'node:path'; + +import { WorkflowTestCaseSchema } from '../data/workflows/schema'; + +// Validates the REAL shipped test-case JSONs against the schema. `data-workflows-schema.test.ts` +// mocks `fs`, so it can't catch a malformed real case; this reads the actual directory and parses +// every case — including the multi-line array `text` form used by long stage directions. +const WORKFLOWS_DIR = join(__dirname, '..', 'data', 'workflows'); +const caseFiles = readdirSync(WORKFLOWS_DIR).filter((f) => f.endsWith('.json')); + +describe('case file schema validation', () => { + it('finds at least one case file', () => { + expect(caseFiles.length).toBeGreaterThan(0); + }); + + it.each(caseFiles)('%s parses against WorkflowTestCaseSchema', (file) => { + const raw = jsonParse<unknown>(readFileSync(join(WORKFLOWS_DIR, file), 'utf8')); + const result = WorkflowTestCaseSchema.safeParse(raw); + if (!result.success) { + throw new Error(`${file} failed schema validation:\n${result.error.message}`); + } + }); +}); diff --git a/packages/@n8n/instance-ai/evaluations/__tests__/comparison-format.test.ts b/packages/@n8n/instance-ai/evaluations/__tests__/comparison-format.test.ts index 37154ac62d1..2fe471a4c65 100644 --- a/packages/@n8n/instance-ai/evaluations/__tests__/comparison-format.test.ts +++ b/packages/@n8n/instance-ai/evaluations/__tests__/comparison-format.test.ts @@ -87,6 +87,7 @@ function evaluation( executionScenarioResults: [], })), buildSuccessCount, + buildExpectations: [], }; }), }; @@ -181,13 +182,14 @@ describe('formatComparisonMarkdown', () => { expect(md).toMatch(/#### Improvements/); }); - it('embeds commit SHA in heading when provided', () => { + it('omits commit SHA from the PR-comment heading even when provided', () => { const pr = bucket('pr', [s('a', 'happy', 8, 10)]); const base = bucket('master', [s('a', 'happy', 8, 10)]); const md = formatComparisonMarkdown(evalFixture, ok(compareBuckets(pr, base)), { commitSha: 'abc1234567890def', }); - expect(md).toMatch(/### Instance AI Workflow Eval — `abc12345`/); + expect(md).toContain('### Instance AI Workflow Eval'); + expect(md).not.toContain('abc12345'); }); it('renders the Workflow checks table when at least one run has outcomes', () => { diff --git a/packages/@n8n/instance-ai/evaluations/__tests__/conversation-text.test.ts b/packages/@n8n/instance-ai/evaluations/__tests__/conversation-text.test.ts index 0f276836a8a..384bd4bbaac 100644 --- a/packages/@n8n/instance-ai/evaluations/__tests__/conversation-text.test.ts +++ b/packages/@n8n/instance-ai/evaluations/__tests__/conversation-text.test.ts @@ -1,5 +1,5 @@ import type { TranscriptTurn } from '../types'; -import { userTurnsAsText } from '../utils/conversation-text'; +import { transcriptAsText, userTurnsAsText } from '../utils/conversation-text'; describe('userTurnsAsText', () => { it('returns empty string on empty transcript', () => { @@ -8,18 +8,96 @@ describe('userTurnsAsText', () => { it('returns the lone user message as plain text on single-turn', () => { const transcript: TranscriptTurn[] = [ - { userMessage: 'build a webhook', agentText: 'sure', toolInteractions: [] }, + { userMessage: 'build a webhook', steps: [{ kind: 'agent-text', text: 'sure' }] }, ]; expect(userTurnsAsText(transcript)).toBe('build a webhook'); }); it('numbers user turns on multi-turn and drops empty/agent-only turns', () => { const transcript: TranscriptTurn[] = [ - { userMessage: 'build it', agentText: 'what kind?', toolInteractions: [] }, - { userMessage: undefined, agentText: 'thinking…', toolInteractions: [] }, - { userMessage: '', agentText: 'plan emitted', toolInteractions: [] }, - { userMessage: 'a webhook', agentText: 'done', toolInteractions: [] }, + { userMessage: 'build it', steps: [{ kind: 'agent-text', text: 'what kind?' }] }, + { userMessage: undefined, steps: [{ kind: 'agent-text', text: 'thinking…' }] }, + { userMessage: '', steps: [{ kind: 'agent-text', text: 'plan emitted' }] }, + { userMessage: 'a webhook', steps: [{ kind: 'agent-text', text: 'done' }] }, ]; expect(userTurnsAsText(transcript)).toBe('Turn 1: build it\n\nTurn 2: a webhook'); }); }); + +describe('transcriptAsText', () => { + it('surfaces tool-call args and result so the judge sees what each call did', () => { + const transcript: TranscriptTurn[] = [ + { + userMessage: 'fetch the rows', + steps: [ + { + kind: 'tool-call', + toolName: 'add-nodes', + args: { nodeType: 'n8n-nodes-base.httpRequest' }, + result: { added: 1 }, + }, + ], + }, + ]; + const text = transcriptAsText(transcript); + expect(text).toContain('Tool: add-nodes'); + expect(text).toContain('n8n-nodes-base.httpRequest'); + expect(text).toContain('"added":1'); + }); + + it('prefers the error over the result and caps long fields', () => { + const transcript: TranscriptTurn[] = [ + { + steps: [ + { + kind: 'tool-call', + toolName: 'httpRequest', + args: { url: 'x'.repeat(5000) }, + error: 'boom', + }, + ], + }, + ]; + const text = transcriptAsText(transcript); + expect(text).toContain('error: boom'); + expect(text).not.toContain('result:'); + expect(text).toContain('more chars)'); + }); + + it('surfaces plan task descriptions, not just titles', () => { + const transcript: TranscriptTurn[] = [ + { + steps: [ + { + kind: 'plan', + tasks: [{ title: 'Fetch posts', description: 'GET /posts with pagination' }], + }, + ], + }, + ]; + const text = transcriptAsText(transcript); + expect(text).toContain('Fetch posts'); + expect(text).toContain('GET /posts with pagination'); + }); + + it('surfaces the confirmation prompt and the user feedback on a decision', () => { + const transcript: TranscriptTurn[] = [ + { + steps: [ + { + kind: 'confirmation', + toolName: 'create-tasks', + resumeReason: 'approval', + approved: false, + message: 'Here is the plan, approve?', + feedback: 'No — use a Webhook trigger, not a Schedule', + }, + ], + }, + ]; + const text = transcriptAsText(transcript); + expect(text).toContain('(rejected)'); + expect(text).toContain('prompt: Here is the plan, approve?'); + expect(text).toContain('user feedback: No — use a Webhook trigger, not a Schedule'); + }); +}); diff --git a/packages/@n8n/instance-ai/evaluations/__tests__/data-workflows-schema.test.ts b/packages/@n8n/instance-ai/evaluations/__tests__/data-workflows-schema.test.ts index cde986820ed..e7e6d2f2696 100644 --- a/packages/@n8n/instance-ai/evaluations/__tests__/data-workflows-schema.test.ts +++ b/packages/@n8n/instance-ai/evaluations/__tests__/data-workflows-schema.test.ts @@ -61,6 +61,31 @@ describe('WorkflowTestCaseSchema', () => { expect(parsed.triggerType).toBe('webhook'); }); + it('accepts the optional buildExpectations array', () => { + const parsed = WorkflowTestCaseSchema.parse({ + ...validFixture(), + buildExpectations: ['the agent asked which channel before building'], + }); + expect(parsed.buildExpectations).toEqual(['the agent asked which channel before building']); + }); + + it('leaves buildExpectations undefined when omitted', () => { + const parsed = WorkflowTestCaseSchema.parse(validFixture()); + expect(parsed.buildExpectations).toBeUndefined(); + }); + + it('rejects a non-array buildExpectations', () => { + expect(() => + WorkflowTestCaseSchema.parse({ ...validFixture(), buildExpectations: 'nope' }), + ).toThrow(); + }); + + it('rejects an empty-string expectation', () => { + expect(() => + WorkflowTestCaseSchema.parse({ ...validFixture(), buildExpectations: [''] }), + ).toThrow(); + }); + it('accepts the optional requires hint on scenarios', () => { const fixture = validFixture(); fixture.executionScenarios[0] = { diff --git a/packages/@n8n/instance-ai/evaluations/__tests__/event-parser.test.ts b/packages/@n8n/instance-ai/evaluations/__tests__/event-parser.test.ts index ce684267a93..12f7cf25bcd 100644 --- a/packages/@n8n/instance-ai/evaluations/__tests__/event-parser.test.ts +++ b/packages/@n8n/instance-ai/evaluations/__tests__/event-parser.test.ts @@ -527,14 +527,14 @@ describe('buildConversationMetrics', () => { expect(result.perTurn[0].replanAfterErrorCount).toBe(1); }); - it('counts replan_after_error when a tool-error is followed by a plan-typed tool-call', () => { + it('counts replan_after_error when a tool-error is followed by create-tasks', () => { const events: CapturedEvent[] = [ { timestamp: 1, type: 'run-start', data: { type: 'run-start' } }, { timestamp: 2, type: 'tool-error', data: { type: 'tool-error' } }, { timestamp: 3, type: 'tool-call', - data: { type: 'tool-call', payload: { toolName: 'plan' } }, + data: { type: 'tool-call', payload: { toolName: 'create-tasks' } }, }, { timestamp: 4, type: 'run-finish', data: { type: 'run-finish' } }, ]; diff --git a/packages/@n8n/instance-ai/evaluations/__tests__/export-latest-verifier-request.test.ts b/packages/@n8n/instance-ai/evaluations/__tests__/export-latest-verifier-request.test.ts new file mode 100644 index 00000000000..39830f10178 --- /dev/null +++ b/packages/@n8n/instance-ai/evaluations/__tests__/export-latest-verifier-request.test.ts @@ -0,0 +1,84 @@ +import { findStoredTestCaseResult, findStoredVerifierRun } from '../eval-results-artifact'; +import { getScenarios } from '../export-latest-verifier-request'; + +function evalResult(marker: string) { + return { + success: true, + nodeResults: { + [marker]: { + interceptedRequests: [], + executionMode: 'real' as const, + }, + }, + errors: [], + hints: { + warnings: [], + triggerContent: {}, + }, + }; +} + +describe('export-latest-verifier-request helpers', () => { + it('reads workflow test case executionScenarios', () => { + const scenario = { + name: 'happy-path', + description: '', + dataSetup: '', + successCriteria: '', + }; + + expect(getScenarios({ executionScenarios: [scenario] })).toEqual([scenario]); + }); + + it('selects stored eval results within the requested test case', () => { + const testCase = { + conversation: [{ role: 'user' as const, text: 'Prompt B' }], + executionScenarios: [ + { + name: 'happy-path', + description: '', + dataSetup: '', + successCriteria: '', + }, + ], + }; + const evalResults = { + testCases: [ + { + name: 'Prompt A', + testCaseFile: 'other-case', + scenarios: [ + { + name: 'happy-path', + runs: [{ workflowId: 'wf-other', evalResult: evalResult('other-node') }], + }, + ], + }, + { + name: 'Prompt B', + testCaseFile: 'target-case', + scenarios: [ + { + name: 'happy-path', + runs: [ + { evalResult: evalResult('unusable-without-workflow-id') }, + { workflowId: 'wf-target', evalResult: evalResult('target-node') }, + ], + }, + ], + }, + ], + }; + + const storedTestCase = findStoredTestCaseResult( + evalResults, + '/tmp/target-case.json', + testCase.conversation[0]?.text.slice(0, 70), + ); + const storedRun = findStoredVerifierRun(storedTestCase, 'happy-path'); + + expect(storedRun?.runIndex).toBe(1); + expect(storedRun?.evalResult.nodeResults).toHaveProperty('target-node'); + expect(storedRun?.workflowId).toBe('wf-target'); + }); +}); diff --git a/packages/@n8n/instance-ai/evaluations/__tests__/prebuilt-workflows.test.ts b/packages/@n8n/instance-ai/evaluations/__tests__/prebuilt-workflows.test.ts index a1c7208f46c..6915b7b5539 100644 --- a/packages/@n8n/instance-ai/evaluations/__tests__/prebuilt-workflows.test.ts +++ b/packages/@n8n/instance-ai/evaluations/__tests__/prebuilt-workflows.test.ts @@ -7,6 +7,7 @@ import type { Mock } from 'vitest'; import type { N8nClient, WorkflowResponse } from '../clients/n8n-client'; import type { EvalLogger } from '../harness/logger'; import { + cleanupPrebuiltWorkflows, fetchPrebuiltBuild, loadPrebuiltManifest, pickPrebuiltWorkflowId, @@ -153,3 +154,45 @@ describe('fetchPrebuiltBuild', () => { expect(result.error).toContain('plain string failure'); }); }); + +describe('cleanupPrebuiltWorkflows', () => { + function makeLogger(): EvalLogger & { info: Mock; warn: Mock } { + return { + info: vi.fn(), + verbose: vi.fn(), + success: vi.fn(), + warn: vi.fn(), + error: vi.fn(), + isVerbose: false, + }; + } + + it('deletes each workflow ID once', async () => { + const deleteWorkflow = vi.fn().mockResolvedValue(undefined); + const client = { deleteWorkflow } as unknown as N8nClient; + const logger = makeLogger(); + + await cleanupPrebuiltWorkflows(client, ['W1', 'W1', 'W2'], logger); + + expect(deleteWorkflow).toHaveBeenCalledTimes(2); + expect(deleteWorkflow).toHaveBeenNthCalledWith(1, 'W1'); + expect(deleteWorkflow).toHaveBeenNthCalledWith(2, 'W2'); + expect(logger.info).toHaveBeenCalledWith('Deleted 2/2 prebuilt workflow(s)'); + expect(logger.warn).not.toHaveBeenCalled(); + }); + + it('continues deleting after a workflow deletion fails', async () => { + const deleteWorkflow = vi + .fn() + .mockRejectedValueOnce(new Error('HTTP 404')) + .mockResolvedValueOnce(undefined); + const client = { deleteWorkflow } as unknown as N8nClient; + const logger = makeLogger(); + + await cleanupPrebuiltWorkflows(client, ['W1', 'W2'], logger); + + expect(deleteWorkflow).toHaveBeenCalledTimes(2); + expect(logger.warn).toHaveBeenCalledWith('Failed to delete prebuilt workflow W1: HTTP 404'); + expect(logger.info).toHaveBeenCalledWith('Deleted 1/2 prebuilt workflow(s)'); + }); +}); diff --git a/packages/@n8n/instance-ai/evaluations/__tests__/redact.test.ts b/packages/@n8n/instance-ai/evaluations/__tests__/redact.test.ts index a17d223a33c..f4d8a96ca14 100644 --- a/packages/@n8n/instance-ai/evaluations/__tests__/redact.test.ts +++ b/packages/@n8n/instance-ai/evaluations/__tests__/redact.test.ts @@ -1,4 +1,4 @@ -import { redactSecrets, stringifyError, truncate } from '../harness/redact'; +import { redactSecrets, redactSecretsInText, stringifyError, truncate } from '../harness/redact'; describe('redactSecrets', () => { it('redacts values under secret-shaped keys', () => { @@ -78,6 +78,42 @@ describe('redactSecrets', () => { }); }); +describe('redactSecretsInText', () => { + it('masks an Authorization credential while keeping the scheme and message', () => { + const out = redactSecretsInText('Request failed: Authorization: Bearer sk-abc.def123 (401)'); + expect(out).not.toContain('sk-abc.def123'); + expect(out).toContain('Authorization: Bearer [REDACTED]'); + expect(out).toContain('Request failed:'); + expect(out).toContain('(401)'); + }); + + it('masks a standalone Bearer/Basic credential', () => { + expect(redactSecretsInText('header was Bearer eyJ0eXAiOiJ.payload')).toBe( + 'header was Bearer [REDACTED]', + ); + expect(redactSecretsInText('got Basic dXNlcjpwYXNz back')).toBe('got Basic [REDACTED] back'); + }); + + it('masks secret-shaped key/value pairs in query strings and JSON', () => { + expect(redactSecretsInText('GET https://api.x.com/v1?api_key=secret123&page=2')).toBe( + 'GET https://api.x.com/v1?api_key=[REDACTED]&page=2', + ); + expect(redactSecretsInText('body {"token":"abc","ok":true}')).toBe( + 'body {"token":"[REDACTED]","ok":true}', + ); + expect(redactSecretsInText('password: hunter2')).toBe('password: [REDACTED]'); + }); + + it('leaves secret words used as prose untouched (no separator → no match)', () => { + expect(redactSecretsInText('Invalid token format in the request')).toBe( + 'Invalid token format in the request', + ); + expect(redactSecretsInText('the secret sauce was missing')).toBe( + 'the secret sauce was missing', + ); + }); +}); + describe('truncate', () => { it('passes short values through after redaction', () => { expect(truncate({ name: 'a', token: 't' }, 200)).toEqual({ name: 'a', token: '[REDACTED]' }); diff --git a/packages/@n8n/instance-ai/evaluations/__tests__/reshape.test.ts b/packages/@n8n/instance-ai/evaluations/__tests__/reshape.test.ts new file mode 100644 index 00000000000..f7daec38470 --- /dev/null +++ b/packages/@n8n/instance-ai/evaluations/__tests__/reshape.test.ts @@ -0,0 +1,260 @@ +import type { Run } from 'langsmith/schemas'; + +import { reshapeLangSmithRuns } from '../cli/reshape'; +import type { WorkflowTestCaseWithFile } from '../data/workflows'; +import type { + BuildExpectationResult, + ExecutionScenario, + TranscriptTurn, + WorkflowTestCase, +} from '../types'; + +// --------------------------------------------------------------------------- +// Fixtures — reshape only reads `run.inputs` and `run.outputs`, so a minimal +// Run is enough. `as Run` is fine in test code. +// --------------------------------------------------------------------------- + +function scenario(name: string): ExecutionScenario { + return { name, description: '', dataSetup: '', successCriteria: '' }; +} + +function testCase(scenarios: ExecutionScenario[]): WorkflowTestCase { + return { + conversation: [{ role: 'user', text: 'build it' }], + complexity: 'simple', + tags: [], + executionScenarios: scenarios, + datasets: ['full'], + }; +} + +function withFile(fileSlug: string, scenarios: ExecutionScenario[]): WorkflowTestCaseWithFile { + return { testCase: testCase(scenarios), fileSlug }; +} + +function row(inputs: Record<string, unknown>, outputs: Record<string, unknown>): { run: Run } { + return { run: { inputs, outputs } as Run }; +} + +const turn: TranscriptTurn = { steps: [{ kind: 'agent-text', text: 'building...' }] }; +const verdict: BuildExpectationResult = { expectation: 'asked first', pass: true, reason: 'did' }; + +describe('reshapeLangSmithRuns', () => { + it('reattaches transcript + build-expectation verdicts to the test case by threadId', () => { + const cases = [withFile('airtable', [scenario('s1'), scenario('s2')])]; + const rows = [ + row( + { testCaseFile: 'airtable', scenarioName: 's1', _iteration: 0 }, + { buildSuccess: true, passed: true, score: 1, reasoning: 'ok', threadId: 'tid-1' }, + ), + row( + { testCaseFile: 'airtable', scenarioName: 's2', _iteration: 0 }, + { buildSuccess: true, passed: true, score: 1, reasoning: 'ok', threadId: 'tid-1' }, + ), + ]; + + const result = reshapeLangSmithRuns( + rows, + cases, + 1, + new Map([['tid-1', [turn]]]), + new Map([['tid-1', [verdict]]]), + 'http://localhost:5678', + ); + + expect(result).toHaveLength(1); + const tc = result[0][0]; + expect(tc.threadId).toBe('tid-1'); + expect(tc.transcript).toEqual([turn]); + expect(tc.buildExpectationResults).toEqual([verdict]); + expect(tc.workflowBuildSuccess).toBe(true); + expect(tc.n8nBaseUrl).toBe('http://localhost:5678'); + expect(tc.executionScenarioResults.map((r) => r.success)).toEqual([true, true]); + }); + + it('leaves transcript + verdicts undefined when the run output carries no threadId (regression: dropped threadId)', () => { + // Models the exec-error return that omitted threadId: build succeeded, but + // with no threadId on the output the join can't find the maps' entries. + const cases = [withFile('airtable', [scenario('s1')])]; + const rows = [ + row( + { testCaseFile: 'airtable', scenarioName: 's1', _iteration: 0 }, + { buildSuccess: true, passed: false, score: 0, reasoning: 'exec error' }, + ), + ]; + + // Maps DO hold data under a real threadId — proving we don't misattach it. + const result = reshapeLangSmithRuns( + rows, + cases, + 1, + new Map([['tid-real', [turn]]]), + new Map([['tid-real', [verdict]]]), + undefined, + ); + + const tc = result[0][0]; + expect(tc.workflowBuildSuccess).toBe(true); + expect(tc.threadId).toBeUndefined(); + expect(tc.transcript).toBeUndefined(); + expect(tc.buildExpectationResults).toBeUndefined(); + }); + + it('stubs a build_failure for a scenario with no matching run', () => { + const cases = [withFile('airtable', [scenario('s1'), scenario('s2')])]; + const rows = [ + row( + { testCaseFile: 'airtable', scenarioName: 's1', _iteration: 0 }, + { buildSuccess: true, passed: true, score: 1, reasoning: 'ok', threadId: 'tid-1' }, + ), + ]; + + const result = reshapeLangSmithRuns(rows, cases, 1, new Map(), new Map(), undefined); + + const [s1, s2] = result[0][0].executionScenarioResults; + expect(s1.success).toBe(true); + expect(s2.success).toBe(false); + expect(s2.reasoning).toBe('No run result for this scenario'); + expect(s2.score).toBe(0); + }); + + it('skips a malformed run output rather than scoring it as a failure', () => { + const cases = [withFile('airtable', [scenario('s1')])]; + const rows = [row({ testCaseFile: 'airtable', scenarioName: 's1', _iteration: 0 }, {})]; + + const result = reshapeLangSmithRuns(rows, cases, 1, new Map(), new Map(), undefined); + + const s1 = result[0][0].executionScenarioResults[0]; + expect(s1.success).toBe(false); + expect(s1.reasoning).toBe('Malformed run output — skipped'); + }); + + it('groups runs into separate iterations by the injected _iteration index', () => { + const cases = [withFile('airtable', [scenario('s1')])]; + const rows = [ + row( + { testCaseFile: 'airtable', scenarioName: 's1', _iteration: 0 }, + { buildSuccess: true, passed: true, score: 1, reasoning: 'ok', threadId: 'tid-0' }, + ), + row( + { testCaseFile: 'airtable', scenarioName: 's1', _iteration: 1 }, + { buildSuccess: true, passed: false, score: 0, reasoning: 'flaked', threadId: 'tid-1' }, + ), + ]; + + const result = reshapeLangSmithRuns(rows, cases, 2, new Map(), new Map(), undefined); + + expect(result).toHaveLength(2); + expect(result[0][0].threadId).toBe('tid-0'); + expect(result[0][0].executionScenarioResults[0].success).toBe(true); + expect(result[1][0].threadId).toBe('tid-1'); + expect(result[1][0].executionScenarioResults[0].success).toBe(false); + }); + + it('captures buildError and workflowChecks from the build scenario', () => { + const cases = [withFile('airtable', [scenario('s1')])]; + const checks = [ + { + name: 'has_trigger', + description: 'has a trigger', + kind: 'deterministic' as const, + dimension: 'structure' as const, + status: 'pass' as const, + }, + ]; + const rows = [ + row( + { testCaseFile: 'airtable', scenarioName: 's1', _iteration: 0 }, + { + buildSuccess: false, + passed: false, + score: 0, + reasoning: 'build blew up', + workflowChecks: checks, + }, + ), + ]; + + const result = reshapeLangSmithRuns(rows, cases, 1, new Map(), new Map(), undefined); + + const tc = result[0][0]; + expect(tc.workflowBuildSuccess).toBe(false); + expect(tc.buildError).toBe('build blew up'); + expect(tc.workflowChecks).toEqual(checks); + }); + + it('preserves workflow JSON and build trace from LangSmith outputs', () => { + const cases = [withFile('airtable', [scenario('s1')])]; + const workflowJson = { + id: 'wf-1', + name: 'Workflow', + active: false, + versionId: 'v1', + nodes: [], + connections: {}, + }; + const buildTrace = { finalText: 'done', toolCalls: [], agentActivities: [] }; + const rows = [ + row( + { testCaseFile: 'airtable', scenarioName: 's1', _iteration: 0 }, + { + buildSuccess: true, + passed: true, + score: 1, + reasoning: 'ok', + workflowJson, + buildTrace, + }, + ), + ]; + + const result = reshapeLangSmithRuns(rows, cases, 1, new Map(), new Map(), undefined); + + const tc = result[0][0]; + expect(tc.workflowJson).toEqual(workflowJson); + expect(tc.buildTrace).toEqual(buildTrace); + }); + + it('merges stashed run debug by thread id', () => { + const cases = [withFile('airtable', [scenario('s1')])]; + const rows = [ + row( + { testCaseFile: 'airtable', scenarioName: 's1', _iteration: 0 }, + { + buildSuccess: true, + passed: true, + score: 1, + reasoning: 'ok', + threadId: 'thread-1', + }, + ), + ]; + const runDebugByThreadId = new Map([ + [ + 'thread-1', + [ + { + threadId: 'thread-1', + runId: 'run-1', + startedAt: 1, + steps: [{ stepNumber: 0 }], + workflowCode: [], + }, + ], + ], + ]); + + const result = reshapeLangSmithRuns( + rows, + cases, + 1, + new Map(), + new Map(), + undefined, + runDebugByThreadId, + ); + + expect(result[0][0]?.runDebug).toHaveLength(1); + expect(result[0][0]?.runDebug?.[0]?.runId).toBe('run-1'); + }); +}); diff --git a/packages/@n8n/instance-ai/evaluations/__tests__/run-debug-report.test.ts b/packages/@n8n/instance-ai/evaluations/__tests__/run-debug-report.test.ts new file mode 100644 index 00000000000..e2f9497ab97 --- /dev/null +++ b/packages/@n8n/instance-ai/evaluations/__tests__/run-debug-report.test.ts @@ -0,0 +1,83 @@ +import { getTestCaseAnchorId } from '../report/report-anchors'; +import { generateRunDebugReport } from '../report/run-debug-report'; +import type { WorkflowTestCase, WorkflowTestCaseResult } from '../types'; + +const TEST_CASE: WorkflowTestCase = { + conversation: [{ role: 'user', text: 'Build a Slack notifier' }], + complexity: 'simple', + tags: [], + executionScenarios: [{ name: 's', description: 'd', dataSetup: '', successCriteria: 'ok' }], + datasets: ['full'], +}; + +function resultWithRunDebug( + runDebug: WorkflowTestCaseResult['runDebug'], + overrides: Partial<WorkflowTestCaseResult> = {}, +): WorkflowTestCaseResult { + return { + testCase: TEST_CASE, + workflowBuildSuccess: true, + executionScenarioResults: [], + fileSlug: 'slack-notifier', + threadId: 'thread-1', + runDebug, + ...overrides, + }; +} + +describe('run debug report', () => { + it('renders runs, steps, and escaped user content', () => { + const html = generateRunDebugReport([ + resultWithRunDebug([ + { + threadId: 'thread-1', + runId: 'run-1', + startedAt: 1_700_000_000_000, + label: 'Build a Slack notifier', + steps: [ + { + stepNumber: 0, + input: { + system: 'You are helpful <script>alert(1)</script>', + messages: [{ role: 'user', content: 'Build a Slack notifier' }], + }, + output: { + finishReason: 'tool-calls', + toolCalls: [{ toolName: 'search_nodes', input: { query: 'slack' } }], + usage: { inputTokens: 10, outputTokens: 5, totalTokens: 15 }, + }, + }, + ], + workflowCode: [], + }, + ]), + ]); + + expect(html).toContain('id="tc-slack-notifier"'); + expect(html).toContain('Build a Slack notifier'); + expect(html).toContain('search_nodes'); + expect(html).toContain('tool-calls'); + expect(html).toContain('<script>alert(1)</script>'); + expect(html).toContain('selectRun('); + expect(html).toContain('selectStep('); + }); + + it('uses stable anchor ids from file slugs', () => { + const result = resultWithRunDebug([]); + expect(getTestCaseAnchorId(result, 0)).toBe('tc-slack-notifier'); + }); + + it('renders an empty-state stub when no debug was captured', () => { + const html = generateRunDebugReport([ + { + testCase: TEST_CASE, + workflowBuildSuccess: false, + executionScenarioResults: [], + }, + ]); + + expect(html).toContain('No LLM run debug was captured'); + expect(html).toContain('N8N_INSTANCE_AI_RUN_DEBUG_ENABLED=true'); + expect(html).toContain('Workflow eval — LLM debug'); + }); +}); diff --git a/packages/@n8n/instance-ai/evaluations/__tests__/runner-thread-id.test.ts b/packages/@n8n/instance-ai/evaluations/__tests__/runner-thread-id.test.ts new file mode 100644 index 00000000000..436ba2c64f3 --- /dev/null +++ b/packages/@n8n/instance-ai/evaluations/__tests__/runner-thread-id.test.ts @@ -0,0 +1,45 @@ +import { vi } from 'vitest'; + +import type { N8nClient } from '../clients/n8n-client'; +import type { EvalLogger } from '../harness/logger'; +import { buildWorkflow } from '../harness/runner'; + +const silentLogger: EvalLogger = { + info: () => {}, + verbose: () => {}, + success: () => {}, + warn: () => {}, + error: () => {}, + isVerbose: false, +}; + +const uuidV4Pattern = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/; + +describe('buildWorkflow thread IDs', () => { + it('uses UUID thread IDs and the personal project for the instance-ai thread endpoint', async () => { + let capturedThreadId = ''; + let capturedProjectId = ''; + const client = { + getPersonalProjectId: vi.fn(async () => await Promise.resolve('project-1')), + ensureThread: vi.fn(async (threadId: string, projectId: string) => { + capturedThreadId = threadId; + capturedProjectId = projectId; + await Promise.resolve(); + throw new Error('stop after ensureThread'); + }), + } as unknown as N8nClient; + + await buildWorkflow({ + client, + conversation: [{ role: 'user', text: 'build a workflow' }], + preRunWorkflowIds: new Set(), + claimedWorkflowIds: new Set(), + logger: silentLogger, + }); + + expect(client.getPersonalProjectId).toHaveBeenCalledTimes(1); + expect(client.ensureThread).toHaveBeenCalledTimes(1); + expect(capturedThreadId).toMatch(uuidV4Pattern); + expect(capturedProjectId).toBe('project-1'); + }); +}); 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 ad012d12e84..028a4c60dad 100644 --- a/packages/@n8n/instance-ai/evaluations/__tests__/subagent-runner.test.ts +++ b/packages/@n8n/instance-ai/evaluations/__tests__/subagent-runner.test.ts @@ -56,7 +56,7 @@ describe('runWorkflowBuildEval', () => { workflowJsons: [workflow], createdWorkflowIds: [workflow.id], createdDataTableIds: [], - transcript: [{ agentText: 'Built the workflow.', toolInteractions: [] }], + transcript: [{ steps: [{ kind: 'agent-text', text: 'Built the workflow.' }] }], }; mockedBuildWorkflow.mockResolvedValue(build); diff --git a/packages/@n8n/instance-ai/evaluations/__tests__/transcript-from-events.test.ts b/packages/@n8n/instance-ai/evaluations/__tests__/transcript-from-events.test.ts index bf76e96a147..fd07702ade5 100644 --- a/packages/@n8n/instance-ai/evaluations/__tests__/transcript-from-events.test.ts +++ b/packages/@n8n/instance-ai/evaluations/__tests__/transcript-from-events.test.ts @@ -18,9 +18,100 @@ describe('buildTranscriptFromEvents', () => { openingMessage: 'Build me a workflow', }); expect(turns).toHaveLength(1); - expect(turns[0]).toMatchObject({ - userMessage: 'Build me a workflow', - agentText: 'Hello there', + expect(turns[0].userMessage).toBe('Build me a workflow'); + expect(turns[0].steps).toEqual([{ kind: 'agent-text', text: 'Hello there' }]); + }); + + it('interleaves agent narration with actions in event order', () => { + const turns = buildTranscriptFromEvents({ + events: [ + RUN_START, + evt('text-delta', { text: 'Let me search. ' }), + evt('tool-call', { payload: { toolName: 'search-nodes', args: {} } }), + evt('text-delta', { text: 'Found them.' }), + evt('tool-call', { payload: { toolName: 'add-nodes', args: {} } }), + ], + openingMessage: 'build it', + }); + expect(turns[0].steps).toEqual([ + { kind: 'agent-text', text: 'Let me search. ' }, + { kind: 'tool-call', toolName: 'search-nodes' }, + { kind: 'agent-text', text: 'Found them.' }, + { kind: 'tool-call', toolName: 'add-nodes' }, + ]); + }); + + describe('secret redaction', () => { + it('redacts secret-shaped keys in tool-call args', () => { + const turns = buildTranscriptFromEvents({ + events: [ + RUN_START, + evt('tool-call', { + payload: { + toolName: 'httpRequest', + toolCallId: 'tc1', + args: { + url: 'https://api.example.com', + apiKey: 'sk-secret', + headers: { authorization: 'Bearer xyz' }, + }, + }, + }), + ], + }); + expect(turns[0].steps[0]).toMatchObject({ + kind: 'tool-call', + args: { + url: 'https://api.example.com', + apiKey: '[REDACTED]', + headers: { authorization: '[REDACTED]' }, + }, + }); + }); + + it('redacts secret-shaped keys in a paired tool-result', () => { + const turns = buildTranscriptFromEvents({ + events: [ + RUN_START, + evt('tool-call', { + payload: { toolName: 'credentials', toolCallId: 'tc2', args: { name: 'slack' } }, + }), + evt('tool-result', { + payload: { + toolName: 'credentials', + toolCallId: 'tc2', + result: { id: 'c1', token: 'secret-token' }, + }, + }), + ], + }); + expect(turns[0].steps[0]).toMatchObject({ + kind: 'tool-call', + result: { id: 'c1', token: '[REDACTED]' }, + }); + }); + + it('scrubs a secret embedded in a paired tool-error string', () => { + const turns = buildTranscriptFromEvents({ + events: [ + RUN_START, + evt('tool-call', { + payload: { toolName: 'httpRequest', toolCallId: 'tc3', args: {} }, + }), + evt('tool-error', { + payload: { + toolCallId: 'tc3', + error: 'Request failed: Authorization: Bearer sk-leaked.token (401)', + }, + }), + ], + }); + const step = turns[0].steps[0]; + expect(step.kind).toBe('tool-call'); + const error = step.kind === 'tool-call' ? (step.error ?? '') : ''; + expect(error).not.toContain('sk-leaked.token'); + expect(error).toContain('[REDACTED]'); + expect(error).toContain('(401)'); }); }); @@ -46,7 +137,7 @@ describe('buildTranscriptFromEvents', () => { ], ]), }); - const interactions = turns[0].toolInteractions; + const interactions = turns[0].steps; expect(interactions).toHaveLength(1); expect(interactions[0]).toMatchObject({ kind: 'ask-user', @@ -65,7 +156,7 @@ describe('buildTranscriptFromEvents', () => { }), ], }); - const askUserInteractions = turns[0].toolInteractions.filter((i) => i.kind === 'ask-user'); + const askUserInteractions = turns[0].steps.filter((i) => i.kind === 'ask-user'); expect(askUserInteractions).toHaveLength(1); }); }); @@ -77,38 +168,38 @@ describe('buildTranscriptFromEvents', () => { RUN_START, evt('tool-call', { payload: { - toolName: 'plan', + toolName: 'create-tasks', args: { tasks: [{ title: 'Fetch posts', description: 'GET /posts' }] }, }, }), ], }); - expect(turns[0].toolInteractions[0]).toMatchObject({ + expect(turns[0].steps[0]).toMatchObject({ kind: 'plan', tasks: [{ title: 'Fetch posts', description: 'GET /posts' }], }); }); - - it('treats `add-plan-item` as plan (alias in the dispatch table)', () => { - const turns = buildTranscriptFromEvents({ - events: [ - RUN_START, - evt('tool-call', { - payload: { toolName: 'add-plan-item', args: { tasks: [{ title: 'A' }] } }, - }), - ], - }); - expect(turns[0].toolInteractions[0]).toMatchObject({ kind: 'plan' }); - }); }); describe('setup wizard routing', () => { - it('renders the outcome from tool-result and skips the confirmation-request twin', () => { + it('renders the setup-card ask and the setup-wizard outcome', () => { const turns = buildTranscriptFromEvents({ events: [ RUN_START, evt('confirmation-request', { - payload: { requestId: 'r1', setupRequests: [{ nodeName: 'Slack' }] }, + payload: { + requestId: 'r1', + setupRequests: [ + { + node: { name: 'Slack' }, + credentialType: 'slackApi', + editableParameters: [ + { name: 'channel', displayName: 'Channel', type: 'resourceLocator' }, + ], + parameterIssues: { text: ['Text is required'] }, + }, + ], + }, }), evt('tool-result', { payload: { @@ -121,14 +212,59 @@ describe('buildTranscriptFromEvents', () => { }), ], }); - const interactions = turns[0].toolInteractions; - expect(interactions).toHaveLength(1); + const interactions = turns[0].steps; + expect(interactions).toHaveLength(2); + // The confirmation-request renders as the setup-card (what the agent asked for)... expect(interactions[0]).toMatchObject({ + kind: 'setup-card', + requests: [{ nodeName: 'Slack', credentialType: 'slackApi', params: ['channel', 'text'] }], + }); + // ...and the tool-result renders as the setup-wizard outcome (what was configured/skipped). + expect(interactions[1]).toMatchObject({ kind: 'setup-wizard', completedNodes: [{ nodeName: 'Schedule', parametersSet: ['cron'] }], skippedNodes: [{ nodeName: 'Slack', credentialType: 'slackApi' }], }); }); + + it('redacts secret values the proxy filled into a setup card', () => { + const turns = buildTranscriptFromEvents({ + events: [ + RUN_START, + evt('confirmation-request', { + payload: { + requestId: 'r1', + setupRequests: [{ node: { name: 'HTTP' }, editableParameters: [] }], + }, + }), + ], + proxyResponses: new Map([ + [ + 'r1', + { + kind: 'setupWorkflowApply' as const, + nodeCredentials: {}, + nodeParameters: { + HTTP: { + apiKey: 'sk-live-supersecret', + authorization: 'Bearer abc123token', + channel: '#general', + }, + }, + }, + ], + ]), + }); + const card = turns[0].steps.find((s) => s.kind === 'setup-card'); + expect(card).toMatchObject({ kind: 'setup-card', outcome: 'filled' }); + const filled = card?.kind === 'setup-card' ? (card.filled ?? []) : []; + // Secret-shaped key → value masked; benign param survives. + expect(filled).toContain('apiKey=[REDACTED]'); + expect(filled).toContain('authorization=[REDACTED]'); + expect(filled).toContain('channel=#general'); + expect(filled.join(' ')).not.toContain('sk-live-supersecret'); + expect(filled.join(' ')).not.toContain('abc123token'); + }); }); describe('generic confirmation', () => { @@ -137,22 +273,22 @@ describe('buildTranscriptFromEvents', () => { events: [ RUN_START, evt('confirmation-request', { - payload: { requestId: 'r1', toolName: 'submit-plan' }, + payload: { requestId: 'r1', toolName: 'create-tasks' }, }), ], proxyResponses: new Map([['r1', { kind: 'approval' as const, approved: false }]]), }); - expect(turns[0].toolInteractions[0]).toMatchObject({ + expect(turns[0].steps[0]).toMatchObject({ kind: 'confirmation', - toolName: 'submit-plan', + toolName: 'create-tasks', resumeReason: 'approval', approved: false, }); }); }); - describe('plain tool-call dedupe', () => { - it('collapses repeat invocations of the same tool name within a turn', () => { + describe('plain tool-calls', () => { + it('renders every invocation of a repeated tool (no de-duping)', () => { const turns = buildTranscriptFromEvents({ events: [ RUN_START, @@ -161,8 +297,35 @@ describe('buildTranscriptFromEvents', () => { evt('tool-call', { payload: { toolName: 'credentials', args: {} } }), ], }); - const calls = turns[0].toolInteractions.filter((i) => i.kind === 'tool-call'); + const calls = turns[0].steps.filter((i) => i.kind === 'tool-call'); + expect(calls).toHaveLength(3); + }); + + it('renders an empty plan as a visible tool-call instead of dropping it', () => { + const turns = buildTranscriptFromEvents({ + events: [ + RUN_START, + evt('tool-call', { payload: { toolName: 'plan', args: { tasks: [] } } }), + ], + }); + const calls = turns[0].steps.filter((i) => i.kind === 'tool-call'); expect(calls).toHaveLength(1); + expect(calls[0]).toMatchObject({ kind: 'tool-call', toolName: 'plan' }); + }); + + it('keeps narration on either side of a tool call as separate blocks', () => { + const turns = buildTranscriptFromEvents({ + events: [ + RUN_START, + evt('text-delta', { text: 'here is my plan' }), + evt('tool-call', { payload: { toolName: 'plan', args: { tasks: [] } } }), + evt('text-delta', { text: 'planner returned nothing, building directly' }), + ], + }); + const texts = turns[0].steps + .filter((s) => s.kind === 'agent-text') + .map((s) => (s.kind === 'agent-text' ? s.text : '')); + expect(texts).toEqual(['here is my plan', 'planner returned nothing, building directly']); }); }); @@ -172,6 +335,7 @@ describe('buildTranscriptFromEvents', () => { openingMessage: 'go', }); expect(turns).toHaveLength(1); - expect(turns[0]).toMatchObject({ userMessage: 'go', agentText: 'hi' }); + expect(turns[0].userMessage).toBe('go'); + expect(turns[0].steps).toEqual([{ kind: 'agent-text', text: 'hi' }]); }); }); diff --git a/packages/@n8n/instance-ai/evaluations/__tests__/user-proxy.test.ts b/packages/@n8n/instance-ai/evaluations/__tests__/user-proxy.test.ts index 3a67b033505..68a36c58877 100644 --- a/packages/@n8n/instance-ai/evaluations/__tests__/user-proxy.test.ts +++ b/packages/@n8n/instance-ai/evaluations/__tests__/user-proxy.test.ts @@ -77,7 +77,7 @@ function planReviewEvent(requestId: string): CapturedEvent { payload: { requestId, toolCallId: 'tc-x', - toolName: 'plan', + toolName: 'create-tasks', args: {}, severity: 'info', message: 'Approve plan?', @@ -210,6 +210,49 @@ describe('UserProxyLlm.respondToConfirmation', () => { expect(agent.callCount).toBe(1); }); + it('routes ask-user questions to the agent even when scripted user turns remain (no deterministic shortcut)', async () => { + const agent = new FakeAgent(); + agent.enqueue({ + action: 'answer_questions', + answers: [ + { questionId: 'cities', selectedOptions: [], customText: 'London, New York, Tokyo' }, + { questionId: 'destination', selectedOptions: ['Slack'] }, + ], + }); + const proxy = new UserProxyLlm({ + conversation: [ + { role: 'user', text: 'I need weather alerts.' }, + { role: 'assistant', text: 'Which cities and where should alerts go?' }, + { + role: 'user', + text: 'London, New York, Tokyo. Alert above 30C via Telegram chat -1001234567890.', + }, + ], + agent, + }); + + const response = await proxy.respondToConfirmation( + questionEvent('req-scripted-q', [ + { id: 'cities', question: 'Which cities?', type: 'text' }, + { + id: 'destination', + question: 'Where should alerts go?', + type: 'single', + options: ['Email', 'Slack', 'SMS'], + }, + ]), + ); + + expect(agent.callCount).toBe(1); + expect(response.kind).toBe('questions'); + if (response.kind === 'questions') { + expect(response.answers).toEqual([ + { questionId: 'cities', selectedOptions: [], customText: 'London, New York, Tokyo' }, + { questionId: 'destination', selectedOptions: ['Slack'] }, + ]); + } + }); + it('returns approval with userInput when the agent picks approve_or_reject', async () => { const agent = new FakeAgent(); agent.enqueue({ @@ -230,6 +273,32 @@ describe('UserProxyLlm.respondToConfirmation', () => { } }); + it('rejects plan review with remaining scripted details before consulting the agent', async () => { + const agent = new FakeAgent(); + const proxy = new UserProxyLlm({ + conversation: [ + { role: 'user', text: 'Build an Airtable to Slack workflow.' }, + { role: 'assistant', text: 'Which table and channel?' }, + { + role: 'user', + text: 'Use GET https://api.airtable.com/v0/app123abc/Tasks and Slack #daily-tasks.', + }, + ], + agent, + }); + + const response = await proxy.respondToConfirmation(planReviewEvent('req-scripted-plan')); + + expect(response.kind).toBe('approval'); + if (response.kind === 'approval') { + expect(response.approved).toBe(false); + expect(response.userInput).toContain('Before I approve'); + expect(response.userInput).toContain('https://api.airtable.com/v0/app123abc/Tasks'); + expect(response.userInput).toContain('#daily-tasks'); + } + expect(agent.callCount).toBe(0); + }); + it('returns approval with no userInput when the agent omits it', async () => { const agent = new FakeAgent(); agent.enqueue({ action: 'approve_or_reject', approved: true }); @@ -391,7 +460,7 @@ describe('UserProxyLlm.respondToConfirmation', () => { expect(response.kind).toBe('approval'); }); - it('returns the permissive payload on a repeat requestId without consulting the agent', async () => { + it('reuses the first payload on a repeat requestId without consulting the agent', async () => { const agent = new FakeAgent(); agent.enqueue({ action: 'answer_questions', @@ -408,13 +477,37 @@ describe('UserProxyLlm.respondToConfirmation', () => { await proxy.respondToConfirmation(event); const second = await proxy.respondToConfirmation(event); - // Repeat falls back to buildAutoApprovePayload; for questions inputType - // that means kind: 'questions' with empty answers. expect(second.kind).toBe('questions'); - if (second.kind === 'questions') expect(second.answers).toEqual([]); + if (second.kind === 'questions') { + expect(second.answers).toEqual([{ questionId: 'q1', selectedOptions: ['#general'] }]); + } expect(agent.callCount).toBe(1); // only first call invoked the agent }); + it('does not treat a requestId as handled when decision generation throws', async () => { + const agent = new FakeAgent(); + agent.enqueue(new Error('temporary model failure'), { + action: 'answer_questions', + answers: [{ questionId: 'q1', selectedOptions: ['#general'] }], + }); + const proxy = new UserProxyLlm({ + conversation: [{ role: 'user', text: 'go' }], + agent, + }); + const event = questionEvent('req-retry', [ + { id: 'q1', question: 'Q?', type: 'single', options: ['#general'] }, + ]); + + await expect(proxy.respondToConfirmation(event)).rejects.toThrow('temporary model failure'); + const response = await proxy.respondToConfirmation(event); + + expect(response.kind).toBe('questions'); + if (response.kind === 'questions') { + expect(response.answers).toEqual([{ questionId: 'q1', selectedOptions: ['#general'] }]); + } + expect(agent.callCount).toBe(2); + }); + it('handles text input by routing to the agent and encoding as approval', async () => { const agent = new FakeAgent(); agent.enqueue({ @@ -523,6 +616,24 @@ describe('UserProxyLlm.decideFollowUp', () => { expect(decision.kind).toBe('done'); }); + it('falls back to the next scripted user turn when follow-up generation fails', async () => { + const agent = new FakeAgent(); + agent.enqueue(undefined); + const proxy = new UserProxyLlm({ + conversation: [ + { role: 'user', text: 'Build a workflow.' }, + { role: 'assistant', text: 'Which channel?' }, + { role: 'user', text: 'Use #ops-alerts.' }, + ], + messageBudget: 3, + agent, + }); + + const decision = await proxy.decideFollowUp(); + + expect(decision).toEqual({ kind: 'followUp', message: 'Use #ops-alerts.' }); + }); + it('returns done when the agent picks a confirmation-only action', async () => { const agent = new FakeAgent(); agent.enqueue({ diff --git a/packages/@n8n/instance-ai/evaluations/__tests__/verifier.test.ts b/packages/@n8n/instance-ai/evaluations/__tests__/verifier.test.ts new file mode 100644 index 00000000000..ce68dbaf9e4 --- /dev/null +++ b/packages/@n8n/instance-ai/evaluations/__tests__/verifier.test.ts @@ -0,0 +1,16 @@ +import { supportsOpenAiReasoning } from '../checklist/verifier'; + +describe('supportsOpenAiReasoning', () => { + it('enables reasoning for GPT-5 and o-series models', () => { + expect(supportsOpenAiReasoning('gpt-5')).toBe(true); + expect(supportsOpenAiReasoning('gpt-5.5')).toBe(true); + expect(supportsOpenAiReasoning('o3-mini')).toBe(true); + expect(supportsOpenAiReasoning('o4')).toBe(true); + }); + + it('does not enable reasoning for older OpenAI models', () => { + expect(supportsOpenAiReasoning('gpt-4.1')).toBe(false); + expect(supportsOpenAiReasoning('gpt-4o')).toBe(false); + expect(supportsOpenAiReasoning('gpt-3.5-turbo')).toBe(false); + }); +}); diff --git a/packages/@n8n/instance-ai/evaluations/__tests__/workflow-discovery.test.ts b/packages/@n8n/instance-ai/evaluations/__tests__/workflow-discovery.test.ts new file mode 100644 index 00000000000..63e2870063b --- /dev/null +++ b/packages/@n8n/instance-ai/evaluations/__tests__/workflow-discovery.test.ts @@ -0,0 +1,103 @@ +import type { Mock } from 'vitest'; + +import type { N8nClient, WorkflowResponse } from '../clients/n8n-client'; +import { buildAgentOutcome } from '../outcome/workflow-discovery'; +import type { EventOutcome } from '../types'; + +const emptyEventOutcome: EventOutcome = { + workflowIds: [], + executionIds: [], + dataTableIds: [], + finalText: '', + toolCalls: [], + agentActivities: [], +}; + +function workflow(id: string): WorkflowResponse { + return { + id, + name: `Workflow ${id}`, + active: false, + versionId: `version-${id}`, + nodes: [], + connections: {}, + }; +} + +function clientWithWorkflows(workflows: WorkflowResponse[]): { + client: N8nClient; + listWorkflows: Mock; + getWorkflow: Mock; +} { + const listWorkflows = vi.fn().mockResolvedValue(workflows); + const getWorkflow = vi + .fn() + .mockImplementation( + async (id: string) => + await Promise.resolve(workflows.find((wf) => wf.id === id) ?? workflow(id)), + ); + + return { + client: { + listWorkflows, + getWorkflow, + listExecutions: vi.fn().mockResolvedValue([]), + } as unknown as N8nClient, + listWorkflows, + getWorkflow, + }; +} + +describe('buildAgentOutcome', () => { + it('does not claim diff-only workflows when list-diff fallback is disabled', async () => { + const { client, getWorkflow } = clientWithWorkflows([workflow('other-run-workflow')]); + + const outcome = await buildAgentOutcome(client, emptyEventOutcome, new Set(), new Set(), { + allowListDiffFallback: false, + }); + + expect(outcome.workflowsCreated).toEqual([]); + expect(getWorkflow).not.toHaveBeenCalled(); + }); + + it('can still use list-diff fallback when explicitly enabled', async () => { + const { client } = clientWithWorkflows([workflow('fallback-workflow')]); + const claimedWorkflowIds = new Set<string>(); + + const outcome = await buildAgentOutcome( + client, + emptyEventOutcome, + new Set(), + claimedWorkflowIds, + { allowListDiffFallback: true }, + ); + + expect(outcome.workflowsCreated).toEqual([ + { + id: 'fallback-workflow', + name: 'Workflow fallback-workflow', + nodeCount: 0, + active: false, + }, + ]); + expect(claimedWorkflowIds.has('fallback-workflow')).toBe(true); + }); + + it('uses thread-scoped workflow ids without list-diffing visible workflows', async () => { + const { client, listWorkflows } = clientWithWorkflows([ + workflow('thread-workflow'), + workflow('other-workflow'), + ]); + + const outcome = await buildAgentOutcome( + client, + { ...emptyEventOutcome, workflowIds: ['thread-workflow'] }, + new Set(), + new Set(), + { allowListDiffFallback: true }, + ); + + expect(outcome.workflowsCreated.map((wf) => wf.id)).toEqual(['thread-workflow']); + expect(listWorkflows).not.toHaveBeenCalled(); + }); +}); diff --git a/packages/@n8n/instance-ai/evaluations/__tests__/workflow-report.test.ts b/packages/@n8n/instance-ai/evaluations/__tests__/workflow-report.test.ts new file mode 100644 index 00000000000..9012c649de5 --- /dev/null +++ b/packages/@n8n/instance-ai/evaluations/__tests__/workflow-report.test.ts @@ -0,0 +1,135 @@ +import { generateWorkflowReport } from '../report/workflow-report'; +import type { WorkflowTestCase, WorkflowTestCaseResult } from '../types'; + +const TEST_CASE: WorkflowTestCase = { + conversation: [{ role: 'user', text: 'Build a Slack notifier' }], + complexity: 'simple', + tags: [], + executionScenarios: [{ name: 's', description: 'd', dataSetup: '', successCriteria: 'ok' }], + datasets: ['full'], +}; + +function resultWith( + buildExpectationResults: WorkflowTestCaseResult['buildExpectationResults'], +): WorkflowTestCaseResult { + return { + testCase: TEST_CASE, + workflowBuildSuccess: true, + executionScenarioResults: [], + buildExpectationResults, + }; +} + +describe('build expectations in the workflow report', () => { + it('renders a section with per-expectation verdicts and reasons', () => { + const html = generateWorkflowReport([ + resultWith([ + { expectation: 'asked which channel', pass: true, reason: 'asked in turn 1' }, + { expectation: 'posts to Slack', pass: false, reason: 'no Slack node' }, + ]), + ]); + + expect(html).toContain('Build expectations'); + expect(html).toContain('asked which channel'); + expect(html).toContain('posts to Slack'); + expect(html).toContain('asked in turn 1'); + expect(html).toContain('no Slack node'); + expect(html).toContain('✓'); // pass icon + expect(html).toContain('✗'); // fail icon + }); + + it('links to the LLM debug report when run debug was captured', () => { + const html = generateWorkflowReport([ + { + ...resultWith([]), + fileSlug: 'slack-notifier', + runDebug: [ + { + threadId: 'thread-1', + runId: 'run-1', + startedAt: 1, + steps: [], + workflowCode: [], + }, + ], + }, + ]); + + expect(html).toContain('workflow-eval-llm-debug.html#tc-slack-notifier'); + expect(html).toContain('LLM steps →'); + }); + + it('renders an incomplete verdict neutrally and keeps it out of the count', () => { + const html = generateWorkflowReport([ + resultWith([ + { expectation: 'posts to Slack', pass: true, reason: 'has Slack node' }, + { + expectation: 'asked before building', + pass: false, + reason: 'no verdict returned', + incomplete: true, + }, + ]), + ]); + + // 1 graded pass, 0 graded fails, 1 no-verdict — not "1/2" (which would read as a fail). + expect(html).toContain('1/1 · 1 no verdict'); + expect(html).toContain('⌀'); // neutral no-verdict icon + expect(html).toContain('expectation n_a'); + expect(html).not.toContain('✗'); // no genuine-fail icon + }); + + it('omits the section entirely when there are no expectation results', () => { + const html = generateWorkflowReport([resultWith(undefined)]); + expect(html).not.toContain('Build expectations'); + }); +}); + +describe('transcript rendering', () => { + it('renders an ordered dialogue with inline tools and elevated user turns', () => { + const result: WorkflowTestCaseResult = { + testCase: TEST_CASE, + workflowBuildSuccess: true, + executionScenarioResults: [], + transcript: [ + { + userMessage: 'Build a Slack notifier', + steps: [ + { kind: 'agent-text', text: 'Planning first.' }, + { kind: 'tool-call', toolName: 'search-nodes' }, + { + kind: 'confirmation', + toolName: 'submit-plan', + resumeReason: 'approval', + approved: true, + }, + ], + }, + { userMessage: 'Actually use #alerts', steps: [{ kind: 'agent-text', text: 'Updated.' }] }, + ], + }; + const html = generateWorkflowReport([result]); + expect(html).toContain('Planning first.'); // agent narration + expect(html).toContain('search-nodes'); // inline tool, in order + expect(html).toContain('👤 approved'); // elevated user decision + expect(html).toContain('Actually use #alerts'); // follow-up user message + }); + + it('surfaces load_skill skillId inline in the tool-call header', () => { + const result: WorkflowTestCaseResult = { + testCase: TEST_CASE, + workflowBuildSuccess: true, + executionScenarioResults: [], + transcript: [ + { + userMessage: 'Build it', + steps: [ + { kind: 'tool-call', toolName: 'load_skill', args: { skillId: 'workflow-builder' } }, + ], + }, + ], + }; + const html = generateWorkflowReport([result]); + expect(html).toContain('<span class="transcript-inline-arg">workflow-builder</span>'); + }); +}); diff --git a/packages/@n8n/instance-ai/evaluations/binaryChecks/checks/code-node-no-http-requests.test.ts b/packages/@n8n/instance-ai/evaluations/binaryChecks/checks/code-node-no-http-requests.test.ts new file mode 100644 index 00000000000..faaa1dfd189 --- /dev/null +++ b/packages/@n8n/instance-ai/evaluations/binaryChecks/checks/code-node-no-http-requests.test.ts @@ -0,0 +1,174 @@ +import { codeNodeNoHttpRequests } from './code-node-no-http-requests'; +import type { WorkflowResponse } from '../../clients/n8n-client'; + +function workflowWithCodeNode(parameters: Record<string, unknown>): WorkflowResponse { + return { + id: 'wf-1', + name: 'Code HTTP test', + active: false, + nodes: [ + { + name: 'Manual Trigger', + type: 'n8n-nodes-base.manualTrigger', + parameters: {}, + }, + { + name: 'Code', + type: 'n8n-nodes-base.code', + parameters, + }, + ], + connections: { + 'Manual Trigger': { + main: [[{ node: 'Code', type: 'main', index: 0 }]], + }, + }, + }; +} + +describe('codeNodeNoHttpRequests', () => { + it('fails when a Code node uses fetch()', async () => { + const workflow = workflowWithCodeNode({ + mode: 'runOnceForAllItems', + jsCode: "const res = await fetch('https://api.example.com/items');\nreturn await res.json();", + }); + + const result = await codeNodeNoHttpRequests.run(workflow, { prompt: 'Fetch items' }); + + expect(result.pass).toBe(false); + expect(result.comment).toContain('fetch()'); + expect(result.comment).toContain('HTTP Request node'); + }); + + it('fails when a Code node uses axios', async () => { + const workflow = workflowWithCodeNode({ + jsCode: + "const axios = require('axios');\nconst res = await axios.get(url);\nreturn res.data;", + }); + + const result = await codeNodeNoHttpRequests.run(workflow, { prompt: 'Call an API' }); + + expect(result.pass).toBe(false); + expect(result.comment).toContain('axios'); + }); + + it('fails when a Code node requires the http module', async () => { + const workflow = workflowWithCodeNode({ + jsCode: "const https = require('https');\nreturn [];", + }); + + const result = await codeNodeNoHttpRequests.run(workflow, { prompt: 'Call an API' }); + + expect(result.pass).toBe(false); + expect(result.comment).toContain('require of an HTTP module'); + }); + + it('fails when a Code node uses this.helpers.httpRequest', async () => { + const workflow = workflowWithCodeNode({ + jsCode: 'const res = await this.helpers.httpRequest({ url });\nreturn [{ json: res }];', + }); + + const result = await codeNodeNoHttpRequests.run(workflow, { prompt: 'Call an API' }); + + expect(result.pass).toBe(false); + expect(result.comment).toContain('this.helpers.httpRequest'); + }); + + it('fails when a Python Code node uses requests', async () => { + const workflow = workflowWithCodeNode({ + language: 'python', + pythonCode: + "import requests\nres = requests.get('https://api.example.com')\nreturn res.json()", + }); + + const result = await codeNodeNoHttpRequests.run(workflow, { prompt: 'Call an API' }); + + expect(result.pass).toBe(false); + expect(result.comment).toContain('requests'); + }); + + it('fails when a Python Code node uses a from-import of an HTTP library', async () => { + const workflow = workflowWithCodeNode({ + language: 'pythonNative', + pythonCode: + "from requests import get\nres = get('https://api.example.com')\nreturn res.json()", + }); + + const result = await codeNodeNoHttpRequests.run(workflow, { prompt: 'Call an API' }); + + expect(result.pass).toBe(false); + expect(result.comment).toContain('requests'); + }); + + it('fails when a Python Code node imports urllib via from-import', async () => { + const workflow = workflowWithCodeNode({ + language: 'python', + pythonCode: + "from urllib.request import urlopen\nres = urlopen('https://api.example.com')\nreturn res.read()", + }); + + const result = await codeNodeNoHttpRequests.run(workflow, { prompt: 'Call an API' }); + + expect(result.pass).toBe(false); + expect(result.comment).toContain('urllib'); + }); + + it('ignores code of the inactive language', async () => { + const workflow = workflowWithCodeNode({ + language: 'python', + jsCode: "const res = await fetch('https://api.example.com');\nreturn await res.json();", + pythonCode: 'return [item.json for item in _input.all()]', + }); + + const result = await codeNodeNoHttpRequests.run(workflow, { prompt: 'Process data' }); + + expect(result).toEqual({ pass: true }); + }); + + it('passes when Code nodes only transform data', async () => { + const workflow = workflowWithCodeNode({ + mode: 'runOnceForAllItems', + jsCode: + 'const items = $input.all();\nreturn items.map((item) => ({ json: { ...item.json, processed: true } }));', + }); + + const result = await codeNodeNoHttpRequests.run(workflow, { prompt: 'Process data' }); + + expect(result).toEqual({ pass: true }); + }); + + it('does not flag comments mentioning fetched data', async () => { + const workflow = workflowWithCodeNode({ + jsCode: '// transform the data fetched by the HTTP Request node\nreturn $input.all();', + }); + + const result = await codeNodeNoHttpRequests.run(workflow, { prompt: 'Process data' }); + + expect(result).toEqual({ pass: true }); + }); + + it('reports N/A when the workflow has no Code nodes', async () => { + const workflow: WorkflowResponse = { + id: 'wf-2', + name: 'No code', + active: false, + nodes: [ + { + name: 'Manual Trigger', + type: 'n8n-nodes-base.manualTrigger', + parameters: {}, + }, + { + name: 'HTTP Request', + type: 'n8n-nodes-base.httpRequest', + parameters: { url: 'https://api.example.com' }, + }, + ], + connections: {}, + }; + + const result = await codeNodeNoHttpRequests.run(workflow, { prompt: 'Call an API' }); + + expect(result).toEqual({ pass: true, applicable: false }); + }); +}); diff --git a/packages/@n8n/instance-ai/evaluations/binaryChecks/checks/code-node-no-http-requests.ts b/packages/@n8n/instance-ai/evaluations/binaryChecks/checks/code-node-no-http-requests.ts new file mode 100644 index 00000000000..1d3d48c404f --- /dev/null +++ b/packages/@n8n/instance-ai/evaluations/binaryChecks/checks/code-node-no-http-requests.ts @@ -0,0 +1,71 @@ +import type { WorkflowNodeResponse } from '../../clients/n8n-client'; +import type { BinaryCheck } from '../types'; + +const CODE_NODE_TYPE = 'n8n-nodes-base.code'; + +const HTTP_CODE_PATTERNS: Array<{ pattern: RegExp; label: string }> = [ + { pattern: /\bfetch\s*\(/, label: 'fetch()' }, + { pattern: /\bXMLHttpRequest\b/, label: 'XMLHttpRequest' }, + { pattern: /\baxios\s*[.(]/, label: 'axios' }, + { pattern: /\bthis\.helpers\.httpRequest/, label: 'this.helpers.httpRequest' }, + { + pattern: + /require\s*\(\s*['"`](?:node:)?(?:https?|node-fetch|axios|got|undici|superagent|request)['"`]\s*\)/, + label: 'require of an HTTP module', + }, + { + pattern: + /\burllib\.|(?:^|\n)\s*(?:import\s+urllib(?:\.\w+)*\b|from\s+urllib(?:\.\w+)*\s+import\b)/, + label: 'urllib', + }, + { + pattern: + /(?:^|\n)\s*(?:import\s+requests\b|from\s+requests(?:\.\w+)*\s+import\b)|\brequests\.(?:get|post|put|patch|delete|head|request)\s*\(/, + label: 'requests', + }, + { pattern: /\bhttpx\s*[.(]|(?:^|\n)\s*from\s+httpx(?:\.\w+)*\s+import\b/, label: 'httpx' }, + { pattern: /\bhttp\.client\b|(?:^|\n)\s*from\s+http\.client\s+import\b/, label: 'http.client' }, + { pattern: /\baiohttp\.|(?:^|\n)\s*from\s+aiohttp(?:\.\w+)*\s+import\b/, label: 'aiohttp' }, +]; + +function isCodeNode(node: WorkflowNodeResponse): boolean { + return node.type === CODE_NODE_TYPE; +} + +function getCodeText(node: WorkflowNodeResponse): string { + const { jsCode, pythonCode, language } = node.parameters ?? {}; + const activeCode = language === 'python' || language === 'pythonNative' ? pythonCode : jsCode; + return typeof activeCode === 'string' ? activeCode : ''; +} + +export const codeNodeNoHttpRequests: BinaryCheck = { + name: 'code_node_no_http_requests', + description: + 'Code nodes do not hand-roll HTTP requests — the sandbox has no network access (fetch/axios/require fail at runtime); HTTP calls belong in the HTTP Request node', + kind: 'deterministic', + dimension: 'nodes_craftsmanship', + run(workflow) { + const codeNodes = (workflow.nodes ?? []).filter(isCodeNode); + if (codeNodes.length === 0) return { pass: true, applicable: false }; + + const issues: string[] = []; + for (const node of codeNodes) { + const code = getCodeText(node); + if (!code) continue; + + const matched = HTTP_CODE_PATTERNS.filter(({ pattern }) => pattern.test(code)).map( + ({ label }) => label, + ); + if (matched.length > 0) { + issues.push( + `"${node.name}" makes HTTP requests in code (${matched.join(', ')}) — use the HTTP Request node instead`, + ); + } + } + + return { + pass: issues.length === 0, + ...(issues.length > 0 ? { comment: issues.join('; ') } : {}), + }; + }, +}; diff --git a/packages/@n8n/instance-ai/evaluations/binaryChecks/checks/error-routes-consistent.test.ts b/packages/@n8n/instance-ai/evaluations/binaryChecks/checks/error-routes-consistent.test.ts new file mode 100644 index 00000000000..0b2f5921a35 --- /dev/null +++ b/packages/@n8n/instance-ai/evaluations/binaryChecks/checks/error-routes-consistent.test.ts @@ -0,0 +1,108 @@ +import { errorRoutesConsistent } from './error-routes-consistent'; +import type { WorkflowResponse } from '../../clients/n8n-client'; + +function reminderWorkflow(overrides: { + markSentMain?: Array<Array<{ node: string; type: string; index: number }>>; + gmailMain?: Array<Array<{ node: string; type: string; index: number }>>; + gmailOnError?: 'continueErrorOutput'; +}): WorkflowResponse { + return { + id: 'wf-1', + name: 'Reminder sender', + active: false, + nodes: [ + { name: 'Daily', type: 'n8n-nodes-base.scheduleTrigger', parameters: {} }, + { + name: 'Send Gmail', + type: 'n8n-nodes-base.gmail', + parameters: {}, + ...(overrides.gmailOnError ? { onError: overrides.gmailOnError } : {}), + }, + { name: 'Mark Sent', type: 'n8n-nodes-base.dataTable', parameters: {} }, + { name: 'Mark Failed', type: 'n8n-nodes-base.dataTable', parameters: {} }, + ], + connections: { + Daily: { main: [[{ node: 'Send Gmail', type: 'main', index: 0 }]] }, + 'Send Gmail': { + main: overrides.gmailMain ?? [[{ node: 'Mark Sent', type: 'main', index: 0 }]], + }, + ...(overrides.markSentMain ? { 'Mark Sent': { main: overrides.markSentMain } } : {}), + }, + }; +} + +describe('errorRoutesConsistent', () => { + it('fails when a connection leaves an output port the node does not have (INS-425 shape)', async () => { + const workflow = reminderWorkflow({ + markSentMain: [[], [{ node: 'Mark Failed', type: 'main', index: 0 }]], + }); + + const result = await errorRoutesConsistent.run(workflow, { prompt: 'Send reminders' }); + + expect(result.pass).toBe(false); + expect(result.comment).toContain('Mark Sent'); + expect(result.comment).toContain('output index 1'); + }); + + it('fails when an error output is enabled but wired to nothing', async () => { + const workflow = reminderWorkflow({ gmailOnError: 'continueErrorOutput' }); + + const result = await errorRoutesConsistent.run(workflow, { prompt: 'Send reminders' }); + + expect(result.pass).toBe(false); + expect(result.comment).toContain('Send Gmail'); + expect(result.comment).toContain('wired to nothing'); + }); + + it('passes when the error route originates from the node that declares it', async () => { + const workflow = reminderWorkflow({ + gmailOnError: 'continueErrorOutput', + gmailMain: [ + [{ node: 'Mark Sent', type: 'main', index: 0 }], + [{ node: 'Mark Failed', type: 'main', index: 0 }], + ], + }); + + const result = await errorRoutesConsistent.run(workflow, { prompt: 'Send reminders' }); + + expect(result).toEqual({ pass: true }); + }); + + it('does not flag natural multi-output nodes like IF', async () => { + const workflow: WorkflowResponse = { + id: 'wf-2', + name: 'Branching', + active: false, + nodes: [ + { name: 'Start', type: 'n8n-nodes-base.manualTrigger', parameters: {} }, + { name: 'IF', type: 'n8n-nodes-base.if', parameters: {} }, + { name: 'A', type: 'n8n-nodes-base.set', parameters: {} }, + { name: 'B', type: 'n8n-nodes-base.set', parameters: {} }, + ], + connections: { + Start: { main: [[{ node: 'IF', type: 'main', index: 0 }]] }, + IF: { + main: [[{ node: 'A', type: 'main', index: 0 }], [{ node: 'B', type: 'main', index: 0 }]], + }, + }, + }; + + const result = await errorRoutesConsistent.run(workflow, { prompt: 'Branch' }); + + expect(result).toEqual({ pass: true }); + }); + + it('reports N/A when there are no connections or error outputs to inspect', async () => { + const workflow: WorkflowResponse = { + id: 'wf-3', + name: 'Empty', + active: false, + nodes: [{ name: 'Start', type: 'n8n-nodes-base.manualTrigger', parameters: {} }], + connections: {}, + }; + + const result = await errorRoutesConsistent.run(workflow, { prompt: 'Nothing' }); + + expect(result).toEqual({ pass: true, applicable: false }); + }); +}); diff --git a/packages/@n8n/instance-ai/evaluations/binaryChecks/checks/error-routes-consistent.ts b/packages/@n8n/instance-ai/evaluations/binaryChecks/checks/error-routes-consistent.ts new file mode 100644 index 00000000000..b01ef33e521 --- /dev/null +++ b/packages/@n8n/instance-ai/evaluations/binaryChecks/checks/error-routes-consistent.ts @@ -0,0 +1,78 @@ +import type { WorkflowNodeResponse } from '../../clients/n8n-client'; +import type { BinaryCheck } from '../types'; + +/** Node types whose extra main outputs are natural, not error pins. */ +const MULTI_OUTPUT_TYPES = new Set([ + 'n8n-nodes-base.if', + 'n8n-nodes-base.switch', + 'n8n-nodes-base.splitInBatches', + 'n8n-nodes-base.compareDatasets', + '@n8n/n8n-nodes-langchain.textClassifier', + '@n8n/n8n-nodes-langchain.sentimentAnalysis', +]); + +type MainConnections = Array<Array<{ node: string }> | null | undefined>; + +function getMainConnections(value: unknown): MainConnections | undefined { + if (!value || typeof value !== 'object') return undefined; + const main = (value as { main?: unknown }).main; + return Array.isArray(main) ? (main as MainConnections) : undefined; +} + +function hasErrorOutput(node: WorkflowNodeResponse): boolean { + return node.onError === 'continueErrorOutput'; +} + +export const errorRoutesConsistent: BinaryCheck = { + name: 'error_routes_consistent', + description: + 'Error routing is real: nodes with onError: continueErrorOutput have their error output wired, and no connection leaves an output port the node does not have', + kind: 'deterministic', + dimension: 'connection_topology', + run(workflow) { + const nodes = workflow.nodes ?? []; + const nodesByName = new Map(nodes.map((node) => [node.name, node])); + const connections: Record<string, unknown> = workflow.connections ?? {}; + + const relevant = nodes.filter( + (node) => hasErrorOutput(node) || getMainConnections(connections[node.name]), + ); + if (relevant.length === 0) return { pass: true, applicable: false }; + + const issues: string[] = []; + + for (const [sourceName, nodeConnections] of Object.entries(connections)) { + const main = getMainConnections(nodeConnections); + if (!main) continue; + const sourceNode = nodesByName.get(sourceName); + if (!sourceNode) continue; + if (MULTI_OUTPUT_TYPES.has(sourceNode.type)) continue; + + const errorPinAllowed = hasErrorOutput(sourceNode); + for (let index = 1; index < main.length; index++) { + if (!main[index] || main[index]?.length === 0) continue; + if (index === 1 && errorPinAllowed) continue; + issues.push( + `"${sourceName}" has a connection from output index ${index}, a port it does not have${errorPinAllowed ? '' : " (no onError: 'continueErrorOutput')"}`, + ); + } + } + + for (const node of nodes) { + if (!hasErrorOutput(node) || MULTI_OUTPUT_TYPES.has(node.type)) continue; + const main = getMainConnections(connections[node.name]); + const lastSlot = main?.[main.length - 1]; + const errorWired = !!main && main.length >= 2 && !!lastSlot && lastSlot.length > 0; + if (!errorWired) { + issues.push( + `"${node.name}" sets onError: 'continueErrorOutput' but its error output is wired to nothing — failures vanish silently`, + ); + } + } + + return { + pass: issues.length === 0, + ...(issues.length > 0 ? { comment: issues.join('; ') } : {}), + }; + }, +}; diff --git a/packages/@n8n/instance-ai/evaluations/binaryChecks/checks/index.ts b/packages/@n8n/instance-ai/evaluations/binaryChecks/checks/index.ts index d634212c7b5..d061d7165ce 100644 --- a/packages/@n8n/instance-ai/evaluations/binaryChecks/checks/index.ts +++ b/packages/@n8n/instance-ai/evaluations/binaryChecks/checks/index.ts @@ -8,8 +8,10 @@ import type { BinaryCheck } from '../types'; import { agentHasDynamicPrompt } from './agent-has-dynamic-prompt'; import { agentHasLanguageModel } from './agent-has-language-model'; import { allNodesConnected } from './all-nodes-connected'; +import { codeNodeNoHttpRequests } from './code-node-no-http-requests'; import { correctNodeOperations } from './correct-node-operations'; import { descriptiveNodeNames } from './descriptive-node-names'; +import { errorRoutesConsistent } from './error-routes-consistent'; import { expressionsReferenceExistingNodes } from './expressions-reference-existing-nodes'; import { fulfillsUserRequest } from './fulfills-user-request'; import { handlesMultipleItems } from './handles-multiple-items'; @@ -48,6 +50,7 @@ export const CONNECTION_TOPOLOGY_CHECKS: BinaryCheck[] = [ noUnreachableNodes, switchFallbackOutputEnabled, handlesMultipleItems, + errorRoutesConsistent, ]; export const PARAMETER_CORRECTNESS_CHECKS: BinaryCheck[] = [ @@ -76,6 +79,7 @@ export const AI_NODES_CHECKS: BinaryCheck[] = [ export const NODES_CRAFTSMANSHIP_CHECKS: BinaryCheck[] = [ noUnnecessaryCodeNodes, + codeNodeNoHttpRequests, descriptiveNodeNames, responseMatchesWorkflowChanges, ]; diff --git a/packages/@n8n/instance-ai/evaluations/build-expectations/verifier.ts b/packages/@n8n/instance-ai/evaluations/build-expectations/verifier.ts new file mode 100644 index 00000000000..021fcf76b11 --- /dev/null +++ b/packages/@n8n/instance-ai/evaluations/build-expectations/verifier.ts @@ -0,0 +1,168 @@ +import type { Message } from '@n8n/agents'; +import { z } from 'zod'; + +import { EPHEMERAL_CACHE, SONNET_MODEL, createEvalAgent } from '../../src/utils/eval-agents'; +import type { WorkflowResponse } from '../clients/n8n-client'; +import { buildWorkflowContextBlock } from '../harness/workflow-context'; +import { BUILD_EXPECTATIONS_VERIFY_PROMPT } from '../system-prompts/build-expectations-verify'; +import type { BuildExpectationResult, ConversationMetrics, TranscriptTurn } from '../types'; +import { transcriptAsText } from '../utils/conversation-text'; + +// --------------------------------------------------------------------------- +// Structured output schema +// --------------------------------------------------------------------------- + +const expectationResultSchema = z.object({ + results: z.array( + z.object({ + index: z.number(), + pass: z.boolean(), + reason: z.string(), + }), + ), +}); + +// --------------------------------------------------------------------------- +// Public API +// --------------------------------------------------------------------------- + +/** The conversation/build artifacts the judge reasons over. */ +export interface BuildExpectationsInput { + transcript: TranscriptTurn[]; + workflowJson?: WorkflowResponse; + metrics?: ConversationMetrics; +} + +const JUDGE_MODEL = SONNET_MODEL; +const MAX_VERIFY_ATTEMPTS = 2; +const VERIFY_ATTEMPT_TIMEOUT_MS = 120_000; + +/** + * Judge author-written natural-language expectations about the build conversation + + * resulting workflow. Informational only — never feeds verify_pass@k. On judge failure + * (errors or timeouts across all attempts) it returns `incomplete` verdicts so the report + * stays complete while reading as "no verdict" rather than failures; callers additionally + * guard with `.catch()`. + */ +export async function verifyBuildExpectations( + expectations: string[], + build: BuildExpectationsInput, +): Promise<BuildExpectationResult[]> { + if (expectations.length === 0) return []; + + // Workflow block is stable per build — mark it as an Anthropic cache breakpoint. + const messages: Message[] = [ + { + role: 'user', + content: [ + { + type: 'text', + text: buildWorkflowContextBlock(build.workflowJson), + providerOptions: EPHEMERAL_CACHE, + }, + { + type: 'text', + text: buildConversationContext(expectations, build.transcript, build.metrics), + }, + ], + }, + ]; + + for (let attempt = 1; attempt <= MAX_VERIFY_ATTEMPTS; attempt++) { + const agent = createEvalAgent('eval-build-expectations-verifier', { + instructions: BUILD_EXPECTATIONS_VERIFY_PROMPT, + cache: true, + model: JUDGE_MODEL, + }).structuredOutput(expectationResultSchema); + + const abortController = new AbortController(); + const timer = setTimeout( + () => + abortController.abort( + new Error(`expectations judge timed out after ${VERIFY_ATTEMPT_TIMEOUT_MS}ms`), + ), + VERIFY_ATTEMPT_TIMEOUT_MS, + ); + let result; + try { + result = await agent.generate(messages, { abortSignal: abortController.signal }); + } catch (error: unknown) { + const msg = error instanceof Error ? error.message : String(error); + console.warn(`[expectations] attempt ${attempt}/${MAX_VERIFY_ATTEMPTS} failed: ${msg}`); + continue; + } finally { + clearTimeout(timer); + } + + const parsed = expectationResultSchema.safeParse(result.structuredOutput); + const byIndex = new Map<number, { pass: boolean; reason: string }>(); + if (parsed.success) { + for (const entry of parsed.data.results) { + // Schema validated index/pass/reason types; only the range needs checking. + if (entry.index >= 0 && entry.index < expectations.length) { + byIndex.set(entry.index, { pass: entry.pass, reason: entry.reason }); + } + } + } + + if (byIndex.size > 0) { + // Omitted expectations are marked `incomplete` (not a genuine fail). + return expectations.map((expectation, i) => { + const verdict = byIndex.get(i); + return verdict + ? { expectation, pass: verdict.pass, reason: verdict.reason } + : { expectation, pass: false, reason: 'no verdict returned', incomplete: true }; + }); + } + + console.warn( + `[expectations] attempt ${attempt}/${MAX_VERIFY_ATTEMPTS} produced no parseable results`, + ); + } + + console.warn(`[expectations] exhausted ${MAX_VERIFY_ATTEMPTS} attempts, returning all-fail`); + return allFailVerdicts(expectations, 'judge produced no result'); +} + +/** + * Verdicts when the judge produced nothing (exhausted attempts, or callers' + * `.catch()`). Marked `incomplete` so a dead judge renders as neutral "no + * verdict" rather than every expectation failing. + */ +export function allFailVerdicts(expectations: string[], reason: string): BuildExpectationResult[] { + return expectations.map((expectation) => ({ + expectation, + pass: false, + reason, + incomplete: true, + })); +} + +// --------------------------------------------------------------------------- +// Artifact assembly +// --------------------------------------------------------------------------- + +function buildConversationContext( + expectations: string[], + transcript: TranscriptTurn[], + metrics: ConversationMetrics | undefined, +): string { + const metricsBlock = metrics + ? `\`\`\`json\n${JSON.stringify(metrics, null, 2)}\n\`\`\`` + : '(none captured)'; + return [ + '## Conversation transcript', + '', + transcriptAsText(transcript), + '', + '## Conversation metrics (ground truth — do not recount)', + '', + metricsBlock, + '', + '## Expectations', + '', + expectations.map((e, i) => `${String(i)}. ${e}`).join('\n'), + '', + 'Return a verdict for every numbered expectation, using its 0-based index.', + ].join('\n'); +} diff --git a/packages/@n8n/instance-ai/evaluations/checklist/verifier.ts b/packages/@n8n/instance-ai/evaluations/checklist/verifier.ts index 056ddb009c4..4ccd7ab53ce 100644 --- a/packages/@n8n/instance-ai/evaluations/checklist/verifier.ts +++ b/packages/@n8n/instance-ai/evaluations/checklist/verifier.ts @@ -1,7 +1,12 @@ import type { Message } from '@n8n/agents'; import { z } from 'zod'; -import { EPHEMERAL_CACHE, createEvalAgent } from '../../src/utils/eval-agents'; +import { + EPHEMERAL_CACHE, + createEvalAgent, + extractText, + resolveEvalModelConfig, +} from '../../src/utils/eval-agents'; import type { VerificationArtifact } from '../harness/runner'; import { MOCK_EXECUTION_VERIFY_PROMPT } from '../system-prompts/mock-execution-verify'; import type { ChecklistItem, ChecklistResult } from '../types'; @@ -16,8 +21,8 @@ const checklistResultSchema = z.object({ id: z.number(), pass: z.boolean(), reasoning: z.string(), - failureCategory: z.string().optional(), - rootCause: z.string().optional(), + failureCategory: z.string().nullable().optional(), + rootCause: z.string().nullable().optional(), }), ), }); @@ -28,17 +33,255 @@ const checklistResultSchema = z.object({ const MAX_VERIFY_ATTEMPTS = 2; const VERIFY_ATTEMPT_TIMEOUT_MS = 120_000; +const VERIFIER_DEBUG = process.env.N8N_EVAL_VERIFIER_DEBUG === '1'; -export async function verifyChecklist( - checklist: ChecklistItem[], +export interface VerifierAttemptDebug { + attempt: number; + status: 'threw' | 'model_error' | 'no_parseable_results' | 'success'; + error: string | null; + finishReason: unknown; + usage: unknown; + hasStructuredOutput: boolean; + structuredOutput: z.infer<typeof checklistResultSchema> | null; + assistantText: string; + parsedResultsCount: number; + acceptedResultsCount: number; +} + +export interface VerifyChecklistResult { + results: ChecklistResult[]; + attempts: VerifierAttemptDebug[]; +} + +function parseStructuredOutputFromText( + text: string, +): z.infer<typeof checklistResultSchema> | undefined { + const trimmed = text.trim(); + if (trimmed.length === 0) return undefined; + + try { + const parsed: unknown = JSON.parse(trimmed); + const validated = checklistResultSchema.safeParse(parsed); + return validated.success ? validated.data : undefined; + } catch { + return undefined; + } +} + +function buildChecklistResults( + parsed: z.infer<typeof checklistResultSchema> | undefined, + validIds: Set<number>, +): ChecklistResult[] { + const results: ChecklistResult[] = []; + + if (!parsed?.results) return results; + + for (const entry of parsed.results) { + if (typeof entry.id === 'number' && typeof entry.pass === 'boolean' && validIds.has(entry.id)) { + results.push({ + id: entry.id, + pass: entry.pass, + reasoning: entry.reasoning ?? '', + strategy: 'llm', + failureCategory: + entry.failureCategory ?? (!entry.pass ? 'verification_failure' : undefined), + rootCause: entry.rootCause ?? undefined, + }); + } + } + + return results; +} + +function logVerifierDebug(label: string, payload?: unknown): void { + if (!VERIFIER_DEBUG) return; + + if (payload === undefined) { + console.warn(`[verifier-debug] ${label}`); + return; + } + + console.warn(`[verifier-debug] ${label}: ${JSON.stringify(payload, null, 2)}`); +} + +function getOpenAiResponsesUrl(baseUrl?: string): string { + const trimmedBaseUrl = baseUrl?.trim(); + const base = ( + trimmedBaseUrl && trimmedBaseUrl.length > 0 ? trimmedBaseUrl : 'https://api.openai.com/v1' + ).replace(/\/+$/, ''); + return `${base}/responses`; +} + +function asRecord(value: unknown): Record<string, unknown> | undefined { + return value && typeof value === 'object' && !Array.isArray(value) + ? (value as Record<string, unknown>) + : undefined; +} + +function extractOpenAiAssistantText(response: unknown): string { + const responseRecord = asRecord(response); + if (!responseRecord) return ''; + + const output = responseRecord.output; + if (!Array.isArray(output)) return ''; + + const texts: string[] = []; + for (const item of output) { + const itemRecord = asRecord(item); + if (itemRecord?.type !== 'message') continue; + const content = itemRecord.content; + if (!Array.isArray(content)) continue; + for (const part of content) { + const partRecord = asRecord(part); + if (partRecord?.type !== 'output_text' || !('text' in partRecord)) continue; + const text = partRecord.text; + texts.push(typeof text === 'string' ? text : JSON.stringify(text)); + } + } + + return texts.join(''); +} + +export function supportsOpenAiReasoning(modelId: string): boolean { + const normalized = modelId.trim().toLowerCase(); + return /^(gpt-5(?:$|[-.])|o[1-9](?:$|[-.]))/.test(normalized); +} + +async function runNativeOpenAiVerifier( + userMessage: string, + abortSignal: AbortSignal, +): Promise<{ + finishReason: unknown; + usage: unknown; + assistantText: string; + parsed: z.infer<typeof checklistResultSchema> | undefined; +}> { + const model = resolveEvalModelConfig(); + const requestBody = { + model: model.providerModelId, + ...(supportsOpenAiReasoning(model.providerModelId) ? { reasoning: { effort: 'high' } } : {}), + input: [ + { + role: 'developer', + content: MOCK_EXECUTION_VERIFY_PROMPT, + }, + { + role: 'user', + content: [ + { + type: 'input_text', + text: userMessage, + }, + ], + }, + ], + text: { + format: { + type: 'json_schema', + strict: true, + name: 'response', + schema: { + type: 'object', + properties: { + results: { + type: 'array', + items: { + type: 'object', + properties: { + id: { type: 'number' }, + pass: { type: 'boolean' }, + reasoning: { type: 'string' }, + failureCategory: { type: ['string', 'null'] }, + rootCause: { type: ['string', 'null'] }, + }, + required: ['id', 'pass', 'reasoning', 'failureCategory', 'rootCause'], + additionalProperties: false, + }, + }, + }, + required: ['results'], + additionalProperties: false, + $schema: 'http://json-schema.org/draft-07/schema#', + }, + }, + }, + }; + const response = await fetch(getOpenAiResponsesUrl(model.url), { + method: 'POST', + headers: { + Authorization: `Bearer ${model.apiKey}`, + 'Content-Type': 'application/json', + }, + body: JSON.stringify(requestBody), + signal: abortSignal, + }); + + if (!response.ok) { + const body = await response.text(); + throw new Error(`OpenAI Responses API ${response.status}: ${body}`); + } + + const json = (await response.json()) as Record<string, unknown>; + const assistantText = extractOpenAiAssistantText(json); + + return { + finishReason: 'status' in json ? json.status : null, + usage: 'usage' in json ? json.usage : null, + assistantText, + parsed: parseStructuredOutputFromText(assistantText), + }; +} + +function createAttemptDebug(input: { + attempt: number; + status: VerifierAttemptDebug['status']; + error?: string | null; + finishReason?: unknown; + usage?: unknown; + assistantText?: string; + parsed?: z.infer<typeof checklistResultSchema>; + acceptedResultsCount?: number; +}): VerifierAttemptDebug { + return { + attempt: input.attempt, + status: input.status, + error: input.error ?? null, + finishReason: input.finishReason ?? null, + usage: input.usage ?? null, + hasStructuredOutput: input.parsed !== undefined, + structuredOutput: input.parsed ?? null, + assistantText: input.assistantText ?? '', + parsedResultsCount: input.parsed?.results?.length ?? 0, + acceptedResultsCount: input.acceptedResultsCount ?? 0, + }; +} + +function buildNativeVerifierMessage( + llmItems: ChecklistItem[], artifact: VerificationArtifact, -): Promise<ChecklistResult[]> { - const llmItems = checklist.filter((i) => i.strategy === 'llm'); - if (llmItems.length === 0) return []; +): string { + return `## Checklist +${JSON.stringify(llmItems, null, 2)} + +## Workflow Context + +${artifact.workflowContext} + +## Scenario Context + +${artifact.scenarioContext} + +Verify each checklist item against the workflow + scenario artifact above.`; +} + +function buildVerifierMessages( + llmItems: ChecklistItem[], + artifact: VerificationArtifact, +): Message[] { // Multi-block user message: the workflow context is stable across scenarios of // the same build, so we mark it as a cache breakpoint for Anthropic prompt caching. - const messages: Message[] = [ + return [ { role: 'user', content: [ @@ -54,65 +297,164 @@ export async function verifyChecklist( ], }, ]; +} + +export async function verifyChecklist( + checklist: ChecklistItem[], + artifact: VerificationArtifact, +): Promise<VerifyChecklistResult> { + const llmItems = checklist.filter((i) => i.strategy === 'llm'); + if (llmItems.length === 0) return { results: [], attempts: [] }; + + const nativeUserMessage = buildNativeVerifierMessage(llmItems, artifact); + const messages = buildVerifierMessages(llmItems, artifact); const validIds = new Set(llmItems.map((i) => i.id)); + const attempts: VerifierAttemptDebug[] = []; + const model = resolveEvalModelConfig(); + const useNativeOpenAiVerifier = model.provider === 'openai'; + + logVerifierDebug('request summary', { + checklistIds: Array.from(validIds), + userMessageChars: nativeUserMessage.length, + path: useNativeOpenAiVerifier ? 'native-openai' : 'agents-wrapper', + }); for (let attempt = 1; attempt <= MAX_VERIFY_ATTEMPTS; attempt++) { - const agent = createEvalAgent('eval-checklist-verifier', { - instructions: MOCK_EXECUTION_VERIFY_PROMPT, - cache: true, - }).structuredOutput(checklistResultSchema); - const abortController = new AbortController(); const timer = setTimeout( () => abortController.abort(new Error(`verifier timed out after ${VERIFY_ATTEMPT_TIMEOUT_MS}ms`)), VERIFY_ATTEMPT_TIMEOUT_MS, ); - let result; + try { - result = await agent.generate(messages, { abortSignal: abortController.signal }); + let assistantText = ''; + let parsed: z.infer<typeof checklistResultSchema> | undefined; + let finishReason: unknown = null; + let usage: unknown = null; + let modelError: string | null = null; + let hasStructuredOutput = false; + + if (useNativeOpenAiVerifier) { + const nativeResult = await runNativeOpenAiVerifier( + nativeUserMessage, + abortController.signal, + ); + assistantText = nativeResult.assistantText; + parsed = nativeResult.parsed; + finishReason = nativeResult.finishReason; + usage = nativeResult.usage; + hasStructuredOutput = parsed !== undefined; + } else { + const agent = createEvalAgent('eval-checklist-verifier', { + instructions: MOCK_EXECUTION_VERIFY_PROMPT, + cache: true, + }).structuredOutput(checklistResultSchema); + + const result = await agent.generate(messages, { abortSignal: abortController.signal }); + assistantText = extractText(result); + const parsedStructuredOutput = checklistResultSchema.safeParse(result.structuredOutput); + parsed = parsedStructuredOutput.success + ? parsedStructuredOutput.data + : parseStructuredOutputFromText(assistantText); + finishReason = 'finishReason' in result ? result.finishReason : null; + usage = 'usage' in result ? result.usage : null; + hasStructuredOutput = result.structuredOutput !== undefined; + + if (result.error) { + modelError = + result.error instanceof Error ? result.error.message : JSON.stringify(result.error); + } + + logVerifierDebug(`attempt ${attempt} raw result`, { + resultKeys: Object.keys(result as Record<string, unknown>), + finishReason, + error: 'error' in result ? result.error : null, + model: 'model' in result ? result.model : null, + usage, + messages: 'messages' in result ? result.messages : null, + hasStructuredOutput, + structuredOutput: result.structuredOutput ?? null, + assistantTextChars: assistantText.length, + assistantTextPreview: assistantText.slice(0, 2_000), + }); + } + + const results = buildChecklistResults(parsed, validIds); + + logVerifierDebug(`attempt ${attempt} parse summary`, { + parsedResultsCount: parsed?.results?.length ?? 0, + acceptedResultsCount: results.length, + parsedIds: parsed?.results?.map((entry) => entry.id) ?? [], + validIds: Array.from(validIds), + finishReason, + hasStructuredOutput, + }); + + if (modelError) { + attempts.push( + createAttemptDebug({ + attempt, + status: 'model_error', + error: modelError, + finishReason, + usage, + assistantText, + parsed, + }), + ); + console.warn( + `[verifier] attempt ${attempt}/${MAX_VERIFY_ATTEMPTS} returned model error: ${modelError}`, + ); + continue; + } + + if (results.length > 0) { + attempts.push( + createAttemptDebug({ + attempt, + status: 'success', + finishReason, + usage, + assistantText, + parsed, + acceptedResultsCount: results.length, + }), + ); + results.sort((a, b) => a.id - b.id); + return { results, attempts }; + } + + attempts.push( + createAttemptDebug({ + attempt, + status: 'no_parseable_results', + finishReason, + usage, + assistantText, + parsed, + acceptedResultsCount: results.length, + }), + ); + console.warn( + `[verifier] attempt ${attempt}/${MAX_VERIFY_ATTEMPTS} produced no parseable results`, + ); } catch (error: unknown) { const msg = error instanceof Error ? error.message : String(error); + attempts.push( + createAttemptDebug({ + attempt, + status: 'threw', + error: msg, + }), + ); console.warn(`[verifier] attempt ${attempt}/${MAX_VERIFY_ATTEMPTS} failed: ${msg}`); - continue; } finally { clearTimeout(timer); } - - const parsed = result.structuredOutput as z.infer<typeof checklistResultSchema> | undefined; - const results: ChecklistResult[] = []; - - if (parsed?.results) { - for (const entry of parsed.results) { - if ( - typeof entry.id === 'number' && - typeof entry.pass === 'boolean' && - validIds.has(entry.id) - ) { - results.push({ - id: entry.id, - pass: entry.pass, - reasoning: entry.reasoning ?? '', - strategy: 'llm', - failureCategory: - entry.failureCategory ?? (!entry.pass ? 'verification_failure' : undefined), - rootCause: entry.rootCause, - }); - } - } - } - - if (results.length > 0) { - results.sort((a, b) => a.id - b.id); - return results; - } - - console.warn( - `[verifier] attempt ${attempt}/${MAX_VERIFY_ATTEMPTS} produced no parseable results`, - ); } console.warn(`[verifier] exhausted ${MAX_VERIFY_ATTEMPTS} attempts, returning empty result`); - return []; + return { results: [], attempts }; } diff --git a/packages/@n8n/instance-ai/evaluations/cli/aggregator.ts b/packages/@n8n/instance-ai/evaluations/cli/aggregator.ts index a390f6bc59d..608a170c450 100644 --- a/packages/@n8n/instance-ai/evaluations/cli/aggregator.ts +++ b/packages/@n8n/instance-ai/evaluations/cli/aggregator.ts @@ -3,6 +3,8 @@ import type { MultiRunEvaluation, TestCaseAggregation, ExecutionScenarioAggregation, + BuildExpectationAggregation, + BuildExpectationResult, } from '../types'; /** @@ -92,7 +94,30 @@ export function aggregateResults( }); } - testCases.push({ testCase, runs, buildSuccessCount, executionScenarios }); + // Aggregate each build expectation as a measured unit alongside scenarios. + // `incomplete` verdicts are excluded from the count (denominator = evaluated runs). + const buildExpectations: BuildExpectationAggregation[] = (testCase.buildExpectations ?? []).map( + (expectation) => { + const expRuns = runs + .map((r) => (r.buildExpectationResults ?? []).find((e) => e.expectation === expectation)) + .filter((e): e is BuildExpectationResult => e !== undefined); + const evaluated = expRuns.filter((e) => !e.incomplete); + const passCount = evaluated.filter((e) => e.pass).length; + const n = evaluated.length; + const { passAtKValues, passHatKValues } = computePassMetrics(n, passCount); + return { + expectation, + runs: expRuns, + evaluatedCount: n, + passCount, + passRate: n > 0 ? passCount / n : 0, + passAtK: passAtKValues, + passHatK: passHatKValues, + }; + }, + ); + + testCases.push({ testCase, runs, buildSuccessCount, executionScenarios, buildExpectations }); } return { totalRuns, testCases }; diff --git a/packages/@n8n/instance-ai/evaluations/cli/args.ts b/packages/@n8n/instance-ai/evaluations/cli/args.ts index 30d2fab009f..a8748968f0a 100644 --- a/packages/@n8n/instance-ai/evaluations/cli/args.ts +++ b/packages/@n8n/instance-ai/evaluations/cli/args.ts @@ -35,6 +35,8 @@ export interface CliArgs { prebuiltWorkflows?: string; /** Keep built workflows after evaluation instead of deleting them */ keepWorkflows: boolean; + /** Delete successfully used workflows from --prebuilt-workflows after evaluation */ + deletePrebuiltWorkflows: boolean; /** Directory to write eval-results.json (defaults to cwd) */ outputDir?: string; /** LangSmith dataset name (synced from JSON test cases before each run) */ @@ -72,6 +74,7 @@ const cliArgsSchema = z.object({ exclude: z.string().optional(), prebuiltWorkflows: z.string().optional(), keepWorkflows: z.boolean().default(false), + deletePrebuiltWorkflows: z.boolean().default(false), outputDir: z.string().optional(), dataset: z.string().default('instance-ai-workflow-evals'), concurrency: z.number().int().positive().default(16), @@ -88,6 +91,12 @@ const cliArgsSchema = z.object({ export function parseCliArgs(argv: string[]): CliArgs { const raw = parseRawArgs(argv); const validated = cliArgsSchema.parse(raw); + if (validated.deletePrebuiltWorkflows && !validated.prebuiltWorkflows) { + throw new Error('--delete-prebuilt-workflows requires --prebuilt-workflows'); + } + if (validated.deletePrebuiltWorkflows && validated.keepWorkflows) { + throw new Error('--delete-prebuilt-workflows cannot be used with --keep-workflows'); + } return { timeoutMs: validated.timeoutMs, @@ -99,6 +108,7 @@ export function parseCliArgs(argv: string[]): CliArgs { exclude: validated.exclude, prebuiltWorkflows: validated.prebuiltWorkflows, keepWorkflows: validated.keepWorkflows, + deletePrebuiltWorkflows: validated.deletePrebuiltWorkflows, outputDir: validated.outputDir, dataset: validated.dataset, concurrency: validated.concurrency, @@ -123,6 +133,7 @@ interface RawArgs { exclude?: string; prebuiltWorkflows?: string; keepWorkflows: boolean; + deletePrebuiltWorkflows: boolean; outputDir?: string; dataset: string; concurrency: number; @@ -138,6 +149,7 @@ function parseRawArgs(argv: string[]): RawArgs { baseUrls: ['http://localhost:5678'], verbose: false, keepWorkflows: false, + deletePrebuiltWorkflows: false, outputDir: undefined, dataset: 'instance-ai-workflow-evals', concurrency: 16, @@ -198,6 +210,10 @@ function parseRawArgs(argv: string[]): RawArgs { result.keepWorkflows = true; break; + case '--delete-prebuilt-workflows': + result.deletePrebuiltWorkflows = true; + break; + case '--output-dir': result.outputDir = nextArg(argv, i, '--output-dir'); i++; diff --git a/packages/@n8n/instance-ai/evaluations/cli/build-mcp-manifest.ts b/packages/@n8n/instance-ai/evaluations/cli/build-mcp-manifest.ts index 308d54ba29c..f3e8d6105e1 100644 --- a/packages/@n8n/instance-ai/evaluations/cli/build-mcp-manifest.ts +++ b/packages/@n8n/instance-ai/evaluations/cli/build-mcp-manifest.ts @@ -7,7 +7,7 @@ import { execSync, spawn } from 'child_process'; import { existsSync, mkdirSync, readFileSync, readdirSync, unlinkSync, writeFileSync } from 'fs'; import { homedir, tmpdir } from 'os'; -import { basename, join } from 'path'; +import { basename, join, resolve } from 'path'; import { z } from 'zod'; import { prebuiltManifestSchema, type PrebuiltManifest } from '../harness/prebuilt-workflows'; @@ -241,21 +241,30 @@ const claudeConfigSchema = z.object({ .optional(), }); -function stageMcpConfig(serverName: string, repoRoot: string | undefined): string { +function uniqueProjectScopes(scopes: Array<string | undefined>): string[] { + const uniqueScopes: string[] = []; + for (const scope of scopes) { + if (!scope || uniqueScopes.includes(scope)) continue; + uniqueScopes.push(scope); + } + return uniqueScopes; +} + +function stageMcpConfig(serverName: string, projectScopes: readonly string[]): string { const claudeConfigPath = join(homedir(), '.claude.json'); if (!existsSync(claudeConfigPath)) { throw new Error(`${claudeConfigPath} not found`); } const parsed = claudeConfigSchema.parse(readJson(claudeConfigPath, 'Claude Code config')); - const projectScopedBlock = repoRoot - ? parsed.projects?.[repoRoot]?.mcpServers?.[serverName] - : undefined; + const projectScopedBlock = projectScopes + .map((scope) => parsed.projects?.[scope]?.mcpServers?.[serverName]) + .find((block) => block !== undefined); const block = projectScopedBlock ?? parsed.mcpServers?.[serverName]; - if (!block) { - const scope = repoRoot - ? `project-scope under "${repoRoot}" or global` - : 'global (no repo root, project-scope skipped)'; + if (block === undefined) { + const scope = projectScopes.length + ? `project-scope under ${projectScopes.map((projectScope) => `"${projectScope}"`).join(', ')} or global` + : 'global (no project scopes)'; throw new Error(`MCP server "${serverName}" not configured in ${claudeConfigPath} (${scope})`); } @@ -582,7 +591,12 @@ async function main(): Promise<void> { throw new Error('No scenarios to build'); } - const mcpConfigPath = stageMcpConfig(args.mcpServerName, repoRoot); + const projectScopes = uniqueProjectScopes([ + args.buildCwd ? resolve(args.buildCwd) : undefined, + repoRoot, + repoRoot ? undefined : process.cwd(), + ]); + const mcpConfigPath = stageMcpConfig(args.mcpServerName, projectScopes); process.on('exit', () => { try { unlinkSync(mcpConfigPath); diff --git a/packages/@n8n/instance-ai/evaluations/cli/index.ts b/packages/@n8n/instance-ai/evaluations/cli/index.ts index 06b6c874423..188b9e15b16 100644 --- a/packages/@n8n/instance-ai/evaluations/cli/index.ts +++ b/packages/@n8n/instance-ai/evaluations/cli/index.ts @@ -7,7 +7,7 @@ // falls back to a direct loop with the same eval-results.json output. // --------------------------------------------------------------------------- -import type { InstanceAiEvalExecutionResult } from '@n8n/api-types'; +import type { InstanceAiRunDebugResponse } from '@n8n/api-types'; import { mkdirSync, writeFileSync } from 'fs'; import { Client } from 'langsmith'; import { evaluate } from 'langsmith/evaluation'; @@ -15,15 +15,20 @@ import type { EvaluationResult } from 'langsmith/evaluation'; import type { Example, Run } from 'langsmith/schemas'; import { traceable } from 'langsmith/traceable'; import { join } from 'path'; -import { z } from 'zod'; import { aggregateResults, passAtK, passHatK } from './aggregator'; import { parseCliArgs } from './args'; import { buildCIMetadata, computeExperimentPrefix } from './ci-metadata'; import { LaneAllocator } from './lane-allocator'; import { expandWithIterations, partitionRoundRobin } from './lanes'; +import { + isPlainObject, + parseTargetOutput, + reshapeLangSmithRuns, + type TargetOutput, +} from './reshape'; import { aggregateWorkflowChecks, statusMap } from '../binaryChecks/aggregate'; -import { CHECK_DIMENSIONS, type CheckOutcome } from '../binaryChecks/types'; +import { allFailVerdicts, verifyBuildExpectations } from '../build-expectations/verifier'; import { N8nClient } from '../clients/n8n-client'; import { compareBuckets, @@ -37,9 +42,11 @@ import { formatComparisonMarkdown, formatComparisonTerminal } from '../compariso import { seedCredentials, cleanupCredentials } from '../credentials/seeder'; import { loadWorkflowTestCasesWithFiles } from '../data/workflows'; import type { WorkflowTestCaseWithFile } from '../data/workflows'; +import { captureThreadRunDebug } from '../harness/capture-run-debug'; import { createLogger } from '../harness/logger'; import type { EvalLogger } from '../harness/logger'; import { + cleanupPrebuiltWorkflows, fetchPrebuiltBuild, loadPrebuiltManifest, pickPrebuiltWorkflowId, @@ -55,11 +62,13 @@ import { type BuildResult, } from '../harness/runner'; import { syncDataset, type DatasetExampleInputs } from '../langsmith/dataset-sync'; +import { seedMcpRegistry } from '../mcp-registry/seeder'; import { snapshotWorkflowIds } from '../outcome/workflow-discovery'; +import { writeRunDebugReport } from '../report/run-debug-report'; import { writeWorkflowReport } from '../report/workflow-report'; import type { + BuildExpectationResult, MultiRunEvaluation, - ExecutionScenarioResult, ExecutionScenario, TranscriptTurn, WorkflowTestCase, @@ -69,78 +78,6 @@ import type { // n8n degrades above ~4 concurrent builds. const MAX_CONCURRENT_BUILDS = 4; -const checkOutcomeSchema = z.object({ - name: z.string(), - description: z.string(), - kind: z.enum(['deterministic', 'llm']), - dimension: z.enum(CHECK_DIMENSIONS), - status: z.enum(['pass', 'fail', 'n_a']), - comment: z.string().optional(), -}); - -const targetOutputSchema = z.object({ - buildSuccess: z.boolean().default(false), - passed: z.boolean().default(false), - score: z.number().default(0), - reasoning: z.string().default(''), - workflowId: z.string().optional(), - failureCategory: z.string().optional(), - rootCause: z.string().optional(), - execErrors: z.array(z.string()).default([]), - evalResult: z.unknown().optional(), - /** Only set on the scenario that initiated the build. */ - buildDurationMs: z.number().optional(), - execDurationMs: z.number().default(0), - nodeCount: z.number().default(0), - /** The thread id used during the build — keys the LangSmith trace lookup. */ - threadId: z.string().optional(), - workflowChecks: z.array(checkOutcomeSchema).optional(), -}); - -type TargetOutput = Omit<z.infer<typeof targetOutputSchema>, 'evalResult'> & { - evalResult?: InstanceAiEvalExecutionResult; -}; - -function isPlainObject(v: unknown): v is Record<string, unknown> { - return typeof v === 'object' && v !== null && !Array.isArray(v); -} - -function isEvalResult(v: unknown): v is InstanceAiEvalExecutionResult { - if (!isPlainObject(v)) return false; - return ( - typeof v.nodeResults === 'object' && - v.nodeResults !== null && - Array.isArray(v.errors) && - typeof v.hints === 'object' && - v.hints !== null - ); -} - -/** Safe-parse a run's outputs. Returns `undefined` if the row is malformed - * or missing, so callers can skip it instead of treating it as a genuine - * failed evaluation. Every field in the schema has a default, so an empty - * or nullish raw value would otherwise parse successfully into a "failed" - * shape (passed:false, score:0) — masking infra errors as builder regressions. - */ -function parseTargetOutput(raw: unknown): TargetOutput | undefined { - if (!isPlainObject(raw) || Object.keys(raw).length === 0) return undefined; - const parsed = targetOutputSchema.safeParse(raw); - if (!parsed.success) return undefined; - return { - ...parsed.data, - evalResult: isEvalResult(parsed.data.evalResult) ? parsed.data.evalResult : undefined, - }; -} - -const runInputsSchema = z - .object({ - testCaseFile: z.string().default(''), - scenarioName: z.string().default(''), - /** 0-based iteration index; injected during multi-run expansion. */ - _iteration: z.number().int().nonnegative().default(0), - }) - .passthrough(); - /** Target input shape with the iteration index we inject for multi-run. */ type TargetInputs = DatasetExampleInputs & { _iteration?: number }; @@ -158,6 +95,7 @@ interface RunConfig { lanes: Lane[]; logger: EvalLogger; prebuiltManifest?: PrebuiltManifest; + prebuiltWorkflowIdsToDelete?: Set<string>; } async function main(): Promise<void> { @@ -212,6 +150,14 @@ async function main(): Promise<void> { const seedResult = await seedCredentials(client, undefined, logger); logger.info(`Seeded ${String(seedResult.credentialIds.length)} credential(s)${tag}`); + logger.info(`Seeding MCP registry...${tag}`); + const mcpSeedResult = await seedMcpRegistry(client, logger); + if (mcpSeedResult.seeded) { + logger.info(`Seeded ${String(mcpSeedResult.count)} MCP registry server(s)${tag}`); + } else { + logger.info(`Skipped MCP registry seed (test endpoint unavailable)${tag}`); + } + const preRunWorkflowIds = await snapshotWorkflowIds(client); const claimedWorkflowIds = new Set<string>(); return { client, baseUrl, preRunWorkflowIds, claimedWorkflowIds, seedResult }; @@ -219,6 +165,7 @@ async function main(): Promise<void> { ); const startTime = Date.now(); + const prebuiltWorkflowIdsToDelete = args.deletePrebuiltWorkflows ? new Set<string>() : undefined; try { const hasLangSmith = Boolean(process.env.LANGSMITH_API_KEY); @@ -230,14 +177,28 @@ async function main(): Promise<void> { if (hasLangSmith) { logger.info('LangSmith API key detected, using evaluate() with experiment tracking'); - const langsmithRun = await runWithLangSmith({ args, lanes, logger, prebuiltManifest }); + const langsmithRun = await runWithLangSmith({ + args, + lanes, + logger, + prebuiltManifest, + prebuiltWorkflowIdsToDelete, + }); evaluation = langsmithRun.evaluation; experimentName = langsmithRun.experimentName; outcome = langsmithRun.outcome; slugByTestCase = langsmithRun.slugByTestCase; } else { logger.info('No LANGSMITH_API_KEY, running direct loop (results in eval-results.json only)'); - evaluation = await runDirectLoop({ args, lanes, logger, prebuiltManifest }); + const directRun = await runDirectLoop({ + args, + lanes, + logger, + prebuiltManifest, + prebuiltWorkflowIdsToDelete, + }); + evaluation = directRun.evaluation; + slugByTestCase = directRun.slugByTestCase; } const totalDuration = Date.now() - startTime; @@ -250,16 +211,22 @@ async function main(): Promise<void> { outcome, commitSha, slugByTestCase, + ciRunUrl(), ); console.log(`Results: ${jsonPath}`); console.log(`PR comment: ${prCommentPath}`); const reportResults = flattenRunsForReport(evaluation); const htmlPath = writeWorkflowReport(reportResults); console.log(`Report: ${htmlPath}`); + const debugHtmlPath = writeRunDebugReport(reportResults); + console.log(`LLM debug: ${debugHtmlPath}`); console.log( '\n' + formatComparisonTerminal(evaluation, outcome, { commitSha, slugByTestCase }), ); } finally { + if (prebuiltWorkflowIdsToDelete && lanes[0]) { + await cleanupPrebuiltWorkflows(lanes[0].client, prebuiltWorkflowIdsToDelete, logger); + } await Promise.all( lanes.map(async (lane) => { await cleanupCredentials(lane.client, lane.seedResult.credentialIds).catch(() => {}); @@ -278,26 +245,45 @@ async function runWithLangSmith(config: RunConfig): Promise<{ outcome: ComparisonOutcome; slugByTestCase: Map<WorkflowTestCase, string>; }> { - const { args, lanes, logger, prebuiltManifest } = config; + const { args, lanes, logger, prebuiltManifest, prebuiltWorkflowIdsToDelete } = config; + + const testCasesWithFiles = loadWorkflowTestCasesWithFiles(args.filter, args.exclude, args.tier); + if (testCasesWithFiles.length === 0) { + logger.info('No workflow test cases found in evaluations/data/workflows/'); + return { + evaluation: { totalRuns: 0, testCases: [] }, + experimentName: '', + outcome: { kind: 'no_baseline' }, + slugByTestCase: new Map(), + }; + } const lsClient = new Client(); const datasetName = await syncDataset(lsClient, args.dataset, logger, args.filter, args.exclude); - const testCasesWithFiles = loadWorkflowTestCasesWithFiles(args.filter, args.exclude, args.tier); // Stash transcripts by threadId so reshapeLangSmithRuns can merge them in — // the LangSmith target() output schema doesn't carry the full transcript. const transcriptByThreadId = new Map<string, TranscriptTurn[]>(); + // Build-expectation verdicts, judged once per build and merged the same way — + // fired during getOrBuild, awaited before reshapeLangSmithRuns. + const buildExpectationsByThreadId = new Map<string, Promise<BuildExpectationResult[]>>(); + const runDebugByThreadId = new Map<string, Promise<InstanceAiRunDebugResponse[]>>(); - // LangSmith dataset rows carry only per-scenario fields. The conversation - // for the build is sourced locally, keyed by fileSlug. + // LangSmith dataset rows carry only per-scenario fields. The conversation and + // build expectations for the build are sourced locally, keyed by fileSlug. const conversationByFileSlug = new Map< string, - { conversation: WorkflowTestCase['conversation']; messageBudget?: number } + { + conversation: WorkflowTestCase['conversation']; + messageBudget?: number; + buildExpectations?: string[]; + } >(); for (const { testCase, fileSlug } of testCasesWithFiles) { conversationByFileSlug.set(fileSlug, { conversation: testCase.conversation, messageBudget: testCase.messageBudget, + buildExpectations: testCase.buildExpectations, }); } @@ -317,6 +303,7 @@ async function runWithLangSmith(config: RunConfig): Promise<{ workflowId: string; scenario: ExecutionScenario; workflowJsons: BuildResult['workflowJsons']; + buildTrace?: BuildResult['buildTrace']; }) => Promise<Awaited<ReturnType<typeof executeScenario>>>; } @@ -354,6 +341,7 @@ async function runWithLangSmith(config: RunConfig): Promise<{ workflowId: string; scenario: ExecutionScenario; workflowJsons: BuildResult['workflowJsons']; + buildTrace?: BuildResult['buildTrace']; }) => await executeScenario( lane.client, @@ -362,6 +350,8 @@ async function runWithLangSmith(config: RunConfig): Promise<{ execArgs.workflowJsons, logger, args.timeoutMs, + undefined, + execArgs.buildTrace, args.pinAiRoots, ), { @@ -402,9 +392,14 @@ async function runWithLangSmith(config: RunConfig): Promise<{ const lane = laneStates[0]; const start = Date.now(); const build = await fetchPrebuiltBuild(lane.runner.client, prebuiltId, logger); + if (build.success && build.workflowId) { + prebuiltWorkflowIdsToDelete?.add(build.workflowId); + } const buildDurationMs = Date.now() - start; buildDurations.set(key, buildDurationMs); stashTranscript(build); + stashBuildExpectations(fileSlug, build); + stashRunDebug(lane.runner.client, build); if (build.success && !build.workflowChecks) { // No transcript in prebuilt mode — checks run with empty prompt context. build.workflowChecks = await runWorkflowChecks({ @@ -430,6 +425,8 @@ async function runWithLangSmith(config: RunConfig): Promise<{ const buildDurationMs = Date.now() - start; buildDurations.set(key, buildDurationMs); stashTranscript(build); + stashBuildExpectations(fileSlug, build); + stashRunDebug(lane.runner.client, build); return { build, lane, buildDurationMs }; } finally { allocator.release(lane, fileSlug); @@ -445,6 +442,35 @@ async function runWithLangSmith(config: RunConfig): Promise<{ } } + function stashRunDebug(client: N8nClient, build: BuildResult): void { + if (!build.threadId) return; + runDebugByThreadId.set(build.threadId, captureThreadRunDebug(client, build.threadId, logger)); + } + + // Judge build expectations once per build (off the scenario critical path); + // reshapeLangSmithRuns awaits and merges the verdicts by threadId. + function stashBuildExpectations(fileSlug: string, build: BuildResult): void { + const expectations = conversationByFileSlug.get(fileSlug)?.buildExpectations; + // Judge whenever there's a transcript — even on build failure, matching the + // direct-loop runner; the judge prompt handles the "no workflow produced" case. + if (!build.threadId || !expectations?.length || !build.transcript?.length) { + return; + } + buildExpectationsByThreadId.set( + build.threadId, + verifyBuildExpectations(expectations, { + transcript: build.transcript, + workflowJson: build.workflowJsons[0], + metrics: build.conversationMetrics, + }).catch((error: unknown) => + allFailVerdicts( + expectations, + `judge error: ${error instanceof Error ? error.message : String(error)}`, + ), + ), + ); + } + const target = async (inputs: TargetInputs): Promise<TargetOutput> => { const iteration = inputs._iteration ?? 0; const scenario: ExecutionScenario = { @@ -473,6 +499,7 @@ async function runWithLangSmith(config: RunConfig): Promise<{ nodeCount: 0, threadId: build.threadId, workflowChecks: build.workflowChecks, + buildTrace: build.buildTrace, }; } @@ -486,6 +513,7 @@ async function runWithLangSmith(config: RunConfig): Promise<{ workflowId: build.workflowId, scenario, workflowJsons: build.workflowJsons, + buildTrace: build.buildTrace, }); break; } catch (error: unknown) { @@ -524,7 +552,10 @@ async function runWithLangSmith(config: RunConfig): Promise<{ buildDurationMs, execDurationMs: Date.now() - execStart, nodeCount, + threadId: build.threadId, workflowChecks: build.workflowChecks, + workflowJson: build.workflowJsons[0], + buildTrace: build.buildTrace, }; } } @@ -550,6 +581,8 @@ async function runWithLangSmith(config: RunConfig): Promise<{ nodeCount, threadId: build.threadId, workflowChecks: build.workflowChecks, + workflowJson: build.workflowJsons[0], + buildTrace: build.buildTrace, }; }; @@ -642,12 +675,22 @@ async function runWithLangSmith(config: RunConfig): Promise<{ logger.info(`Experiment: ${experimentResults.experimentName}`); await lsClient.awaitPendingTraceBatches(); + const buildExpectationsResolved = new Map<string, BuildExpectationResult[]>(); + for (const [threadId, verdictsPromise] of buildExpectationsByThreadId) { + buildExpectationsResolved.set(threadId, await verdictsPromise); + } + const runDebugResolved = new Map<string, InstanceAiRunDebugResponse[]>(); + for (const [threadId, runDebugPromise] of runDebugByThreadId) { + runDebugResolved.set(threadId, await runDebugPromise); + } const allRunResults = reshapeLangSmithRuns( experimentResults.results, testCasesWithFiles, args.iterations, transcriptByThreadId, + buildExpectationsResolved, lanes[0]?.baseUrl, + runDebugResolved, ); const evaluation = aggregateResults(allRunResults, args.iterations); @@ -839,97 +882,23 @@ async function writePerRunPassMetrics(config: { ); } -/** - * Convert LangSmith's flat `Run[]` into the `WorkflowTestCaseResult[][]` shape - * the aggregator expects (outer: runs, inner: test cases). Groups by - * (testCaseFile, scenarioName), then reconstructs per-iteration test case - * results. Scenarios with no matching run get a build_failure stub. - */ -function reshapeLangSmithRuns( - rows: Array<{ run: Run }>, - testCasesWithFiles: WorkflowTestCaseWithFile[], - numIterations: number, - transcriptByThreadId: Map<string, TranscriptTurn[]>, - n8nBaseUrl: string | undefined, -): WorkflowTestCaseResult[][] { - // Index runs by (iteration, testCaseFile, scenarioName) using the `_iteration` - // we injected in expandExamplesForIterations. Falls back to 0 for single-run. - const byKey = new Map<string, Run>(); - for (const { run } of rows) { - const inputs = runInputsSchema.safeParse(run.inputs ?? {}); - if (!inputs.success) continue; - const key = `${String(inputs.data._iteration)}/${inputs.data.testCaseFile}/${inputs.data.scenarioName}`; - byKey.set(key, run); - } - - const allRunResults: WorkflowTestCaseResult[][] = []; - for (let iter = 0; iter < numIterations; iter++) { - const runResults: WorkflowTestCaseResult[] = []; - for (const { testCase, fileSlug } of testCasesWithFiles) { - const executionScenarioResults: ExecutionScenarioResult[] = []; - let workflowBuildSuccess = false; - let workflowId: string | undefined; - let buildError: string | undefined; - let threadId: string | undefined; - let workflowChecks: CheckOutcome[] | undefined; - - for (const scenario of testCase.executionScenarios) { - const run = byKey.get(`${String(iter)}/${fileSlug}/${scenario.name}`); - const output = run ? parseTargetOutput(run.outputs) : undefined; - if (!run || !output) { - executionScenarioResults.push({ - scenario, - success: false, - score: 0, - reasoning: run ? 'Malformed run output — skipped' : 'No run result for this scenario', - }); - continue; - } - if (output.buildSuccess) workflowBuildSuccess = true; - if (output.workflowId) workflowId = output.workflowId; - if (output.threadId) threadId = output.threadId; - if (!output.buildSuccess && output.reasoning) buildError = output.reasoning; - if (output.workflowChecks && !workflowChecks) workflowChecks = output.workflowChecks; - executionScenarioResults.push({ - scenario, - success: output.passed, - evalResult: output.evalResult, - score: output.score, - reasoning: output.reasoning, - failureCategory: output.failureCategory, - rootCause: output.rootCause, - }); - } - - const transcript = threadId ? transcriptByThreadId.get(threadId) : undefined; - runResults.push({ - testCase, - workflowBuildSuccess, - workflowId, - executionScenarioResults, - buildError, - threadId, - transcript, - workflowChecks, - n8nBaseUrl, - }); - } - allRunResults.push(runResults); - } - return allRunResults; -} - // --------------------------------------------------------------------------- // Direct mode: simple loop, no LangSmith dependency // --------------------------------------------------------------------------- -async function runDirectLoop(config: RunConfig): Promise<MultiRunEvaluation> { - const { args, lanes, logger, prebuiltManifest } = config; +async function runDirectLoop(config: RunConfig): Promise<{ + evaluation: MultiRunEvaluation; + slugByTestCase: Map<WorkflowTestCase, string>; +}> { + const { args, lanes, logger, prebuiltManifest, prebuiltWorkflowIdsToDelete } = config; const testCasesWithFiles = loadWorkflowTestCasesWithFiles(args.filter, args.exclude, args.tier); + const slugByTestCase = new Map<WorkflowTestCase, string>( + testCasesWithFiles.map(({ testCase, fileSlug }) => [testCase, fileSlug]), + ); if (testCasesWithFiles.length === 0) { console.log('No workflow test cases found in evaluations/data/workflows/'); - return { totalRuns: 0, testCases: [] }; + return { evaluation: { totalRuns: 0, testCases: [] }, slugByTestCase }; } const totalScenarios = testCasesWithFiles.reduce( @@ -959,8 +928,13 @@ async function runDirectLoop(config: RunConfig): Promise<MultiRunEvaluation> { lanes.length > 1 ? ` [lane ${String(laneIdx + 1)}/${String(lanes.length)}]` : ''; const results = await runWithConcurrency( bucket, - async ({ tc }) => - await runWorkflowTestCase({ + async ({ tc }) => { + const prebuiltWorkflowId = pickPrebuiltWorkflowId( + prebuiltManifest, + tc.fileSlug, + iter, + ); + const result = await runWorkflowTestCase({ client: lane.client, baseUrl: lane.baseUrl, testCase: tc.testCase, @@ -971,9 +945,18 @@ async function runDirectLoop(config: RunConfig): Promise<MultiRunEvaluation> { logger, keepWorkflows: args.keepWorkflows, laneTag, - prebuiltWorkflowId: pickPrebuiltWorkflowId(prebuiltManifest, tc.fileSlug, iter), + prebuiltWorkflowId, pinAiRoots: args.pinAiRoots, - }), + }); + if ( + prebuiltWorkflowId !== undefined && + result.workflowBuildSuccess && + result.workflowId + ) { + prebuiltWorkflowIdsToDelete?.add(result.workflowId); + } + return result; + }, MAX_CONCURRENT_BUILDS, ); return bucket.map((b, i) => ({ origIdx: b.origIdx, result: results[i] })); @@ -985,7 +968,7 @@ async function runDirectLoop(config: RunConfig): Promise<MultiRunEvaluation> { }), ); - return aggregateResults(allRunResults, args.iterations); + return { evaluation: aggregateResults(allRunResults, args.iterations), slugByTestCase }; } // --------------------------------------------------------------------------- @@ -1029,49 +1012,80 @@ interface AggregateMetrics { built: number; /** Total scenarios across all test cases. */ scenariosTotal: number; - /** Mean pass@k across scenarios at k = totalRuns (0..1). */ + /** Mean pass@k across units (scenarios + evaluated expectations), each at its terminal k (0..1). */ passAtK: number; - /** Mean pass^k across scenarios at k = totalRuns (0..1). */ + /** Mean pass^k across units (scenarios + evaluated expectations), each at its terminal k (0..1). */ passHatK: number; - /** Index into each scenario's passAtK/passHatK array for k = totalRuns. */ - kIndex: number; /** Pass rate of each iteration formatted as e.g. "37% / 37% / 37%". */ passRatePerIter: string; } +/** Terminal pass@k/pass^k for a unit = its last evaluated k (totalRuns for scenarios, evaluatedCount for expectations). */ +function terminalRate(arr: number[]): number { + return arr[arr.length - 1] ?? 0; +} + function computeAggregateMetrics(evaluation: MultiRunEvaluation): AggregateMetrics { - const { totalRuns, testCases } = evaluation; - const allScenarios = testCases.flatMap((tc) => tc.executionScenarios); - const total = allScenarios.length; - const kIndex = Math.max(totalRuns - 1, 0); + const { testCases } = evaluation; + // Units = scenarios + evaluated build-expectations — mirrors the per-card badge + // and the terminal per-case table so the headline rate can't disagree with them. + const units = testCases.flatMap((tc) => [ + ...tc.executionScenarios, + ...tc.buildExpectations.filter((ea) => ea.evaluatedCount > 0), + ]); + const total = units.length; + const scenariosTotal = testCases.reduce((n, tc) => n + tc.executionScenarios.length, 0); const built = testCases.filter((tc) => tc.buildSuccessCount > 0).length; const passAtK = - total > 0 ? allScenarios.reduce((sum, s) => sum + (s.passAtK[kIndex] ?? 0), 0) / total : 0; + total > 0 ? units.reduce((sum, u) => sum + terminalRate(u.passAtK), 0) / total : 0; const passHatK = - total > 0 ? allScenarios.reduce((sum, s) => sum + (s.passHatK[kIndex] ?? 0), 0) / total : 0; + total > 0 ? units.reduce((sum, u) => sum + terminalRate(u.passHatK), 0) / total : 0; return { built, - scenariosTotal: total, + scenariosTotal, passAtK, passHatK, - kIndex, passRatePerIter: computePassRatePerIter(evaluation), }; } -/** Pass rate of each iteration formatted as e.g. "37% / 37% / 37%". */ +/** Pass rate of each iteration (over units = scenarios + evaluated expectations). */ function computePassRatePerIter(evaluation: MultiRunEvaluation): string { const { totalRuns, testCases } = evaluation; - const allScenarios = testCases.flatMap((tc) => tc.executionScenarios); - if (allScenarios.length === 0) return ''; + const hasUnits = testCases.some( + (tc) => + tc.executionScenarios.length > 0 || tc.buildExpectations.some((ea) => ea.evaluatedCount > 0), + ); + if (!hasUnits) return ''; const rates: string[] = []; for (let i = 0; i < totalRuns; i++) { - const passed = allScenarios.filter((s) => s.runs[i]?.success).length; - rates.push(`${String(Math.round((passed / allScenarios.length) * 100))}%`); + let passed = 0; + let total = 0; + for (const tc of testCases) { + for (const sa of tc.executionScenarios) { + total++; + if (sa.runs[i]?.success) passed++; + } + // Count each scored verdict in this iteration directly — skips incomplete + // (build-failed) verdicts and is robust to duplicate expectation strings. + for (const verdict of tc.runs[i]?.buildExpectationResults ?? []) { + if (verdict.incomplete) continue; + total++; + if (verdict.pass) passed++; + } + } + rates.push(`${String(total > 0 ? Math.round((passed / total) * 100) : 0)}%`); } return rates.join(' / '); } +// GitHub Actions run URL (for the PR comment's re-run link); undefined outside CI. +function ciRunUrl(): string | undefined { + const { GITHUB_SERVER_URL, GITHUB_REPOSITORY, GITHUB_RUN_ID } = process.env; + if (!GITHUB_SERVER_URL || !GITHUB_REPOSITORY || !GITHUB_RUN_ID) return undefined; + return `${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}`; +} + function writeEvalResults( evaluation: MultiRunEvaluation, duration: number, @@ -1080,6 +1094,7 @@ function writeEvalResults( outcome: ComparisonOutcome | undefined, commitSha: string | undefined, slugByTestCase: Map<WorkflowTestCase, string> | undefined, + runUrl: string | undefined, ): { jsonPath: string; prCommentPath: string } { const { totalRuns, testCases } = evaluation; const metrics = computeAggregateMetrics(evaluation); @@ -1117,18 +1132,29 @@ function writeEvalResults( comparisonError: outcome?.kind === 'fetch_failed' ? outcome.error : undefined, testCases: testCases.map((tc) => ({ name: tc.testCase.conversation[0].text.slice(0, 70), + testCaseFile: slugByTestCase?.get(tc.testCase), buildSuccessCount: tc.buildSuccessCount, totalRuns, workflowChecksPerRun: tc.runs.map((run) => run.workflowChecks ? statusMap(run.workflowChecks) : null, ), + buildExpectationResultsPerRun: tc.runs.map((run) => run.buildExpectationResults ?? null), + buildExpectations: tc.buildExpectations.map((ea) => ({ + expectation: ea.expectation, + passCount: ea.passCount, + evaluatedCount: ea.evaluatedCount, + passAtK: terminalRate(ea.passAtK), + passHatK: terminalRate(ea.passHatK), + })), + threadIds: tc.runs.map((run) => run.threadId ?? null), scenarios: tc.executionScenarios.map((sa) => ({ name: sa.scenario.name, passCount: sa.passCount, totalRuns, - passAtK: sa.passAtK[metrics.kIndex] ?? 0, - passHatK: sa.passHatK[metrics.kIndex] ?? 0, - runs: sa.runs.map((sr) => ({ + passAtK: terminalRate(sa.passAtK), + passHatK: terminalRate(sa.passHatK), + runs: sa.runs.map((sr, runIndex) => ({ + workflowId: tc.runs[runIndex]?.workflowId ?? null, passed: sr.success, score: sr.score, reasoning: sr.reasoning, @@ -1152,7 +1178,7 @@ function writeEvalResults( const prCommentPath = join(targetDir, 'eval-pr-comment.md'); writeFileSync( prCommentPath, - formatComparisonMarkdown(evaluation, outcome, { commitSha, slugByTestCase }), + formatComparisonMarkdown(evaluation, outcome, { commitSha, slugByTestCase, runUrl }), ); return { jsonPath, prCommentPath }; diff --git a/packages/@n8n/instance-ai/evaluations/cli/pairwise.ts b/packages/@n8n/instance-ai/evaluations/cli/pairwise.ts index 2d925de78ef..4dd19f1c528 100644 --- a/packages/@n8n/instance-ai/evaluations/cli/pairwise.ts +++ b/packages/@n8n/instance-ai/evaluations/cli/pairwise.ts @@ -377,9 +377,7 @@ function buildInteractivity( ): BuildInteractivity { return { askUserCount: toolCalls.filter((toolCall) => toolCall.toolName === 'ask-user').length, - planToolCount: toolCalls.filter( - (toolCall) => toolCall.toolName === 'plan' || toolCall.toolName === 'create-tasks', - ).length, + planToolCount: toolCalls.filter((toolCall) => toolCall.toolName === 'create-tasks').length, autoApprovedSuspensions: events.filter((event) => event.type === 'confirmation-request').length, mockedCredentialTypes: [], }; diff --git a/packages/@n8n/instance-ai/evaluations/cli/report.ts b/packages/@n8n/instance-ai/evaluations/cli/report.ts index a3c657cd78a..b467c74a0d5 100644 --- a/packages/@n8n/instance-ai/evaluations/cli/report.ts +++ b/packages/@n8n/instance-ai/evaluations/cli/report.ts @@ -362,7 +362,7 @@ function renderExample(record: ResultRecord, idPrefix: string): string { const interact = record.build.interactivity; const interactBits: string[] = []; if (interact.askUserCount > 0) interactBits.push(`ask-user ×${interact.askUserCount}`); - if (interact.planToolCount > 0) interactBits.push(`plan ×${interact.planToolCount}`); + if (interact.planToolCount > 0) interactBits.push(`create-tasks ×${interact.planToolCount}`); if (interact.autoApprovedSuspensions > 0) interactBits.push(`suspend ×${interact.autoApprovedSuspensions}`); if (interact.mockedCredentialTypes.length > 0) @@ -476,7 +476,7 @@ function renderRun(run: Run, index: number): string { ? `<div class="run-interactivity"> <strong>Interactivity:</strong> ask-user ×${s.interactivity.askUserCount} · - plan ×${s.interactivity.planToolCount} · + create-tasks ×${s.interactivity.planToolCount} · suspend ×${s.interactivity.autoApprovedSuspensions} · mocked creds: ${s.interactivity.mockedCredentialTypes.map(escapeHtml).join(', ') || 'none'} </div>` diff --git a/packages/@n8n/instance-ai/evaluations/cli/reshape.ts b/packages/@n8n/instance-ai/evaluations/cli/reshape.ts new file mode 100644 index 00000000000..3b917064c4c --- /dev/null +++ b/packages/@n8n/instance-ai/evaluations/cli/reshape.ts @@ -0,0 +1,221 @@ +// --------------------------------------------------------------------------- +// LangSmith run reshaping +// +// Pure transform from LangSmith's flat `Run[]` into the +// `WorkflowTestCaseResult[][]` shape the aggregator + HTML report expect. +// Extracted from cli/index.ts so the verdict-reattachment logic is +// unit-testable on its own (index.ts runs main() at import time). +// --------------------------------------------------------------------------- + +import type { InstanceAiEvalExecutionResult, InstanceAiRunDebugResponse } from '@n8n/api-types'; +import type { Run } from 'langsmith/schemas'; +import { z } from 'zod'; + +import { CHECK_DIMENSIONS, type CheckOutcome } from '../binaryChecks/types'; +import type { WorkflowResponse } from '../clients/n8n-client'; +import type { WorkflowTestCaseWithFile } from '../data/workflows'; +import type { + BuildTrace, + BuildExpectationResult, + ExecutionScenarioResult, + TranscriptTurn, + WorkflowTestCaseResult, +} from '../types'; + +const checkOutcomeSchema = z.object({ + name: z.string(), + description: z.string(), + kind: z.enum(['deterministic', 'llm']), + dimension: z.enum(CHECK_DIMENSIONS), + status: z.enum(['pass', 'fail', 'n_a']), + comment: z.string().optional(), +}); + +const targetOutputSchema = z.object({ + buildSuccess: z.boolean().default(false), + passed: z.boolean().default(false), + score: z.number().default(0), + reasoning: z.string().default(''), + workflowId: z.string().optional(), + failureCategory: z.string().optional(), + rootCause: z.string().optional(), + execErrors: z.array(z.string()).default([]), + evalResult: z.unknown().optional(), + /** Only set on the scenario that initiated the build. */ + buildDurationMs: z.number().optional(), + execDurationMs: z.number().default(0), + nodeCount: z.number().default(0), + /** The thread id used during the build — keys the LangSmith trace lookup. */ + threadId: z.string().optional(), + workflowChecks: z.array(checkOutcomeSchema).optional(), + workflowJson: z.unknown().optional(), + buildTrace: z.unknown().optional(), +}); + +export type TargetOutput = Omit< + z.infer<typeof targetOutputSchema>, + 'evalResult' | 'workflowJson' | 'buildTrace' +> & { + evalResult?: InstanceAiEvalExecutionResult; + workflowJson?: WorkflowResponse; + buildTrace?: BuildTrace; +}; + +export function isPlainObject(v: unknown): v is Record<string, unknown> { + return typeof v === 'object' && v !== null && !Array.isArray(v); +} + +function isEvalResult(v: unknown): v is InstanceAiEvalExecutionResult { + if (!isPlainObject(v)) return false; + return ( + typeof v.nodeResults === 'object' && + v.nodeResults !== null && + Array.isArray(v.errors) && + typeof v.hints === 'object' && + v.hints !== null + ); +} + +function isWorkflowResponse(v: unknown): v is WorkflowResponse { + if (!isPlainObject(v)) return false; + return ( + typeof v.id === 'string' && + typeof v.name === 'string' && + typeof v.active === 'boolean' && + typeof v.versionId === 'string' && + Array.isArray(v.nodes) && + isPlainObject(v.connections) + ); +} + +function isBuildTrace(v: unknown): v is BuildTrace { + if (!isPlainObject(v)) return false; + return ( + typeof v.finalText === 'string' && + Array.isArray(v.toolCalls) && + Array.isArray(v.agentActivities) + ); +} + +/** Safe-parse a run's outputs. Returns `undefined` if the row is malformed + * or missing, so callers can skip it instead of treating it as a genuine + * failed evaluation. Every field in the schema has a default, so an empty + * or nullish raw value would otherwise parse successfully into a "failed" + * shape (passed:false, score:0) — masking infra errors as builder regressions. + */ +export function parseTargetOutput(raw: unknown): TargetOutput | undefined { + if (!isPlainObject(raw) || Object.keys(raw).length === 0) return undefined; + const parsed = targetOutputSchema.safeParse(raw); + if (!parsed.success) return undefined; + return { + ...parsed.data, + evalResult: isEvalResult(parsed.data.evalResult) ? parsed.data.evalResult : undefined, + workflowJson: isWorkflowResponse(parsed.data.workflowJson) + ? parsed.data.workflowJson + : undefined, + buildTrace: isBuildTrace(parsed.data.buildTrace) ? parsed.data.buildTrace : undefined, + }; +} + +const runInputsSchema = z + .object({ + testCaseFile: z.string().default(''), + scenarioName: z.string().default(''), + /** 0-based iteration index; injected during multi-run expansion. */ + _iteration: z.number().int().nonnegative().default(0), + }) + .passthrough(); + +/** + * Convert LangSmith's flat `Run[]` into the `WorkflowTestCaseResult[][]` shape + * the aggregator expects (outer: runs, inner: test cases). Groups by + * (testCaseFile, scenarioName), then reconstructs per-iteration test case + * results. Scenarios with no matching run get a build_failure stub. + */ +export function reshapeLangSmithRuns( + rows: Array<{ run: Run }>, + testCasesWithFiles: WorkflowTestCaseWithFile[], + numIterations: number, + transcriptByThreadId: Map<string, TranscriptTurn[]>, + buildExpectationsByThreadId: Map<string, BuildExpectationResult[]>, + n8nBaseUrl: string | undefined, + runDebugByThreadId: Map<string, InstanceAiRunDebugResponse[]> = new Map(), +): WorkflowTestCaseResult[][] { + // Index runs by (iteration, testCaseFile, scenarioName) using the `_iteration` + // we injected in expandExamplesForIterations. Falls back to 0 for single-run. + const byKey = new Map<string, Run>(); + for (const { run } of rows) { + const inputs = runInputsSchema.safeParse(run.inputs ?? {}); + if (!inputs.success) continue; + const key = `${String(inputs.data._iteration)}/${inputs.data.testCaseFile}/${inputs.data.scenarioName}`; + byKey.set(key, run); + } + + const allRunResults: WorkflowTestCaseResult[][] = []; + for (let iter = 0; iter < numIterations; iter++) { + const runResults: WorkflowTestCaseResult[] = []; + for (const { testCase, fileSlug } of testCasesWithFiles) { + const executionScenarioResults: ExecutionScenarioResult[] = []; + let workflowBuildSuccess = false; + let workflowId: string | undefined; + let buildError: string | undefined; + let threadId: string | undefined; + let workflowChecks: CheckOutcome[] | undefined; + let workflowJson: WorkflowResponse | undefined; + let buildTrace: BuildTrace | undefined; + + for (const scenario of testCase.executionScenarios) { + const run = byKey.get(`${String(iter)}/${fileSlug}/${scenario.name}`); + const output = run ? parseTargetOutput(run.outputs) : undefined; + if (!run || !output) { + executionScenarioResults.push({ + scenario, + success: false, + score: 0, + reasoning: run ? 'Malformed run output — skipped' : 'No run result for this scenario', + }); + continue; + } + if (output.buildSuccess) workflowBuildSuccess = true; + if (output.workflowId) workflowId = output.workflowId; + if (output.threadId) threadId = output.threadId; + if (!output.buildSuccess && output.reasoning) buildError = output.reasoning; + if (output.workflowChecks && !workflowChecks) workflowChecks = output.workflowChecks; + if (output.workflowJson && !workflowJson) workflowJson = output.workflowJson; + if (output.buildTrace && !buildTrace) buildTrace = output.buildTrace; + executionScenarioResults.push({ + scenario, + success: output.passed, + evalResult: output.evalResult, + score: output.score, + reasoning: output.reasoning, + failureCategory: output.failureCategory, + rootCause: output.rootCause, + }); + } + + const transcript = threadId ? transcriptByThreadId.get(threadId) : undefined; + const buildExpectationResults = threadId + ? buildExpectationsByThreadId.get(threadId) + : undefined; + runResults.push({ + testCase, + fileSlug, + workflowBuildSuccess, + workflowId, + executionScenarioResults, + buildError, + threadId, + transcript, + buildExpectationResults, + workflowChecks, + workflowJson, + buildTrace, + n8nBaseUrl, + runDebug: threadId ? runDebugByThreadId.get(threadId) : undefined, + }); + } + allRunResults.push(runResults); + } + return allRunResults; +} diff --git a/packages/@n8n/instance-ai/evaluations/clients/n8n-client.ts b/packages/@n8n/instance-ai/evaluations/clients/n8n-client.ts index eeff07627f7..0ab1ddd2668 100644 --- a/packages/@n8n/instance-ai/evaluations/clients/n8n-client.ts +++ b/packages/@n8n/instance-ai/evaluations/clients/n8n-client.ts @@ -10,6 +10,8 @@ import type { InstanceAiConfirmRequest, InstanceAiRichMessagesResponse, InstanceAiEvalExecutionResult, + InstanceAiRunDebugResponse, + InstanceAiThreadDebugRunsResponse, } from '@n8n/api-types'; import { z } from 'zod'; @@ -137,12 +139,13 @@ export class N8nClient { /** * Ensure a conversation thread exists before sending chat messages. - * POST /rest/instance-ai/threads body: { threadId } + * POST /rest/instance-ai/threads body: { threadId, projectId } */ - async ensureThread(threadId: string): Promise<void> { + async ensureThread(threadId: string, projectId?: string): Promise<void> { + const resolvedProjectId = projectId ?? (await this.getPersonalProjectId()); await this.fetch('/rest/instance-ai/threads', { method: 'POST', - body: { threadId }, + body: { threadId, projectId: resolvedProjectId }, }); } @@ -207,6 +210,26 @@ export class N8nClient { await this.fetch(`/rest/instance-ai/threads/${threadId}`, { method: 'DELETE' }); } + /** + * List captured LLM debug runs for a thread. + * GET /rest/instance-ai/debug/threads/:threadId/runs + */ + async listThreadDebugRuns(threadId: string): Promise<InstanceAiThreadDebugRunsResponse> { + return this.unwrapRestData<InstanceAiThreadDebugRunsResponse>( + await this.fetch(`/rest/instance-ai/debug/threads/${threadId}/runs`), + ); + } + + /** + * Fetch full LLM step debug for a single run. + * GET /rest/instance-ai/debug/runs/:runId + */ + async getRunDebug(runId: string): Promise<InstanceAiRunDebugResponse> { + return this.unwrapRestData<InstanceAiRunDebugResponse>( + await this.fetch(`/rest/instance-ai/debug/runs/${runId}`), + ); + } + // -- Computer-use gateway (pairing + status) ----------------------------- /** @@ -435,6 +458,19 @@ export class N8nClient { return { id: result.data.id }; } + /** + * Seed the MCP registry with the test fixture (Notion + Linear mock servers) + * and trigger a synthetic node-type reload. Requires the server to be running + * with `E2E_TESTS=true` so the test controller is mounted. + * POST /rest/mcp-registry/test/seed body: none + */ + async seedMcpRegistry(): Promise<{ count: number }> { + const result = (await this.fetch('/rest/mcp-registry/test/seed', { + method: 'POST', + })) as { data: { ok: boolean; count: number } }; + return { count: result.data.count }; + } + /** * Delete a credential by ID. * DELETE /rest/credentials/:id @@ -538,6 +574,13 @@ export class N8nClient { // -- Internal fetch ------------------------------------------------------ + private unwrapRestData<T>(result: unknown): T { + if (result && typeof result === 'object' && 'data' in result) { + return (result as { data: T }).data; + } + return result as T; + } + private async fetch( path: string, options: { method?: string; body?: unknown; timeoutMs?: number } = {}, diff --git a/packages/@n8n/instance-ai/evaluations/comparison/format.ts b/packages/@n8n/instance-ai/evaluations/comparison/format.ts index 6540717be6f..46be12b9a85 100644 --- a/packages/@n8n/instance-ai/evaluations/comparison/format.ts +++ b/packages/@n8n/instance-ai/evaluations/comparison/format.ts @@ -36,8 +36,10 @@ import type { } from '../types'; interface FormatOptions { - /** Optional commit SHA to include in the heading. Truncated to 8 chars. */ + /** Optional commit SHA for the terminal heading. Truncated to 8 chars. */ commitSha?: string; + /** GitHub Actions run URL; when set, the comment leads with a re-run link. */ + runUrl?: string; /** Maps each test-case reference to its file slug. When provided, the * per-scenario failure breakdown looks up failed runs by * `${fileSlug}/${scenarioName}` — deterministic across collisions like @@ -58,7 +60,9 @@ export function formatComparisonMarkdown( const lines: string[] = []; const comparison = outcome?.kind === 'ok' ? outcome.result : undefined; - lines.push(formatHeading(options.commitSha)); + lines.push(formatHeading()); + lines.push(''); + lines.push(renderRerunCallout(options.runUrl)); lines.push(''); lines.push(formatTopAlert(outcome)); lines.push(''); @@ -142,39 +146,75 @@ export function formatComparisonMarkdown( return lines.join('\n'); } +// Evals fire on PR open/ready, not on push — lead with a one-click re-run prompt. +function renderRerunCallout(runUrl?: string): string { + const cta = runUrl + ? `[▶ Re-run this eval](${runUrl}) (then **Re-run jobs**)` + : 'Re-run it from the **Checks** tab (**Re-run jobs**)'; + return [ + '> [!IMPORTANT]', + `> **This eval does not re-run on new commits** — ${cta} when you're ready to merge.`, + ].join('\n'); +} + function renderWorkflowChecksSection(evaluation: MultiRunEvaluation): string[] { const aggregate = aggregateWorkflowChecks(evaluation); if (!aggregate) return []; + const names = Object.keys(aggregate.perCheck).sort(); + const rowByName: Record<string, { dimension: string; row: string; failed: boolean }> = {}; + let failingChecks = 0; + for (const name of names) { + const entry = aggregate.perCheck[name]; + const scored = entry.passes + entry.fails; + const rate = scored > 0 ? `${String(Math.round((entry.passes / scored) * 100))}%` : '—'; + if (entry.fails > 0) failingChecks++; + rowByName[name] = { + dimension: entry.dimension, + failed: entry.fails > 0, + row: `| \`${entry.dimension}\` | \`${name}\` | ${entry.kind} | ${String(entry.passes)} | ${String(entry.fails)} | ${String(entry.nA)} | ${rate} |`, + }; + } + + const header = [ + '| Dimension | Check | Kind | Pass | Fail | N/A | Pass rate |', + '|---|---|---|---|---|---|---|', + ]; + const rowsWhere = (keep: (name: string) => boolean): string[] => { + const byDimension: Record<string, string[]> = {}; + for (const name of names) { + if (keep(name)) (byDimension[rowByName[name].dimension] ??= []).push(rowByName[name].row); + } + return CHECK_DIMENSIONS.flatMap((dim) => byDimension[dim] ?? []); + }; + const lines: string[] = [ '#### Workflow checks', '', `_Scored over ${String(aggregate.scoredBuilds)} successful build(s). N/A = check did not apply to that workflow._`, '', - '| Dimension | Check | Kind | Pass | Fail | N/A | Pass rate |', - '|---|---|---|---|---|---|---|', ]; - const byDimension: Record<string, string[]> = {}; - for (const name of Object.keys(aggregate.perCheck).sort()) { - const entry = aggregate.perCheck[name]; - const scored = entry.passes + entry.fails; - const rate = scored > 0 ? `${String(Math.round((entry.passes / scored) * 100))}%` : '—'; - (byDimension[entry.dimension] ??= []).push( - `| \`${entry.dimension}\` | \`${name}\` | ${entry.kind} | ${String(entry.passes)} | ${String(entry.fails)} | ${String(entry.nA)} | ${rate} |`, - ); - } + // Failing checks render inline (the only rows that usually carry signal); the + // full, mostly-100% table collapses into <details> so an all-green run is a + // one-line summary instead of a ~30-row wall. + const failingRows = rowsWhere((name) => rowByName[name].failed); + if (failingRows.length > 0) lines.push(...header, ...failingRows, ''); - for (const dim of CHECK_DIMENSIONS) { - if (byDimension[dim]) lines.push(...byDimension[dim]); - } - lines.push(''); + lines.push( + `<details><summary>All workflow checks (${String(failingChecks)} failing of ${String(names.length)} checks)</summary>`, + '', + ...header, + ...rowsWhere(() => true), + '', + '</details>', + '', + ); return lines; } -function formatHeading(commitSha?: string): string { - const sha = commitSha ? ` — \`${commitSha.slice(0, 8)}\`` : ''; - return `### Instance AI Workflow Eval${sha}`; +function formatHeading(): string { + return '### Instance AI Workflow Eval'; } function formatTopAlert(outcome?: ComparisonOutcome): string { @@ -212,7 +252,7 @@ function formatTopAlert(outcome?: ComparisonOutcome): string { const aggDelta = comparison.aggregate.delta * 100; const aggDeltaText = `${aggDelta >= 0 ? '+' : ''}${aggDelta.toFixed(1)}pp`; - const passRateText = `pass rate ${aggDeltaText} vs master`; + const passRateText = `pass rate ${aggDeltaText} vs baseline`; // Two-line summary: regression-tier counts on top, positives/neutrals on the // bottom. The pass-rate delta tails whichever line matches its sign so the @@ -757,7 +797,7 @@ function formatTerminalVerdictLine(outcome?: ComparisonOutcome): string { const aggDelta = comparison.aggregate.delta * 100; const aggDeltaText = `${aggDelta >= 0 ? '+' : ''}${aggDelta.toFixed(1)}pp`; - const passRateText = `pass rate ${aggDeltaText} vs master`; + const passRateText = `pass rate ${aggDeltaText} vs baseline`; const concernsParts = [ `${hard} regression${hard === 1 ? '' : 's'}`, @@ -843,25 +883,23 @@ function formatTerminalPerTestCase( if (totalRuns > 1) { const rows = testCases.map((tc) => { + const units = [ + ...tc.executionScenarios, + ...tc.buildExpectations.filter((ea) => ea.evaluatedCount > 0), + ]; const meanPassAtK = - tc.executionScenarios.length > 0 + units.length > 0 ? Math.round( - (tc.executionScenarios.reduce( - (sum, sa) => sum + (sa.passAtK[totalRuns - 1] ?? 0), - 0, - ) / - tc.executionScenarios.length) * + (units.reduce((sum, u) => sum + (u.passAtK[u.passAtK.length - 1] ?? 0), 0) / + units.length) * 100, ) : 0; const meanPassHatK = - tc.executionScenarios.length > 0 + units.length > 0 ? Math.round( - (tc.executionScenarios.reduce( - (sum, sa) => sum + (sa.passHatK[totalRuns - 1] ?? 0), - 0, - ) / - tc.executionScenarios.length) * + (units.reduce((sum, u) => sum + (u.passHatK[u.passHatK.length - 1] ?? 0), 0) / + units.length) * 100, ) : 0; @@ -925,6 +963,15 @@ function formatTerminalPerTestCase( lines.push(TERMINAL_INDENT + ` diagnosis: ${sr.reasoning.slice(0, 200)}`); } } + for (const ea of tc.buildExpectations) { + const er = ea.runs[0]; + if (!er) continue; + const status = er.incomplete ? 'SKIP' : er.pass ? 'PASS' : 'FAIL'; + lines.push(TERMINAL_INDENT + ` ${status} expectation: ${ea.expectation.slice(0, 80)}`); + if (status === 'FAIL') { + lines.push(TERMINAL_INDENT + ` ${er.reason.slice(0, 200)}`); + } + } } } lines.push(''); diff --git a/packages/@n8n/instance-ai/evaluations/computer-use/chat.ts b/packages/@n8n/instance-ai/evaluations/computer-use/chat.ts index 1242181231e..e107d613aaf 100644 --- a/packages/@n8n/instance-ai/evaluations/computer-use/chat.ts +++ b/packages/@n8n/instance-ai/evaluations/computer-use/chat.ts @@ -42,7 +42,7 @@ export interface RunChatOptions { */ export async function runChat(options: RunChatOptions): Promise<ScenarioTrace> { const { client, prompt, timeoutMs, logger } = options; - const threadId = `cu-eval-${crypto.randomUUID()}`; + const threadId = crypto.randomUUID(); const startTime = Date.now(); const abortController = new AbortController(); diff --git a/packages/@n8n/instance-ai/evaluations/credentials/seeder.ts b/packages/@n8n/instance-ai/evaluations/credentials/seeder.ts index 857269a5ecf..879dd0a37bf 100644 --- a/packages/@n8n/instance-ai/evaluations/credentials/seeder.ts +++ b/packages/@n8n/instance-ai/evaluations/credentials/seeder.ts @@ -1,10 +1,9 @@ // --------------------------------------------------------------------------- // Credential seeding and cleanup for evaluation runs // -// External service credentials (Slack, GitHub, etc.) require real tokens -// via environment variables. If the env var is not set, the credential -// is skipped. Generic HTTP credentials use placeholder values and are -// always seeded. +// External service credentials (Slack, GitHub, etc.) are always seeded with a +// placeholder token — execution is mocked at the wire level, so the value is +// never used. Set EVAL_*_ACCESS_TOKEN to override with a real token for a live run. // // POST /rest/credentials takes raw values -- n8n encrypts them server-side. // --------------------------------------------------------------------------- @@ -33,6 +32,9 @@ interface GenericCredentialConfig { // Credential definitions // --------------------------------------------------------------------------- +// Stand-in token for mocked runs; overridden per service by EVAL_*_ACCESS_TOKEN. +const PLACEHOLDER_TOKEN = 'eval-placeholder'; + const CREDENTIAL_CONFIGS: CredentialConfig[] = [ { envVar: 'EVAL_SLACK_ACCESS_TOKEN', @@ -94,8 +96,8 @@ export interface SeedResult { /** * Seed credentials into the n8n instance for evaluation runs. * - * For env-var-based configs, the credential is skipped if the env var is not - * set. Generic credentials (HTTP Header, HTTP Basic) are always seeded. + * Always seeds placeholder credentials; set EVAL_*_ACCESS_TOKEN to override a + * service with a real token for a live run. * * When `requiredTypes` is provided, only credentials matching those types are * seeded. When omitted, all available credentials are seeded. @@ -109,15 +111,12 @@ export async function seedCredentials( const seededTypes: string[] = []; const typeFilter = requiredTypes ? new Set(requiredTypes) : undefined; - // Seed env-var-based credentials + // Seed external-service credentials (placeholder token unless an env var overrides) for (const config of CREDENTIAL_CONFIGS) { if (typeFilter && !typeFilter.has(config.type)) continue; - const token = process.env[config.envVar]; - if (!token) { - logger?.verbose(` Skipping ${config.name}: ${config.envVar} not set`); - continue; - } + const token = process.env[config.envVar] ?? PLACEHOLDER_TOKEN; + logger?.verbose(` Seeding ${config.name}`); try { const data = config.dataBuilder(token); diff --git a/packages/@n8n/instance-ai/evaluations/data/discovery/data-table-natural-list-skill-loading.json b/packages/@n8n/instance-ai/evaluations/data/discovery/data-table-natural-list-skill-loading.json index 6957c347f4f..b4df3d9971c 100644 --- a/packages/@n8n/instance-ai/evaluations/data/discovery/data-table-natural-list-skill-loading.json +++ b/packages/@n8n/instance-ai/evaluations/data/discovery/data-table-natural-list-skill-loading.json @@ -13,11 +13,9 @@ } ], "noneOf": [ - "plan", "create-tasks", "build-workflow", "delegate", - "spawn_sub_agent:planner", "spawn_sub_agent:workflow-builder", "spawn_sub_agent:delegate" ] diff --git a/packages/@n8n/instance-ai/evaluations/data/discovery/data-table-skill-loading.json b/packages/@n8n/instance-ai/evaluations/data/discovery/data-table-skill-loading.json index 4707a2b0b4a..0120588619d 100644 --- a/packages/@n8n/instance-ai/evaluations/data/discovery/data-table-skill-loading.json +++ b/packages/@n8n/instance-ai/evaluations/data/discovery/data-table-skill-loading.json @@ -13,11 +13,9 @@ } ], "noneOf": [ - "plan", "create-tasks", "build-workflow", "delegate", - "spawn_sub_agent:planner", "spawn_sub_agent:workflow-builder", "spawn_sub_agent:delegate" ] diff --git a/packages/@n8n/instance-ai/evaluations/data/discovery/data-table-workflow-skill-loading.json b/packages/@n8n/instance-ai/evaluations/data/discovery/data-table-workflow-skill-loading.json index 346659b3f74..73071166274 100644 --- a/packages/@n8n/instance-ai/evaluations/data/discovery/data-table-workflow-skill-loading.json +++ b/packages/@n8n/instance-ai/evaluations/data/discovery/data-table-workflow-skill-loading.json @@ -2,7 +2,6 @@ "id": "data-table-workflow-skill-loading", "userMessage": "Create me a workflow that implements an n8n form to capture responses into a data table. The form should be a decklist submission form for a MTG tournament, asking for player name and a deck list as text fields they'll fill.", "expectedToolInvocations": { - "anyOf": ["plan"], "allOfToolCalls": [ { "toolName": "load_skill", @@ -11,9 +10,12 @@ { "toolName": "load_skill", "argsContainAny": ["workflow-builder"] + }, + { + "toolName": "build-workflow" } ], - "noneOf": ["delegate", "spawn_sub_agent:delegate"] + "noneOf": ["create-tasks", "delegate", "spawn_sub_agent:delegate"] }, - "rationale": "Regression coverage for workflow-build prompts that depend on Data Tables. The orchestrator should plan the work and load both the data-table-manager skill and the workflow-builder skill so table schema and row-handling guidance influence the build path without delegating to a sub-agent." + "rationale": "Regression coverage for single-workflow build prompts that depend on Data Tables. The orchestrator should load both the data-table-manager skill and the workflow-builder skill, include workflow-local table requirements in the build, and avoid task planning or delegation." } diff --git a/packages/@n8n/instance-ai/evaluations/data/discovery/workflow-builder-no-credential-ask.json b/packages/@n8n/instance-ai/evaluations/data/discovery/workflow-builder-no-credential-ask.json index 75eedca8514..0b89203a6f3 100644 --- a/packages/@n8n/instance-ai/evaluations/data/discovery/workflow-builder-no-credential-ask.json +++ b/packages/@n8n/instance-ai/evaluations/data/discovery/workflow-builder-no-credential-ask.json @@ -2,13 +2,16 @@ "id": "workflow-builder-no-credential-ask", "userMessage": "Build a workflow that lets customers request a meeting time in natural language, parses the preferred time with OpenAI, creates a Google Calendar event, and sends a Gmail confirmation email.", "expectedToolInvocations": { - "anyOf": ["plan"], "allOfToolCalls": [ { "toolName": "load_skill", "argsContainAny": ["workflow-builder"] + }, + { + "toolName": "build-workflow" } ], + "noneOf": ["create-tasks", "delegate", "spawn_sub_agent:delegate"], "noneOfToolCalls": [ { "toolName": "ask-user", @@ -20,5 +23,5 @@ } ] }, - "rationale": "Regression coverage for INS-204. A fresh workflow build should route through planning and may use credentials(action=\"list\") for discovery, but it must not ask the user which credential/account to use when the builder can auto-select or mock unresolved credentials. It should also use contextual timezone data rather than asking for it." + "rationale": "Regression coverage for INS-204. A clear single-workflow build should route through the workflow-builder skill directly, may use credentials(action=\"list\") for discovery, and must not ask the user which credential/account to use when the builder can auto-select or mock unresolved credentials. It should also use contextual timezone data rather than asking for it." } diff --git a/packages/@n8n/instance-ai/evaluations/data/subagent/code-node-http-fetch.json b/packages/@n8n/instance-ai/evaluations/data/subagent/code-node-http-fetch.json new file mode 100644 index 00000000000..b9a52927614 --- /dev/null +++ b/packages/@n8n/instance-ai/evaluations/data/subagent/code-node-http-fetch.json @@ -0,0 +1,4 @@ +{ + "id": "code-node-http-fetch", + "prompt": "Build a workflow that runs manually and uses a Code node to fetch the JSON from https://api.example.com/v1/products with fetch(), then keeps only the products with a price above 100. Configure all nodes completely and don't ask me for credentials — I'll set them up later." +} diff --git a/packages/@n8n/instance-ai/evaluations/data/subagent/error-route-dual-channel.json b/packages/@n8n/instance-ai/evaluations/data/subagent/error-route-dual-channel.json new file mode 100644 index 00000000000..9a0fdf908ee --- /dev/null +++ b/packages/@n8n/instance-ai/evaluations/data/subagent/error-route-dual-channel.json @@ -0,0 +1,4 @@ +{ + "id": "error-route-dual-channel", + "prompt": "Build a workflow that runs daily at 9am, reads pending reminders from a data table called camp_reminders, and sends each reminder both by Gmail and by WhatsApp via Twilio. After sending, update the row in camp_reminders: mark it sent when the message goes out, and mark it failed if a send errors. Configure all nodes completely and don't ask me for credentials — I'll set them up later." +} diff --git a/packages/@n8n/instance-ai/evaluations/data/subagent/sdk-language-digest-formatting.json b/packages/@n8n/instance-ai/evaluations/data/subagent/sdk-language-digest-formatting.json new file mode 100644 index 00000000000..70cdab5e7e4 --- /dev/null +++ b/packages/@n8n/instance-ai/evaluations/data/subagent/sdk-language-digest-formatting.json @@ -0,0 +1,4 @@ +{ + "id": "sdk-language-digest-formatting", + "prompt": "Build a workflow that runs every weekday at 8am, reads Gmail messages from the last 24 hours, creates a prioritized daily action-item digest with bullet lines for each message, and sends that digest to manager@example.com. The digest formatting can use n8n expressions or a Code node for runtime aggregation, but the workflow SDK builder code must stay in the supported SDK subset and must not use native top-level array/string helpers like .join(), .map(), .filter(), or .reduce(). Configure all nodes completely and don't ask for credentials." +} diff --git a/packages/@n8n/instance-ai/evaluations/data/workflows/agent-with-notion-mcp.json b/packages/@n8n/instance-ai/evaluations/data/workflows/agent-with-notion-mcp.json new file mode 100644 index 00000000000..22df36f10cc --- /dev/null +++ b/packages/@n8n/instance-ai/evaluations/data/workflows/agent-with-notion-mcp.json @@ -0,0 +1,18 @@ +{ + "conversation": [ + { + "role": "user", + "text": "Build a workflow with a chat-triggered AI agent that can search my Notion workspace to answer questions about ongoing projects. The agent should use the Notion connection from n8n's built-in service connections (the one optimized for agent tool use), not the standard Notion action node. Configure all nodes as completely as possible and don't ask me for credentials, I'll set them up later." + } + ], + "complexity": "medium", + "tags": ["build", "agent", "ai-tool", "mcp-registry", "notion"], + "executionScenarios": [ + { + "name": "happy-path", + "description": "User asks about a project; agent uses the Notion MCP registry node to find the answer", + "dataSetup": "User asks 'what's the status of the Phoenix project?'. The Notion MCP server responds to a notion-search call with one matching page summarized as: title 'Phoenix', status 'in progress', owner 'Mira', last updated '3 days ago'.", + "successCriteria": "The workflow contains a chat trigger, an Agent node, and a Notion MCP registry node (the node provided by the @n8n/mcp-registry package — its node type is 'notion' and its credential type is 'notionMcpOAuth2Api', NOT the native 'n8n-nodes-base.notion' node with 'notionApi' credentials). The Notion MCP node is wired to the Agent as an ai_tool connection. When executed, the Agent's final response references 'Phoenix', 'in progress', and 'Mira'." + } + ] +} diff --git a/packages/@n8n/instance-ai/evaluations/data/workflows/airtable-split-to-slack.json b/packages/@n8n/instance-ai/evaluations/data/workflows/airtable-split-to-slack.json index d71ef80136a..455692fab94 100644 --- a/packages/@n8n/instance-ai/evaluations/data/workflows/airtable-split-to-slack.json +++ b/packages/@n8n/instance-ai/evaluations/data/workflows/airtable-split-to-slack.json @@ -22,6 +22,10 @@ } ], "messageBudget": 6, + "buildExpectations": [ + "The agent honored the user's explicit instruction to fetch the tasks via an HTTP Request node with Bearer auth, not the dedicated Airtable node.", + "The final workflow reflects the user's follow-up that Airtable returns a `{records: [...]}` envelope, splitting it into individual items (e.g. a Split Out node) before posting to Slack." + ], "complexity": "medium", "tags": ["build", "schedule", "http-request", "airtable", "slack", "split-out"], "triggerType": "schedule", diff --git a/packages/@n8n/instance-ai/evaluations/data/workflows/applies-each-change-when-asked.json b/packages/@n8n/instance-ai/evaluations/data/workflows/applies-each-change-when-asked.json new file mode 100644 index 00000000000..50aa49a455b --- /dev/null +++ b/packages/@n8n/instance-ai/evaluations/data/workflows/applies-each-change-when-asked.json @@ -0,0 +1,46 @@ +{ + "description": "Long conversation: as the user asks for many small changes one at a time, the agent should apply each one when asked and end up with all of them — not fall a step behind or drop one.", + "conversation": [ + { + "role": "user", + "text": "Every weekday at 9am, post a 'Daily standup starting soon' reminder to our Slack #standup channel." + }, + { + "role": "assistant", + "text": "Got it — I'll build that now." + }, + { + "role": "user", + "text": [ + "[You have a list of changes to make to the workflow, one at a time. Each time the agent finishes applying a change, ask for the next one, then wait for it before asking for the following one. Ask for ONLY ONE change per message, in this exact order:", + "(1) move the time to 8:45am;", + "(2) only run on Monday, Wednesday and Friday;", + "(3) change the message text to 'Standup in 5 minutes';", + "(4) add an @here mention to that message;", + "(5) add a second Slack message 25 minutes later that says 'Standup now';", + "(6) also include today's date in the first message;", + "(7) add a step before the first post that builds the message text into a field, and have the post use that field;", + "(8) add error handling so that if a Slack post fails the workflow keeps going and posts a short note to a #alerts channel;", + "(9) make the second 'Standup now' message reply in the same Slack thread as the first message.", + "Keep going until all nine changes are made, then you can finish.]" + ] + } + ], + "messageBudget": 40, + "complexity": "complex", + "tags": ["behaviour", "changes-applied", "long-conversation", "schedule", "slack"], + "triggerType": "schedule", + "datasets": ["behaviour", "full"], + "buildExpectations": [ + "By the end, the workflow reflects every change the user asked for: it runs at 8:45am, only on Monday/Wednesday/Friday; the first message's text is assembled in a preceding Set/Edit Fields step that the post references, reads 'Standup in 5 minutes', mentions @here, and includes today's date; there is a second message 25 minutes later that says 'Standup now' and replies in the first message's Slack thread; and if a Slack post fails the workflow continues and posts to a #alerts channel. Nothing the user asked for is missing.", + "After every change the user asked for, there is a before and after diff in the workflow that shows the change was applied. User request was accurately applied in the workflow." + ], + "executionScenarios": [ + { + "name": "standup-reminder", + "description": "Built on a weekday (later Mon/Wed/Fri) morning schedule that assembles a standup message, posts it to Slack #standup with a threaded follow-up, and falls back to #alerts on failure", + "dataSetup": "No external data is needed. Each Slack postMessage call returns { \"ok\": true, \"ts\": \"1700000000.000300\" }.", + "successCriteria": "The workflow is built correctly: a schedule trigger (8:45am, Mon/Wed/Fri after the user's changes) → a Set/Edit Fields step that builds the message → a Slack post to #standup carrying the text, @here mention and today's date, plus a second 'Standup now' post 25 minutes later that threads under the first; a Slack failure routes to a #alerts post. A successful mocked post is the ideal result; if the run trips on the channel format or an unconfigured value when it runs, treat that as an acceptable setup detail (not a build mistake) and a pass. Only judge the workflow's structure and how it runs; don't judge anything about the conversation." + } + ] +} diff --git a/packages/@n8n/instance-ai/evaluations/data/workflows/asks-clarifying-question.json b/packages/@n8n/instance-ai/evaluations/data/workflows/asks-clarifying-question.json new file mode 100644 index 00000000000..2da51a76126 --- /dev/null +++ b/packages/@n8n/instance-ai/evaluations/data/workflows/asks-clarifying-question.json @@ -0,0 +1,35 @@ +{ + "description": "#6/#8: A vague request should make the builder ask a clarifying question via the structured question tool and wait for the answer before building.", + "conversation": [ + { + "role": "user", + "text": "Every morning, send my team a summary of yesterday's signups." + }, + { + "role": "assistant", + "text": "Where should I send the summary — which service or channel?" + }, + { + "role": "user", + "text": "[Don't bring up the channel unless the agent explicitly asks where to send the summary; then say 'Slack #growth.']" + } + ], + "messageBudget": 4, + "complexity": "medium", + "tags": ["behaviour", "clarification", "question-tool", "schedule", "slack"], + "triggerType": "schedule", + "datasets": ["behaviour", "full"], + "buildExpectations": [ + "Before building, the agent asked which destination to send the summary to, since the request did not specify one.", + "The agent asked using the structured question tool, not by posing the question in plain assistant text.", + "The agent waited for the user's answer before building." + ], + "executionScenarios": [ + { + "name": "happy-path", + "description": "Signups source returns a few rows; a summary is posted to Slack", + "dataSetup": "The signups data source returns 3 rows for yesterday: names Ana, Ben, Cara. The Slack postMessage call returns { \"ok\": true, \"ts\": \"1700000000.000100\" }.", + "successCriteria": "The workflow executes without errors and posts a summary mentioning the 3 signups (Ana, Ben, Cara) to Slack #growth." + } + ] +} diff --git a/packages/@n8n/instance-ai/evaluations/data/workflows/daily-gmail-action-digest.json b/packages/@n8n/instance-ai/evaluations/data/workflows/daily-gmail-action-digest.json new file mode 100644 index 00000000000..63ea876e089 --- /dev/null +++ b/packages/@n8n/instance-ai/evaluations/data/workflows/daily-gmail-action-digest.json @@ -0,0 +1,26 @@ +{ + "conversation": [ + { + "role": "user", + "text": "Every morning, read all emails received in the last 24 hours from Gmail, use OpenAI to extract action items and prioritize them, then send me a structured daily digest email summarizing what needs my attention." + } + ], + "messageBudget": 4, + "complexity": "medium", + "tags": ["build", "gmail", "ai", "schedule", "conditional", "digest"], + "triggerType": "schedule", + "executionScenarios": [ + { + "name": "emails-with-action-items", + "description": "Recent Gmail messages contain several actionable requests", + "dataSetup": "The Gmail search node should return 5 emails from the last 24 hours. Include requests about approving an invoice by Friday, reviewing a contract today, replying to a customer escalation, and one FYI-only newsletter. The AI/LLM step should extract and prioritize the actionable items. The final Gmail send node returns a success response.", + "successCriteria": "The workflow executes without errors. It fetches Gmail messages from the last 24 hours, runs an AI extraction/prioritization step after the email aggregation, and reaches the final Gmail send node. The digest email includes the invoice approval, contract review, and customer escalation with priorities or urgency labels. The workflow must not stop at an IF/Switch node with no downstream path." + }, + { + "name": "no-recent-emails", + "description": "No Gmail messages arrived in the last 24 hours", + "dataSetup": "The Gmail search node returns no emails. The workflow should take the empty-inbox branch and either send a concise no-action-needed digest email or complete through a clearly named no-op/fallback node.", + "successCriteria": "The workflow executes without errors. The empty-inbox branch is wired downstream from the IF/Switch node. The workflow does not leave the branch node terminal and incomplete." + } + ] +} diff --git a/packages/@n8n/instance-ai/evaluations/data/workflows/dont-ask-the-same-question-twice.json b/packages/@n8n/instance-ai/evaluations/data/workflows/dont-ask-the-same-question-twice.json new file mode 100644 index 00000000000..ecc8ef1cf30 --- /dev/null +++ b/packages/@n8n/instance-ai/evaluations/data/workflows/dont-ask-the-same-question-twice.json @@ -0,0 +1,34 @@ +{ + "description": "If the user doesn't provide a detail the agent asked for, the agent should move on and not keep asking for it.", + "conversation": [ + { + "role": "user", + "text": "Every Monday at 9am, post 'Have a great week, team!' to Slack." + }, + { + "role": "assistant", + "text": "Which Slack channel should I post to?" + }, + { + "role": "user", + "text": "[The user has no channel and won't provide one. Every time the agent asks for the channel — whether as a question or in a setup card, even if it asks more than once — skip or dismiss it without giving a channel, and never pick or invent one.]" + } + ], + "messageBudget": 6, + "complexity": "medium", + "tags": ["behaviour", "clarification", "repeat-questions", "schedule", "slack"], + "triggerType": "schedule", + "datasets": ["behaviour", "full"], + "buildExpectations": [ + "The agent asked for the user to provide a Slack channel, rather than silently picking one itself.", + "The user did not provide the channel, and then the agent moved on — leaving it blank or for setup — never asking for the channel again." + ], + "executionScenarios": [ + { + "name": "channel-skipped", + "description": "Built on a Monday schedule posting to Slack; the user didn't give a channel, so it's left for setup", + "dataSetup": "No mock data is needed. If the Slack node's channel is empty, the workflow fails its validation check before any node runs, so no API call is made.", + "successCriteria": "The workflow is built correctly: a Monday 9am schedule trigger feeding a Slack message node with the text 'Have a great week, team!'. If the Slack channel is empty, the workflow fails its validation check ('Not a valid Slack Channel ID or name') — treat that as fine (an empty channel is something to set up later, not a build mistake) and a pass. If a channel is set and the run succeeds, that's also a pass. Only judge the workflow's structure and how it handles the channel when it runs; don't judge anything about the conversation." + } + ] +} diff --git a/packages/@n8n/instance-ai/evaluations/data/workflows/dont-keep-asking-when-told-later.json b/packages/@n8n/instance-ai/evaluations/data/workflows/dont-keep-asking-when-told-later.json new file mode 100644 index 00000000000..60d291b21dc --- /dev/null +++ b/packages/@n8n/instance-ai/evaluations/data/workflows/dont-keep-asking-when-told-later.json @@ -0,0 +1,42 @@ +{ + "description": "If the user says they'll give a detail later, the agent should build the workflow and stop asking for that detail.", + "conversation": [ + { + "role": "user", + "text": "Every Monday at 9am, post the message 'Have a great week, team!' to the team." + }, + { + "role": "assistant", + "text": "Which service should I post it through?" + }, + { + "role": "user", + "text": "Slack, I don't know which channel yet I'll tell you later." + }, + { + "role": "assistant", + "text": "Which Slack channel should I post to?" + }, + { + "role": "user", + "text": "[The user doesn't answer this one — they don't give a channel and don't tell the agent to pick one. Just skip the question.]" + } + ], + "messageBudget": 6, + "complexity": "medium", + "tags": ["behaviour", "clarification", "repeat-questions", "schedule", "slack"], + "triggerType": "schedule", + "datasets": ["behaviour", "full"], + "buildExpectations": [ + "Before building, the agent asked which app to use, since the user hadn't said which one.", + "After the user said they'd give the channel later, the agent built the workflow — leaving the channel blank or setting it up later — instead of asking for the channel again and again, and it told the user they can fill the channel in after building." + ], + "executionScenarios": [ + { + "name": "channel-skipped", + "description": "Built on a Monday schedule posting to Slack; the user didn't give a channel, so the workflow fails its validation check", + "dataSetup": "No mock data is needed. If the Slack node's channel is empty, the workflow fails its validation check before any node runs, so no API call is made.", + "successCriteria": "The workflow is built correctly: a Monday 9am schedule trigger feeding a Slack message node with the text 'Have a great week, team!'. If the Slack channel is empty, the workflow fails its validation check ('Not a valid Slack Channel ID or name') — treat that as fine (an empty channel is something to set up later, not a build mistake) and a pass. If a channel is set and the run succeeds, that's also a pass. Only judge the workflow's structure and how it handles the channel when it runs; don't judge anything about the conversation." + } + ] +} diff --git a/packages/@n8n/instance-ai/evaluations/data/workflows/http-node-pagination.json b/packages/@n8n/instance-ai/evaluations/data/workflows/http-node-pagination.json new file mode 100644 index 00000000000..eb36549af5a --- /dev/null +++ b/packages/@n8n/instance-ai/evaluations/data/workflows/http-node-pagination.json @@ -0,0 +1,34 @@ +{ + "description": "The builder should fetch all pages using the HTTP Request node's built-in pagination, not a single request, a Code-node loop, or a hard-coded page count.", + "conversation": [ + { + "role": "user", + "text": "On a manual trigger, fetch the full list of items from https://api.example.com/items and return them all." + }, + { + "role": "assistant", + "text": "I'll set that up with a Manual Trigger and an HTTP Request node that GETs the items." + }, + { + "role": "user", + "text": "Make sure you get all of them — that endpoint has hundreds of items across many pages, so it needs to page through to the end, not just the first page." + } + ], + "messageBudget": 6, + "complexity": "medium", + "tags": ["behaviour", "http-request", "pagination"], + "triggerType": "manual", + "datasets": ["behaviour", "full"], + "buildExpectations": [ + "The HTTP Request node fetches across all pages (e.g. via its built-in pagination), not just the first page.", + "The agent did NOT work around paging with a Code node loop, a single request, or a hard-coded number of requests." + ], + "executionScenarios": [ + { + "name": "spans-two-pages", + "description": "Items are split across two pages; full pagination returns 4 records, a single request returns only 2", + "dataSetup": "This is a PAGINATED endpoint — serve each request strictly by its `page` query parameter and do NOT put every item on one page. `GET /items?page=1` returns {\"items\":[{\"id\":1,\"name\":\"Alpha\"},{\"id\":2,\"name\":\"Beta\"}]}. `GET /items?page=2` returns {\"items\":[{\"id\":3,\"name\":\"Gamma\"},{\"id\":4,\"name\":\"Delta\"}]}. `GET /items?page=3` and any later page return {\"items\":[]} to signal the end. A request with no page parameter is page 1.", + "successCriteria": "The workflow executes without errors and returns all FOUR item records — Alpha, Beta, Gamma and Delta — having fetched page 1 and page 2 before the empty page 3 stops paging. A workflow that issues a single request (or only reads page 1) returns just Alpha and Beta and FAILS. Judge by the item records present in the output, not by a single numeric count field." + } + ] +} diff --git a/packages/@n8n/instance-ai/evaluations/data/workflows/mock-test-before-credentials.json b/packages/@n8n/instance-ai/evaluations/data/workflows/mock-test-before-credentials.json new file mode 100644 index 00000000000..8461e088c6e --- /dev/null +++ b/packages/@n8n/instance-ai/evaluations/data/workflows/mock-test-before-credentials.json @@ -0,0 +1,25 @@ +{ + "description": "#4: The builder should verify with mocked data for a credentialed node, not refuse to test until a real credential is added.", + "conversation": [ + { + "role": "user", + "text": "Every morning at 9am, fetch yesterday's invoices from Stripe and return a one-line total of the amounts due." + } + ], + "complexity": "medium", + "tags": ["behaviour", "credentials", "stripe", "verification"], + "triggerType": "schedule", + "datasets": ["behaviour", "full"], + "buildExpectations": [ + "The agent ran a verification of the built workflow (a verification execution was attempted, not skipped).", + "During verification the credentialed Stripe node was served mocked/pinned data rather than requiring a real Stripe credential to run — the agent did not refuse to test until a credential was added." + ], + "executionScenarios": [ + { + "name": "happy-path", + "description": "Stripe returns a couple of invoices; a total is produced", + "dataSetup": "The Stripe invoices endpoint returns 2 invoices with amount_due values of 1200 and 800.", + "successCriteria": "The workflow executes without errors and returns a one-line total reflecting the two invoices (e.g. 2000, or 20.00 if interpreted as cents). A schedule trigger is present." + } + ] +} diff --git a/packages/@n8n/instance-ai/evaluations/data/workflows/no-http-in-code-node.json b/packages/@n8n/instance-ai/evaluations/data/workflows/no-http-in-code-node.json new file mode 100644 index 00000000000..cf960446a43 --- /dev/null +++ b/packages/@n8n/instance-ai/evaluations/data/workflows/no-http-in-code-node.json @@ -0,0 +1,25 @@ +{ + "description": "#5: Network requests should be made by an HTTP Request node, not by fetch/axios/http calls inside a Code node.", + "conversation": [ + { + "role": "user", + "text": "On a manual trigger, fetch the latest releases from https://api.example.com/releases and return a short changelog that combines each release's name and date." + } + ], + "complexity": "simple", + "tags": ["behaviour", "code-node", "http-request"], + "triggerType": "manual", + "datasets": ["behaviour", "full"], + "buildExpectations": [ + "The network request was performed by an HTTP Request node, not by an HTTP/fetch call inside a Code node.", + "No Code node in the final workflow attempts a network/HTTP request (e.g. fetch, axios, http/https, $http)." + ], + "executionScenarios": [ + { + "name": "two-releases", + "description": "The releases endpoint returns two releases; a changelog is produced", + "dataSetup": "GET https://api.example.com/releases returns [ { \"name\": \"v2.1\", \"date\": \"2026-05-01\" }, { \"name\": \"v2.2\", \"date\": \"2026-06-01\" } ].", + "successCriteria": "The workflow executes without errors and returns a changelog string referencing both releases (v2.1 / 2026-05-01 and v2.2 / 2026-06-01). The HTTP request is performed by an HTTP Request node." + } + ] +} diff --git a/packages/@n8n/instance-ai/evaluations/data/workflows/notification-router.json b/packages/@n8n/instance-ai/evaluations/data/workflows/notification-router.json index 44c28477e3b..ebf9a6465f5 100644 --- a/packages/@n8n/instance-ai/evaluations/data/workflows/notification-router.json +++ b/packages/@n8n/instance-ai/evaluations/data/workflows/notification-router.json @@ -22,6 +22,11 @@ } ], "messageBudget": 6, + "buildExpectations": [ + "Before building the workflow, the agent asked clarifying questions about the incoming payload shape and the urgency levels.", + "Before building the workflow, the agent asked where each urgency level should be routed.", + "The final workflow branches on the notification `level` (e.g. a Switch node) and routes High to Microsoft Teams, Medium to Slack, and Low to Gmail, as specified in the follow-up." + ], "complexity": "medium", "tags": ["build", "webhook", "switch", "microsoft-teams", "slack", "gmail", "routing"], "triggerType": "webhook", diff --git a/packages/@n8n/instance-ai/evaluations/data/workflows/rest-api-data-pipeline.json b/packages/@n8n/instance-ai/evaluations/data/workflows/rest-api-data-pipeline.json index da1fe49d3b4..d1604881d4b 100644 --- a/packages/@n8n/instance-ai/evaluations/data/workflows/rest-api-data-pipeline.json +++ b/packages/@n8n/instance-ai/evaluations/data/workflows/rest-api-data-pipeline.json @@ -10,7 +10,7 @@ }, { "role": "user", - "text": "GET https://jsonplaceholder.typicode.com/posts. Drop any post whose title contains the word 'qui'. Post to #api-digest." + "text": "GET https://jsonplaceholder.typicode.com/posts. Drop any post whose title contains the word 'qui'. Post to #api-digest as a single summary message that says how many posts remain and lists their titles." }, { "role": "assistant", @@ -19,9 +19,17 @@ { "role": "user", "text": "It should say how many posts remain after filtering and list each remaining post's title." + }, + { + "role": "assistant", + "text": "Got it. Anything else before I build it?" + }, + { + "role": "user", + "text": "One more thing — if every post gets filtered out, I still want the Slack message posted that day saying 0 posts remain. Don't skip the message just because nothing is left." } ], - "messageBudget": 6, + "messageBudget": 8, "complexity": "medium", "tags": ["build", "http-request", "slack", "data-transformation", "schedule"], "triggerType": "schedule", @@ -37,13 +45,13 @@ "name": "empty-response", "description": "The API returns an empty array", "dataSetup": "The HTTP Request node returns an empty array []. The Slack node returns a success response.", - "successCriteria": "The workflow handles an empty API response without crashing. The Slack message is either posted with a 'no posts' message or the workflow completes gracefully without posting." + "successCriteria": "The workflow handles an empty API response without crashing, and a Slack message is still posted stating that 0 posts remain." }, { "name": "all-filtered", "description": "Every post contains 'qui' in the title and all are filtered out", "dataSetup": "The HTTP Request node returns 3 posts, all with 'qui' in their titles. The Slack node returns a success response.", - "successCriteria": "The workflow handles the case where all items are filtered out. It should not crash or send an empty message to Slack." + "successCriteria": "All posts are filtered out and a Slack message is still posted to #api-digest stating that 0 posts remain. The workflow does not crash and does not send an empty or malformed message." } ] } diff --git a/packages/@n8n/instance-ai/evaluations/data/workflows/schema.ts b/packages/@n8n/instance-ai/evaluations/data/workflows/schema.ts index 8fb3b20584a..967e6a9ed95 100644 --- a/packages/@n8n/instance-ai/evaluations/data/workflows/schema.ts +++ b/packages/@n8n/instance-ai/evaluations/data/workflows/schema.ts @@ -2,7 +2,12 @@ import { z } from 'zod'; const ConversationTurnSchema = z.object({ role: z.enum(['user', 'assistant']), - text: z.string(), + // A string, or an array of lines joined with newlines. The array form lets + // long stage directions be authored readably (one line per element) in the + // JSON file; every consumer still receives a single string. + text: z + .union([z.string(), z.array(z.string())]) + .transform((t) => (Array.isArray(t) ? t.join('\n') : t)), }); const ExecutionScenarioSchema = z.object({ @@ -14,12 +19,16 @@ const ExecutionScenarioSchema = z.object({ }); export const WorkflowTestCaseSchema = z.object({ + /** Optional human-readable note on what this case is testing (esp. for behaviour cases). */ + description: z.string().optional(), conversation: z.array(ConversationTurnSchema).min(1), complexity: z.enum(['simple', 'medium', 'complex']), tags: z.array(z.string()), triggerType: z.enum(['manual', 'webhook', 'schedule', 'form']).optional(), executionScenarios: z.array(ExecutionScenarioSchema).min(1), messageBudget: z.number().int().positive().optional(), + /** Optional NL assertions about the build conversation; LLM-judged, counted as units in the pass rate. */ + buildExpectations: z.array(z.string().min(1)).optional(), /** * Logical groupings this case belongs to (e.g. `['pr', 'full']`). Used by * the eval CLI's `--tier` flag and propagated to LangSmith as example diff --git a/packages/@n8n/instance-ai/evaluations/data/workflows/smartassist-form-booking.json b/packages/@n8n/instance-ai/evaluations/data/workflows/smartassist-form-booking.json new file mode 100644 index 00000000000..289abc15b8c --- /dev/null +++ b/packages/@n8n/instance-ai/evaluations/data/workflows/smartassist-form-booking.json @@ -0,0 +1,41 @@ +{ + "description": "Form booking with OpenAI confirmation and Google Sheets logging, then replace the thank-you completion screen with a Form Ending page showing exact confirmation text.", + "conversation": [ + { + "role": "user", + "text": "Build an appointment booking workflow called SmartAssist Appointment Booking. Use a Form Trigger that collects Customer Name, Service Type, Appointment Date, Appointment Time, Phone Number, and Request Details (all required). Use OpenAI to generate a friendly personalized confirmation paragraph. Append all form fields plus the AI confirmation to a Google Sheet named SmartAssist Bookings (Sheet1) with columns Customer Name, Service Type, Appointment Date, Appointment Time, Phone Number, Request Details, AI Confirmation. End with a Form completion thank-you screen." + }, + { + "role": "assistant", + "text": "I'll build the SmartAssist Appointment Booking workflow with a form trigger, OpenAI confirmation, Google Sheets logging, and a thank-you completion screen." + }, + { + "role": "user", + "text": "Update the workflow: delete the thank-you completion screen and replace it with a Form node (Form Ending) after Append Booking To Sheet. Configure the Form Ending to display this exact text: \"Appointment Request Submitted Successfully Thank you for your booking. Your appointment request has been received and processed by SmartAssist AI. A personalized confirmation has been generated and saved in our system. We will contact you shortly.\" Do not change any other nodes." + } + ], + "messageBudget": 8, + "complexity": "medium", + "tags": ["build", "form-trigger", "google-sheets", "openai", "multi-turn"], + "triggerType": "form", + "datasets": ["full", "form"], + "buildExpectations": [ + "After the first user message, the agent built a workflow with a Form Trigger collecting all six required fields (Customer Name, Service Type, Appointment Date, Appointment Time, Phone Number, Request Details), an OpenAI step that generates a personalized confirmation, a Google Sheets append to SmartAssist Bookings with all seven columns including AI Confirmation, and a form completion or thank-you ending screen.", + "After the second user message, the thank-you/completion screen was removed and replaced with a Form node configured as Form Ending that shows the exact confirmation text the user specified. The Google Sheets node still maps all seven columns from the correct upstream form and AI outputs.", + "The agent did not claim the edit succeeded without verifying the saved workflow reflects the requested change." + ], + "executionScenarios": [ + { + "name": "form-submission-happy-path", + "description": "Complete form submission reaches OpenAI, appends to Google Sheets, and shows the Form Ending confirmation text", + "dataSetup": "The Form Trigger receives: Customer Name='Alice Smith', Service Type='Haircut', Appointment Date='2025-12-15', Appointment Time='14:30', Phone Number='+1 555 123 4567', Request Details='First time visit, please use scissor cut only.' The OpenAI node returns a friendly confirmation paragraph. The Google Sheets append node returns success.", + "successCriteria": "The workflow executes through OpenAI and reaches the Form Ending confirmation text (Appointment Request Submitted Successfully…). OpenAI generates a confirmation paragraph mappable to the AI Confirmation column. Google Sheets document ID may be unset or a placeholder when the user has not completed setup — that alone is not a build failure. Column mappings and expressions for all seven fields must still be correct. When dataSetup says the Sheets append succeeds, treat the append as successful in mock execution. Unset document ID must not block the submitter from seeing Form Ending." + }, + { + "name": "modification-preserves-mappings", + "description": "After the Form Ending modification, Google Sheets still maps all seven columns correctly", + "dataSetup": "The Form Trigger receives: Customer Name='Dana Ortiz', Service Type='Massage', Appointment Date='2025-12-22', Appointment Time='16:00', Phone Number='+1 555 444 3333', Request Details='Prefer quiet room.' The OpenAI node returns: 'Hi Dana, your massage appointment on 2025-12-22 at 16:00 is confirmed.' The Google Sheets append node returns success.", + "successCriteria": "After the Form Ending edit, the Google Sheets node still maps all seven columns — Customer Name, Service Type, Appointment Date, Appointment Time, Phone Number, Request Details, and AI Confirmation — with expressions referencing the correct upstream form and AI outputs. Execution reaches Form Ending and displays the user's exact confirmation text. Google Sheets document ID may be unset or a placeholder pre-setup; do not fail solely because a real spreadsheet was not configured. The modification did not drop field mappings or leave columns.value empty." + } + ] +} diff --git a/packages/@n8n/instance-ai/evaluations/data/workflows/trading-bot-http-array-normalization.json b/packages/@n8n/instance-ai/evaluations/data/workflows/trading-bot-http-array-normalization.json new file mode 100644 index 00000000000..dad73b14101 --- /dev/null +++ b/packages/@n8n/instance-ai/evaluations/data/workflows/trading-bot-http-array-normalization.json @@ -0,0 +1,48 @@ +{ + "conversation": [ + { + "role": "user", + "text": "You are an expert n8n workflow architect and AI systems designer.\n\nI want you to build a complete production-ready n8n workflow for an AI-powered trading signal bot that sends high-probability trade signals to Telegram.\n\nIMPORTANT REQUIREMENTS:\n- Use modular multi-agent architecture\n- Each agent must be a separate logical node (AI or function node)\n- Output must be structured JSON at every stage\n- Workflow must be scalable and clean\n\nSYSTEM GOAL:\nAnalyze live market data and generate high-quality" + }, + { + "role": "assistant", + "text": "Where should the live market data come from, and where do the signals go?" + }, + { + "role": "user", + "text": "Pull OHLCV candles from the Binance klines REST API (GET https://api.binance.com/api/v3/klines) via an HTTP Request node, normalize them, compute indicators, and send the final signal to Telegram. Binance returns a JSON array of candle rows, so the normalize step has to handle every candle, not just the first one." + } + ], + "complexity": "complex", + "tags": [ + "build", + "http-request", + "binance", + "array-normalization", + "code-node", + "telegram", + "trading-bot" + ], + "executionScenarios": [ + { + "name": "happy-path-multi-candle-array", + "description": "Binance klines HTTP Request returns a multi-row candle array; normalization handles every row and a non-HOLD signal reaches Telegram.", + "dataSetup": "Assume Binance, Telegram, and any AI-model credentials are present (mocked). The HTTP Request to GET https://api.binance.com/api/v3/klines returns Binance's real shape: a JSON array of candle rows, each row an array like [1700000000000, '42000.00', '42500.00', '41800.00', '42300.00', '120.5', ...], totaling 250 rows with a clear upward close progression toward the end. The Telegram sendMessage call returns { ok: true, result: { message_id: 9001 } }.", + "successCriteria": "Judge primarily on the Normalize OHLCV Code node's output: it must consume all 250 candle rows from the HTTP Request array (e.g. via $input.all() or iterating the response rows), NOT just the first row. Its output must contain a candle series of ~250 rows with non-null numeric open/high/low/close/volume and a non-null current price (not NaN/null). If the workflow runs to completion, the Telegram sendMessage message text additionally contains a concrete signal value (e.g. 'BUY', 'SELL', or 'HOLD') derived from the computed indicators; treat a missing or null signal as a failure." + }, + { + "name": "array-shape-hidden-by-single-item-mock", + "description": "LOAD-BEARING: the array-vs-single bug must surface under a real multi-row response even though a single-item fixture would have passed verification.", + "dataSetup": "Assume credentials are mocked. The HTTP Request to the Binance klines endpoint returns the REAL array shape: a JSON array of 250 candle rows (each row an array of OHLCV fields). Critically do NOT replay a single-item fixture — inject the full multi-row array so any $input.first()/single-item assumption is exercised. Telegram sendMessage returns { ok: true, result: { message_id: 9002 } }.", + "successCriteria": "Judge on the Normalize OHLCV node's output when the 250-row Binance array is fed in: its candle series must have ~250 rows with populated (non-null) OHLCV values and a non-null current price — it must NOT collapse to a single row, a handful of rows, or NaN/null values, which is what happens when the node maps over $input.first().json instead of $input.all(). A collapsed or null series is a failure even if the workflow otherwise completes. If indicators are computed and reach Telegram, the message must reflect the multi-row data rather than a perpetual HOLD forced by null inputs." + }, + { + "name": "empty-klines-response", + "description": "Binance returns an empty candle array — the workflow degrades cleanly instead of erroring.", + "dataSetup": "Assume credentials are mocked. The HTTP Request to the Binance klines endpoint returns an empty JSON array []. Telegram sendMessage, if called, returns { ok: true, result: { message_id: 9003 } }.", + "successCriteria": "The workflow handles the empty array without throwing. The Normalize OHLCV node yields zero rows / no indicators, and either no Telegram message is sent or a Telegram message is sent that explicitly indicates no data / no signal — the workflow completes cleanly with no unhandled error." + } + ], + "triggerType": "schedule", + "messageBudget": 4 +} diff --git a/packages/@n8n/instance-ai/evaluations/discovery/__tests__/expected-tools-invoked.test.ts b/packages/@n8n/instance-ai/evaluations/discovery/__tests__/expected-tools-invoked.test.ts index 382b5de79c4..6be582559bf 100644 --- a/packages/@n8n/instance-ai/evaluations/discovery/__tests__/expected-tools-invoked.test.ts +++ b/packages/@n8n/instance-ai/evaluations/discovery/__tests__/expected-tools-invoked.test.ts @@ -54,15 +54,15 @@ describe('runExpectedToolsInvokedCheck', () => { { id: 'test', userMessage: '', - expectedToolInvocations: { anyOf: ['spawn_sub_agent:planner'] }, + expectedToolInvocations: { anyOf: ['spawn_sub_agent:researcher'] }, }, makeOutcome({ - agents: [{ role: 'planner', tools: ['credentials'] }], + agents: [{ role: 'researcher', tools: ['credentials'] }], }), ); expect(result.pass).toBe(true); - expect(result.spawnedAgents).toContain('spawn_sub_agent:planner'); + expect(result.spawnedAgents).toContain('spawn_sub_agent:researcher'); }); it('passes when the spawned sub-agent had the expected tool attached (sub-agent tools list)', () => { @@ -73,7 +73,7 @@ describe('runExpectedToolsInvokedCheck', () => { expectedToolInvocations: { anyOf: ['credentials'] }, }, makeOutcome({ - agents: [{ role: 'planner', tools: ['credentials'] }], + agents: [{ role: 'researcher', tools: ['credentials'] }], }), ); @@ -180,21 +180,21 @@ describe('runExpectedToolsInvokedCheck', () => { }); describe('noneOfToolCalls — actual tool-call guard', () => { - const plannerScenario: DiscoveryTestCase = { + const planningScenario: DiscoveryTestCase = { id: 'test', userMessage: 'Build a Gmail and Calendar workflow', expectedToolInvocations: { - anyOf: ['plan', 'spawn_sub_agent:planner'], + anyOf: ['create-tasks'], noneOfToolCalls: [{ toolName: 'ask-user', argsContainAny: ['credential'] }], }, }; - it('passes when a spawned planner has ask-user available but does not call it', () => { + it('passes when ask-user is available to a spawned agent but is not called', () => { const result = runExpectedToolsInvokedCheck( - plannerScenario, + planningScenario, makeOutcome({ - toolCalls: [{ toolName: 'plan' }], - agents: [{ role: 'planner', tools: ['credentials', 'ask-user'] }], + toolCalls: [{ toolName: 'create-tasks' }], + agents: [{ role: 'delegate', tools: ['credentials', 'ask-user'] }], }), ); @@ -204,16 +204,16 @@ describe('runExpectedToolsInvokedCheck', () => { it('fails when the forbidden tool call happens with matching args', () => { const result = runExpectedToolsInvokedCheck( - plannerScenario, + planningScenario, makeOutcome({ toolCalls: [ - { toolName: 'plan' }, + { toolName: 'create-tasks' }, { toolName: 'ask-user', args: { question: 'Which Google Calendar credential should I use?' }, }, ], - agents: [{ role: 'planner', tools: ['credentials', 'ask-user'] }], + agents: [{ role: 'delegate', tools: ['credentials', 'ask-user'] }], }), ); @@ -224,13 +224,13 @@ describe('runExpectedToolsInvokedCheck', () => { it('passes when the same tool is called for unrelated args', () => { const result = runExpectedToolsInvokedCheck( - plannerScenario, + planningScenario, makeOutcome({ toolCalls: [ - { toolName: 'plan' }, + { toolName: 'create-tasks' }, { toolName: 'ask-user', args: { question: 'Which failure branch should run?' } }, ], - agents: [{ role: 'planner', tools: ['credentials', 'ask-user'] }], + agents: [{ role: 'delegate', tools: ['credentials', 'ask-user'] }], }), ); diff --git a/packages/@n8n/instance-ai/evaluations/discovery/expected-tools-invoked.ts b/packages/@n8n/instance-ai/evaluations/discovery/expected-tools-invoked.ts index c1dbbca0a95..b2a930394cd 100644 --- a/packages/@n8n/instance-ai/evaluations/discovery/expected-tools-invoked.ts +++ b/packages/@n8n/instance-ai/evaluations/discovery/expected-tools-invoked.ts @@ -11,9 +11,9 @@ // - the rule names `spawn_sub_agent:<role>` and a sub-agent with that role // was spawned. // -// The asymmetry (sub-agent existence counts as discovery) lets planner and -// builder dispatch checks assert that a specialized background agent was -// reached even before it emits its own tool calls. +// The asymmetry (sub-agent existence counts as discovery) lets dispatch checks +// assert that a specialized background agent was reached even before it emits +// its own tool calls. // --------------------------------------------------------------------------- import type { EventOutcome } from '../types'; diff --git a/packages/@n8n/instance-ai/evaluations/discovery/runner.ts b/packages/@n8n/instance-ai/evaluations/discovery/runner.ts index 5e713cbe9aa..9ad43d4fba2 100644 --- a/packages/@n8n/instance-ai/evaluations/discovery/runner.ts +++ b/packages/@n8n/instance-ai/evaluations/discovery/runner.ts @@ -111,7 +111,7 @@ export async function runDiscoveryScenario( }); // `OrchestrationContext` is required for the orchestrator to receive tools like - // `delegate`, `plan`, and runtime skills. We provide stubs for the heavy fields: + // `delegate`, `create-tasks`, and runtime skills. We provide stubs for the heavy fields: // discovery scenarios measure first-step tool-call decisions, not background // execution. const orchestrationContext = createStubOrchestrationContext({ diff --git a/packages/@n8n/instance-ai/evaluations/eval-results-artifact.ts b/packages/@n8n/instance-ai/evaluations/eval-results-artifact.ts new file mode 100644 index 00000000000..582b98e87e4 --- /dev/null +++ b/packages/@n8n/instance-ai/evaluations/eval-results-artifact.ts @@ -0,0 +1,85 @@ +import path from 'node:path'; + +export type StoredScenarioRun<TEvalResult> = { + workflowId?: string | null; + evalResult?: TEvalResult; +}; + +export type StoredScenarioResult<TEvalResult> = { + name: string; + runs: Array<StoredScenarioRun<TEvalResult>>; +}; + +export type StoredTestCaseResult<TEvalResult> = { + name?: string; + testCaseFile?: string; + scenarios: Array<StoredScenarioResult<TEvalResult>>; +}; + +export type StoredEvalResults<TEvalResult> = { + testCases: Array<StoredTestCaseResult<TEvalResult>>; +}; + +export type StoredVerifierRun<TEvalResult> = { + workflowId: string; + evalResult: TEvalResult; + runIndex: number; +}; + +export function getTestCaseSlug(testCasePath: string): string { + return path.basename(testCasePath, path.extname(testCasePath)); +} + +export function findStoredTestCaseResult<TEvalResult>( + evalResults: StoredEvalResults<TEvalResult>, + testCasePath: string, + serializedTestCaseName: string | undefined, +): StoredTestCaseResult<TEvalResult> | undefined { + const slug = getTestCaseSlug(testCasePath); + const bySlug = evalResults.testCases.filter( + (testCaseResult) => testCaseResult.testCaseFile === slug, + ); + if (bySlug.length === 1) return bySlug[0]; + if (bySlug.length > 1) { + throw new Error(`Found multiple eval-results entries for test case slug "${slug}"`); + } + + const byName = serializedTestCaseName + ? evalResults.testCases.filter( + (testCaseResult) => testCaseResult.name === serializedTestCaseName, + ) + : []; + if (byName.length === 1) return byName[0]; + if (byName.length > 1) { + throw new Error( + `Found multiple eval-results entries for test case "${serializedTestCaseName}"`, + ); + } + + return evalResults.testCases.length === 1 ? evalResults.testCases[0] : undefined; +} + +export function findStoredVerifierRun<TEvalResult>( + storedTestCase: StoredTestCaseResult<TEvalResult> | undefined, + scenarioName: string, +): StoredVerifierRun<TEvalResult> | undefined { + const storedScenario = storedTestCase?.scenarios.find( + (scenarioResult) => scenarioResult.name === scenarioName, + ); + if (!storedScenario) return undefined; + + for (let runIndex = 0; runIndex < storedScenario.runs.length; runIndex++) { + const run = storedScenario.runs[runIndex]; + if (!run?.evalResult || typeof run.workflowId !== 'string' || run.workflowId.length === 0) { + continue; + } + + return { + workflowId: run.workflowId, + evalResult: run.evalResult, + runIndex, + }; + } + + return undefined; +} diff --git a/packages/@n8n/instance-ai/evaluations/export-latest-verifier-request.ts b/packages/@n8n/instance-ai/evaluations/export-latest-verifier-request.ts new file mode 100644 index 00000000000..10c18bcb695 --- /dev/null +++ b/packages/@n8n/instance-ai/evaluations/export-latest-verifier-request.ts @@ -0,0 +1,412 @@ +import { jsonParse } from 'n8n-workflow'; +import { execFileSync } from 'node:child_process'; +import { mkdirSync, readFileSync, writeFileSync } from 'node:fs'; +import path from 'node:path'; + +import { + findStoredTestCaseResult, + findStoredVerifierRun, + type StoredEvalResults, +} from './eval-results-artifact'; +import { MOCK_EXECUTION_VERIFY_PROMPT } from './system-prompts/mock-execution-verify'; + +type Scenario = { + name: string; + description: string; + dataSetup: string; + successCriteria: string; +}; + +type ConversationTurn = { + role: 'user' | 'assistant'; + text: string; +}; + +type WorkflowTestCaseJson = { + conversation?: ConversationTurn[]; + scenarios?: Scenario[]; + executionScenarios?: Scenario[]; +}; + +type EvalNodeResult = { + output?: unknown; + interceptedRequests: Array<{ + url: string; + method: string; + requestBody?: unknown; + mockResponse?: unknown; + }>; + executionMode: 'mocked' | 'pinned' | 'real'; + startTime?: number; + configIssues?: Record<string, string[]>; + outputCount?: number; +}; + +type EvalResult = { + success: boolean; + nodeResults: Record<string, EvalNodeResult>; + errors: string[]; + hints: { + warnings: string[]; + triggerContent: Record<string, unknown>; + }; +}; + +type WorkflowNode = { + name?: string; + type: string; + typeVersion?: number; + disabled?: boolean; + parameters?: Record<string, unknown>; +}; + +type WorkflowJson = { + nodes: WorkflowNode[]; + connections: Record<string, unknown>; +}; + +const repoRoot = path.resolve(__dirname, '..', '..', '..', '..'); +const instanceAiRoot = path.resolve(__dirname, '..'); +const dataDir = path.join(instanceAiRoot, '.data'); +const evalResultsPath = path.join(instanceAiRoot, 'eval-results.json'); +const sqliteDbPath = path.join(repoRoot, '.n8n-instance-ai', '.n8n', 'database.sqlite'); + +type CliArgs = { + testCasePath: string; + scenarioName?: string; +}; + +function parseCliArgs(argv: string[]): CliArgs { + let testCasePath: string | undefined; + let scenarioName: string | undefined; + + for (let i = 0; i < argv.length; i++) { + const arg = argv[i]; + switch (arg) { + case '--test-case': + case '--slug': { + const slug = argv[++i]; + if (!slug) throw new Error(`Missing value for ${arg}`); + testCasePath = path.join( + instanceAiRoot, + 'evaluations', + 'data', + 'workflows', + `${slug}.json`, + ); + break; + } + case '--test-case-path': { + const rawPath = argv[++i]; + if (!rawPath) throw new Error('Missing value for --test-case-path'); + testCasePath = path.resolve(process.cwd(), rawPath); + break; + } + case '--scenario': { + scenarioName = argv[++i]; + if (!scenarioName) throw new Error('Missing value for --scenario'); + break; + } + default: + if (arg.startsWith('--')) throw new Error(`Unknown flag: ${arg}`); + if (!scenarioName) { + scenarioName = arg; + } else if (!testCasePath) { + testCasePath = path.join( + instanceAiRoot, + 'evaluations', + 'data', + 'workflows', + `${arg}.json`, + ); + } else { + throw new Error(`Unexpected positional argument: ${arg}`); + } + } + } + + return { + testCasePath: + testCasePath ?? + path.join( + instanceAiRoot, + 'evaluations', + 'data', + 'workflows', + 'cross-team-linear-report.json', + ), + scenarioName, + }; +} + +function buildVerificationArtifact( + scenario: Scenario, + evalResult: EvalResult, + workflowJson: WorkflowJson, +): string { + const sections: string[] = []; + + sections.push( + '## Scenario', + '', + `**Name:** ${scenario.name} — ${scenario.description}`, + `**Data setup:** ${scenario.dataSetup}`, + '', + ); + + const preAnalysis: string[] = []; + if (evalResult.hints.warnings.length > 0) { + for (const warning of evalResult.hints.warnings) { + preAnalysis.push(`⚠ FRAMEWORK ISSUE: ${warning}`); + } + } + if (Object.keys(evalResult.hints.triggerContent).length === 0) { + preAnalysis.push( + '⚠ FRAMEWORK ISSUE: Trigger content is empty — the start node received no input data. All downstream failures are likely caused by this, not by the workflow builder.', + ); + } + + for (const [nodeName, nr] of Object.entries(evalResult.nodeResults)) { + if (nr.configIssues && Object.keys(nr.configIssues).length > 0) { + preAnalysis.push( + `⚠ BUILDER ISSUE: "${nodeName}" has missing config: ${Object.values(nr.configIssues).flat().join('; ')}`, + ); + } + for (const req of nr.interceptedRequests) { + if ( + typeof req.mockResponse === 'object' && + req.mockResponse !== null && + '_evalMockError' in (req.mockResponse as Record<string, unknown>) + ) { + const msg = (req.mockResponse as Record<string, unknown>).message; + const msgStr = typeof msg === 'string' ? msg : 'unknown'; + preAnalysis.push( + `⚠ MOCK ISSUE: "${nodeName}" ${req.method} ${req.url} → mock generation failed: ${msgStr}`, + ); + } + } + } + + if (preAnalysis.length > 0) { + sections.push('## Pre-analysis (automated flags)', '', ...preAnalysis, ''); + } + + const mockedNodes: string[] = []; + const pinnedNodes: string[] = []; + const realNodes: string[] = []; + for (const [nodeName, nr] of Object.entries(evalResult.nodeResults)) { + if (nr.executionMode === 'mocked') mockedNodes.push(nodeName); + else if (nr.executionMode === 'pinned') pinnedNodes.push(nodeName); + else realNodes.push(nodeName); + } + + sections.push( + '## Execution summary', + '', + `**Status:** ${evalResult.success ? 'success' : 'failed'}`, + `**Mocked nodes** (HTTP intercepted, responses generated by LLM): ${mockedNodes.join(', ') || 'none'}`, + `**Pinned nodes** (trigger data provided, not executed): ${pinnedNodes.join(', ') || 'none'}`, + `**Real nodes** (executed with actual logic on mock/pinned data): ${realNodes.join(', ') || 'none'}`, + '', + ); + + if (evalResult.errors.length > 0) { + sections.push('## Errors', '', ...evalResult.errors.map((e) => `- ${e}`), ''); + } + + const nodeConfigs = new Map<string, Record<string, unknown>>(); + for (const node of workflowJson.nodes) { + if (node.name && node.parameters) { + nodeConfigs.set(node.name, { type: node.type, parameters: node.parameters }); + } + } + + const executedNodeNames = new Set(Object.keys(evalResult.nodeResults)); + sections.push('## Workflow structure (all nodes)', ''); + for (const node of workflowJson.nodes) { + const ran = node.name ? executedNodeNames.has(node.name) : false; + const status = ran ? 'EXECUTED' : 'DID NOT RUN'; + sections.push(`- **${node.name ?? '(unnamed)'}** (${node.type}) — ${status}`); + } + sections.push(''); + sections.push( + '**All node configs** (from saved workflow JSON, including nodes that did not run):', + ); + sections.push( + '```json', + JSON.stringify( + workflowJson.nodes.map((node) => ({ + name: node.name ?? '(unnamed)', + type: node.type, + typeVersion: node.typeVersion, + ...(node.disabled !== undefined ? { disabled: node.disabled } : {}), + parameters: node.parameters ?? {}, + })), + null, + 2, + ), + '```', + ); + sections.push(''); + sections.push('**Connections:**'); + sections.push('```json', JSON.stringify(workflowJson.connections, null, 2), '```'); + sections.push(''); + + sections.push('## Execution trace', ''); + const sortedNodeResults = Object.entries(evalResult.nodeResults).sort( + ([, a], [, b]) => (a.startTime ?? 0) - (b.startTime ?? 0), + ); + for (const [nodeName, nr] of sortedNodeResults) { + sections.push(`### ${nodeName} [${nr.executionMode}]`); + const nodeConfig = nodeConfigs.get(nodeName); + if (nodeConfig) { + sections.push('**Node config:**'); + sections.push('```json', JSON.stringify(nodeConfig, null, 2), '```'); + } + if (nr.configIssues && Object.keys(nr.configIssues).length > 0) { + sections.push(`**Config issues:** ${Object.values(nr.configIssues).flat().join('; ')}`); + } + for (const req of nr.interceptedRequests) { + sections.push(`**Request:** ${req.method} ${req.url}`); + if (req.requestBody) { + sections.push('```json', JSON.stringify(req.requestBody, null, 2), '```'); + } + if (req.mockResponse !== undefined) { + sections.push('**Mock response:**'); + sections.push('```json', JSON.stringify(req.mockResponse, null, 2), '```'); + } + } + if (nr.output !== null && nr.output !== undefined) { + sections.push('**Output:**'); + sections.push('```json', JSON.stringify(nr.output, null, 2), '```'); + } else { + sections.push('**Output:** none'); + } + sections.push(''); + } + + return sections.join('\n'); +} + +function readJson<T>(filePath: string): T { + return jsonParse<T>(readFileSync(filePath, 'utf8')); +} + +function querySqlite(sql: string): string { + return execFileSync('sqlite3', [sqliteDbPath, sql], { encoding: 'utf8' }).trim(); +} + +function getScenarios(testCase: WorkflowTestCaseJson): Scenario[] { + return testCase.executionScenarios ?? testCase.scenarios ?? []; +} + +function getTestCasePrompt(testCase: WorkflowTestCaseJson): string | undefined { + return testCase.conversation?.[0]?.text; +} + +function getSerializedTestCaseName(testCase: WorkflowTestCaseJson): string | undefined { + return getTestCasePrompt(testCase)?.slice(0, 70); +} + +function getWorkflowJson(workflowId: string): WorkflowJson { + const row = querySqlite( + `select json_object('nodes', json(nodes), 'connections', json(connections)) from workflow_entity where id='${workflowId}';`, + ); + if (!row) throw new Error(`Workflow ${workflowId} not found in sqlite db`); + return jsonParse<WorkflowJson>(row); +} + +function main(): void { + const args = parseCliArgs(process.argv.slice(2)); + const testCase = readJson<WorkflowTestCaseJson>(args.testCasePath); + const scenarios = getScenarios(testCase); + const scenarioName = args.scenarioName ?? scenarios[0]?.name; + if (!scenarioName) throw new Error(`No scenarios found in ${args.testCasePath}`); + const scenario = scenarios.find((item) => item.name === scenarioName); + if (!scenario) throw new Error(`Scenario "${scenarioName}" not found in ${args.testCasePath}`); + const evalResults = readJson<StoredEvalResults<EvalResult>>(evalResultsPath); + const storedTestCase = findStoredTestCaseResult( + evalResults, + args.testCasePath, + getSerializedTestCaseName(testCase), + ); + const storedRun = findStoredVerifierRun(storedTestCase, scenarioName); + if (!storedRun) { + throw new Error( + `eval-results.json does not include a workflowId and evalResult for scenario "${scenarioName}" in test case "${getSerializedTestCaseName(testCase) ?? args.testCasePath}". Re-run the workflow evals with this branch.`, + ); + } + + const workflowJson = getWorkflowJson(storedRun.workflowId); + const checklist = [ + { + id: 1, + description: scenario.successCriteria, + category: 'execution', + strategy: 'llm', + }, + ]; + const evalResult = storedRun.evalResult; + const artifact = buildVerificationArtifact(scenario, evalResult, workflowJson); + const userMessage = `## Checklist\n\n${JSON.stringify(checklist, null, 2)}\n\n## Verification Artifact\n\n${artifact}\n\nVerify each checklist item against the artifact above.`; + + const requestBody = { + model: (process.env.N8N_INSTANCE_AI_MODEL ?? 'openai/gpt-5.5').split('/').at(-1) ?? 'gpt-5.5', + input: [ + { + role: 'developer', + content: MOCK_EXECUTION_VERIFY_PROMPT, + }, + { + role: 'user', + content: [ + { + type: 'input_text', + text: userMessage, + }, + ], + }, + ], + text: { + format: { + type: 'json_schema', + strict: true, + name: 'response', + schema: { + type: 'object', + properties: { + results: { + type: 'array', + items: { + type: 'object', + properties: { + id: { type: 'number' }, + pass: { type: 'boolean' }, + reasoning: { type: 'string' }, + failureCategory: { type: ['string', 'null'] }, + rootCause: { type: ['string', 'null'] }, + }, + required: ['id', 'pass', 'reasoning', 'failureCategory', 'rootCause'], + additionalProperties: false, + }, + }, + }, + required: ['results'], + additionalProperties: false, + $schema: 'http://json-schema.org/draft-07/schema#', + }, + }, + }, + }; + + mkdirSync(dataDir, { recursive: true }); + const outputPath = path.join(dataDir, `openai-verifier-request-${scenarioName}.json`); + writeFileSync(outputPath, JSON.stringify(requestBody, null, 2)); + console.log(outputPath); +} + +if (require.main === module) { + main(); +} + +export { getScenarios }; diff --git a/packages/@n8n/instance-ai/evaluations/harness/capture-run-debug.ts b/packages/@n8n/instance-ai/evaluations/harness/capture-run-debug.ts new file mode 100644 index 00000000000..95aa7596c18 --- /dev/null +++ b/packages/@n8n/instance-ai/evaluations/harness/capture-run-debug.ts @@ -0,0 +1,49 @@ +import type { InstanceAiRunDebugResponse } from '@n8n/api-types'; +import pLimit from 'p-limit'; + +import type { EvalLogger } from './logger'; +import type { N8nClient } from '../clients/n8n-client'; + +const RUN_FETCH_CONCURRENCY = 4; + +export async function captureThreadRunDebug( + client: N8nClient, + threadId: string, + logger?: EvalLogger, +): Promise<InstanceAiRunDebugResponse[]> { + try { + const response = await client.listThreadDebugRuns(threadId); + const runs = response.runs ?? []; + if (runs.length === 0) { + logger?.verbose(` No run debug records for thread ${threadId}`); + return []; + } + + const limit = pLimit(RUN_FETCH_CONCURRENCY); + const records = await Promise.all( + runs.map( + async (summary) => + await limit(async (): Promise<InstanceAiRunDebugResponse | null> => { + try { + const record = await client.getRunDebug(summary.runId); + return summary.label ? { ...record, label: summary.label } : record; + } catch (error: unknown) { + logger?.warn( + ` Run debug fetch failed for ${summary.runId}: ${error instanceof Error ? error.message : String(error)}`, + ); + return null; + } + }), + ), + ); + + return records + .filter((record): record is InstanceAiRunDebugResponse => record !== null) + .sort((a, b) => a.startedAt - b.startedAt); + } catch (error: unknown) { + logger?.warn( + ` Run debug capture skipped for thread ${threadId}: ${error instanceof Error ? error.message : String(error)}`, + ); + return []; + } +} diff --git a/packages/@n8n/instance-ai/evaluations/harness/chat-loop.ts b/packages/@n8n/instance-ai/evaluations/harness/chat-loop.ts index eecb42b2200..a51a3ec0a26 100644 --- a/packages/@n8n/instance-ai/evaluations/harness/chat-loop.ts +++ b/packages/@n8n/instance-ai/evaluations/harness/chat-loop.ts @@ -17,6 +17,7 @@ import type { EvalLogger } from './logger'; import type { N8nClient } from '../clients/n8n-client'; import { consumeSseStream } from '../clients/sse-client'; import type { CapturedEvent } from '../types'; +import { USER_TURN_EVENT } from '../types'; import { getEventPayload, tryInfrastructureResponse } from '../utils/confirmation-payload'; import { getNestedRecord } from '../utils/safe-extract'; @@ -29,6 +30,25 @@ export const POLL_INTERVAL_MS = 500; export const BACKGROUND_TASK_POLL_INTERVAL_MS = 2_000; export const MAX_CONFIRMATION_RETRIES = 5; +/** + * Inject a marker into the captured event stream at each user-message send so + * the transcript can group all of a message's runs — including agent *resumes*, + * which each emit their own `run-start` — under the one message that triggered + * them. Without this, runs are aligned to messages positionally and a single + * message that spans a resume shifts every later message by one turn. + * + * Pushed synchronously just before `sendMessage`; `waitForAllActivity` has already + * drained the prior run (incl. the `SSE_SETTLE_DELAY_MS` settle), so the marker + * reliably precedes the next run's events rather than racing a straggler. + */ +export function recordUserTurn(events: CapturedEvent[], text: string): void { + events.push({ + timestamp: Date.now(), + type: USER_TURN_EVENT, + data: { type: USER_TURN_EVENT, payload: { text } }, + }); +} + // --------------------------------------------------------------------------- // SSE connection // --------------------------------------------------------------------------- @@ -217,6 +237,7 @@ export async function runMultiTurnConversation(config: MultiTurnConfig): Promise config.logger.verbose( `[multi-turn] Sending follow-up: ${decision.message.slice(0, 80)}${decision.message.length > 80 ? '...' : ''}`, ); + recordUserTurn(config.events, decision.message); try { await config.client.sendMessage(config.threadId, decision.message); } catch (error: unknown) { @@ -287,12 +308,6 @@ export function buildAutoApprovePayload(event: CapturedEvent): InstanceAiConfirm return { kind: 'approval', approved: true }; } -function isResourceDecision( - value: string | undefined, -): value is 'denyOnce' | 'allowOnce' | 'allowForSession' { - return value === 'denyOnce' || value === 'allowOnce' || value === 'allowForSession'; -} - // --------------------------------------------------------------------------- // Event helpers // --------------------------------------------------------------------------- diff --git a/packages/@n8n/instance-ai/evaluations/harness/prebuilt-workflows.ts b/packages/@n8n/instance-ai/evaluations/harness/prebuilt-workflows.ts index 6e889a1ca9d..1c16e357889 100644 --- a/packages/@n8n/instance-ai/evaluations/harness/prebuilt-workflows.ts +++ b/packages/@n8n/instance-ai/evaluations/harness/prebuilt-workflows.ts @@ -76,7 +76,7 @@ export function pickPrebuiltWorkflowId( * * `createdWorkflowIds` is intentionally left empty: cleanupBuild() iterates * that array and would delete the workflow otherwise. Prebuilt workflows - * are owned by the caller, not the eval run. + * are owned by the caller unless they opt into cleanupPrebuiltWorkflows(). */ export async function fetchPrebuiltBuild( client: N8nClient, @@ -103,3 +103,28 @@ export async function fetchPrebuiltBuild( }; } } + +/** Explicit opt-in cleanup for workflows supplied via --prebuilt-workflows. */ +export async function cleanupPrebuiltWorkflows( + client: N8nClient, + workflowIds: Iterable<string>, + logger: EvalLogger, +): Promise<void> { + const uniqueWorkflowIds = [...new Set(workflowIds)]; + if (uniqueWorkflowIds.length === 0) return; + + let deleted = 0; + for (const workflowId of uniqueWorkflowIds) { + try { + await client.deleteWorkflow(workflowId); + deleted++; + } catch (error) { + const message = error instanceof Error ? error.message : String(error); + logger.warn(`Failed to delete prebuilt workflow ${workflowId}: ${message}`); + } + } + + logger.info( + `Deleted ${String(deleted)}/${String(uniqueWorkflowIds.length)} prebuilt workflow(s)`, + ); +} diff --git a/packages/@n8n/instance-ai/evaluations/harness/redact.ts b/packages/@n8n/instance-ai/evaluations/harness/redact.ts index d384e54bf4a..6e9dd2fa568 100644 --- a/packages/@n8n/instance-ai/evaluations/harness/redact.ts +++ b/packages/@n8n/instance-ai/evaluations/harness/redact.ts @@ -48,6 +48,31 @@ export function redactSecrets(value: unknown, depth = 0): unknown { return value; } +// Content-based redaction: `redactSecrets` only masks secret-shaped keys, but a +// tool error arrives as a flat string where a token can sit inline. Order matters. +const SECRET_TEXT_PATTERNS: ReadonlyArray<readonly [RegExp, string]> = [ + // Authorization header: keep the scheme word, mask the credential token. + [ + /\b((?:proxy-)?authorization\s*[:=]\s*)((?:bearer|basic|digest|negotiate)\s+)?\S+/gi, + '$1$2[REDACTED]', + ], + // Standalone "Bearer <token>" / "Basic <creds>". + [/\b(bearer|basic)\s+[\w.+/=~-]+/gi, '$1 [REDACTED]'], + // Secret-shaped key/value pairs: "api_key=abc", '"token":"abc"'. + [ + /\b(api[-_]?key|access[-_]?key|x-api-key|access[-_]?token|refresh[-_]?token|client[-_]?secret|private[-_]?key|secret|token|password|passwd|cookie|set-cookie|session[-_]?id)("?\s*[:=]\s*"?)[^\s"',&}]+/gi, + '$1$2[REDACTED]', + ], +]; + +/** Mask secrets embedded inline in free text (e.g. a token in a tool-error string). */ +export function redactSecretsInText(text: string): string { + return SECRET_TEXT_PATTERNS.reduce( + (acc, [pattern, replacement]) => acc.replace(pattern, replacement), + text, + ); +} + /** * Truncates serializable values to a max stringified length, redacting * secrets first. Returns the redacted value when it fits, the truncated diff --git a/packages/@n8n/instance-ai/evaluations/harness/runner.ts b/packages/@n8n/instance-ai/evaluations/harness/runner.ts index 0f8a5010a11..91c83e422ec 100644 --- a/packages/@n8n/instance-ai/evaluations/harness/runner.ts +++ b/packages/@n8n/instance-ai/evaluations/harness/runner.ts @@ -8,28 +8,37 @@ import type { InstanceAiConfirmRequest, InstanceAiEvalExecutionResult } from '@n8n/api-types'; import crypto from 'node:crypto'; +import { mkdir, writeFile } from 'node:fs/promises'; +import path from 'node:path'; import { setTimeout as delay } from 'node:timers/promises'; +import { captureThreadRunDebug } from './capture-run-debug'; import { SSE_SETTLE_DELAY_MS, startSseConnection, waitForAllActivity, runMultiTurnConversation, + recordUserTurn, type ConfirmationStrategy, } from './chat-loop'; import { type EvalLogger } from './logger'; import { fetchPrebuiltBuild } from './prebuilt-workflows'; +import { buildWorkflowContextBlock } from './workflow-context'; import { SONNET_MODEL } from '../../src/utils/eval-agents'; import { runBinaryChecks } from '../binaryChecks/index'; import type { BinaryCheckContext, CheckOutcome } from '../binaryChecks/types'; -import { verifyChecklist } from '../checklist/verifier'; +import { allFailVerdicts, verifyBuildExpectations } from '../build-expectations/verifier'; +import { type VerifierAttemptDebug, verifyChecklist } from '../checklist/verifier'; import type { N8nClient, WorkflowResponse } from '../clients/n8n-client'; import { buildConversationMetrics, extractOutcomeFromEvents } from '../outcome/event-parser'; import { buildTranscriptFromEvents } from '../outcome/transcript-from-events'; import { buildAgentOutcome, extractWorkflowIdsFromMessages } from '../outcome/workflow-discovery'; import type { + BuildTrace, ChecklistItem, + ChecklistResult, CapturedEvent, + BuildExpectationResult, ConversationMetrics, ConversationTurn, ExecutionScenarioResult, @@ -46,9 +55,84 @@ import { UserProxyLlm, type ProxyDecisionStats } from '../utils/user-proxy'; // --------------------------------------------------------------------------- const DEFAULT_TIMEOUT_MS = 900_000; +const EVAL_DATA_DIR = path.join(__dirname, '..', '..', '.data'); -/** Max concurrent scenario executions per test case */ -const MAX_CONCURRENT_SCENARIOS = 99; +function getMaxConcurrentScenarios(): number { + const raw = process.env.N8N_EVAL_MAX_CONCURRENT_SCENARIOS; + const parsed = raw ? Number.parseInt(raw, 10) : 4; + return Number.isFinite(parsed) && parsed > 0 ? parsed : 4; +} + +/** + * Max concurrent scenario executions per test case. + * + * Each scenario can trigger multiple LLM calls (mock generation + verifier), + * so effectively-unbounded fan-out causes provider-side throttling and turns + * verifier/model errors into noisy batch-wide failures. + */ +const MAX_CONCURRENT_SCENARIOS = getMaxConcurrentScenarios(); + +function makeArtifactTimestamp(): string { + return new Date().toISOString().replace(/[:.]/g, '-'); +} + +function slugifyArtifactSegment(value: string, fallback: string): string { + const slug = value + .toLowerCase() + .replace(/[^a-z0-9]+/g, '-') + .replace(/^-+|-+$/g, '') + .slice(0, 64); + + return slug.length > 0 ? slug : fallback; +} + +function deriveTestCaseArtifactName(testCase: WorkflowTestCase): string { + return slugifyArtifactSegment(testCase.conversation[0]?.text ?? '', 'workflow'); +} + +async function writeScenarioVerificationSnapshot(input: { + testCaseName: string; + scenarioName: string; + workflowId: string; + passed: boolean; + result: ChecklistResult | undefined; + verificationResults: ChecklistResult[]; + verifierAttempts: VerifierAttemptDebug[]; + buildTrace?: BuildTrace; + logger: EvalLogger; +}): Promise<void> { + const timestamp = makeArtifactTimestamp(); + const fileName = `${slugifyArtifactSegment(input.testCaseName, 'workflow')}_${slugifyArtifactSegment(input.scenarioName, 'scenario')}_${timestamp}.json`; + const filePath = path.join(EVAL_DATA_DIR, fileName); + + try { + await mkdir(EVAL_DATA_DIR, { recursive: true }); + await writeFile( + filePath, + JSON.stringify( + { + timestamp, + workflowId: input.workflowId, + testCaseName: input.testCaseName, + scenarioName: input.scenarioName, + passed: input.passed, + result: input.result ?? null, + verificationResults: input.verificationResults, + verifierAttempts: input.verifierAttempts, + buildTrace: input.buildTrace ?? null, + }, + null, + 2, + ), + 'utf8', + ); + input.logger.verbose(` [${input.scenarioName}] wrote verifier snapshot: ${filePath}`); + } catch (error) { + input.logger.warn( + ` [${input.scenarioName}] failed to write verifier snapshot: ${error instanceof Error ? error.message : String(error)}`, + ); + } +} // --------------------------------------------------------------------------- // Workflow test case runner — build once, run scenarios against it @@ -123,6 +207,9 @@ export async function runWorkflowTestCase( } if (build.threadId) { result.threadId = build.threadId; + if (!config.prebuiltWorkflowId) { + result.runDebug = await captureThreadRunDebug(client, build.threadId, logger); + } } if (build.transcript) { result.transcript = build.transcript; @@ -131,17 +218,37 @@ export async function runWorkflowTestCase( result.workflowChecks = build.workflowChecks; } + // Optional author build expectations — informational, judged concurrently with scenarios. + const wantsExpectations = + (testCase.buildExpectations?.length ?? 0) > 0 && (build.transcript?.length ?? 0) > 0; + const expectationsPromise: Promise<BuildExpectationResult[]> = wantsExpectations + ? verifyBuildExpectations(testCase.buildExpectations!, { + transcript: build.transcript!, + workflowJson: build.workflowJsons[0], + metrics: build.conversationMetrics, + }).catch((error: unknown) => { + logger.warn( + ` Build expectations judge errored: ${error instanceof Error ? error.message : String(error)}`, + ); + return allFailVerdicts(testCase.buildExpectations!, 'judge error'); + }) + : Promise.resolve<BuildExpectationResult[]>([]); + if (!build.success || !build.workflowId) { result.buildError = build.error; + const expectationResults = await expectationsPromise; + if (expectationResults.length > 0) result.buildExpectationResults = expectationResults; return result; } result.workflowBuildSuccess = true; result.workflowId = build.workflowId; result.workflowJson = build.workflowJsons[0]; + result.buildTrace = build.buildTrace; + const testCaseArtifactName = deriveTestCaseArtifactName(testCase); const scenarioStart = Date.now(); - result.executionScenarioResults = await runWithConcurrency( + const scenariosPromise = runWithConcurrency( testCase.executionScenarios, async (scenario) => { try { @@ -152,6 +259,8 @@ export async function runWorkflowTestCase( build.workflowJsons, logger, timeoutMs, + testCaseArtifactName, + build.buildTrace, config.pinAiRoots, ); } catch (error: unknown) { @@ -167,6 +276,12 @@ export async function runWorkflowTestCase( }, MAX_CONCURRENT_SCENARIOS, ); + const [scenarioResults, expectationResults] = await Promise.all([ + scenariosPromise, + expectationsPromise, + ]); + result.executionScenarioResults = scenarioResults; + if (expectationResults.length > 0) result.buildExpectationResults = expectationResults; const scenarioMs = Date.now() - scenarioStart; logger.info( @@ -220,6 +335,7 @@ async function driveMultiTurnConversation( return decision; }; + recordUserTurn(config.events, openingMessage); await config.client.sendMessage(config.threadId, openingMessage); await runMultiTurnConversation({ @@ -247,6 +363,7 @@ export interface BuildResult { workflowId?: string; workflowJsons: WorkflowResponse[]; error?: string; + buildTrace?: BuildTrace; /** IDs to pass to cleanupBuild() */ createdWorkflowIds: string[]; createdDataTableIds: string[]; @@ -280,6 +397,12 @@ export interface BuildWorkflowConfig { logger: EvalLogger; /** Optional " [lane N/M]" suffix appended to the build log line. */ laneTag?: string; + /** + * Last-resort workflow discovery by list-diffing visible workflows. Keep this + * disabled for normal eval runs because concurrent builds make the diff + * non-attributable. + */ + allowWorkflowListDiffFallback?: boolean; /** Let callers that own their own scoring avoid duplicate binary checks. */ skipWorkflowChecks?: boolean; } @@ -299,7 +422,7 @@ function isMultiTurnConversation(conversation: ConversationTurn[]): boolean { export async function buildWorkflow(config: BuildWorkflowConfig): Promise<BuildResult> { const { client, conversation, logger } = config; const openingMessage = conversation[0]?.text ?? ''; - const threadId = `eval-${crypto.randomUUID()}`; + const threadId = crypto.randomUUID(); const startTime = Date.now(); const timeoutMs = config.timeoutMs ?? DEFAULT_TIMEOUT_MS; @@ -316,7 +439,8 @@ export async function buildWorkflow(config: BuildWorkflowConfig): Promise<BuildR ` Building workflow${isMultiTurn ? ' [multi-turn]' : ''}: "${truncate(openingMessage, 60)}"${config.laneTag ?? ''}`, ); - await client.ensureThread(threadId); + const projectId = await client.getPersonalProjectId(); + await client.ensureThread(threadId, projectId); const ssePromise = startSseConnection(client, threadId, events, abortController.signal).catch( () => {}, @@ -340,6 +464,7 @@ export async function buildWorkflow(config: BuildWorkflowConfig): Promise<BuildR followUpMessagesOut: followUpMessages, }); } else { + recordUserTurn(events, openingMessage); await client.sendMessage(threadId, openingMessage); await waitForAllActivity({ client, @@ -373,21 +498,20 @@ export async function buildWorkflow(config: BuildWorkflowConfig): Promise<BuildR const messageWorkflowIds = extractWorkflowIdsFromMessages(threadMessages.messages); const eventOutcome = extractOutcomeFromEvents(events); + const threadWorkflowIds = [...new Set([...eventOutcome.workflowIds, ...messageWorkflowIds])]; + const buildTrace: BuildTrace = { + finalText: eventOutcome.finalText, + toolCalls: eventOutcome.toolCalls, + agentActivities: eventOutcome.agentActivities, + }; const outcome = await buildAgentOutcome( client, - eventOutcome, + { ...eventOutcome, workflowIds: threadWorkflowIds }, config.preRunWorkflowIds, config.claimedWorkflowIds, + { allowListDiffFallback: config.allowWorkflowListDiffFallback === true }, ); - if (messageWorkflowIds.length > 0) { - const messageWfSet = new Set(messageWorkflowIds); - outcome.workflowsCreated = outcome.workflowsCreated.filter((wf) => messageWfSet.has(wf.id)); - outcome.workflowJsons = outcome.workflowJsons.filter( - (wf) => typeof wf.id === 'string' && messageWfSet.has(wf.id), - ); - } - if (outcome.workflowsCreated.length === 0) { const toolErrors = events .filter((e) => e.type === 'tool-error') @@ -426,6 +550,7 @@ export async function buildWorkflow(config: BuildWorkflowConfig): Promise<BuildR success: false, error: buildError, workflowJsons: [], + buildTrace, createdWorkflowIds: [], createdDataTableIds: outcome.dataTablesCreated, conversationMetrics, @@ -439,7 +564,7 @@ export async function buildWorkflow(config: BuildWorkflowConfig): Promise<BuildR const buildMs = Date.now() - buildStart; const proxySuffix = formatProxyStatsSuffix(proxyDecisionStats); logger.info( - ` Workflow built: ${outcome.workflowsCreated[0].name} (${String(outcome.workflowsCreated[0].nodeCount)} nodes) [${String(Math.round(buildMs / 1000))}s]${isMultiTurn ? ` (${String(conversationMetrics.turnCount)} turn${conversationMetrics.turnCount === 1 ? '' : 's'})` : ''}${proxySuffix}`, + ` Workflow built: ${outcome.workflowsCreated[0].name} (${String(outcome.workflowsCreated[0].nodeCount)} nodes) [${String(Math.round(buildMs / 1000))}s]${isMultiTurn ? ` (${String(conversationMetrics.turnCount)} turn${conversationMetrics.turnCount === 1 ? '' : 's'})` : ''}${proxySuffix} [thread ${threadId}]`, ); const workflowChecks = config.skipWorkflowChecks @@ -455,6 +580,7 @@ export async function buildWorkflow(config: BuildWorkflowConfig): Promise<BuildR success: true, workflowId: outcome.workflowsCreated[0].id, workflowJsons: outcome.workflowJsons, + buildTrace, createdWorkflowIds: outcome.workflowsCreated.map((wf) => wf.id), createdDataTableIds: outcome.dataTablesCreated, conversationMetrics, @@ -498,6 +624,8 @@ export async function executeScenario( workflowJsons: WorkflowResponse[], logger: EvalLogger, timeoutMs?: number, + testCaseName?: string, + buildTrace?: BuildTrace, pinAiRoots?: string[], ): Promise<ExecutionScenarioResult> { return await runScenario( @@ -507,6 +635,8 @@ export async function executeScenario( workflowJsons, logger, timeoutMs, + testCaseName, + buildTrace, pinAiRoots, ); } @@ -555,6 +685,8 @@ async function runScenario( workflowJsons: WorkflowResponse[], logger: EvalLogger, timeoutMs?: number, + testCaseName?: string, + buildTrace?: BuildTrace, pinAiRoots?: string[], ): Promise<ExecutionScenarioResult> { const pinNodes = pinAiRoots && pinAiRoots.length > 0 ? pinAiRoots : undefined; @@ -585,11 +717,23 @@ async function runScenario( }, ]; - const verificationResults = await verifyChecklist(scenarioChecklist, artifact); + const verification = await verifyChecklist(scenarioChecklist, artifact); + const verificationResults = verification.results; const verifyMs = Date.now() - verifyStart; const passed = verificationResults.length > 0 && verificationResults[0].pass; const result = verificationResults[0]; + await writeScenarioVerificationSnapshot({ + testCaseName: testCaseName ?? `workflow-${workflowId}`, + scenarioName: scenario.name, + workflowId, + passed, + result, + verificationResults, + verifierAttempts: verification.attempts, + buildTrace, + logger, + }); const reasoning = result?.reasoning ?? 'No verification result — LLM verifier returned empty'; const failureCategory = result?.failureCategory ?? (result ? undefined : 'verification_failure'); const rootCause = result?.rootCause; @@ -624,40 +768,29 @@ export interface VerificationArtifact { scenarioContext: string; } -/** Render the per-build workflow structure: nodes, connections, all configs. */ -function buildWorkflowContextBlock(wf: WorkflowResponse | undefined): string { - if (!wf) return '## Workflow structure\n\n(no workflow built)'; - const lines: string[] = ['## Workflow structure', '']; - for (const node of wf.nodes) { - lines.push(`- **${node.name ?? '(unnamed)'}** (${node.type})`); - } - lines.push(''); - lines.push('**All node configs:**'); - lines.push( - '```json', - JSON.stringify( - wf.nodes.map((node) => ({ - name: node.name ?? '(unnamed)', - type: node.type, - typeVersion: node.typeVersion, - ...(node.disabled !== undefined ? { disabled: node.disabled } : {}), - parameters: node.parameters ?? {}, - })), - null, - 2, - ), - '```', - '', - ); - lines.push('**Connections:**'); - lines.push('```json', JSON.stringify(wf.connections, null, 2), '```'); - return lines.join('\n'); -} - function isObjectRecord(v: unknown): v is Record<string, unknown> { return typeof v === 'object' && v !== null && !Array.isArray(v); } +function isNodeOutputs(value: unknown): value is Record<string, unknown[][]> { + if (!isObjectRecord(value)) return false; + return Object.values(value).every( + (branches) => Array.isArray(branches) && branches.every((branch) => Array.isArray(branch)), + ); +} + +function getNodeOutputs(value: unknown): Record<string, unknown[][]> { + return isNodeOutputs(value) ? value : {}; +} + +function getNumber(value: unknown, fallback = 0): number { + return typeof value === 'number' ? value : fallback; +} + +function getOptionalBoolean(value: unknown): boolean | undefined { + return typeof value === 'boolean' ? value : undefined; +} + /** For a given node + connection type, return downstream node names per output port. */ function getDownstreamsByBranch( nodeName: string, @@ -832,14 +965,17 @@ function buildScenarioContextBlock( if (req.requestBody) { sections.push('```json', JSON.stringify(req.requestBody, null, 2), '```'); } - if (req.mockResponse) { + if (req.mockResponse !== undefined) { sections.push('**Mock response:**'); sections.push('```json', JSON.stringify(req.mockResponse, null, 2), '```'); } } + const nodeOutputs = getNodeOutputs(nr.outputs); + const outputCount = getNumber(nr.outputCount); + const truncated = getOptionalBoolean(nr.truncated); sections.push( - ...renderNodeOutputs(nodeName, nr.outputs, nr.outputCount, nr.truncated, wf?.connections), + ...renderNodeOutputs(nodeName, nodeOutputs, outputCount, truncated, wf?.connections), ); sections.push(''); diff --git a/packages/@n8n/instance-ai/evaluations/harness/workflow-context.ts b/packages/@n8n/instance-ai/evaluations/harness/workflow-context.ts new file mode 100644 index 00000000000..a7eee11f077 --- /dev/null +++ b/packages/@n8n/instance-ai/evaluations/harness/workflow-context.ts @@ -0,0 +1,33 @@ +import type { WorkflowResponse } from '../clients/n8n-client'; + +/** Render the per-build workflow structure: nodes, connections, all configs. */ +export function buildWorkflowContextBlock(wf: WorkflowResponse | undefined): string { + if (!wf) return '## Workflow structure\n\n(no workflow built)'; + const lines: string[] = ['## Workflow structure', '']; + for (const node of wf.nodes) { + lines.push(`- **${node.name ?? '(unnamed)'}** (${node.type})`); + } + lines.push(''); + lines.push('**All node configs:**'); + lines.push( + '```json', + JSON.stringify( + wf.nodes.map((node) => ({ + name: node.name ?? '(unnamed)', + type: node.type, + typeVersion: node.typeVersion, + ...(node.disabled !== undefined ? { disabled: node.disabled } : {}), + ...(node.onError !== undefined ? { onError: node.onError } : {}), + ...(node.credentials !== undefined ? { credentials: node.credentials } : {}), + parameters: node.parameters ?? {}, + })), + null, + 2, + ), + '```', + '', + ); + lines.push('**Connections:**'); + lines.push('```json', JSON.stringify(wf.connections, null, 2), '```'); + return lines.join('\n'); +} diff --git a/packages/@n8n/instance-ai/evaluations/index.ts b/packages/@n8n/instance-ai/evaluations/index.ts index 99b02cd00fc..51ba24312bc 100644 --- a/packages/@n8n/instance-ai/evaluations/index.ts +++ b/packages/@n8n/instance-ai/evaluations/index.ts @@ -17,6 +17,10 @@ export type { WorkflowTestCaseWithFile } from './data/workflows'; export { seedCredentials, cleanupCredentials } from './credentials/seeder'; export type { SeedResult } from './credentials/seeder'; +// -- MCP Registry -- +export { seedMcpRegistry } from './mcp-registry/seeder'; +export type { McpRegistrySeedResult } from './mcp-registry/seeder'; + // -- Runner (all-in-one) -- export { runWorkflowTestCase, runWithConcurrency } from './harness/runner'; diff --git a/packages/@n8n/instance-ai/evaluations/mcp-registry/seeder.ts b/packages/@n8n/instance-ai/evaluations/mcp-registry/seeder.ts new file mode 100644 index 00000000000..e6c13cc5e85 --- /dev/null +++ b/packages/@n8n/instance-ai/evaluations/mcp-registry/seeder.ts @@ -0,0 +1,46 @@ +// --------------------------------------------------------------------------- +// MCP registry seeding for evaluation runs +// +// The MCP registry catalog drives the synthetic registry nodes (Notion MCP, +// Linear MCP, etc.) that workflow-builder evals depend on. In production the +// catalog is fetched from the n8n.io Strapi API on the leader instance — but +// the fire-and-forget boot fetch swallows errors, so an eval run can otherwise +// silently start with an empty catalog and no MCP nodes available to the +// builder agent. +// +// This seeder calls the test endpoint to deterministically upsert the Notion + +// Linear mock entries and trigger a node-type reload. Best-effort and +// idempotent — multiple calls are no-ops. +// +// Requires the n8n server to be running with E2E_TESTS=true so the test +// controller is mounted. CI containers already set this; local dev does not by +// default. +// --------------------------------------------------------------------------- + +import type { N8nClient } from '../clients/n8n-client'; +import type { EvalLogger } from '../harness/logger'; + +export interface McpRegistrySeedResult { + seeded: boolean; + count: number; +} + +/** + * Seed the MCP registry into the n8n instance for evaluation runs. + * + * Non-fatal on failure — the most common cause is `E2E_TESTS=true` not being + * set on the server, which is informative rather than a run-stopper. + */ +export async function seedMcpRegistry( + client: N8nClient, + logger?: EvalLogger, +): Promise<McpRegistrySeedResult> { + try { + const { count } = await client.seedMcpRegistry(); + return { seeded: true, count }; + } catch (error) { + const message = error instanceof Error ? error.message : String(error); + logger?.verbose(` Skipping MCP registry seed: ${message}`); + return { seeded: false, count: 0 }; + } +} diff --git a/packages/@n8n/instance-ai/evaluations/outcome/event-parser.ts b/packages/@n8n/instance-ai/evaluations/outcome/event-parser.ts index 72a5f0e6e39..b468e161d93 100644 --- a/packages/@n8n/instance-ai/evaluations/outcome/event-parser.ts +++ b/packages/@n8n/instance-ai/evaluations/outcome/event-parser.ts @@ -305,7 +305,7 @@ export function buildMetrics(events: CapturedEvent[], startTime: number): Instan // Per-turn conversation metrics // --------------------------------------------------------------------------- -const PLAN_RECOVERY_TOOL_NAMES = new Set(['plan', 'planWithAgent', 'plan-with-agent']); +const PLAN_RECOVERY_TOOL_NAMES = new Set(['create-tasks']); export function buildConversationMetrics(events: CapturedEvent[]): ConversationMetrics { const turns = splitEventsIntoTurns(events); diff --git a/packages/@n8n/instance-ai/evaluations/outcome/transcript-from-events.ts b/packages/@n8n/instance-ai/evaluations/outcome/transcript-from-events.ts index d09fd1d31e7..a633ba874c6 100644 --- a/packages/@n8n/instance-ai/evaluations/outcome/transcript-from-events.ts +++ b/packages/@n8n/instance-ai/evaluations/outcome/transcript-from-events.ts @@ -13,12 +13,16 @@ import type { AskUserQuestion, CapturedEvent, PlanTask, + SetupCardRequest, SetupWizardCompletedNode, SetupWizardSkippedNode, ToolInteraction, + TranscriptStep, TranscriptTurn, } from '../types'; +import { USER_TURN_EVENT } from '../types'; import { splitEventsIntoTurns } from './event-parser'; +import { redactSecrets, redactSecretsInText } from '../harness/redact'; import { getNestedRecord as getRecord, getString, isRecord } from '../utils/safe-extract'; type ProxyResponses = Map<string, InstanceAiConfirmRequest>; @@ -34,20 +38,57 @@ export function buildTranscriptFromEvents(opts: BuildTranscriptOptions): Transcr const { events, openingMessage, followUpMessages = [], proxyResponses } = opts; if (events.length === 0) return []; + const turns: TranscriptTurn[] = []; + + // Preferred path: the harness injected a USER_TURN_EVENT marker at each send, + // so each turn is one user message plus every run it triggered (agent resumes + // included) — no positional drift between messages and runs. + if (events.some((e) => e.type === USER_TURN_EVENT)) { + for (const segment of splitEventsByUserTurn(events)) { + const turn = buildTurn(segment.events, segment.userMessage, proxyResponses); + if (turn.userMessage || turn.steps.length > 0) turns.push(turn); + } + return turns; + } + + // Fallback (no markers, e.g. legacy captures): align messages to run-start + // turns positionally. const userMessages: string[] = []; if (openingMessage) userMessages.push(openingMessage); userMessages.push(...followUpMessages); - - const turns: TranscriptTurn[] = []; for (const turnEvents of splitEventsIntoTurns(events)) { const turn = buildTurn(turnEvents, userMessages.shift(), proxyResponses); - if (turn.userMessage || turn.agentText || turn.toolInteractions.length > 0) { - turns.push(turn); - } + if (turn.userMessage || turn.steps.length > 0) turns.push(turn); } return turns; } +/** Split events into per-user-message turns using the injected USER_TURN_EVENT + * markers. Each turn carries the message text and all events up to the next + * marker — spanning any number of agent runs/resumes. */ +function splitEventsByUserTurn( + events: CapturedEvent[], +): Array<{ userMessage?: string; events: CapturedEvent[] }> { + const turns: Array<{ userMessage?: string; events: CapturedEvent[] }> = []; + let current: { userMessage?: string; events: CapturedEvent[] } | null = null; + for (const event of events) { + if (event.type === USER_TURN_EVENT) { + if (current) turns.push(current); + current = { userMessage: extractUserTurnText(event), events: [] }; + } else { + current ??= { userMessage: undefined, events: [] }; + current.events.push(event); + } + } + if (current) turns.push(current); + return turns; +} + +function extractUserTurnText(event: CapturedEvent): string | undefined { + const payload = getRecord(event.data, 'payload'); + return payload ? getString(payload, 'text') : undefined; +} + // --------------------------------------------------------------------------- // Per-turn assembly // @@ -63,81 +104,122 @@ function buildTurn( userMessage: string | undefined, proxyResponses: ProxyResponses | undefined, ): TranscriptTurn { - const textChunks: string[] = []; - const toolInteractions: ToolInteraction[] = []; - const seenPlainTools = new Set<string>(); + const steps: TranscriptStep[] = []; + const outcomeByCallId = collectToolOutcomes(events); + let textBuffer = ''; + + const flushText = () => { + if (textBuffer.length > 0) { + steps.push({ kind: 'agent-text', text: textBuffer }); + textBuffer = ''; + } + }; for (const event of events) { if (event.type === 'text-delta') { const text = getString(event.data, 'text') ?? getString(getRecord(event.data, 'payload') ?? {}, 'text'); - if (text) textChunks.push(text); + if (text) textBuffer += text; continue; } + let interaction: ToolInteraction | null = null; + // A tool call or confirmation is an action boundary: flush the narration + // before it even when the action itself doesn't render a step, so distinct + // thoughts never fuse across a dropped/empty interaction. + let isActionBoundary = false; if (event.type === 'tool-call') { - handleToolCall(event, toolInteractions, seenPlainTools); - continue; + interaction = interpretToolCall(event, outcomeByCallId); + isActionBoundary = true; + } else if (event.type === 'tool-result') { + interaction = interpretToolResult(event); + } else if (event.type === 'confirmation-request') { + interaction = interpretConfirmationRequest(event, proxyResponses); + isActionBoundary = true; } - if (event.type === 'tool-result') { - handleToolResult(event, toolInteractions); - continue; - } - - if (event.type === 'confirmation-request') { - handleConfirmationRequest(event, proxyResponses, toolInteractions); - continue; - } + if (isActionBoundary || interaction) flushText(); + if (interaction) steps.push(interaction); } - return { - userMessage, - agentText: textChunks.join(''), - toolInteractions, - }; + flushText(); + return { userMessage, steps }; } -function handleToolCall( +interface ToolOutcome { + result?: unknown; + error?: string; +} + +/** Pair every tool result/error in the turn to its originating call by toolCallId. */ +function collectToolOutcomes(events: CapturedEvent[]): Map<string, ToolOutcome> { + const map = new Map<string, ToolOutcome>(); + for (const event of events) { + if (event.type !== 'tool-result' && event.type !== 'tool-error') continue; + const payload = getRecord(event.data, 'payload') ?? event.data; + const callId = getString(payload, 'toolCallId'); + if (!callId) continue; + if (event.type === 'tool-error') { + // Flat string, so content-scrub (key-based redaction can't reach an inline token). + map.set(callId, { error: redactSecretsInText(getString(payload, 'error') ?? 'tool error') }); + } else { + // Redact secret-shaped keys before the result reaches the report/judge. + map.set(callId, { result: redactSecrets(payload.result) }); + } + } + return map; +} + +function interpretToolCall( event: CapturedEvent, - out: ToolInteraction[], - seenPlainTools: Set<string>, -): void { + outcomeByCallId: Map<string, ToolOutcome>, +): ToolInteraction | null { const payload = getRecord(event.data, 'payload') ?? event.data; const toolName = getString(payload, 'toolName') ?? ''; const args = getRecord(payload, 'args') ?? {}; // ask-user is rendered from the confirmation-request (which has the answers). - if (toolName === 'ask-user') return; + if (toolName === 'ask-user') return null; - if (toolName === 'plan' || toolName === 'add-plan-item') { + if (toolName === 'create-tasks') { const tasks = Array.isArray(args.tasks) ? extractPlanTasks(args.tasks) : []; - if (tasks.length > 0) out.push({ kind: 'plan', tasks }); - return; + if (tasks.length > 0) return { kind: 'plan', tasks }; + // Empty plan: fall through and render as a plain tool-call so the call + // stays visible (1:1 with what happened) instead of vanishing. } - // Plain tool-call — collapsed to one entry per tool name within the turn. - if (!toolName || seenPlainTools.has(toolName)) return; - seenPlainTools.add(toolName); - out.push({ kind: 'tool-call', toolName }); + // Every named call renders — no de-duping, so repeat calls aren't dropped. + if (!toolName) return null; + const callId = getString(payload, 'toolCallId'); + const outcome = callId ? outcomeByCallId.get(callId) : undefined; + // `workflows` output is rendered as the setup-wizard block — don't duplicate its result here. + const result = toolName === 'workflows' ? undefined : outcome?.result; + return { + kind: 'tool-call', + toolName, + toolCallId: callId, + args: + Object.keys(args).length > 0 ? (redactSecrets(args) as Record<string, unknown>) : undefined, + result, + error: outcome?.error, + }; } -function handleToolResult(event: CapturedEvent, out: ToolInteraction[]): void { +function interpretToolResult(event: CapturedEvent): ToolInteraction | null { const payload = getRecord(event.data, 'payload') ?? event.data; const toolName = getString(payload, 'toolName') ?? ''; const result = payload.result; if (toolName === 'workflows' && isRecord(result)) { - const interaction = extractSetupWizardOutcome(result); - if (interaction) out.push(interaction); + return extractSetupWizardOutcome(result); } + return null; } -function handleConfirmationRequest( +function interpretConfirmationRequest( event: CapturedEvent, proxyResponses: ProxyResponses | undefined, - out: ToolInteraction[], -): void { +): ToolInteraction | null { const payload = getRecord(event.data, 'payload') ?? {}; const requestId = getString(payload, 'requestId'); const response = requestId ? proxyResponses?.get(requestId) : undefined; @@ -146,24 +228,34 @@ function handleConfirmationRequest( const questions = Array.isArray(payload.questions) ? extractAskUserQuestions(payload.questions) : []; - if (questions.length === 0) return; + if (questions.length === 0) return null; const answers = response?.kind === 'questions' ? extractAskUserAnswers(response.answers) : undefined; - out.push({ kind: 'ask-user', questions, answers }); - return; + return { kind: 'ask-user', questions, answers }; } - // setup wizard suspend — its outcome is rendered from the tool-result instead. - if (Array.isArray(payload.setupRequests)) return; + // Setup card (configure credentials / fill parameters). Render the prompt + // itself — generic across node types and params — so it stays visible even + // when the proxy skips it; the apply outcome, if any, renders separately. + if (Array.isArray(payload.setupRequests)) { + return interpretSetupCard(payload.setupRequests, response); + } const toolName = getString(payload, 'toolName') ?? getString(payload, 'agentId') ?? 'confirmation'; - out.push({ + return { kind: 'confirmation', toolName, resumeReason: inferResumeReason(payload, response), approved: inferApproval(response), - }); + // Plan-review prompts are boilerplate and the plan is rendered separately; + // keep the message only for confirm types where it's specific. + message: + payload.inputType === 'plan-review' + ? undefined + : (getString(payload, 'message') ?? getString(payload, 'introMessage')), + feedback: inferFeedback(response), + }; } // --------------------------------------------------------------------------- @@ -182,6 +274,103 @@ function extractSetupWizardOutcome(result: Record<string, unknown>): ToolInterac return { kind: 'setup-wizard', completedNodes: completed, skippedNodes: skipped, reason }; } +/** + * Render a setup card (a `workflows action:"setup"` suspend) as a transcript + * step. Generic: works for any node type, credential, or set of parameters the + * card surfaces — it reads the node name, the credential type, and the names of + * the parameters the card flags, plus how the proxy responded. + */ +function interpretSetupCard( + rawRequests: unknown[], + response: InstanceAiConfirmRequest | undefined, +): ToolInteraction | null { + const requests = extractSetupCardRequests(rawRequests); + if (requests.length === 0) return null; + const { outcome, filled } = describeSetupCardResponse(response); + return { kind: 'setup-card', requests, outcome, filled }; +} + +function extractSetupCardRequests(raw: unknown[]): SetupCardRequest[] { + const requests: SetupCardRequest[] = []; + for (const item of raw) { + if (!isRecord(item)) continue; + const node = isRecord(item.node) ? item.node : undefined; + // Server payloads nest the name under `node.name`; `nodeName` is only a + // loose fallback for hand-built/partial inputs. + const nodeName = (node ? getString(node, 'name') : undefined) ?? getString(item, 'nodeName'); + const credentialType = getString(item, 'credentialType'); + // The card surfaces `editableParameters` for the user to fill; `parameterIssues` + // is only the subset with validation problems. Union both (editable first) so the + // "the agent asked for X" evidence isn't under-reported. + const editable = Array.isArray(item.editableParameters) + ? item.editableParameters.flatMap((p) => (isRecord(p) ? [getString(p, 'name')] : [])) + : []; + const issues = isRecord(item.parameterIssues) ? Object.keys(item.parameterIssues) : []; + const params = [...new Set([...editable, ...issues].filter((n): n is string => Boolean(n)))]; + requests.push({ + nodeName: nodeName ?? 'node', + credentialType: credentialType ?? undefined, + params: params.length > 0 ? params : undefined, + }); + } + return requests; +} + +function describeSetupCardResponse(response: InstanceAiConfirmRequest | undefined): { + outcome: 'filled' | 'skipped' | 'declined' | 'pending'; + filled?: string[]; +} { + if (!response) return { outcome: 'pending' }; + if (response.kind === 'setupWorkflowApply') { + // An apply (even the empty auto-approve apply) means the user accepted the + // setup — never report "skipped" here; that would contradict the sibling + // setup-wizard outcome reporting those same nodes as completed. + const filled = collectFilledParams(response.nodeParameters); + return { outcome: 'filled', filled: filled.length > 0 ? filled : undefined }; + } + if (response.kind === 'approval' && !response.approved) return { outcome: 'declined' }; + if (response.kind === 'questions') { + const allSkipped = response.answers.length === 0 || response.answers.every((a) => a.skipped); + return allSkipped ? { outcome: 'skipped' } : { outcome: 'filled' }; + } + return { outcome: 'pending' }; +} + +function collectFilledParams(nodeParameters: unknown): string[] { + // Key-based pass first: mask values under secret-shaped names (apiKey, token, …) + // before they're rendered into the transcript/report. + const redacted = redactSecrets(nodeParameters); + if (!isRecord(redacted)) return []; + const filled: string[] = []; + for (const params of Object.values(redacted)) { + if (!isRecord(params)) continue; + for (const [name, value] of Object.entries(params)) { + // Content-based pass: scrub any token inlined in a non-secret-shaped value. + filled.push(redactSecretsInText(`${name}=${formatParamValue(value)}`)); + } + } + return filled; +} + +/** Compact, readable rendering of a filled parameter value (objects → JSON, truncated). */ +function formatParamValue(value: unknown): string { + if (typeof value === 'string') return value.length > 0 ? value : '(empty)'; + // Resource-locator values render the human-readable name (or id), not raw JSON. + if (isRecord(value) && value.__rl === true) { + const name = getString(value, 'cachedResultName'); + if (name && name.length > 0) return name; + const id = getString(value, 'value'); + if (id && id.length > 0) return id; + return '(unset)'; + } + try { + const s = JSON.stringify(value); + return s.length > 80 ? `${s.slice(0, 80)}…` : s; + } catch { + return String(value); + } +} + function inferResumeReason( payload: Record<string, unknown>, response: InstanceAiConfirmRequest | undefined, @@ -198,9 +387,16 @@ function inferResumeReason( function inferApproval(response: InstanceAiConfirmRequest | undefined): boolean | undefined { if (!response) return undefined; if (response.kind === 'approval') return response.approved; + if (response.kind === 'planDeny' || response.kind === 'domainAccessDeny') return false; return true; } +/** Free-text the user attached to their decision (e.g. plan-review feedback via userInput). */ +function inferFeedback(response: InstanceAiConfirmRequest | undefined): string | undefined { + if (response?.kind === 'approval' && response.userInput) return response.userInput; + return undefined; +} + function extractPlanTasks(raw: unknown[]): PlanTask[] { const tasks: PlanTask[] = []; for (const item of raw) { diff --git a/packages/@n8n/instance-ai/evaluations/outcome/workflow-discovery.ts b/packages/@n8n/instance-ai/evaluations/outcome/workflow-discovery.ts index 1cad6d0230a..0ee5f53709a 100644 --- a/packages/@n8n/instance-ai/evaluations/outcome/workflow-discovery.ts +++ b/packages/@n8n/instance-ai/evaluations/outcome/workflow-discovery.ts @@ -30,11 +30,21 @@ export async function snapshotWorkflowIds(client: N8nClient): Promise<Set<string // buildAgentOutcome // --------------------------------------------------------------------------- +export interface BuildAgentOutcomeOptions { + /** + * Last-resort workflow discovery by diffing all workflows visible to the + * lane. This is unsafe under concurrent eval builds because an unrelated + * run can create a workflow while the current thread produces no IDs. + */ + allowListDiffFallback?: boolean; +} + export async function buildAgentOutcome( client: N8nClient, eventOutcome: EventOutcome, preRunWorkflowIds?: Set<string>, claimedWorkflowIds?: Set<string>, + options: BuildAgentOutcomeOptions = {}, ): Promise<AgentOutcome> { const workflowsCreated: WorkflowSummary[] = []; const workflowJsons: WorkflowResponse[] = []; @@ -51,9 +61,10 @@ export async function buildAgentOutcome( } // Diff against pre-run snapshot to find workflows created by background tasks - // that didn't surface in the SSE events we parsed. - // When running concurrently, skip workflows already claimed by another run. - if (preRunWorkflowIds) { + // that didn't surface in the SSE events/messages we parsed. This is a + // single-thread fallback only: in concurrent evals a blocked/no-build thread + // can otherwise claim a workflow created by another test case. + if (preRunWorkflowIds && knownWfIds.size === 0 && options.allowListDiffFallback === true) { try { const currentWorkflows = await client.listWorkflows(); for (const wf of currentWorkflows) { diff --git a/packages/@n8n/instance-ai/evaluations/report/report-anchors.ts b/packages/@n8n/instance-ai/evaluations/report/report-anchors.ts new file mode 100644 index 00000000000..4c444c3587c --- /dev/null +++ b/packages/@n8n/instance-ai/evaluations/report/report-anchors.ts @@ -0,0 +1,10 @@ +import type { WorkflowTestCaseResult } from '../types'; + +function sanitizeAnchor(value: string): string { + return value.replace(/[^a-zA-Z0-9_-]+/g, '-').replace(/^-+|-+$/g, ''); +} + +export function getTestCaseAnchorId(result: WorkflowTestCaseResult, index: number): string { + const base = result.fileSlug ?? `case-${String(index)}`; + return `tc-${sanitizeAnchor(base)}`; +} diff --git a/packages/@n8n/instance-ai/evaluations/report/run-debug-report.ts b/packages/@n8n/instance-ai/evaluations/report/run-debug-report.ts new file mode 100644 index 00000000000..efccbd125c3 --- /dev/null +++ b/packages/@n8n/instance-ai/evaluations/report/run-debug-report.ts @@ -0,0 +1,428 @@ +/** + * HTML report generator for LLM run/step debug captured during workflow evals. + * + * Mirrors the frontend InstanceAiLlmStepsModal layout: runs sidebar, steps + * sidebar, and per-step input/output detail. + */ + +import type { + InstanceAiRunDebugResponse, + InstanceAiRunDebugStep, + InstanceAiRunDebugWorkflowCodeSnapshot, + ReadableContentBlock, + ReadableSegment, +} from '@n8n/api-types'; +import { + formatDebugJson, + parseInputExtras, + parseMessageBlocks, + parseOutputDisplayBlocks, + parseOutputExtras, + parseStepSummary, + parseSystemPromptForDisplay, + parseUsageSummary, +} from '@n8n/api-types'; +import fs from 'fs'; +import path from 'path'; + +import { getTestCaseAnchorId } from './report-anchors'; +import type { WorkflowTestCaseResult } from '../types'; + +// --------------------------------------------------------------------------- +// Helpers +// --------------------------------------------------------------------------- + +function escapeHtml(str: string): string { + return str + .replace(/&/g, '&') + .replace(/</g, '<') + .replace(/>/g, '>') + .replace(/"/g, '"') + .replace(/'/g, '''); +} + +function sanitizeAnchor(value: string): string { + return value.replace(/[^a-zA-Z0-9_-]+/g, '-').replace(/^-+|-+$/g, ''); +} + +function getTestCaseLabel(result: WorkflowTestCaseResult): string { + const prompt = result.testCase.conversation[0]?.text ?? ''; + const iterPrefix = /^\[iter \d+\/\d+\]\s*/.exec(prompt)?.[0] ?? ''; + const truncatedPrompt = prompt.length > 100 ? `${prompt.slice(0, 100)}...` : prompt; + return iterPrefix + (result.fileSlug ?? result.testCase.description ?? truncatedPrompt); +} + +function formatTimestamp(ms: number): string { + try { + return new Date(ms).toLocaleString(); + } catch { + return String(ms); + } +} + +function renderJsonBlock(value: unknown, label?: string): string { + const summary = label ? `<span class="json-label">${escapeHtml(label)}</span>` : ''; + return `<details class="json-panel"><summary>${summary || 'JSON'} ${escapeHtml(formatDebugJson(value).slice(0, 80))}…</summary><pre class="json-block"><code>${escapeHtml(formatDebugJson(value))}</code></pre></details>`; +} + +function renderSegments(segments: ReadableSegment[]): string { + return segments + .map((segment) => { + switch (segment.type) { + case 'text': + return `<p class="segment-text">${escapeHtml(segment.text)}</p>`; + case 'reasoning': + return `<div class="segment-block segment-reasoning"><div class="segment-kind">Reasoning</div><p class="segment-text">${escapeHtml(segment.text)}</p></div>`; + case 'tool-call': + return `<div class="segment-block segment-tool-call"><div class="segment-kind">Tool call · <code>${escapeHtml(segment.name)}</code></div>${segment.payload !== undefined ? renderJsonBlock(segment.payload, 'Input') : ''}${segment.metadata ? renderJsonBlock(segment.metadata, 'Metadata') : ''}</div>`; + case 'tool-result': + return `<div class="segment-block segment-tool-result"><div class="segment-kind">Tool result${segment.name ? ` · <code>${escapeHtml(segment.name)}</code>` : ''}</div>${segment.payload !== undefined ? renderJsonBlock(segment.payload, 'Output') : ''}${segment.metadata ? renderJsonBlock(segment.metadata, 'Metadata') : ''}</div>`; + case 'json': + return renderJsonBlock(segment.payload, segment.label); + } + }) + .join(''); +} + +function renderContentBlock(block: ReadableContentBlock): string { + const roleClass = `role-${sanitizeAnchor(block.role.toLowerCase())}`; + const segmentsHtml = block.segments?.length + ? renderSegments(block.segments) + : `<p class="segment-text">${escapeHtml(block.content)}</p>`; + const metadataHtml = block.metadata ? renderJsonBlock(block.metadata, 'Metadata') : ''; + + return `<div class="content-block ${roleClass}"><div class="content-role">${escapeHtml(block.role)}</div>${segmentsHtml}${metadataHtml}</div>`; +} + +function renderWorkflowCodeSnapshot(snapshot: InstanceAiRunDebugWorkflowCodeSnapshot): string { + const status = snapshot.success + ? '<span class="badge badge-pass">ok</span>' + : '<span class="badge badge-fail">failed</span>'; + const errors = + snapshot.errors && snapshot.errors.length > 0 + ? `<ul class="error-list">${snapshot.errors.map((e) => `<li>${escapeHtml(e)}</li>`).join('')}</ul>` + : ''; + + return `<div class="workflow-code-snapshot"> + <div class="workflow-code-header">${status} <code>${escapeHtml(snapshot.source)}</code>${snapshot.workflowId ? ` · ${escapeHtml(snapshot.workflowId)}` : ''}</div> + <pre class="code-block"><code>${escapeHtml(snapshot.code)}</code></pre> + ${snapshot.patches ? renderJsonBlock(snapshot.patches, 'Patches') : ''} + ${errors} + </div>`; +} + +function renderStepDetail( + step: InstanceAiRunDebugStep, + workflowCode: InstanceAiRunDebugWorkflowCodeSnapshot[], +): string { + const parsedSystem = parseSystemPromptForDisplay(step.input?.system); + const messageBlocks = parseMessageBlocks(step.input?.messages); + const inputExtras = parseInputExtras(step.input); + const outputBlocks = parseOutputDisplayBlocks(step.output); + const outputExtras = parseOutputExtras(step.output); + const usage = parseUsageSummary(step.output?.usage); + const finishReason = + typeof step.output?.finishReason === 'string' ? step.output.finishReason : undefined; + + const systemHtml = [ + ...parsedSystem.systemBlocks.map(renderContentBlock), + parsedSystem.observations + ? `<div class="content-block role-observations"><div class="content-role">Observations</div><p class="segment-text">${escapeHtml(parsedSystem.observations)}</p></div>` + : '', + ].join(''); + + const workflowCodeHtml = + workflowCode.length > 0 + ? `<div class="detail-section"><div class="detail-section-title">Workflow code</div>${workflowCode.map(renderWorkflowCodeSnapshot).join('')}</div>` + : ''; + + return `<div class="step-detail-inner"> + <div class="detail-meta">${finishReason ? `<span class="meta-chip">finish: ${escapeHtml(finishReason)}</span>` : ''}${usage ? `<span class="meta-chip">${escapeHtml(usage.label)}</span>` : ''}</div> + <div class="detail-section"><div class="detail-section-title">Input</div> + ${systemHtml ? `<div class="detail-subsection"><div class="detail-subsection-title">System</div>${systemHtml}</div>` : ''} + ${messageBlocks.length > 0 ? `<div class="detail-subsection"><div class="detail-subsection-title">Messages</div>${messageBlocks.map(renderContentBlock).join('')}</div>` : ''} + ${inputExtras ? renderJsonBlock(inputExtras, 'Input extras') : ''} + </div> + <div class="detail-section"><div class="detail-section-title">Output</div> + ${outputBlocks.length > 0 ? outputBlocks.map(renderContentBlock).join('') : '<div class="muted">No structured output</div>'} + ${usage ? renderJsonBlock(usage.metadata, 'Usage') : ''} + ${outputExtras ? renderJsonBlock(outputExtras, 'Output extras') : ''} + </div> + ${workflowCodeHtml} + </div>`; +} + +function renderStepSummaryChips(summary: ReturnType<typeof parseStepSummary>): string { + const chips: string[] = []; + if (summary.finishReason) { + chips.push(`<span class="chip">${escapeHtml(summary.finishReason)}</span>`); + } + for (const tool of summary.toolNames) { + chips.push(`<span class="chip chip-tool">${escapeHtml(tool)}</span>`); + } + if (summary.usageLabel) { + chips.push(`<span class="chip chip-muted">${escapeHtml(summary.usageLabel)}</span>`); + } + if (summary.messagePreview) { + chips.push(`<span class="chip chip-preview">${escapeHtml(summary.messagePreview)}</span>`); + } + return chips.join(''); +} + +function renderRunPanel( + run: InstanceAiRunDebugResponse, + caseIndex: number, + runIndex: number, +): string { + const label = run.label; + const displayLabel = label ?? `Run ${String(runIndex + 1)}`; + + const stepsList = run.steps + .map((step, stepIndex) => { + const summary = parseStepSummary(step.input, step.output); + const active = stepIndex === 0 ? ' active' : ''; + return `<button type="button" class="step-btn${active}" data-step-index="${String(stepIndex)}" onclick="selectStep(${String(caseIndex)}, ${String(runIndex)}, ${String(stepIndex)})"> + <span class="step-num">#${String(step.stepNumber)}</span> + <span class="step-chips">${renderStepSummaryChips(summary)}</span> + </button>`; + }) + .join(''); + + const stepPanels = run.steps + .map((step, stepIndex) => { + const hidden = stepIndex === 0 ? '' : ' hidden'; + return `<div class="step-panel${hidden}" data-step-index="${String(stepIndex)}">${renderStepDetail(step, run.workflowCode)}</div>`; + }) + .join(''); + + const hidden = runIndex === 0 ? '' : ' hidden'; + + return `<div class="run-panel${hidden}" data-run-index="${String(runIndex)}"> + <div class="steps-col"> + <div class="col-title">Steps (${String(run.steps.length)})</div> + <div class="steps-list">${stepsList || '<div class="muted">No steps captured</div>'}</div> + </div> + <div class="detail-col"> + <div class="col-title">${escapeHtml(displayLabel)} · ${escapeHtml(formatTimestamp(run.startedAt))}</div> + <div class="step-panels">${stepPanels || '<div class="muted">No step detail</div>'}</div> + </div> + </div>`; +} + +function renderTestCaseDebug(result: WorkflowTestCaseResult, caseIndex: number): string { + const runs = result.runDebug ?? []; + const anchorId = getTestCaseAnchorId(result, caseIndex); + const label = getTestCaseLabel(result); + const totalSteps = runs.reduce((sum, run) => sum + run.steps.length, 0); + + const runTabs = runs + .map((run, runIndex) => { + const tabLabel = run.label ?? `Run ${String(runIndex + 1)}`; + const active = runIndex === 0 ? ' active' : ''; + return `<button type="button" class="run-btn${active}" data-run-index="${String(runIndex)}" onclick="selectRun(${String(caseIndex)}, ${String(runIndex)})"> + <span class="run-label">${escapeHtml(tabLabel)}</span> + <span class="run-meta">${String(run.steps.length)} steps · ${escapeHtml(formatTimestamp(run.startedAt))}</span> + </button>`; + }) + .join(''); + + const runPanels = runs.map((run, runIndex) => renderRunPanel(run, caseIndex, runIndex)).join(''); + + return `<section class="debug-case" id="${escapeHtml(anchorId)}" data-case-index="${String(caseIndex)}"> + <header class="debug-case-header"> + <h2>${escapeHtml(label)}</h2> + <div class="debug-case-meta"> + <span class="meta-item">${String(runs.length)} run${runs.length === 1 ? '' : 's'}</span> + <span class="meta-item">${String(totalSteps)} step${totalSteps === 1 ? '' : 's'}</span> + ${result.threadId ? `<span class="meta-item mono">thread ${escapeHtml(result.threadId)}</span>` : ''} + </div> + </header> + <div class="debug-grid"> + <aside class="runs-col"> + <div class="col-title">Runs</div> + <div class="runs-list">${runTabs}</div> + </aside> + <div class="debug-main" id="debug-main-${String(caseIndex)}">${runPanels}</div> + </div> + </section>`; +} + +function countDebugStats(results: WorkflowTestCaseResult[]): { + testCases: number; + runs: number; + steps: number; +} { + const withDebug = results.filter((r) => (r.runDebug?.length ?? 0) > 0); + return { + testCases: withDebug.length, + runs: withDebug.reduce((sum, r) => sum + (r.runDebug?.length ?? 0), 0), + steps: withDebug.reduce( + (sum, r) => sum + (r.runDebug?.reduce((s, run) => s + run.steps.length, 0) ?? 0), + 0, + ), + }; +} + +// --------------------------------------------------------------------------- +// Full report +// --------------------------------------------------------------------------- + +export function generateRunDebugReport(results: WorkflowTestCaseResult[]): string { + const casesWithDebug = results.filter((r) => (r.runDebug?.length ?? 0) > 0); + const stats = countDebugStats(results); + + const body = + casesWithDebug.length > 0 + ? casesWithDebug + .map((result) => { + const caseIndex = results.indexOf(result); + return renderTestCaseDebug(result, caseIndex); + }) + .join('\n') + : '<div class="empty-state">No LLM run debug was captured for this eval. Set <code>N8N_INSTANCE_AI_RUN_DEBUG_ENABLED=true</code> on the target n8n instance, ensure it exposes <code>/instance-ai/debug/*</code> endpoints, and that builds completed with a thread id.</div>'; + + return `<!DOCTYPE html> +<html lang="en"> +<head> +<meta charset="UTF-8"> +<meta name="viewport" content="width=device-width, initial-scale=1.0"> +<title>Workflow eval — LLM debug + + + +

Workflow eval — LLM debug

+

Captured orchestrator LLM steps per test case (same data as the Instance AI debug modal)

+
+
Test cases
${String(stats.testCases)}
+
Runs
${String(stats.runs)}
+
Steps
${String(stats.steps)}
+
+ ${body} + + +`; +} + +export function writeRunDebugReport(results: WorkflowTestCaseResult[]): string { + const reportDir = path.join(__dirname, '..', '..', '.data'); + if (!fs.existsSync(reportDir)) { + fs.mkdirSync(reportDir, { recursive: true }); + } + const html = generateRunDebugReport(results); + const timestamp = new Date().toISOString().replace(/[:.]/g, '-').slice(0, 19); + const reportPath = path.join(reportDir, `workflow-eval-llm-debug-${timestamp}.html`); + fs.writeFileSync(reportPath, html); + fs.writeFileSync(path.join(reportDir, 'workflow-eval-llm-debug.html'), html); + return reportPath; +} diff --git a/packages/@n8n/instance-ai/evaluations/report/workflow-report.ts b/packages/@n8n/instance-ai/evaluations/report/workflow-report.ts index 03d967bbe9f..88f4c942853 100644 --- a/packages/@n8n/instance-ai/evaluations/report/workflow-report.ts +++ b/packages/@n8n/instance-ai/evaluations/report/workflow-report.ts @@ -10,12 +10,15 @@ import fs from 'fs'; import path from 'path'; +import { getTestCaseAnchorId } from './report-anchors'; import { groupOutcomesByDimension } from '../binaryChecks/aggregate'; import { CHECK_DIMENSIONS, type CheckDimension, type CheckOutcome } from '../binaryChecks/types'; import type { + BuildExpectationResult, ConversationMetrics, ExecutionScenarioResult, ToolInteraction, + TranscriptStep, TranscriptTurn, TurnCounter, WorkflowTestCaseResult, @@ -34,6 +37,469 @@ function escapeHtml(str: string): string { .replace(/'/g, '''); } +type StageStatus = 'pass' | 'fail'; + +interface StageReview { + label: string; + status: StageStatus; + reason: string; + body: string; +} + +function asRecord(value: unknown): Record | undefined { + return value && typeof value === 'object' && !Array.isArray(value) + ? (value as Record) + : undefined; +} + +function getNodeOutputEntries(outputs: unknown): Array<[string, unknown[][]]> { + const record = asRecord(outputs); + if (!record) return []; + return Object.entries(record).filter( + (entry): entry is [string, unknown[][]] => + Array.isArray(entry[1]) && entry[1].every((branch) => Array.isArray(branch)), + ); +} + +function getString(value: unknown): string | undefined { + return typeof value === 'string' && value.trim().length > 0 ? value : undefined; +} + +function getStringArray(value: unknown): string[] { + return Array.isArray(value) + ? value.filter((entry): entry is string => typeof entry === 'string' && entry.trim().length > 0) + : []; +} + +function joinList(items: string[]): string { + if (items.length === 0) return ''; + return `
    ${items.map((item) => `
  • ${escapeHtml(item)}
  • `).join('')}
`; +} + +interface WorkflowDiagramNode { + name: string; + type: string; + mode: string; + x: number; + y: number; +} + +interface WorkflowDiagramEdge { + source: string; + target: string; + connType: string; + outputIndex: number; + inputIndex: number; + label: string; +} + +function truncateText(value: string, maxLength: number): string { + return value.length > maxLength ? `${value.slice(0, Math.max(0, maxLength - 1))}…` : value; +} + +function getNodePosition(node: unknown, fallbackIndex: number): { x: number; y: number } { + const record = asRecord(node); + const position = Array.isArray(record?.position) ? record.position : undefined; + const x = typeof position?.[0] === 'number' ? position[0] : (fallbackIndex % 4) * 280; + const y = typeof position?.[1] === 'number' ? position[1] : Math.floor(fallbackIndex / 4) * 160; + return { x, y }; +} + +function getWorkflowDiagramNodes(result: WorkflowTestCaseResult): WorkflowDiagramNode[] { + const workflowJson = result.workflowJson; + if (!workflowJson) return []; + + const firstEval = result.executionScenarioResults[0]?.evalResult; + const modeByNode = new Map( + firstEval + ? Object.entries(firstEval.nodeResults).map(([name, nodeResult]) => [ + name, + nodeResult.executionMode, + ]) + : [], + ); + + return workflowJson.nodes.map((node, index) => { + const { x, y } = getNodePosition(node, index); + return { + name: node.name, + type: node.type, + mode: modeByNode.get(node.name) ?? (node.disabled ? 'disabled' : 'real'), + x, + y, + }; + }); +} + +function describeOutputLabel(nodeType: string, connType: string, outputIndex: number): string { + if (connType !== 'main') return `${connType}[${String(outputIndex)}]`; + if (nodeType.includes('.if')) return outputIndex === 0 ? 'true' : 'false'; + if (nodeType.includes('.switch')) return `case ${String(outputIndex + 1)}`; + if (nodeType.includes('.splitInBatches')) return outputIndex === 0 ? 'loop' : 'done'; + return outputIndex === 0 ? '' : `main[${String(outputIndex)}]`; +} + +function getWorkflowDiagramEdges(result: WorkflowTestCaseResult): WorkflowDiagramEdge[] { + const workflowJson = result.workflowJson; + if (!workflowJson) return []; + + const nodeTypeByName = new Map(workflowJson.nodes.map((node) => [node.name, node.type])); + const edges: WorkflowDiagramEdge[] = []; + + for (const [source, outputs] of Object.entries(workflowJson.connections ?? {})) { + const outputsRecord = asRecord(outputs); + if (!outputsRecord) continue; + + for (const [connType, groups] of Object.entries(outputsRecord)) { + if (!Array.isArray(groups)) continue; + + groups.forEach((group, outputIndex) => { + if (!Array.isArray(group)) return; + + group.forEach((link) => { + const linkRecord = asRecord(link); + const target = getString(linkRecord?.node); + if (!target) return; + const inputIndex = + typeof linkRecord?.index === 'number' && Number.isFinite(linkRecord.index) + ? linkRecord.index + : 0; + edges.push({ + source, + target, + connType, + outputIndex, + inputIndex, + label: describeOutputLabel(nodeTypeByName.get(source) ?? '', connType, outputIndex), + }); + }); + }); + } + } + + return edges; +} + +function renderWorkflowEdgeList(edges: WorkflowDiagramEdge[]): string { + if (edges.length === 0) return ''; + const items = edges + .map((edge) => { + const prefix = edge.label ? `${edge.label}: ` : ''; + const suffix = + edge.connType !== 'main' || edge.inputIndex > 0 + ? ` (${escapeHtml(edge.connType)} → input ${String(edge.inputIndex)})` + : ''; + return `
  • ${escapeHtml(prefix + edge.source)} -> ${escapeHtml(edge.target)}${suffix}
  • `; + }) + .join(''); + return `
    Workflow edges (${String(edges.length)})
      ${items}
    `; +} + +function renderWorkflowDiagram(result: WorkflowTestCaseResult): string { + const nodes = getWorkflowDiagramNodes(result); + if (nodes.length === 0) return ''; + + const edges = getWorkflowDiagramEdges(result); + const boxWidth = 220; + const boxHeight = 58; + const padding = 48; + const minX = Math.min(...nodes.map((node) => node.x)); + const minY = Math.min(...nodes.map((node) => node.y)); + + const shiftedNodes = nodes.map((node) => ({ + ...node, + x: node.x - minX + padding, + y: node.y - minY + padding, + })); + const shiftedByName = new Map(shiftedNodes.map((node) => [node.name, node])); + + const maxX = Math.max(...shiftedNodes.map((node) => node.x + boxWidth)) + padding; + const maxY = Math.max(...shiftedNodes.map((node) => node.y + boxHeight)) + padding; + + const edgeSvg = edges + .map((edge, index) => { + const source = shiftedByName.get(edge.source); + const target = shiftedByName.get(edge.target); + if (!source || !target) return ''; + + const startX = source.x + boxWidth; + const startY = source.y + boxHeight / 2; + const endX = target.x; + const endY = target.y + boxHeight / 2; + const deltaX = Math.max(40, Math.abs(endX - startX) / 2); + const path = `M ${startX} ${startY} C ${startX + deltaX} ${startY}, ${endX - deltaX} ${endY}, ${endX} ${endY}`; + const labelX = (startX + endX) / 2; + const labelY = (startY + endY) / 2 - 6; + const label = + edge.label.length > 0 + ? `${escapeHtml(edge.label)}` + : ''; + + return ` + + ${label} + `; + }) + .join(''); + + const nodeSvg = shiftedNodes + .map((node) => { + const safeMode = ['mocked', 'pinned', 'real', 'disabled'].includes(node.mode) + ? node.mode + : 'real'; + const name = truncateText(node.name, 28); + const type = truncateText(node.type.replace(/^n8n-nodes-base\./, ''), 30); + return ` + + ${escapeHtml(name)} + ${escapeHtml(type)} + `; + }) + .join(''); + + const svg = `
    + + + + + + + ${edgeSvg} + ${nodeSvg} + +
    `; + + return `
    Workflow diagram${svg}
    `; +} + +function renderStageReview(stage: StageReview): string { + return `
    +
    +
    + + ${escapeHtml(stage.label)} +
    + ${stage.status === 'pass' ? 'green' : 'red'} +
    +
    ${escapeHtml(stage.reason)}
    +
    ${stage.body}
    +
    `; +} + +function firstPromptText(result: WorkflowTestCaseResult): string { + return result.testCase.conversation[0]?.text ?? ''; +} + +function promptReview(result: WorkflowTestCaseResult, sr: ExecutionScenarioResult): StageReview { + const evidence = `${sr.reasoning} ${sr.rootCause ?? ''}`.toLowerCase(); + const promptLooksUnderspecified = + sr.failureCategory === 'legitimate_failure' && + ['ambiguous', 'unclear', 'not specified', 'not define', 'does not specify'].some((needle) => + evidence.includes(needle), + ); + + return { + label: '1. Prompt', + status: promptLooksUnderspecified ? 'fail' : 'pass', + reason: promptLooksUnderspecified + ? 'The failure analysis points to an under-specified request or acceptance condition.' + : 'No direct prompt-spec issue was identified from the recorded scenario verdict.', + body: `
    ${escapeHtml(firstPromptText(result))}
    `, + }; +} + +function plannerReview(result: WorkflowTestCaseResult): StageReview { + const buildTrace = result.buildTrace; + if (!buildTrace) { + return { + label: "2. Planner's understanding", + status: 'pass', + reason: + 'Planner trace details were not captured in this report, and no planner-specific failure marker is available.', + body: '
    Planner trace details were not captured for this run.
    ', + }; + } + + const plannerActivity = buildTrace?.agentActivities.find( + (activity) => activity.role === 'planner', + ); + const planCalls = buildTrace?.toolCalls.filter((call) => call.toolName === 'add-plan-item') ?? []; + const submitPlan = buildTrace?.toolCalls.find((call) => call.toolName === 'submit-plan'); + const submitPlanResult = asRecord(submitPlan?.result); + const approved = submitPlanResult?.approved === true; + const plannerLooksHealthy = + plannerActivity?.status === 'completed' && approved && planCalls.length > 0; + + const workflowItems = planCalls + .map((call) => { + const item = asRecord(call.args.item); + const itemKind = getString(item?.kind); + if (itemKind !== 'workflow') return undefined; + const name = getString(item.name); + const summary = + getString(call.args.summary) ?? getString(item.purpose) ?? getString(item.name); + return [name, summary].filter(Boolean).join(': '); + }) + .filter((item): item is string => Boolean(item)); + + const checkpointItems = planCalls + .map((call) => { + const item = asRecord(call.args.item); + const itemKind = getString(item?.kind); + if (itemKind !== 'checkpoint') return undefined; + return getString(item.title) ?? getString(item.instructions); + }) + .filter((item): item is string => Boolean(item)); + + const assumptions = planCalls + .flatMap((call) => getStringArray(call.args.assumptions)) + .slice(0, 5); + const bodyParts = [ + workflowItems.length > 0 + ? `
    Workflow intent
    ${joinList(workflowItems)}
    ` + : '', + checkpointItems.length > 0 + ? `
    Verification checkpoint
    ${joinList(checkpointItems)}
    ` + : '', + assumptions.length > 0 + ? `
    Planner assumptions
    ${joinList(assumptions)}
    ` + : '', + plannerActivity?.textContent + ? `
    Planner output
    ${escapeHtml(plannerActivity.textContent)}
    ` + : '', + ].filter(Boolean); + + return { + label: "2. Planner's understanding", + status: plannerLooksHealthy ? 'pass' : 'fail', + reason: plannerLooksHealthy + ? 'The trace contains an approved plan with explicit workflow/checkpoint items.' + : 'The report does not show a completed approved plan with recorded plan items.', + body: + bodyParts.join('') || + '
    Planner trace details were not captured for this run.
    ', + }; +} + +function summarizeToolCalls(result: WorkflowTestCaseResult): string[] { + const toolCalls = result.buildTrace?.toolCalls ?? []; + const count = (toolName: string): number => + toolCalls.filter((call) => call.toolName === toolName).length; + const submitCalls = toolCalls.filter((call) => call.toolName === 'submit-workflow'); + const verifyCalls = toolCalls.filter((call) => call.toolName === 'verify-built-workflow'); + + const summaries = [ + count('nodes') > 0 ? `${String(count('nodes'))} node-research call(s)` : '', + count('credentials') > 0 ? `${String(count('credentials'))} credential lookup call(s)` : '', + submitCalls.length > 0 ? `${String(submitCalls.length)} workflow submission call(s)` : '', + verifyCalls.length > 0 ? `${String(verifyCalls.length)} builder verification call(s)` : '', + ]; + + return summaries.filter((summary) => summary.length > 0); +} + +function builderReview(result: WorkflowTestCaseResult, sr: ExecutionScenarioResult): StageReview { + const builderActivity = result.buildTrace?.agentActivities.find((activity) => + activity.role.includes('builder'), + ); + const builderFailedScenario = + !result.workflowBuildSuccess || sr.failureCategory === 'builder_issue'; + const summaryItems = summarizeToolCalls(result); + const bodyParts = [ + builderActivity?.textContent + ? `
    Builder output
    ${escapeHtml(builderActivity.textContent)}
    ` + : '', + summaryItems.length > 0 + ? `
    Observed builder actions
    ${joinList(summaryItems)}
    ` + : '', + result.buildError ? `
    ${escapeHtml(result.buildError)}
    ` : '', + ].filter(Boolean); + + return { + label: '3. Builder action', + status: builderFailedScenario ? 'fail' : 'pass', + reason: builderFailedScenario + ? sr.failureCategory === 'builder_issue' + ? (sr.rootCause ?? 'The verifier attributed this failed scenario to the builder.') + : (result.buildError ?? 'The workflow build itself did not complete successfully.') + : 'No builder-attributed issue was recorded for this scenario.', + body: + bodyParts.join('') || + '
    Builder trace details were not captured for this run.
    ', + }; +} + +function verifierReview(sr: ExecutionScenarioResult): StageReview { + const evalErrors = sr.evalResult?.errors ?? []; + const warnings = sr.evalResult?.hints?.warnings ?? []; + const bodyParts = [ + sr.reasoning + ? `
    Verifier reasoning
    ${escapeHtml(sr.reasoning)}
    ` + : '
    Verifier reasoning was not captured.
    ', + !sr.success && sr.rootCause + ? `
    Root cause
    ${escapeHtml(sr.rootCause)}
    ` + : '', + evalErrors.length > 0 + ? `
    ${escapeHtml(evalErrors.join('; '))}
    ` + : '', + warnings.length > 0 ? `
    ${escapeHtml(warnings.join('; '))}
    ` : '', + ].filter(Boolean); + + return { + label: '4. Verifier judgment', + status: sr.success ? 'pass' : 'fail', + reason: sr.success + ? 'The verifier accepted this scenario.' + : `The verifier rejected this scenario${sr.failureCategory ? ` as ${sr.failureCategory}` : ''}.`, + body: bodyParts.join(''), + }; +} + +function promptImprovementSuggestion(sr: ExecutionScenarioResult): string { + switch (sr.failureCategory) { + case 'builder_issue': + return 'For workflows with multiple required effects, branches, or error paths, state each required action explicitly and add observable acceptance conditions for every branch. This reduces silent omission during planning or build.'; + case 'mock_issue': + return 'When success depends on an external response shape or an edge-case payload, specify the response envelope, key fields, and failure variant explicitly so the mock path is constrained and comparable across runs.'; + case 'framework_issue': + return 'Make trigger preconditions and scenario setup requirements explicit in the test prompt or fixture description so empty-input framework failures are easier to separate from workflow defects.'; + case 'verification_gap': + return 'Add concrete, inspectable success evidence to the prompt, such as the exact side effect, branch behavior, or output field that should be observed, so the verifier has less room to infer.'; + case 'legitimate_failure': + return 'If this behavior is required, move it from an implied expectation into an explicit prompt requirement with a clear fallback path and observable success criterion.'; + default: + return 'Turn the failed behavior into a more explicit, testable requirement in future prompts: name the required step, the expected branch, and the observable evidence that proves it happened.'; + } +} + +function renderScenarioReview(result: WorkflowTestCaseResult, sr: ExecutionScenarioResult): string { + const stages = [ + promptReview(result, sr), + plannerReview(result), + builderReview(result, sr), + verifierReview(sr), + ]; + const improvement = sr.success + ? '' + : `
    +
    Generalisable prompt improvement
    +
    ${escapeHtml(promptImprovementSuggestion(sr))}
    +
    `; + + return `
    +
    + ${stages + .map( + (stage) => + `${escapeHtml(stage.label.replace(/^\d+\.\s*/, ''))}`, + ) + .join('')} +
    +
    ${stages.map(renderStageReview).join('')}
    + ${improvement} +
    `; +} + function trimTrailingSlash(url: string): string { return url.endsWith('/') ? url.slice(0, -1) : url; } @@ -64,12 +530,11 @@ function renderExecutionLink( function renderScenario( sr: ExecutionScenarioResult, index: number, - baseUrl: string | undefined, - workflowId: string | undefined, + result: WorkflowTestCaseResult, ): string { const icon = sr.success ? '✓' : '✗'; const statusClass = sr.success ? 'pass' : 'fail'; - const execLink = renderExecutionLink(sr, baseUrl, workflowId); + const execLink = renderExecutionLink(sr, result.n8nBaseUrl, result.workflowId); // Passing scenarios: compact one-liner with collapsible detail if (sr.success) { @@ -82,6 +547,7 @@ function renderScenario( ${execLink}
    + ${renderScenarioReview(result, sr)} ${renderScenarioDetail(sr)}
    `; @@ -96,6 +562,7 @@ function renderScenario( ${execLink}
    + ${renderScenarioReview(result, sr)} ${renderScenarioDetail(sr)}
    `; @@ -201,7 +668,7 @@ function renderScenarioDetail(sr: ExecutionScenarioResult): string { html += `
    ${escapeHtml(JSON.stringify(req.requestBody, null, 2))}
    `; } html += '
    Mock returned
    '; - if (req.mockResponse) { + if (req.mockResponse !== undefined) { html += `
    ${escapeHtml(JSON.stringify(req.mockResponse, null, 2))}
    `; } else { html += '
    no mock response
    '; @@ -209,7 +676,7 @@ function renderScenarioDetail(sr: ExecutionScenarioResult): string { html += ''; } - const outputEntries = Object.entries(nr.outputs); + const outputEntries = getNodeOutputEntries(nr.outputs); const hasOutput = outputEntries.some(([, branches]) => branches.length > 0); if (hasOutput) { html += '
    Node output'; @@ -315,27 +782,21 @@ function renderTranscriptTurn(turn: TranscriptTurn, turnNum: number): string { `
    👤${escapeHtml(turn.userMessage)}
    `, ); } - if (turn.agentText) { - parts.push( - `
    🤖${escapeHtml(turn.agentText)}
    `, - ); - } - - const toolNames: string[] = []; - for (const interaction of turn.toolInteractions) { - const block = renderInteraction(interaction); + for (const step of turn.steps) { + const block = renderStep(step); if (block) parts.push(block); - if (interaction.kind === 'tool-call') toolNames.push(interaction.toolName); - } - - if (toolNames.length > 0) { - parts.push( - `
    🔧 ${toolNames.map((t) => escapeHtml(t)).join(', ')}
    `, - ); } return `
    ${parts.join('')}
    `; } +function renderStep(step: TranscriptStep): string | null { + if (step.kind === 'agent-text') { + if (!step.text) return null; + return `
    🤖${escapeHtml(step.text)}
    `; + } + return renderInteraction(step); +} + function renderInteraction(interaction: ToolInteraction): string | null { switch (interaction.kind) { case 'plan': { @@ -420,18 +881,96 @@ function renderInteraction(interaction: ToolInteraction): string | null { } return `
    🛠 setup wizard — ${escapeHtml(header)}${sections.join('')}
    `; } + case 'setup-card': { + if (interaction.requests.length === 0) return null; + const asks = interaction.requests + .map((r) => { + const bits: string[] = []; + if (r.credentialType) bits.push(`${escapeHtml(r.credentialType)} credential`); + if (r.params && r.params.length > 0) + bits.push(r.params.map((p) => escapeHtml(p)).join(', ')); + return bits.length > 0 + ? `${escapeHtml(r.nodeName)} (${bits.join('; ')})` + : escapeHtml(r.nodeName); + }) + .join(', '); + const filledList = + interaction.filled && interaction.filled.length > 0 + ? ` (${interaction.filled.map((p) => escapeHtml(p)).join(', ')})` + : ''; + const outcome = + interaction.outcome === 'filled' + ? `user filled it${filledList}` + : interaction.outcome === 'skipped' + ? 'user skipped it' + : interaction.outcome === 'declined' + ? 'user dismissed it' + : 'no response'; + return `
    🪪 Setup card — agent asked the user to configure: ${asks} → ${outcome}
    `; + } case 'confirmation': { const decisionTag = typeof interaction.approved === 'boolean' - ? ` (${interaction.approved ? 'approved' : 'rejected'})` + ? ` 👤 ${interaction.approved ? 'approved' : 'rejected'}` : ''; - return `
    ↪ resume ${escapeHtml(interaction.toolName)}: ${escapeHtml(interaction.resumeReason)}${decisionTag}
    `; + const messageHtml = interaction.message + ? `
    💬 ${escapeHtml(interaction.message)}
    ` + : ''; + const feedbackHtml = interaction.feedback + ? `
    👤 ${escapeHtml(interaction.feedback)}
    ` + : ''; + return `
    ↪ resume ${escapeHtml(interaction.toolName)}: ${escapeHtml(interaction.resumeReason)}${decisionTag}
    ${messageHtml}${feedbackHtml}`; + } + case 'tool-call': { + const args = interaction.args; + const hasArgs = Boolean(args && Object.keys(args).length > 0); + const errorText = typeof interaction.error === 'string' ? interaction.error : ''; + const hasResult = interaction.result !== undefined && interaction.result !== null; + const idTag = interaction.toolCallId + ? ` ${escapeHtml(interaction.toolCallId)}` + : ''; + // Surface load_skill's skillId inline so the loaded skill is visible without expanding args. + const inlineArg = + interaction.toolName === 'load_skill' && args && typeof args.skillId === 'string' + ? ` ${escapeHtml(args.skillId)}` + : ''; + const title = `🔧 ${escapeHtml(interaction.toolName)}${inlineArg}${idTag}`; + if (!hasArgs && !errorText && !hasResult) { + return `
    ${title}
    `; + } + const argsBlock = hasArgs + ? `
    ${escapeHtml(formatJson(args))}
    ` + : ''; + const outcomeBlock = errorText + ? `
    ${escapeHtml(errorText)}
    ` + : hasResult + ? `
    ${escapeHtml(formatJson(interaction.result))}
    ` + : ''; + const badge = errorText ? ' error' : ''; + return `
    ${title}${badge}${argsBlock}${outcomeBlock}
    `; } - case 'tool-call': - return null; // surfaced in the aggregate tool-names line at the bottom } } +function formatJson(value: unknown): string { + const MAX = 2000; + if (typeof value === 'string') { + return value.length > MAX + ? `${value.slice(0, MAX)}\n… (${String(value.length - MAX)} more chars)` + : value; + } + let json: string | undefined; + try { + json = JSON.stringify(value, null, 2); + } catch { + return '[unserializable]'; + } + if (typeof json !== 'string') return String(value); + return json.length > MAX + ? `${json.slice(0, MAX)}\n… (${String(json.length - MAX)} more chars)` + : json; +} + // --------------------------------------------------------------------------- // Workflow check rubric // --------------------------------------------------------------------------- @@ -479,12 +1018,40 @@ function renderWorkflowChecks(outcomes: CheckOutcome[] | undefined): string { return `
    Workflow checks ${summary}${groups}
    `; } +// --------------------------------------------------------------------------- +// Build expectations +// --------------------------------------------------------------------------- + +function renderBuildExpectations(results: BuildExpectationResult[] | undefined): string { + if (!results || results.length === 0) return ''; + // `incomplete` (no verdict) stays out of the pass/fail count — rendered neutrally. + const passCount = results.filter((r) => r.pass && !r.incomplete).length; + const failCount = results.filter((r) => !r.pass && !r.incomplete).length; + const incompleteCount = results.filter((r) => r.incomplete).length; + const scored = passCount + failCount; + const statusClass = failCount > 0 ? 'fail' : 'pass'; + const openAttr = failCount > 0 ? 'open' : ''; + const summary = `${String(passCount)}/${String(scored)}${incompleteCount > 0 ? ` · ${String(incompleteCount)} no verdict` : ''}`; + const items = results + .map((r) => { + const cls = r.incomplete ? 'n_a' : r.pass ? 'pass' : 'fail'; + const icon = r.incomplete ? '⌀' : r.pass ? '✓' : '✗'; + const judgment = r.reason + ? `
    ${escapeHtml(r.reason)}
    ` + : ''; + return `
  • ${icon}
    ${escapeHtml(r.expectation)}
    ${judgment}
  • `; + }) + .join(''); + return `
    Build expectations ${summary}
      ${items}
    `; +} + // --------------------------------------------------------------------------- // Workflow summary // --------------------------------------------------------------------------- function renderWorkflowSummary(result: WorkflowTestCaseResult): string { const firstEval = result.executionScenarioResults[0]?.evalResult; + const edges = getWorkflowDiagramEdges(result); let nodesHtml = ''; if (firstEval) { @@ -506,13 +1073,75 @@ function renderWorkflowSummary(result: WorkflowTestCaseResult): string { } } + const diagramHtml = renderWorkflowDiagram(result); + const edgesHtml = renderWorkflowEdgeList(edges); + let jsonHtml = ''; if (result.workflowJson) { const raw = JSON.stringify(result.workflowJson, null, 2); jsonHtml = `
    Agent output (raw JSON)
    ${escapeHtml(raw)}
    `; } - return nodesHtml + jsonHtml; + let traceHtml = ''; + if (result.buildTrace) { + const nodeResearchCalls = result.buildTrace.toolCalls.filter( + (call) => call.toolName === 'nodes', + ); + const workflowWriteCalls = result.buildTrace.toolCalls.filter((call) => + ['build-workflow', 'submit-workflow', 'build-workflow-with-agent'].includes(call.toolName), + ); + const validationCalls = result.buildTrace.toolCalls.filter( + (call) => call.toolName === 'submit-workflow', + ); + const credentialCalls = result.buildTrace.toolCalls.filter( + (call) => call.toolName === 'credentials', + ); + const verificationCalls = result.buildTrace.toolCalls.filter( + (call) => call.toolName === 'verify-built-workflow', + ); + const completionActivity = [...result.buildTrace.agentActivities] + .reverse() + .find((activity) => activity.status !== 'running'); + + const summary = { + nodeResearchCalls: nodeResearchCalls.map((call) => call.args), + workflowWriteCalls: workflowWriteCalls.map((call) => ({ + toolName: call.toolName, + args: call.args, + result: call.result, + error: call.error, + })), + validationCalls: validationCalls.map((call) => ({ + args: call.args, + result: call.result, + error: call.error, + })), + credentialCalls: credentialCalls.map((call) => ({ + args: call.args, + result: call.result, + error: call.error, + })), + verificationCalls: verificationCalls.map((call) => ({ + args: call.args, + result: call.result, + error: call.error, + })), + completionActivity: completionActivity + ? { + role: completionActivity.role, + status: completionActivity.status, + textContent: completionActivity.textContent, + } + : null, + }; + + traceHtml = + `
    Builder trace summary
    ${escapeHtml(JSON.stringify(summary, null, 2))}
    ` + + `
    Builder tool calls (raw)
    ${escapeHtml(JSON.stringify(result.buildTrace.toolCalls, null, 2))}
    ` + + `
    Builder agent activity (raw)
    ${escapeHtml(JSON.stringify(result.buildTrace.agentActivities, null, 2))}
    `; + } + + return nodesHtml + diagramHtml + edgesHtml + jsonHtml + traceHtml; } // --------------------------------------------------------------------------- @@ -520,8 +1149,12 @@ function renderWorkflowSummary(result: WorkflowTestCaseResult): string { // --------------------------------------------------------------------------- function renderTestCase(result: WorkflowTestCaseResult, tcIndex: number): string { - const passCount = result.executionScenarioResults.filter((sr) => sr.success).length; - const totalCount = result.executionScenarioResults.length; + // Pass rate counts scenarios AND build expectations as units (incomplete expectations excluded). + const scoredExpectations = (result.buildExpectationResults ?? []).filter((e) => !e.incomplete); + const passCount = + result.executionScenarioResults.filter((sr) => sr.success).length + + scoredExpectations.filter((e) => e.pass).length; + const totalCount = result.executionScenarioResults.length + scoredExpectations.length; const allPass = passCount === totalCount && totalCount > 0; const statusClass = result.workflowBuildSuccess ? (allPass ? 'pass' : 'mixed') : 'fail'; @@ -536,19 +1169,32 @@ function renderTestCase(result: WorkflowTestCaseResult, tcIndex: number): string const prompt = result.testCase.conversation[0].text; const truncatedPrompt = prompt.length > 100 ? prompt.slice(0, 100) + '...' : prompt; + // Header label = the source-file slug (the same identifier the PR comment + // uses), falling back to the description then the prompt. The full prompt + // stays in the expandable "Prompt" section below. + // flattenRunsForReport prefixes the prompt with "[iter N/M] " so multi-run cards stay + // distinguishable; carry that marker onto the slug/description header too. + const iterPrefix = /^\[iter \d+\/\d+\]\s*/.exec(prompt)?.[0] ?? ''; + const headerLabel = + iterPrefix + (result.fileSlug ?? result.testCase.description ?? truncatedPrompt); - // Inline scenario indicators for quick triage without expanding - const scenarioIndicators = result.executionScenarioResults - .map( + // Inline indicators for quick triage without expanding — scenarios and expectations as units. + const scenarioIndicators = [ + ...result.executionScenarioResults.map( (sr) => - `${sr.success ? '✓' : '✗'} ${escapeHtml(sr.scenario.name)}`, - ) - .join(' '); + `${sr.success ? '✓' : '✗'} scenario: ${escapeHtml(sr.scenario.name)}`, + ), + ...(result.buildExpectationResults ?? []).map((e) => { + const cls = e.incomplete ? 'na' : e.pass ? 'pass' : 'fail'; + const icon = e.incomplete ? '⌀' : e.pass ? '✓' : '✗'; + return `${icon} expectation: ${escapeHtml(e.expectation)}`; + }), + ].join(' '); let scenariosHtml = ''; if (result.executionScenarioResults.length > 0) { scenariosHtml = result.executionScenarioResults - .map((sr, i) => renderScenario(sr, tcIndex * 100 + i, result.n8nBaseUrl, result.workflowId)) + .map((sr, i) => renderScenario(sr, tcIndex * 100 + i, result)) .join(''); } else if (!result.workflowBuildSuccess) { const errorDetail = result.buildError @@ -562,16 +1208,23 @@ function renderTestCase(result: WorkflowTestCaseResult, tcIndex: number): string ? `open in n8n →` : ''; + const llmDebugLink = + (result.runDebug?.length ?? 0) > 0 + ? `LLM steps →` + : ''; + return `
    ${buildBadge} ${scoreBadge} - ${escapeHtml(truncatedPrompt)} + ${escapeHtml(headerLabel)}
    ${escapeHtml(result.testCase.complexity)} + ${result.threadId ? `🧵 ${escapeHtml(result.threadId)}` : ''} ${result.workflowId ? `${escapeHtml(result.workflowId)}` : ''} ${workflowLink} + ${llmDebugLink}
    ${scenarioIndicators}
    @@ -579,6 +1232,7 @@ function renderTestCase(result: WorkflowTestCaseResult, tcIndex: number): string
    Prompt
    ${escapeHtml(prompt)}
    ${renderConversationMetrics(result.conversationMetrics)} ${renderConversationTranscript(result.transcript)} + ${renderBuildExpectations(result.buildExpectationResults)} ${renderWorkflowChecks(result.workflowChecks)} ${renderWorkflowSummary(result)} ${scenariosHtml} @@ -664,10 +1318,11 @@ export function generateWorkflowReport(results: WorkflowTestCaseResult[]): strin .test-case-prompt { color: var(--text-primary); font-weight: 500; font-size: 13px; } .test-case-meta { display: flex; align-items: center; gap: 6px; margin-bottom: 6px; } .workflow-id { color: var(--text-muted); font-size: 11px; font-family: monospace; } - .scenario-indicators { display: flex; gap: 8px; flex-wrap: wrap; } + .scenario-indicators { display: flex; flex-direction: column; gap: 3px; } .scenario-indicator { font-size: 11px; font-family: monospace; } .scenario-indicator.pass { color: var(--color-pass); } .scenario-indicator.fail { color: var(--color-fail); } + .scenario-indicator.na { color: #8b949e; } .test-case-detail { display: none; padding: 0 16px 16px; } .test-case.expanded .test-case-detail { display: block; } @@ -705,6 +1360,9 @@ export function generateWorkflowReport(results: WorkflowTestCaseResult[]): strin .check.n_a code { color: var(--text-muted); } .check-kind { color: var(--text-muted); font-size: 10px; text-transform: uppercase; letter-spacing: 0.5px; } .check-kind-llm { color: var(--color-purple); } + .expectation { padding: 5px 0; display: flex; align-items: baseline; gap: 8px; list-style: none; line-height: 1.5; } + .expectation-text { font-size: 12px; } + .expectation-judgment { color: var(--text-muted); font-size: 12px; margin-top: 2px; } /* Error and warning boxes */ .error-box { color: var(--color-fail); font-size: 12px; padding: 6px 10px; background: var(--color-fail-bg); border-radius: 4px; margin-bottom: 8px; border-left: 3px solid var(--color-fail); } @@ -717,6 +1375,36 @@ export function generateWorkflowReport(results: WorkflowTestCaseResult[]): strin /* Prompt */ .prompt-text { color: var(--text-secondary); font-size: 13px; line-height: 1.6; padding: 10px; background: var(--bg-primary); border: 1px solid var(--border); border-radius: 6px; white-space: pre-wrap; } + .review-prompt { margin-top: 8px; } + + /* Scenario review lane */ + .review-shell { margin: 8px 0 14px; border: 1px solid var(--border); border-radius: 8px; background: var(--bg-secondary); overflow: hidden; } + .review-overview { display: flex; flex-wrap: wrap; gap: 8px; padding: 10px 12px; border-bottom: 1px solid var(--border-light); background: var(--bg-primary); } + .review-overview-chip { display: inline-flex; align-items: center; min-height: 24px; padding: 0 10px; border: 1px solid var(--border); border-radius: 999px; color: var(--text-secondary); font-size: 11px; font-weight: 600; } + .review-overview-chip.pass { border-color: #238636; color: var(--color-pass); background: var(--color-pass-bg); } + .review-overview-chip.fail { border-color: #da3633; color: var(--color-fail); background: var(--color-fail-bg); } + .review-grid { display: grid; grid-template-columns: 1fr; } + .review-stage { padding: 12px; border-top: 1px solid var(--border-light); border-left: 4px solid var(--border); background: var(--bg-secondary); } + .review-stage:first-child { border-top: 0; } + .review-stage.pass { border-left-color: var(--color-pass); } + .review-stage.fail { border-left-color: var(--color-fail); } + .review-stage-header { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 6px; } + .review-stage-heading { display: flex; align-items: center; gap: 8px; min-width: 0; } + .review-stage-label { color: var(--text-primary); font-size: 12px; font-weight: 700; } + .review-status-dot { width: 10px; height: 10px; border-radius: 50%; flex: 0 0 auto; } + .review-status-dot.pass { background: var(--color-pass); box-shadow: 0 0 0 3px var(--color-pass-bg); } + .review-status-dot.fail { background: var(--color-fail); box-shadow: 0 0 0 3px var(--color-fail-bg); } + .review-status-pill { display: inline-flex; align-items: center; min-height: 22px; padding: 0 8px; border-radius: 999px; font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: 0; } + .review-status-pill.pass { background: var(--color-pass-bg); color: var(--color-pass); } + .review-status-pill.fail { background: var(--color-fail-bg); color: var(--color-fail); } + .review-stage-reason { color: var(--text-secondary); font-size: 12px; line-height: 1.6; margin-bottom: 4px; } + .review-stage-body { margin-top: 6px; } + .review-subsection { padding-top: 4px; } + .review-list { margin: 6px 0 0 18px; color: var(--text-secondary); font-size: 12px; line-height: 1.6; } + .review-list li { margin: 2px 0; } + .prompt-improvement { padding: 12px; border-top: 1px solid var(--border-light); background: #151d18; border-left: 4px solid var(--color-warn); } + .prompt-improvement-label { color: var(--color-warn); font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0; margin-bottom: 4px; } + .prompt-improvement-copy { color: var(--text-secondary); font-size: 12px; line-height: 1.6; } /* Execution trace */ .trace-legend { font-size: 11px; margin-bottom: 8px; display: flex; gap: 12px; } @@ -739,10 +1427,26 @@ export function generateWorkflowReport(results: WorkflowTestCaseResult[]): strin /* Node list */ .node-list { list-style: none; padding: 4px 0; font-size: 12px; font-family: monospace; } .node-list li { padding: 3px 0; } + .edge-list { list-style: none; padding: 4px 0; font-size: 12px; } + .edge-list li { padding: 4px 0; } .node-mode-mocked { color: var(--color-info); font-weight: 600; } .node-mode-pinned { color: var(--color-warn); font-weight: 600; } .node-mode-real { color: var(--color-pass); font-weight: 600; } + /* Workflow diagram */ + .workflow-diagram-shell { margin-top: 8px; padding: 8px; overflow: auto; background: var(--bg-primary); border: 1px solid var(--border); border-radius: 6px; } + .workflow-diagram-svg { display: block; width: 100%; min-width: 720px; height: auto; } + .diagram-edge-path { fill: none; stroke: var(--border); stroke-width: 2; } + .diagram-edge-label { fill: var(--text-muted); font-size: 10px; font-family: monospace; } + .diagram-arrow-head { fill: var(--border); } + .diagram-node-box { fill: var(--bg-secondary); stroke: var(--border); stroke-width: 2; } + .diagram-node-name { fill: var(--text-primary); font-size: 12px; font-weight: 600; } + .diagram-node-type { fill: var(--text-muted); font-size: 10px; font-family: monospace; } + .diagram-node-real .diagram-node-box { stroke: var(--color-pass); } + .diagram-node-mocked .diagram-node-box { stroke: var(--color-info); } + .diagram-node-pinned .diagram-node-box { stroke: var(--color-warn); } + .diagram-node-disabled .diagram-node-box { stroke: var(--text-muted); stroke-dasharray: 5 3; } + /* Node output toggle */ .node-output-toggle { margin: 4px 0; } .node-output-toggle > summary { cursor: pointer; color: var(--text-muted); font-size: 11px; } @@ -762,9 +1466,9 @@ export function generateWorkflowReport(results: WorkflowTestCaseResult[]): strin /* Utilities */ .muted { color: var(--text-muted); font-size: 12px; } - /* Conversation metrics */ - .conv-summary { color: var(--text-secondary); font-size: 12px; padding: 6px 0; } - .conv-table { width: 100%; border-collapse: collapse; font-size: 12px; margin-top: 6px; } + /* Conversation metrics */ + .conv-summary { color: var(--text-secondary); font-size: 12px; padding: 6px 0; } + .conv-table { width: 100%; border-collapse: collapse; font-size: 12px; margin-top: 6px; } .conv-table th, .conv-table td { text-align: left; padding: 4px 8px; border-bottom: 1px solid var(--border-light); } .conv-table th { color: var(--text-muted); font-weight: 600; font-size: 11px; text-transform: uppercase; letter-spacing: 0.04em; } .conv-table td { font-family: monospace; } @@ -789,14 +1493,27 @@ export function generateWorkflowReport(results: WorkflowTestCaseResult[]): strin .transcript-aside > summary { cursor: pointer; color: var(--text-muted); font-size: 11px; padding: 2px 0; } .transcript-reasoning { color: var(--text-muted); font-size: 12px; line-height: 1.5; padding: 6px 8px; background: var(--bg-primary); border-left: 2px solid var(--border); border-radius: 2px; white-space: pre-wrap; margin-top: 4px; } .transcript-tools { color: var(--text-muted); font-size: 11px; font-family: monospace; padding: 4px 0 0 26px; } + .transcript-args { margin: 4px 0 4px 26px; padding: 6px 8px; font-size: 11px; font-family: monospace; line-height: 1.45; color: var(--text-secondary); background: var(--bg-primary); border-left: 2px solid var(--border); border-radius: 2px; white-space: pre-wrap; word-break: break-word; max-height: 280px; overflow: auto; } + .transcript-args.transcript-error { color: var(--color-fail); border-left-color: var(--color-fail); } + .transcript-tool-id { color: var(--text-muted); font-size: 10px; font-family: monospace; opacity: 0.7; } + .transcript-inline-arg { color: var(--text-muted); font-size: 11px; font-family: monospace; } .transcript-plan, .transcript-questions { margin: 4px 0 4px 18px; padding: 0; font-size: 12px; line-height: 1.5; color: var(--text-primary); } .transcript-plan li, .transcript-questions li { margin: 4px 0; } .transcript-answer { color: var(--text-secondary); font-size: 12px; margin: 2px 0 6px 16px; padding: 2px 0; } .transcript-resume { font-size: 11px; font-family: monospace; color: var(--text-muted); padding: 2px 0 2px 26px; } + .transcript-decision { font-weight: 600; } + .transcript-decision.pass { color: var(--color-pass); } + .transcript-decision.fail { color: var(--color-fail); } .transcript-resume code { background: var(--bg-tertiary); padding: 0 4px; border-radius: 2px; } .transcript-section-label { font-size: 11px; color: var(--text-muted); margin: 6px 0 2px 18px; text-transform: uppercase; letter-spacing: 0.04em; } .transcript-empty { font-size: 12px; color: var(--text-muted); font-style: italic; margin: 4px 0 4px 18px; } - + + @media (min-width: 960px) { + .review-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } + .review-stage:nth-child(2) { border-top: 0; } + .review-stage:nth-child(odd) { border-right: 1px solid var(--border-light); } + } + diff --git a/packages/@n8n/instance-ai/evaluations/subagent/runner.ts b/packages/@n8n/instance-ai/evaluations/subagent/runner.ts index 9c868babb53..97e73a33a47 100644 --- a/packages/@n8n/instance-ai/evaluations/subagent/runner.ts +++ b/packages/@n8n/instance-ai/evaluations/subagent/runner.ts @@ -17,6 +17,7 @@ import type { BinaryCheckContext } from '../binaryChecks/types'; import type { N8nClient, WorkflowResponse } from '../clients/n8n-client'; import { createLogger, type EvalLogger } from '../harness/logger'; import { buildWorkflow, cleanupBuild, type BuildResult } from '../harness/runner'; +import { agentTextOf } from '../utils/conversation-text'; /** * Client-side model used by binary checks (they call Anthropic directly with @@ -130,7 +131,7 @@ function toCapturedWorkflow(workflow: WorkflowResponse): CapturedWorkflow { function extractAgentText(build: BuildResult): string { return ( build.transcript - ?.map((turn) => turn.agentText) + ?.map((turn) => agentTextOf(turn)) .filter((text) => text.length > 0) .join('\n\n') ?? '' ); 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 new file mode 100644 index 00000000000..39c0e9ad666 --- /dev/null +++ b/packages/@n8n/instance-ai/evaluations/system-prompts/build-expectations-verify.ts @@ -0,0 +1,36 @@ +export const BUILD_EXPECTATIONS_VERIFY_PROMPT = `You are an expert evaluator for n8n's AI workflow builder. A user (simulated) had a multi-turn conversation with the builder agent, which produced a workflow. Your job is to judge a set of author-written expectations about HOW that conversation went and what it produced. + +These expectations are NOT about whether the workflow executes correctly — they are about the conversation itself and the resulting workflow. Examples: "the agent asked which Slack channel before building", "the agent requested credential setup for Gmail", "the change requested in the follow-up turn is reflected in the final workflow". + +## What you receive + +1. **Workflow structure**: the final built workflow — every node, its config, and the connections JSON. If no workflow was built (the build failed), this says "(no workflow built)". +2. **Conversation transcript**: the full multi-turn conversation, both sides, turn by turn. Each turn shows the user message, the agent's text, and compact summaries of tool interactions — plans, questions asked to the user (with answers), setup cards the agent showed (the values it asked the user to provide — credentials and/or parameters — and whether the user filled or dismissed them), setup-wizard configured/skipped nodes, resumed confirmations (approved/rejected), and the names of tools called. +3. **Conversation metrics (ground truth)**: deterministic counters extracted from the event stream — turn count, how many confirmations were asked and of which kind, whether the run finished cleanly. Treat these as authoritative. Do NOT recount turns or confirmations from the raw transcript when a metric already states the number. +4. **Expectations**: a numbered list (indices start at 0). Judge each one. + +## How to judge + +- Judge **each expectation independently** and literally. Read what it actually asserts. +- **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. A value appearing in a setup card means the builder asked the user to provide that value (the user may fill or dismiss it); treat it the same as the builder asking for that value directly. +- **Outcome claims** ("the final workflow contains a Switch routing to Slack", "the follow-up change is reflected") → judge from the workflow structure. If no workflow was built, any expectation that requires the final workflow **fails**. +- An expectation about something that simply **did not happen is a fail** — never "n/a". Say plainly what was expected and what actually occurred. +- **Be definitive, not speculative.** You have the full transcript, metrics, and workflow. Quote the concrete evidence — the turn where the agent asked, the node that was added, the metric value. Avoid "likely", "might", "probably". +- Keep each \`reason\` to **one sentence**. + +## Output format + +Return an object with a \`results\` array — exactly one entry per expectation, using the 0-based \`index\` from the numbered list: + +\`\`\`json +{ + "results": [ + { "index": 0, "pass": true, "reason": "In turn 1 the agent asked which Slack channel to post to before creating any nodes." }, + { "index": 1, "pass": false, "reason": "The follow-up asked to sort descending, but the final workflow has no Sort node." } + ] +} +\`\`\` + +Return a verdict for every numbered expectation. +`; 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 351b8aa4daf..ad4c9bd1674 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 @@ -50,21 +50,25 @@ Each branch's items are capped at 10 for artifact size. The full untruncated tot - Did a real node crash because a field is missing? → **check the request that was sent**: if the HTTP request (e.g., GraphQL query) didn't ask for that field, the mock correctly omitted it — that's a builder issue (wrong query or wrong node choice), NOT a mock issue. The mock can only return what was requested. - Did the mock response have the wrong shape for the endpoint? (e.g., returning a write response for a GET request) → mock issue - Did the mock return identical responses for multiple calls to the same endpoint with different request bodies? → mock issue + - Did the workflow error with n8n's pagination safety (e.g. "The returned response was identical 5x, so requests got stopped")? → builder_issue: the pagination did not terminate — it failed to stop on the empty page, or never advanced the page parameter. Identical empty pages at end-of-data are the correct stop signal (the builder must detect them), and the mock serving distinct pages in sequence to repeated requests is the testing mechanism working. Only a mock_issue if the mock repeated identical non-empty pages it should have varied. - Did the workflow handle an error scenario but the success criteria is ambiguous about what "graceful" means? → evaluate based on whether data was lost or the workflow crashed entirely KEY PRINCIPLE: A mock response that faithfully matches the HTTP request is NEVER a mock issue, even if downstream nodes needed different data. If the request didn't ask for a field, the mock shouldn't invent it. The fault lies with whatever built the request (the node choice or its configuration). + - Did a node fail to resolve a configured resource against a listing/lookup response (e.g. "X not found") even though the mock's response contains an entity whose name/title matches the configured value? Ask: could ANY faithful response have satisfied the lookup? When the node config holds an identifier of the wrong kind — e.g. a human-readable NAME stored in an id/list-mode resource locator value, which the node parses as a number or compares against numeric IDs — no response the real API could ever return would match, and the workflow fails identically against the real service. That is a builder_issue (wrong resource-locator mode / invented identifier), NOT a mock_issue. Conversely, when the configured mode resolves by name/title and a faithful response WOULD have matched the configured value, the failed lookup means the mock's response shape was wrong — that IS a mock_issue. + 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 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. ## Failure categories When a checklist item fails, categorize the root cause: -- **builder_issue**: The AI agent that built the workflow misconfigured a node (missing parameters, wrong settings, incomplete config, wrong routing logic, missing nodes). Evidence: configIssues flags, nodes crashing before making HTTP requests, Switch/IF nodes missing required options, workflow structure doesn't match what the prompt asked for. Also applies when a Code node receives correct input data but its connected downstream branch produces wrong output — that's wrong node logic. **For Filter / IF / Switch: an item appearing in the unmatched branch is NOT wrong output — it's correctly routed there by the predicate. Only flag a builder_issue when items that should have matched the predicate end up in the wrong branch.** **Also applies when the builder produced an empty or trivial workflow (0 nodes, or only a trigger and no action nodes) — even if the build phase appears to have completed.** A "No trigger or start node found" execution error caused by zero nodes in the saved workflow is a builder failure, not a framework failure: the builder is responsible for committing at least a trigger. +- **builder_issue**: The AI agent that built the workflow misconfigured a node (missing parameters, wrong settings, incomplete config, wrong routing logic, missing nodes). Evidence: configIssues flags, nodes crashing before making HTTP requests, Switch/IF nodes missing required options, workflow structure doesn't match what the prompt asked for. Also applies when the configured identifier could never resolve against any faithful API response (wrong-kind resource-locator value, e.g. "Sheet with ID Reservas not found" — see the lookup bullet in step 3). Also applies when a Code node receives correct input data but its connected downstream branch produces wrong output — that's wrong node logic. **For Filter / IF / Switch: an item appearing in the unmatched branch is NOT wrong output — it's correctly routed there by the predicate. Only flag a builder_issue when items that should have matched the predicate end up in the wrong branch.** **Also applies when the builder produced an empty or trivial workflow (0 nodes, or only a trigger and no action nodes) — even if the build phase appears to have completed.** A "No trigger or start node found" execution error caused by zero nodes in the saved workflow is a builder failure, not a framework failure: the builder is responsible for committing at least a trigger. - **mock_issue**: The LLM mock handler returned incorrect or missing data. Evidence: _evalMockError in responses, mock response shape doesn't match what the node expects, mock data missing fields that downstream nodes reference. IMPORTANT: Trace the data flow carefully — if the mock returned correct data but a downstream filter or code node transformed it incorrectly, that is a builder_issue, not a mock_issue. - **legitimate_failure**: The workflow genuinely doesn't meet the success criteria and neither the builder nor mock is at fault. The test is working as designed — for example, the workflow lacks error handling that the scenario tests for. - **framework_issue**: The evaluation framework itself failed delivering input to an otherwise-built workflow. Evidence: a built workflow with at least a trigger node exists, but Phase 1 returned an error or the trigger output is empty (empty JSON object), causing cascading failures. Pre-analysis flags starting with "FRAMEWORK ISSUE", "Phase 1 error" warnings. DOES NOT apply when the workflow is empty (0 nodes) — that is a builder_issue, see above. @@ -75,34 +79,50 @@ NOT failure categories: - HTTP responses coming from the LLM mock instead of real APIs — this is expected - Trigger nodes having pinned/generated data instead of real events — this is expected - Placeholder or unresolved credential ID values in node configs — these are auto-substituted by the framework and never the cause of a failure +- Unset or placeholder resource IDs (e.g. Google Sheets document ID) when the success criteria explicitly allows deferred setup — not a builder_issue if mappings/structure are correct and the user-facing path still runs. An empty string in a resource-locator \`value\` field (not a placeholder) IS a builder_issue. + +## Deferred setup scenarios + +When success criteria say document/resource IDs may be unset or placeholder pre-setup: +- Judge structure, column mappings, and whether the user-facing completion step ran. +- Do not fail solely because a backend integration node logged config issues for an unset document when mock execution synthesized eval-safe IDs and the scenario's dataSetup steered a successful append. +- DO fail when \`__rl.value\` is an empty string — that is a builder misconfiguration, not deferred setup. ## Output format -Return ONLY a JSON array: +Return ONLY the structured result object with a top-level \`results\` array. +Every result object must include \`failureCategory\` and \`rootCause\`. +Use \`null\` for both fields when the checklist item passes. + +For passes: \`\`\`json -[ - { - "id": 1, - "pass": true, - "reasoning": "All nodes executed without errors. The webhook data flowed through Gmail, Telegram, and Google Sheets correctly.", - "failureCategory": null, - "rootCause": null - } -] +{ + "results": [ + { + "id": 1, + "pass": true, + "reasoning": "All nodes executed without errors. The webhook data flowed through Gmail, Telegram, and Google Sheets correctly.", + "failureCategory": null, + "rootCause": null + } + ] +} \`\`\` For failures: \`\`\`json -[ - { - "id": 1, - "pass": false, - "reasoning": "The Sort node crashed because the upstream Filter & Count node produced {noData: true} instead of items with a 'count' field.", - "failureCategory": "mock_issue", - "rootCause": "The Linear node's mock response didn't include creator.email, so the Filter code node filtered out all items." - } -] +{ + "results": [ + { + "id": 1, + "pass": false, + "reasoning": "The Sort node crashed because the upstream Filter & Count node produced {noData: true} instead of items with a 'count' field.", + "failureCategory": "mock_issue", + "rootCause": "The Linear node's mock response didn't include creator.email, so the Filter code node filtered out all items." + } + ] +} \`\`\` `; diff --git a/packages/@n8n/instance-ai/evaluations/types.ts b/packages/@n8n/instance-ai/evaluations/types.ts index a3a1f3888c6..e233d33ad58 100644 --- a/packages/@n8n/instance-ai/evaluations/types.ts +++ b/packages/@n8n/instance-ai/evaluations/types.ts @@ -2,7 +2,7 @@ // Shared types for the instance-ai workflow test case evaluator // --------------------------------------------------------------------------- -import type { InstanceAiEvalExecutionResult } from '@n8n/api-types'; +import type { InstanceAiEvalExecutionResult, InstanceAiRunDebugResponse } from '@n8n/api-types'; import type { CheckOutcome } from './binaryChecks/types'; import type { WorkflowResponse } from './clients/n8n-client'; @@ -150,6 +150,12 @@ export interface EventOutcome { agentActivities: AgentActivity[]; } +export interface BuildTrace { + finalText: string; + toolCalls: CapturedToolCall[]; + agentActivities: AgentActivity[]; +} + // --------------------------------------------------------------------------- // Workflow evaluation test cases // --------------------------------------------------------------------------- @@ -169,6 +175,8 @@ export interface ConversationTurn { } export interface WorkflowTestCase { + /** Optional human-readable note on what this case is testing (esp. for behaviour cases). */ + description?: string; /** * Hand-authored conversation that drives the build. Must have ≥1 turn, * and the first turn must be `user`. @@ -184,6 +192,10 @@ export interface WorkflowTestCase { executionScenarios: ExecutionScenario[]; /** Max follow-up messages the proxy will send. Ignored in auto-approve mode. */ messageBudget?: number; + /** Optional NL assertions about the build conversation; LLM-judged and counted toward the + * per-case + headline pass rate alongside execution scenarios (baseline-regression folding + * tracked separately in TRUST-158). */ + buildExpectations?: string[]; /** Logical groupings this case belongs to (e.g. `['pr', 'full']`). Defaults to `['full']`. */ datasets: string[]; } @@ -204,8 +216,19 @@ export interface ExecutionScenarioResult { rootCause?: string; } +/** Verdict for one author-written build expectation. Informational only. */ +export interface BuildExpectationResult { + expectation: string; + pass: boolean; + reason: string; + /** Judge returned no verdict (flaky/partial). Rendered neutrally, kept out of the count. */ + incomplete?: boolean; +} + export interface WorkflowTestCaseResult { testCase: WorkflowTestCase; + /** Source-file slug (matches the PR-comment / comparison label, for consistency). */ + fileSlug?: string; workflowId?: string; workflowBuildSuccess: boolean; buildError?: string; @@ -216,9 +239,15 @@ export interface WorkflowTestCaseResult { threadId?: string; transcript?: TranscriptTurn[]; workflowChecks?: CheckOutcome[]; + /** Captured build-time sub-agent/tool activity for builder debugging. */ + buildTrace?: BuildTrace; + /** Per-expectation verdicts from the build-expectations judge. Not consumed by pass@k. */ + buildExpectationResults?: BuildExpectationResult[]; /** Base URL of the n8n instance behind this run. Per-result so multi-lane * configs each get their own URL for canvas/execution links. */ n8nBaseUrl?: string; + /** Per-run LLM step debug captured from the instance-ai debug API after build. */ + runDebug?: InstanceAiRunDebugResponse[]; } // --------------------------------------------------------------------------- @@ -227,21 +256,55 @@ export interface WorkflowTestCaseResult { export interface TranscriptTurn { userMessage?: string; - agentText: string; - toolInteractions: ToolInteraction[]; + /** Agent narration and tool interactions, interleaved in the order they occurred. */ + steps: TranscriptStep[]; } +/** One ordered step within a turn: a slice of agent narration or a tool interaction. */ +/** Synthetic event type injected into the captured stream at each user-message + * send, so the transcript can group an agent's runs (and any resumes, which + * each emit their own `run-start`) under the message that triggered them. + * Ignored by the metric/outcome consumers (unknown type → default case). */ +export const USER_TURN_EVENT = 'eval-user-turn'; + +export type TranscriptStep = ToolInteraction | { kind: 'agent-text'; text: string }; + export type ToolInteraction = | { kind: 'plan'; tasks: PlanTask[] } | { kind: 'ask-user'; questions: AskUserQuestion[]; answers?: AskUserAnswer[] } + | { + kind: 'setup-card'; + requests: SetupCardRequest[]; + /** What the proxy did with the card. */ + outcome: 'filled' | 'skipped' | 'declined' | 'pending'; + /** Parameter names the proxy filled, when outcome is 'filled'. */ + filled?: string[]; + } | { kind: 'setup-wizard'; completedNodes: SetupWizardCompletedNode[]; skippedNodes: SetupWizardSkippedNode[]; reason?: string; } - | { kind: 'confirmation'; toolName: string; resumeReason: string; approved?: boolean } - | { kind: 'tool-call'; toolName: string }; + | { + kind: 'confirmation'; + toolName: string; + resumeReason: string; + approved?: boolean; + /** Prompt the agent showed when requesting confirmation. */ + message?: string; + /** Free-text the user sent with their decision (e.g. plan-review feedback). */ + feedback?: string; + } + | { + kind: 'tool-call'; + toolName: string; + toolCallId?: string; + args?: Record; + /** Tool output (success) or error message — paired to the call by toolCallId. */ + result?: unknown; + error?: string; + }; export interface PlanTask { title?: string; @@ -271,6 +334,13 @@ export interface SetupWizardSkippedNode { credentialType?: string; } +export interface SetupCardRequest { + nodeName: string; + credentialType?: string; + /** Non-credential parameters the card asks the user to fill, by name. */ + params?: string[]; +} + // --------------------------------------------------------------------------- // Multi-run aggregation // --------------------------------------------------------------------------- @@ -286,11 +356,25 @@ export interface ExecutionScenarioAggregation { passHatK: number[]; } +/** A build expectation aggregated across runs as a measured unit (granular, alongside scenarios). */ +export interface BuildExpectationAggregation { + expectation: string; + runs: BuildExpectationResult[]; + /** Runs where the judge returned a verdict (excludes `incomplete`). */ + evaluatedCount: number; + passCount: number; + passRate: number; + passAtK: number[]; + passHatK: number[]; +} + export interface TestCaseAggregation { testCase: WorkflowTestCase; runs: WorkflowTestCaseResult[]; buildSuccessCount: number; executionScenarios: ExecutionScenarioAggregation[]; + /** Build expectations aggregated as measured units (counted in the pass rate). */ + buildExpectations: BuildExpectationAggregation[]; } export interface MultiRunEvaluation { diff --git a/packages/@n8n/instance-ai/evaluations/utils/conversation-text.ts b/packages/@n8n/instance-ai/evaluations/utils/conversation-text.ts index ca1afc44021..bf5b3e4008f 100644 --- a/packages/@n8n/instance-ai/evaluations/utils/conversation-text.ts +++ b/packages/@n8n/instance-ai/evaluations/utils/conversation-text.ts @@ -1,4 +1,4 @@ -import type { TranscriptTurn } from '../types'; +import type { ToolInteraction, TranscriptStep, TranscriptTurn } from '../types'; /** * User-side turns from a captured transcript, flattened as a text block for @@ -13,3 +13,146 @@ export function userTurnsAsText(transcript: TranscriptTurn[]): string { if (turns.length === 1) return turns[0]; return turns.map((text, i) => `Turn ${String(i + 1)}: ${text}`).join('\n\n'); } + +/** Full transcript (agent narration + tool interactions, in order) as plain text for LLM-judged checks. */ +export function transcriptAsText(transcript: TranscriptTurn[]): string { + return transcript + .map((turn, i) => { + const lines: string[] = [`### Turn ${String(i + 1)}`]; + if (turn.userMessage) lines.push(`User: ${turn.userMessage}`); + for (const step of turn.steps) { + const line = describeStep(step); + if (line) lines.push(line); + } + return lines.join('\n'); + }) + .join('\n\n'); +} + +/** Concatenated agent narration across a turn's steps (excludes tool interactions). */ +export function agentTextOf(turn: TranscriptTurn): string { + return turn.steps.flatMap((s) => (s.kind === 'agent-text' ? [s.text] : [])).join(''); +} + +// Cap each serialized field to bound judge token cost (matches the report's cap). +const MAX_STEP_CHARS = 2000; + +function cap(text: string): string { + return text.length > MAX_STEP_CHARS + ? `${text.slice(0, MAX_STEP_CHARS)}… (${String(text.length - MAX_STEP_CHARS)} more chars)` + : text; +} + +function capJson(value: unknown): string { + let str: string; + try { + str = typeof value === 'string' ? value : (JSON.stringify(value) ?? String(value)); + } catch { + str = ''; + } + return cap(str); +} + +function describeStep(step: TranscriptStep): string | null { + if (step.kind === 'agent-text') { + return step.text ? `Assistant: ${cap(step.text)}` : null; + } + return describeInteraction(step); +} + +function describeInteraction(interaction: ToolInteraction): string | null { + switch (interaction.kind) { + case 'plan': { + if (interaction.tasks.length === 0) return null; + const items = interaction.tasks + .map((t, i) => { + const title = t.title ?? `Task ${String(i + 1)}`; + return t.description ? `${title}: ${t.description}` : title; + }) + .join('; '); + return cap(`Plan (${String(interaction.tasks.length)}): ${items}`); + } + case 'ask-user': { + if (interaction.questions.length === 0) return null; + const answerByQId = new Map(); + for (const a of interaction.answers ?? []) { + const text = a.skipped + ? '(skipped)' + : [a.selectedOptions.join(', '), a.customText].filter(Boolean).join(' — '); + if (text) answerByQId.set(a.questionId, text); + } + const qs = interaction.questions + .map((q) => { + const opts = q.options && q.options.length > 0 ? ` [${q.options.join(' / ')}]` : ''; + const answer = answerByQId.get(q.id); + return `Q: ${q.question}${opts}${answer ? ` -> A: ${answer}` : ''}`; + }) + .join(' | '); + return `Asked user: ${qs}`; + } + case 'setup-wizard': { + const parts: string[] = []; + if (interaction.completedNodes.length > 0) { + const configured = interaction.completedNodes.map((c) => + c.parametersSet && c.parametersSet.length > 0 + ? `${c.nodeName} (${c.parametersSet.join(', ')})` + : c.nodeName, + ); + parts.push(`configured ${configured.join('; ')}`); + } + if (interaction.skippedNodes.length > 0) { + const skipped = interaction.skippedNodes.map( + (s) => + `${s.nodeName}${s.credentialType ? ` (needs ${s.credentialType} credential)` : ' (needs parameters)'}`, + ); + parts.push(`skipped ${skipped.join(', ')}`); + } + const body = parts.length > 0 ? parts.join('; ') : 'nothing to apply'; + return `Setup wizard: ${body}${interaction.reason ? ` — ${interaction.reason}` : ''}`; + } + case 'setup-card': { + if (interaction.requests.length === 0) return null; + const asks = interaction.requests.map((r) => { + const needs: string[] = []; + if (r.credentialType) needs.push(`${r.credentialType} credential`); + if (r.params && r.params.length > 0) needs.push(`params: ${r.params.join(', ')}`); + return `${r.nodeName}${needs.length > 0 ? ` (${needs.join('; ')})` : ''}`; + }); + const outcome = + interaction.outcome === 'filled' + ? `filled${interaction.filled && interaction.filled.length > 0 ? ` (${interaction.filled.join(', ')})` : ''} by user` + : interaction.outcome === 'skipped' + ? 'skipped by user' + : interaction.outcome === 'declined' + ? 'dismissed by user' + : 'no response'; + return `Asked user via setup card: ${asks.join('; ')} — ${outcome}`; + } + case 'confirmation': { + const decision = + typeof interaction.approved === 'boolean' + ? interaction.approved + ? ' (approved)' + : ' (rejected)' + : ''; + // Include the prompt and the user's free-text feedback (e.g. plan-rejection reason). + const parts = [`Resume ${interaction.toolName}: ${interaction.resumeReason}${decision}`]; + if (interaction.message) parts.push(`prompt: ${cap(interaction.message)}`); + if (interaction.feedback) parts.push(`user feedback: ${cap(interaction.feedback)}`); + return parts.join(' — '); + } + case 'tool-call': { + // Args/result are the evidence for node-choice expectations; redacted upstream. + const parts = [`Tool: ${interaction.toolName}`]; + if (interaction.args && Object.keys(interaction.args).length > 0) { + parts.push(`args: ${capJson(interaction.args)}`); + } + if (interaction.error) { + parts.push(`error: ${cap(interaction.error)}`); + } else if (interaction.result !== undefined) { + parts.push(`result: ${capJson(interaction.result)}`); + } + return parts.join(' '); + } + } +} diff --git a/packages/@n8n/instance-ai/evaluations/utils/user-proxy/index.ts b/packages/@n8n/instance-ai/evaluations/utils/user-proxy/index.ts index 8b9703a4343..b49850082fa 100644 --- a/packages/@n8n/instance-ai/evaluations/utils/user-proxy/index.ts +++ b/packages/@n8n/instance-ai/evaluations/utils/user-proxy/index.ts @@ -10,6 +10,7 @@ import { buildAutoApprovePayload } from '../../harness/chat-loop'; import type { NextMessageDecision } from '../../harness/chat-loop'; import type { EvalLogger } from '../../harness/logger'; import type { CapturedEvent, ConversationTurn } from '../../types'; +import { getEventPayload } from '../confirmation-payload'; import { getNestedRecord, getString } from '../safe-extract'; /** @@ -73,6 +74,8 @@ export class UserProxyLlm { private messagesSent = 0; private ingestedEventCount = 0; private readonly seenRequestIds = new Set(); + private readonly responseByRequestId = new Map(); + private readonly sentScriptUserTurnIndexes = new Set(); private readonly decisionStats: ProxyDecisionStats = {}; constructor(config: UserProxyConfig) { @@ -84,6 +87,9 @@ export class UserProxyLlm { // Seed with the opener — the harness has already sent it. const opener = this.script[0]; this.actualTranscript = opener ? [{ role: opener.role, text: opener.text }] : []; + if (opener?.role === 'user') { + this.sentScriptUserTurnIndexes.add(0); + } } getMessagesSent(): number { @@ -118,17 +124,21 @@ export class UserProxyLlm { async respondToConfirmation(event: CapturedEvent): Promise { const requestId = extractRequestId(event); const isRepeat = requestId !== undefined && this.seenRequestIds.has(requestId); - if (requestId) this.seenRequestIds.add(requestId); - if (isRepeat) { this.bumpStat('repeat'); - return buildAutoApprovePayload(event); + return this.responseByRequestId.get(requestId) ?? buildAutoApprovePayload(event); } const det = tryDeterministicConfirmationResponse(event); if (det) { this.bumpStat('deterministic'); - return det; + return this.rememberResponse(requestId, det); + } + + const scripted = this.tryScriptedConfirmationResponse(event); + if (scripted) { + this.bumpStat('deterministic'); + return this.rememberResponse(requestId, scripted); } const prompt = buildConfirmationPrompt(this.promptContext(), event); @@ -136,7 +146,7 @@ export class UserProxyLlm { if (!decision) { this.logger?.warn(`[user-proxy] no decision; event=${summarizeEvent(event)}`); this.bumpStat('fallback-no-decision'); - return buildAutoApprovePayload(event); + return this.rememberResponse(requestId, this.fallbackConfirmationResponse(event)); } const encoded = encodeConfirmationDecision(decision, (raw, parseError) => @@ -149,11 +159,11 @@ export class UserProxyLlm { `[user-proxy] action=${decision.action} did not encode to a confirmation payload`, ); this.bumpStat('fallback-unencoded'); - return buildAutoApprovePayload(event); + return this.rememberResponse(requestId, this.fallbackConfirmationResponse(event)); } this.recordDecision(decision, encoded, event); - return encoded; + return this.rememberResponse(requestId, encoded); } private bumpStat(category: ProxyDecisionCategory): void { @@ -190,7 +200,14 @@ export class UserProxyLlm { const prompt = buildFollowUpPrompt(this.promptContext()); const decision = await this.agent.decide(prompt); - if (!decision) return { kind: 'done' }; + if (!decision) { + const [next] = this.remainingUserScriptTurns(); + if (!next || hasStageDirection(next.text)) return { kind: 'done' }; + const scriptedMessage = this.consumeNextRemainingUserScriptTurn(); + if (!scriptedMessage) return { kind: 'done' }; + this.messagesSent++; + return { kind: 'followUp', message: scriptedMessage }; + } if (decision.action === 'send_follow_up_message') { const message = decision.message.trim(); @@ -212,12 +229,90 @@ export class UserProxyLlm { actualTranscript: this.actualTranscript, }; } + + private rememberResponse( + requestId: string | undefined, + response: InstanceAiConfirmRequest, + ): InstanceAiConfirmRequest { + if (requestId) { + this.responseByRequestId.set(requestId, response); + this.seenRequestIds.add(requestId); + } + return response; + } + + private fallbackConfirmationResponse(event: CapturedEvent): InstanceAiConfirmRequest { + return this.tryScriptedConfirmationResponse(event) ?? buildAutoApprovePayload(event); + } + + private tryScriptedConfirmationResponse( + event: CapturedEvent, + ): InstanceAiConfirmRequest | undefined { + const payload = getEventPayload(event); + const inputType = getString(payload, 'inputType'); + + if (this.remainingUserScriptTurns().some((turn) => hasStageDirection(turn.text))) { + return undefined; + } + + // ask-user questions go to the LLM; only single-blob plan-review/text are scripted here. + if (inputType === 'plan-review') { + const userInput = this.consumeAllRemainingUserScriptTurns( + 'Before I approve, use these details:', + ); + if (userInput) return { kind: 'approval', approved: false, userInput }; + } + + if (inputType === 'text') { + const userInput = this.consumeAllRemainingUserScriptTurns(); + if (userInput) return { kind: 'approval', approved: true, userInput }; + } + + return undefined; + } + + private consumeAllRemainingUserScriptTurns(prefix?: string): string | undefined { + const turns = this.remainingUserScriptTurns(); + if (turns.length === 0) return undefined; + + for (const turn of turns) { + this.sentScriptUserTurnIndexes.add(turn.index); + } + + const text = turns.map((turn) => turn.text).join('\n\n'); + this.actualTranscript.push({ role: 'user', text }); + return prefix ? `${prefix}\n${text}` : text; + } + + private consumeNextRemainingUserScriptTurn(): string | undefined { + const [turn] = this.remainingUserScriptTurns(); + if (!turn) return undefined; + + this.sentScriptUserTurnIndexes.add(turn.index); + this.actualTranscript.push({ role: 'user', text: turn.text }); + return turn.text; + } + + private remainingUserScriptTurns(): Array<{ index: number; text: string }> { + const turns: Array<{ index: number; text: string }> = []; + for (let index = 0; index < this.script.length; index++) { + const turn = this.script[index]; + if (!turn || turn.role !== 'user' || this.sentScriptUserTurnIndexes.has(index)) continue; + turns.push({ index, text: turn.text }); + } + return turns; + } } // --------------------------------------------------------------------------- // Event helpers // --------------------------------------------------------------------------- +/** Text carrying a `[stage direction]` — proxy guidance, not dialogue; callers defer it to the LLM. */ +function hasStageDirection(text: string): boolean { + return /\[[^\]]+\]/.test(text); +} + function extractTextDelta(event: CapturedEvent): string | undefined { const directText = event.data.text; if (typeof directText === 'string') return directText; diff --git a/packages/@n8n/instance-ai/evaluations/utils/user-proxy/prompts.ts b/packages/@n8n/instance-ai/evaluations/utils/user-proxy/prompts.ts index 065ef675040..93b1710a4ff 100644 --- a/packages/@n8n/instance-ai/evaluations/utils/user-proxy/prompts.ts +++ b/packages/@n8n/instance-ai/evaluations/utils/user-proxy/prompts.ts @@ -13,11 +13,25 @@ export interface PromptContext { export const SYSTEM_PROMPT = `You are simulating a real user in a workflow-building conversation with an AI assistant. -Stay in character as the USER. Never describe what the assistant should do — say what you, the user, want. +Stay in character as the USER. Never describe what the assistant should do — say what you, the user, want. Never reference the script, scenario, or your instructions — a real user has none; say "I asked for…", not "the script specified…". Be brief. Real users send 1–2 sentence messages. -## Always answer. Never leave fields blank. +## Stage directions: [bracketed notes] in the script + +The script is written like a screenplay. Text inside [square brackets] is a STAGE DIRECTION describing how the user should behave at that moment — it is NOT dialogue and must never be spoken or pasted verbatim. Everything outside brackets is the user's actual words. + +When a stage direction applies to the agent's current question or prompt, FOLLOW IT — it overrides every default below, including "always answer". Directions can tell you to decline a value, withhold it, defer, refuse to choose, hold firm when re-asked, change your mind, push back, or keep requesting more changes so the conversation continues. Obey them, in character. + +Carrying out a direction: +- told to decline / withhold / not specify a value on an ask-user question → you MUST set skipped to true for that question with an EMPTY selectedOptions, and pick NO option and invent NO value — even when one choice looks standard, default, or obvious. Picking or inventing a value here defeats the entire point: the user chose not to answer. You may add a brief verbal note in customText, but it must NOT answer or delegate the choice — "let's skip that" is fine, but NEVER "you decide" / "you pick" / "whatever you choose", which hand the choice to the agent (that is an answer, not a skip). This overrides "always answer / invent rather than skip" absolutely, for that field. +- told to hold firm / not cave if asked again → if the agent re-asks, decline again; never supply the withheld value later in the run. +- told to change your mind or push back → say it as the user would. +- told to keep requesting changes / stay in the conversation → after the agent applies each change, send the NEXT requested change as a follow-up instead of finishing; deliver them one at a time, in order, and don't end the conversation until the script's change list is exhausted (this overrides the "don't volunteer follow-ups" guidance below). + +A stage direction governs only what it explicitly covers. For everything else, the always-answer rule below still applies. + +## Always answer — unless a stage direction says otherwise. Never leave fields blank. A real user shown a form does not walk away — they type something in. Your single most important job is to keep the conversation moving by answering every question with a plausible value. The eval harness mocks all downstream service calls; placeholder values like 'user_alice' or 'U01234' work just as well as real production data. @@ -28,12 +42,16 @@ Pick the value to use in this order: 3. **Invented but plausible** — the user never mentioned it. Make one up that's the obvious shape and would let the workflow run. e.g. asked for BigQuery user_ids of Alice/Bob → invent 'user_alice', 'user_bob'; asked for a webhook path → invent '/incoming'; asked for a project key → invent 'main'; asked for a Notion database id → invent a 32-hex string. -Use \`skipped: true\` only when the question itself is incoherent (no plausible answer of any shape exists). Reluctance to invent is a bug — invent. +Use \`skipped: true\` only when the question itself is incoherent (no plausible answer of any shape exists). Reluctance to invent is a bug — invent. (The sole exception: a [stage direction] in the script that tells the user to decline or withhold a value — then set skipped to true for that field and do not invent.) ## One exception: credentials Never set credentials. They're deferred and the user will configure them via the UI. Credentials are the one and only thing left blank. +## Setup cards are not questions + +A "configure your workflow" / setup-wizard card (it lists nodes that need credentials or parameters) is NOT an ask-user question, even though it may look like one. Fill its non-credential parameters with \`apply_setup_wizard\`. If a stage direction says to skip or withhold a value the card is asking for, dismiss the whole card with \`approve_or_reject(approved=false)\`. Never answer a setup card with \`answer_questions\`. + ## Pushing back on plans and summaries When the agent shows a plan, summary, or "here's what I'll build" preview, **audit it against the script**. The agent is designed to make assumptions rather than ask, so its plan often omits or substitutes things the user actually stated in the script. @@ -54,7 +72,7 @@ You'll be given a SCRIPT (what the user wants overall) and the ACTUAL CONVERSATI - The script is a reference for what the user MIGHT say — not a checklist to mechanically deliver. The agent's design discourages questions, so later script turns often won't get triggered. That's expected. - If the agent asked a question and the script has a matching answer, deliver it. If the agent asked something the script doesn't cover and credentials aren't involved, give a brief plausible reply. -- If the agent finished without asking and the plan was already approved or rejected appropriately, pick \`declare_done\`. Don't volunteer late script content as a proactive follow-up — the plan-rejection path is the right channel for steering. +- If the agent finished without asking and the plan was already approved or rejected appropriately, pick \`declare_done\`. Don't volunteer late script content as a proactive follow-up — the plan-rejection path is the right channel for steering. (Exception: a stage direction telling you to keep requesting changes overrides this — send the next change as a follow-up even after a successful build.) - When delivering a script user turn, adapt its wording so it reads as a real reply to the agent's last message — but keep every concrete value verbatim. - Don't restate what's already in the transcript. - Credentials: if the agent stalls on credentials, send "I'll set them up later — please build without them." Do not provide credentials. @@ -79,7 +97,8 @@ export function buildFollowUpPrompt(ctx: PromptContext): string { 'The agent has just finished a run. Decide what the user would say next.', '', "Pick `send_follow_up_message` when the agent asked a question (in its last response) or stalled and needs unblocking. If the script answers the question, deliver that answer with concrete values verbatim. If the script doesn't cover it and credentials aren't involved, give a brief plausible reply.", - 'Pick `declare_done` when the agent finished a build, approved/rejected a plan appropriately, or otherwise has no open thread for the user to respond to. The script is a reference, not a checklist — late script content gets surfaced via plan rejection, not unsolicited follow-ups.', + 'If a stage direction tells the user to keep requesting changes or stay in the conversation, pick `send_follow_up_message` with the NEXT change — even after a successful build — until the change list is exhausted.', + 'Pick `declare_done` when the agent finished a build, approved/rejected a plan appropriately, or otherwise has no open thread for the user to respond to. The script is a reference, not a checklist — late script content gets surfaced via plan rejection (or an explicit keep-going direction), not unsolicited follow-ups.', ].join('\n\n'); } @@ -88,7 +107,10 @@ export function buildFollowUpPrompt(ctx: PromptContext): string { // --------------------------------------------------------------------------- function formatScriptSection(ctx: PromptContext): string { - const lines: string[] = ['## Script (what the user intends to say across this build)']; + const lines: string[] = [ + '## Script (what the user intends to say across this build)', + 'Text in [brackets] is a stage direction — act on it (e.g. decline), never speak it verbatim.', + ]; for (const turn of ctx.script) { lines.push(`${turn.role === 'user' ? 'USER' : 'ASSISTANT'}: ${turn.text}`); } diff --git a/packages/@n8n/instance-ai/evaluations/utils/user-proxy/tools.ts b/packages/@n8n/instance-ai/evaluations/utils/user-proxy/tools.ts index 1340c9b7f06..799d1f919e7 100644 --- a/packages/@n8n/instance-ai/evaluations/utils/user-proxy/tools.ts +++ b/packages/@n8n/instance-ai/evaluations/utils/user-proxy/tools.ts @@ -56,9 +56,9 @@ export type Decision = z.infer; export const TOOL_DESCRIPTIONS = `Available actions: -- answer_questions(answers[]): The agent fired an ask-user confirmation (inputType=questions). Answer every question with a plausible value — stated → implied → invented. Invent rather than skip. Only set skipped=true when the question has no plausible answer of any shape. +- answer_questions(answers[]): The agent fired an ask-user confirmation (inputType=questions). Answer every question with a plausible value — stated → implied → invented. Invent rather than skip. Set skipped=true only when the question has no plausible answer of any shape, OR when a [stage direction] in the script tells the user to decline or withhold that value — in that case you MUST set skipped=true with an empty selectedOptions and pick NO option (not even one that looks standard or obvious); picking a value defeats the test. -- apply_setup_wizard(nodeParametersJson): The agent fired a setup-wizard event with placeholder parameters. Emit a JSON string that decodes to { "": { "": , ... }, ... }. Fill every non-credential placeholder with a plausible value — stated → implied → invented. Never set credentials. +- apply_setup_wizard(nodeParametersJson): The agent fired a setup-wizard / "configure your workflow" setup card with placeholder parameters. Emit a JSON string that decodes to { "": { "": , ... }, ... }. Fill every non-credential placeholder with a plausible value — stated → implied → invented. Never set credentials. This is the ONLY correct way to fill a setup card — do NOT answer it with answer_questions. To deliberately leave a value unset (e.g. a stage direction says the user skips it), dismiss the whole card with approve_or_reject(approved=false) instead of filling it. - approve_or_reject(approved, userInput?): The agent showed a plan (plan-review) or asked an open free-text question (inputType=text). Approve if the plan matches user intent; reject with reason if it diverges. diff --git a/packages/@n8n/instance-ai/knowledge-base/reference/open-ai-output-shape.md b/packages/@n8n/instance-ai/knowledge-base/reference/open-ai-output-shape.md new file mode 100644 index 00000000000..d72cd9ea305 --- /dev/null +++ b/packages/@n8n/instance-ai/knowledge-base/reference/open-ai-output-shape.md @@ -0,0 +1,79 @@ +# OpenAI node output shape + +Node type: `@n8n/n8n-nodes-langchain.openAi` (default type version **2.3**) + +Use this when mapping downstream fields from an OpenAI node with `$json.` or +`$('NodeName').item.json.`. Output shape depends on **node type version**, +resource, operation, and simplify settings — consult `nodes(action="type-definition")` +when in doubt. + +## Version and operation + +| Node version | Text operation | API | +| --- | --- | --- | +| **v2+** (default) | `response` | OpenAI Responses API | +| **v1.x** | `message` | Chat Completions API | + +On v2+, `operation: message` is invalid. Prefer v2 with `operation: response` for +new workflows. The sections below match the operation for each version. + +Default **Simplify Output** is `true` on both paths unless noted otherwise. + +## Text → Response — v2+ (`resource: text`, `operation: response`) + +With simplify enabled (default), the node emits only `message`-type output items: + +```json +{ + "output": [ + { + "type": "message", + "role": "assistant", + "content": [{ "type": "output_text", "text": "..." }] + } + ] +} +``` + +For a simple single-message text reply, read the assistant text with +**`$json.output[0].content[0].text`**. Do not use `$json.text` — that field does +not exist on this output. + +When the downstream node has a different immediate upstream (e.g. Google Sheets +after OpenAI, with form fields from an earlier node), use an explicit node +reference: + +`={{ $('Generate Confirmation').first().json.output[0].content[0].text }}` + +### Caveats (response) + +- **`[0]` is a convenience, not universal.** Simplified `output` can contain + multiple `message` items, and each message can have multiple `content` parts. + Pick the index that matches the text you need. +- **Structured / JSON output** (`text.format.type` of `json_object` or + `json_schema`): `content[].text` is parsed into an **object**, not a string. +- **`simplify: false`**: `$json` is the full Responses API payload (`id`, `status`, + `output`, `usage`, …). Message text is still under `output`, but `output` may + also include non-message items (reasoning, tool calls, etc.). +- **Tool-heavy runs**: if no `message`-type item exists, `output[0]` may be wrong + or missing — inspect `$json.output` or disable simplify. + +## Text → Message — v1.x only (`resource: text`, `operation: message`) + +With simplify enabled (default), each choice object is emitted at the root of +`$json` (fields such as `message`, `index`, `finish_reason`). Read assistant +content from **`$json.message.content`**, not `$json.text`. + +`message.content` is a **string** for plain text replies. + +### Caveats (message) + +- **v1 only.** Do not use this section when configuring or referencing v2 nodes. +- **Output Content as JSON** enabled: `message.content` may be a parsed **object**, + not a string. +- **`simplify: false`**: `$json` is the full completion (`choices`, `usage`, …). + Read text from `$json.choices[0].message.content`. +- **Multiple choices** (`n` > 1): the node emits one item per choice; each item + has its own `$json.message`. +- **Tool calls**: `message.content` may be empty and `message.tool_calls` may be + populated instead. diff --git a/packages/@n8n/instance-ai/knowledge-base/reference/trigger-input-data-shapes.md b/packages/@n8n/instance-ai/knowledge-base/reference/trigger-input-data-shapes.md new file mode 100644 index 00000000000..4c0dab17264 --- /dev/null +++ b/packages/@n8n/instance-ai/knowledge-base/reference/trigger-input-data-shapes.md @@ -0,0 +1,38 @@ +# Per-trigger `inputData` shape + +Used by `verify-built-workflow`, `executions(action="run")`, and checkpoint +verification. The pin-data adapter spreads or wraps based on trigger type — +passing the wrong shape gives null downstream values that look like an +expression bug. + +## Form Trigger (`n8n-nodes-base.formTrigger`) + +Flat field map, e.g. `{name: "Alice", email: "a@b.c"}`. The production Form +Trigger emits each field directly on `$json`, so the builder's `$json.` +expressions are correct. **Do NOT wrap in `formFields`** — the adapter will +reject the call. + +## Webhook (`n8n-nodes-base.webhook`) + +The body payload, e.g. `{event: "signup", userId: "..."}`. The adapter wraps it +under `body`, so downstream nodes reference `$json.body.`. + +## Chat Trigger (`@n8n/n8n-nodes-langchain.chatTrigger`) + +`{chatInput: "user message"}`. + +## Schedule Trigger (`n8n-nodes-base.scheduleTrigger`) + +Omit `inputData`; the adapter emits synthetic timestamp fields. + +## Other event triggers + +Linear, GitHub, Slack, MCP, and similar triggers: pass `inputData` matching the +trigger's expected payload shape from the node type definition. + +## Debugging wrong null values + +**Do not patch a workflow first when verify returns null downstream values.** +Re-run verify with the corrected `inputData` shape. Only patch the workflow if +the expression is wrong against the *production* trigger output shape (consult +node descriptions), not the `instanceAi` pin data path. diff --git a/packages/@n8n/instance-ai/knowledge-base/reference/workflow-builder-guardrails.md b/packages/@n8n/instance-ai/knowledge-base/reference/workflow-builder-guardrails.md new file mode 100644 index 00000000000..defe16a8df5 --- /dev/null +++ b/packages/@n8n/instance-ai/knowledge-base/reference/workflow-builder-guardrails.md @@ -0,0 +1,101 @@ +# Workflow Builder Guardrails + +Use these guardrails for workflow builds with multiple external systems, +multiple requested effects, digests or reports, non-trivial branching, or Code +nodes. They are a runtime checklist, not extra user-facing output. + +## Preserve Source Data + +Normalize trigger or source data before side effects. Nodes that create, update, +send, or log data often replace the current item JSON with their API response. +If later conditions, messages, upserts, or alerts still need source fields, fan +out from the normalized source item, preserve the fields explicitly, or read +from the correct upstream node. + +Do not recover source identity from item positions after an external read that +can fan one source into many records. Carry fields such as channel, city, +account, request ID, team, label, or origin on the current item before fan-out, +and create failure records with explicit source fields only on real error paths. + +## Keep Effects Independent + +When the user asks for multiple final effects from the same trigger, each effect +must be represented by a real terminal action node on the success path. A +formatter, validation branch, prompt builder, aggregate, or disabled action does +not satisfy a request to send, post, respond, create, update, notify, log, or +upsert. + +Gate only the effect that needs a field. A missing email may skip email sending; +it should not block logging, acknowledgement, or team notification unless the +user explicitly asked for all-or-nothing behavior. + +When one source or final effect may fail independently, use the node's supported +continue/error-output behavior. Feed downstream fan-in with either success data +or one real failure record per source/effect. Do not emit both success and +synthetic failure records for the same source/effect. + +## Preserve List Semantics + +HTTP and app nodes may return one n8n item per record, a top-level array, or an +envelope such as `records`, `body`, or `data`. Before per-record filtering, +upserting, or posting, check the actual item shape. Preserve itemized flow or +split arrays into one item per record; do not collapse to no work because +`$input.first().json` is a single object. + +A top-level array response (for example Binance klines, list endpoints, search +results) is split by the HTTP Request node into one item per element, so +`$input.first().json` is a single element, not the whole array. In a Code node +that must process every row, read `$input.all().map(i => i.json)` (or iterate +the items) instead of mapping over `$input.first().json`, which would only see +the first record and produce null/empty downstream values. + +When a downstream node must reason over the whole collection at once — a single +AI Agent analysing a series, an indicator/metric computed across all rows, a +summary, or a structured-output parser expecting one object — first aggregate +the split items into a single item with a Code node (`return [{ json: { rows: +$input.all().map(i => i.json) } }]`) and feed that one item in. A single-shot +Agent or output parser wired directly to N split items runs once per row and +produces malformed or unparseable output. + +For one digest, ranking, summary, count, or report, aggregate first and send one +final item. For one action per source record, keep the stream itemized. Use +`executeOnce: true` only for shared-context reads, report construction, +rankings, summaries, or final one-message posts that should run once. + +Avoid using `SplitInBatches` as the collector for a fixed set of external +sources in a digest/report path. Its done branch does not accumulate loop-body +outputs. Prefer parallel source branches plus explicit fan-in, or emit one +success/empty/failure record per source before aggregation. + +## Fetch Complete External Data + +If downstream logic depends on labels, memberships, related records, nested +fields, owners, creators, timestamps, date windows, or pagination data, request +those fields explicitly. Do not infer related facts from whichever primary +records happened to arrive first. If the native node cannot fetch the required +shape, use HTTP Request or another API-capable node. + +For reports that combine named sources, make sure every named source has a +reachable read/query/fetch node before the formatter and final action. A +schedule item, date-window calculator, placeholder row, or final formatter is +not source data. + +## Keep Code Nodes Parseable + +Prefer built-in nodes for simple split, map, filter, merge, and aggregate work. +When a Code node is necessary, use real n8n item APIs such as `$input.all()` and +return explicit `json` objects. + +Code nodes run in a restricted runtime. Do not `require()` or `import` +unavailable modules such as `luxon` or `openai`; use JavaScript `Date`, `Intl`, +`$now`, `$today`, existing workflow data, or dedicated AI nodes. + +Code nodes have no network access. `fetch()`, `axios`, `XMLHttpRequest`, and +`require` of http modules all fail at runtime, in JavaScript and Python alike. +Make every HTTP/API call with the HTTP Request node and transform its output in +the Code node, even when the user asks to fetch inside a Code node. + +Keep embedded Code node source parseable after saving. Avoid nested template +literals, raw newlines inside quoted strings, and escape-heavy regex literals. +Prefer arrays joined with a runtime separator such as +`const LF = String.fromCharCode(10);`. diff --git a/packages/@n8n/instance-ai/package.json b/packages/@n8n/instance-ai/package.json index 4510af94057..7f8b77e852d 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.10.0", + "version": "1.12.0", "scripts": { "clean": "rimraf dist .turbo", "typecheck": "tsc --noEmit", @@ -28,6 +28,7 @@ "types": "dist/index.d.ts", "files": [ "dist/**/*", + "knowledge-base/**/*", "skills/**/*" ], "exports": { @@ -52,12 +53,12 @@ }, "dependencies": { "@daytonaio/sdk": "catalog:", - "@joplin/turndown-plugin-gfm": "^1.0.12", - "@mozilla/readability": "^0.6.0", + "@joplin/turndown-plugin-gfm": "catalog:", + "@langchain/anthropic": "catalog:", + "@mozilla/readability": "catalog:", "@n8n/agents": "workspace:*", "@n8n/api-types": "workspace:*", "@n8n/mcp-browser": "workspace:*", - "@n8n/sandbox-client": "0.0.4", "@n8n/utils": "workspace:*", "@n8n/workflow-sdk": "workspace:*", "@opentelemetry/api": "^1.9.0", @@ -74,14 +75,14 @@ "p-limit": "^3.1.0", "pdf-parse": "catalog:", "psl": "1.9.0", - "turndown": "^7.2.0", + "source-map-support": "catalog:", + "turndown": "catalog:", "xlsx": "https://cdn.sheetjs.com/xlsx-0.20.2/xlsx-0.20.2.tgz", "zod": "catalog:", "zod-from-json-schema-v3": "npm:zod-from-json-schema@^0.0.5" }, "devDependencies": { "@ai-sdk/anthropic": "catalog:", - "@langchain/anthropic": "catalog:", "@langchain/core": "catalog:", "@n8n/ai-workflow-builder": "workspace:*", "@n8n/typescript-config": "workspace:*", @@ -93,5 +94,6 @@ "tsx": "catalog:", "vitest": "catalog:", "vitest-mock-extended": "catalog:" - } + }, + "license": "LicenseRef-n8n-sustainable-use" } diff --git a/packages/@n8n/instance-ai/scripts/build-snapshot.cjs b/packages/@n8n/instance-ai/scripts/build-snapshot.cjs index 091e8281949..8a337765151 100755 --- a/packages/@n8n/instance-ai/scripts/build-snapshot.cjs +++ b/packages/@n8n/instance-ai/scripts/build-snapshot.cjs @@ -5,16 +5,15 @@ * Run from the n8n release pipeline (see * `.github/workflows/release-build-daytona-snapshot.yml`). Authenticates * with a static Daytona admin API key supplied via env vars and creates - * the snapshot named `n8n/instance-ai:-` from the same image + * the snapshot named `n8n/instance-ai:` from the same image * descriptor used by the runtime fallback path. Re-runs against the same * version are idempotent — "already exists" is treated as success. * - * The runtime never calls `snapshot.create` through the sandbox proxy in - * cloud mode; CI is the only producer of cloud snapshots. + * The runtime never calls `snapshot.create`; CI is the only producer of + * versioned snapshots. * * The actual create-with-already-exists logic lives in - * `SnapshotManager.createSnapshot` so the runtime (direct mode) and CI - * share a single implementation. + * `SnapshotManager.createSnapshot`. * * CommonJS so Node resolves the package via `main: dist/index.js` instead * of the bundler-only `module: src/index.ts` entry. diff --git a/packages/@n8n/instance-ai/scripts/print-prompts.ts b/packages/@n8n/instance-ai/scripts/print-prompts.ts index b50c2641fa9..acc920a7199 100644 --- a/packages/@n8n/instance-ai/scripts/print-prompts.ts +++ b/packages/@n8n/instance-ai/scripts/print-prompts.ts @@ -2,9 +2,9 @@ // --------------------------------------------------------------------------- // Print Prompts CLI // -// Renders the final system prompt for the main Instance Agent and every -// orchestration sub-agent, then writes one markdown file per agent variant -// into `.output/prompts//.md` (gitignored). Useful for +// Renders the final system prompt for the main Instance Agent and sub-agent +// prompt templates, then writes one markdown file per agent variant into +// `.output/prompts//.md` (gitignored). Useful for // auditing the full prompt verbatim, diffing prompts across branches, or // sharing them outside the codebase. // --------------------------------------------------------------------------- @@ -14,7 +14,6 @@ import { join, resolve } from 'path'; import { buildSubAgentPrompt } from '../src/agent/sub-agent-factory'; import { getSystemPrompt } from '../src/agent/system-prompt'; -import { PLANNER_AGENT_PROMPT } from '../src/tools/orchestration/plan-agent-prompt'; interface Variant { /** File name (without extension) inside the agent's folder. */ @@ -110,12 +109,6 @@ function collectAgents(): AgentEntry[] { }, ], }, - { - folder: 'planner', - displayName: 'Sub-Agent — Workflow Planner', - source: 'src/tools/orchestration/plan-agent-prompt.ts → PLANNER_AGENT_PROMPT', - variants: [{ file: 'prompt', body: PLANNER_AGENT_PROMPT }], - }, { folder: 'delegate', displayName: 'Sub-Agent — Generic Delegate (template)', diff --git a/packages/@n8n/instance-ai/scripts/run-eval-lanes.sh b/packages/@n8n/instance-ai/scripts/run-eval-lanes.sh new file mode 100755 index 00000000000..ae1b4e292ba --- /dev/null +++ b/packages/@n8n/instance-ai/scripts/run-eval-lanes.sh @@ -0,0 +1,399 @@ +#!/usr/bin/env bash +# +# Spin up N local n8n eval lanes and run eval:instance-ai against them. +# +# Usage: +# ./scripts/run-eval-lanes.sh --instance-count 5 +# ./scripts/run-eval-lanes.sh 5 --tier pr --verbose +# ./scripts/run-eval-lanes.sh --instance-count 3 --build -- --filter contact-form +# +# Requires: +# - docker +# - dotenvx (pnpm exec dotenvx works) +# - n8nio/n8n:local image (build with: INCLUDE_TEST_CONTROLLER=true pnpm build:docker) +# - .env.local at repo root with N8N_INSTANCE_AI_MODEL_API_KEY (+ optional N8N_EVAL_*). +# All KEY=VALUE entries from that file are passed into each lane container via +# docker --env-file; lane-specific -e flags below override on conflict. +# +set -euo pipefail + +# --------------------------------------------------------------------------- +# Defaults +# --------------------------------------------------------------------------- +INSTANCE_COUNT="" +START_PORT=6678 +IMAGE="n8nio/n8n:local" +BUILD_IMAGE=false +SKIP_EVAL=false +KEEP_CONTAINERS=false +EVAL_CONCURRENCY="" # auto = instance-count * 4 +EVAL_ITERATIONS=1 +EVAL_TIER="" +ENV_FILE=".env.local" +REPO_ROOT="$(git rev-parse --show-toplevel 2>/dev/null || pwd)" +EVAL_ARGS=() +CONTAINER_NAMES=() + +# --------------------------------------------------------------------------- +# Helpers +# --------------------------------------------------------------------------- +usage() { + cat <<'EOF' +Usage: run-eval-lanes.sh [--instance-count N] [options] [-- eval-args...] + +Options: + --instance-count N Number of n8n instances / ports to open (required) + --start-port N First host port to try (default: 6678; skips Node fetch-blocked ports) + --image NAME Docker image (default: n8nio/n8n:local) + --build Build docker image before starting lanes + --env-file PATH Env file relative to repo root (default: .env.local) + --concurrency N Eval scenario concurrency (default: instance-count * 4) + --iterations N Eval iterations per case (default: 3) + --tier NAME Eval tier filter (default: none; use "pr" for PR suite) + --skip-eval Only start + seed lanes; do not run evals + --keep-containers Do not remove containers on exit + -h, --help Show this help + +Everything after `--` is passed straight to eval:instance-ai +(e.g. --filter foo, --keep-workflows, --exclude bar). + +Examples: + ./scripts/run-eval-lanes.sh --instance-count 5 + ./scripts/run-eval-lanes.sh 5 --build --tier pr --verbose + ./scripts/run-eval-lanes.sh --instance-count 3 -- --filter contact-form --keep-workflows +EOF +} + +log() { + printf '[eval-lanes] %s\n' "$*" +} + +die() { + printf '[eval-lanes] ERROR: %s\n' "$*" >&2 + exit 1 +} + +require_cmd() { + command -v "$1" >/dev/null 2>&1 || die "Missing required command: $1" +} + +port_in_use() { + lsof -nP -iTCP:"$1" -sTCP:LISTEN >/dev/null 2>&1 +} + +# Node's fetch() (undici) refuses a fixed set of "bad" ports. The eval CLI +# uses fetch for every n8n REST call, so lane ports must not land on them. +# See: https://fetch.spec.whatwg.org/#port-blocking +is_node_fetch_blocked_port() { + case "$1" in + 1 | 7 | 9 | 11 | 13 | 15 | 17 | 19 | 20 | 21 | 22 | 23 | 25 | 37 | 42 | 43 | 53 | 69 | 77 | 79 | 87 | 95 | 101 | 102 | 103 | 104 | 109 | 110 | 111 | 113 | 115 | 117 | 119 | 123 | 135 | 137 | 139 | 143 | 161 | 179 | 389 | 427 | 465 | 512 | 513 | 514 | 515 | 526 | 530 | 531 | 532 | 540 | 548 | 554 | 556 | 563 | 587 | 601 | 636 | 989 | 990 | 993 | 995 | 1719 | 1720 | 1723 | 2049 | 3659 | 4045 | 4190 | 5060 | 5061 | 6000 | 6566 | 6665 | 6666 | 6667 | 6668 | 6669 | 6679 | 6697) + return 0 + ;; + *) + return 1 + ;; + esac +} + +# Force-remove any docker container holding the given host port (e.g. a lane +# left over from a previous --keep-containers run). Returns non-zero when the +# port is held by something that isn't a docker container. +remove_container_on_port() { + local port="$1" + local expected_name="n8n-eval-${port}" + local ids + ids="$(docker ps -q --filter "publish=${port}")" + if [[ -z "$ids" ]]; then + return 1 + fi + local id + for id in $ids; do + local name + name="$(docker inspect --format '{{.Name}}' "$id")" + name="${name#/}" + if [[ "$name" != "$expected_name" ]]; then + local names + names="$(docker ps --filter "publish=${port}" --format '{{.Names}}' | tr '\n' ' ')" + die "port ${port} is held by non-eval container(s): ${names}" + fi + done + log "removing existing eval container on port ${port}: ${expected_name}" + # shellcheck disable=SC2086 # ids is a newline-separated list of container IDs + docker rm -f $ids >/dev/null 2>&1 || true + # Wait for the kernel to release the port after the container dies. + for _ in $(seq 1 20); do + port_in_use "$port" || return 0 + sleep 0.5 + done + return 1 +} + +allocate_lane_ports() { + local count="$1" + local start="$2" + local port="$start" + local max_port=65535 + + PORTS=() + while ((${#PORTS[@]} < count)); do + if ((port > max_port)); then + die "could not allocate ${count} fetch-safe ports from ${start} (stopped at ${max_port})" + fi + if is_node_fetch_blocked_port "$port"; then + log "skipping port ${port} (blocked by Node fetch)" + elif port_in_use "$port"; then + if remove_container_on_port "$port"; then + PORTS+=("$port") + else + die "port ${port} is in use by a non-docker process — stop it or pick --start-port" + fi + else + PORTS+=("$port") + fi + port=$((port + 1)) + done +} + +wait_for_lane() { + local port="$1" + local timeout="${2:-120}" + for ((i = 1; i <= timeout; i++)); do + if curl -sf "http://localhost:${port}/healthz/readiness" >/dev/null 2>&1; then + log "lane ready on port ${port} (${i}s)" + return 0 + fi + sleep 1 + done + die "lane on port ${port} did not become ready within ${timeout}s" +} + +load_env_var() { + local key="$1" + local file="$2" + [[ -f "$file" ]] || die "Env file not found: $file" + local line + line="$(grep -E "^${key}=" "$file" | tail -n1 || true)" + [[ -n "$line" ]] || die "Missing ${key} in ${file}" + printf '%s' "${line#*=}" +} + +dotenvx_run() { + if command -v dotenvx >/dev/null 2>&1; then + dotenvx run -f "$ENV_FILE_PATH" -- "$@" + else + pnpm exec dotenvx run -f "$ENV_FILE_PATH" -- "$@" + fi +} + +cleanup() { + local status=$? + if [[ "$KEEP_CONTAINERS" == true ]]; then + log "keeping containers: ${CONTAINER_NAMES[*]:-none}" + exit "$status" + fi + + if [[ ${#CONTAINER_NAMES[@]:-0} -gt 0 ]]; then + log "removing containers..." + docker rm -f "${CONTAINER_NAMES[@]}" >/dev/null 2>&1 || true + fi + exit "$status" +} + +# --------------------------------------------------------------------------- +# Parse args +# --------------------------------------------------------------------------- +while [[ $# -gt 0 ]]; do + case "$1" in + --instance-count) + INSTANCE_COUNT="${2:-}" + shift 2 + ;; + --start-port) + START_PORT="${2:-}" + shift 2 + ;; + --image) + IMAGE="${2:-}" + shift 2 + ;; + --build) + BUILD_IMAGE=true + shift + ;; + --env-file) + ENV_FILE="${2:-}" + shift 2 + ;; + --concurrency) + EVAL_CONCURRENCY="${2:-}" + shift 2 + ;; + --iterations) + EVAL_ITERATIONS="${2:-}" + shift 2 + ;; + --tier) + EVAL_TIER="${2:-}" + shift 2 + ;; + --skip-eval) + SKIP_EVAL=true + shift + ;; + --keep-containers) + KEEP_CONTAINERS=true + shift + ;; + -h | --help) + usage + exit 0 + ;; + --) + shift + EVAL_ARGS+=("$@") + break + ;; + [0-9]*) + INSTANCE_COUNT="$1" + shift + ;; + *) + EVAL_ARGS+=("$1") + shift + ;; + esac +done + +[[ -n "$INSTANCE_COUNT" ]] || { + usage + die "--instance-count is required" +} +[[ "$INSTANCE_COUNT" =~ ^[0-9]+$ ]] || die "--instance-count must be a positive integer" +((INSTANCE_COUNT >= 1)) || die "--instance-count must be >= 1" +[[ "$START_PORT" =~ ^[0-9]+$ ]] || die "--start-port must be a number" +((START_PORT >= 1 && START_PORT <= 65535)) || die "invalid --start-port" + +if [[ -z "$EVAL_CONCURRENCY" ]]; then + EVAL_CONCURRENCY=$((INSTANCE_COUNT * 4)) +fi + +ENV_FILE_PATH="${REPO_ROOT}/${ENV_FILE}" +EVAL_PKG_DIR="${REPO_ROOT}/packages/@n8n/instance-ai" +RESET_PAYLOAD='{"owner":{"email":"nathan@n8n.io","password":"PlaywrightTest123","firstName":"Eval","lastName":"Owner"},"admin":{"email":"admin@n8n.io","password":"PlaywrightTest123","firstName":"Admin","lastName":"User"},"members":[],"chat":{"email":"chat@n8n.io","password":"PlaywrightTest123","firstName":"Chat","lastName":"User"}}' + +# --------------------------------------------------------------------------- +# Preflight +# --------------------------------------------------------------------------- +require_cmd docker +require_cmd curl +require_cmd lsof +require_cmd pnpm + +cd "$REPO_ROOT" + +# Port allocation may docker-rm stale lane containers, so it must run after +# the docker preflight check. +PORTS=() +BASE_URLS=() + +allocate_lane_ports "$INSTANCE_COUNT" "$START_PORT" + +for port in "${PORTS[@]}"; do + BASE_URLS+=("http://localhost:${port}") +done + +BASE_URL_CSV="$(IFS=,; printf '%s' "${BASE_URLS[*]}")" + +[[ -f "$ENV_FILE_PATH" ]] || die "Env file not found: $ENV_FILE_PATH" + +API_KEY="$(load_env_var N8N_INSTANCE_AI_MODEL_API_KEY "$ENV_FILE_PATH")" +[[ -n "$API_KEY" ]] || die "N8N_INSTANCE_AI_MODEL_API_KEY is empty" + +if [[ "$BUILD_IMAGE" == true ]]; then + log "building docker image ${IMAGE}..." + INCLUDE_TEST_CONTROLLER=true pnpm build:docker +elif ! docker image inspect "$IMAGE" >/dev/null 2>&1; then + die "docker image '${IMAGE}' not found — rerun with --build" +fi + +trap cleanup EXIT + +# --------------------------------------------------------------------------- +# Start lanes +# --------------------------------------------------------------------------- +log "starting ${INSTANCE_COUNT} lane(s) on ports: ${PORTS[*]}" +log "lane env file: ${ENV_FILE_PATH}" + +for port in "${PORTS[@]}"; do + name="n8n-eval-${port}" + CONTAINER_NAMES+=("$name") + + # A stopped leftover container doesn't hold the port (so allocation passes) + # but would still collide on the name. + if docker container inspect "$name" >/dev/null 2>&1; then + log "removing stale container ${name}" + docker rm -f "$name" >/dev/null 2>&1 || true + fi + + docker run -d --name "$name" \ + --env-file "$ENV_FILE_PATH" \ + -e E2E_TESTS=true \ + -p "${port}:5678" \ + "$IMAGE" >/dev/null + + log "started container ${name}" +done + +for port in "${PORTS[@]}"; do + wait_for_lane "$port" 120 +done + +# --------------------------------------------------------------------------- +# Seed owner on every lane +# --------------------------------------------------------------------------- +log "seeding credentials/users on all lanes..." + +for port in "${PORTS[@]}"; do + curl -sf -X POST "http://localhost:${port}/rest/e2e/reset" \ + -H "Content-Type: application/json" \ + -d "$RESET_PAYLOAD" >/dev/null + log "seeded port ${port}" +done + +# --------------------------------------------------------------------------- +# Run evals +# --------------------------------------------------------------------------- +if [[ "$SKIP_EVAL" == true ]]; then + log "skip-eval set — lanes are up and seeded" + log "base URLs: ${BASE_URL_CSV}" + exit 0 +fi + +[[ -d "$EVAL_PKG_DIR" ]] || die "eval package not found: ${EVAL_PKG_DIR}" + +log "running eval:instance-ai" +log " lanes: ${INSTANCE_COUNT}" +log " base-url: ${BASE_URL_CSV}" +log " concurrency: ${EVAL_CONCURRENCY}" +log " iterations: ${EVAL_ITERATIONS}" +log " tier: ${EVAL_TIER:-}" + +cd "$EVAL_PKG_DIR" + +ARGS=( + pnpm eval:instance-ai + --base-url "$BASE_URL_CSV" + --concurrency "$EVAL_CONCURRENCY" + --iterations "$EVAL_ITERATIONS" + --verbose +) + +if [[ -n "$EVAL_TIER" ]]; then + ARGS+=(--tier "$EVAL_TIER") +fi + +if [[ ${#EVAL_ARGS[@]} -gt 0 ]]; then + ARGS+=("${EVAL_ARGS[@]}") +fi + +dotenvx_run "${ARGS[@]}" diff --git a/packages/@n8n/instance-ai/skills/data-table-manager/SKILL.md b/packages/@n8n/instance-ai/skills/data-table-manager/SKILL.md index 2ae59fee301..6d1af1af3b9 100644 --- a/packages/@n8n/instance-ai/skills/data-table-manager/SKILL.md +++ b/packages/@n8n/instance-ai/skills/data-table-manager/SKILL.md @@ -2,10 +2,10 @@ name: data-table-manager description: >- Designs and manages n8n Data Tables directly with the data-tables and - parse-file tools. Use when the user asks to create, inspect, import, seed, - query, update, clean up, rename columns in, or delete data tables and rows, - especially from CSV/XLSX/JSON attachments, and before planning workflows that - create or write to Data Tables. + parse-file tools. Use when the user asks to list, show, create, inspect, + import, seed, query, update, clean up, rename columns in, or delete data + tables and rows, especially from CSV/XLSX/JSON attachments, and before + building or planning workflows that create or write to Data Tables. recommended_tools: - data-tables - parse-file @@ -21,7 +21,7 @@ sub-agent, or create a background plan for data-table-only work. Also load this skill before planning or building a workflow whose trigger, processing steps, or outputs create, inspect, or write Data Table records, then -pass the relevant schema/row-handling guidance to the planner or builder. +pass the relevant schema/row-handling guidance to the planning skill or builder. n8n Data Tables are flat, workflow-friendly stores. Design them so future workflow expressions can read predictable field names and so updates/deletes @@ -40,7 +40,7 @@ can target rows with narrow filters. 4. Inspect schema before writes, deletes, column changes, imports into an existing table, and workflow-facing summaries. 5. Execute the smallest direct tool sequence. Prefer read -> decide -> write; - never use plan/create-tasks/delegate for standalone table work. + never use create-tasks or delegate for standalone table work. 6. Close with facts: table name, table ID when available, project if relevant, columns changed, row counts inserted/updated/deleted, skipped rows, and any approval or permission blocker. diff --git a/packages/@n8n/instance-ai/skills/debugging-executions/SKILL.md b/packages/@n8n/instance-ai/skills/debugging-executions/SKILL.md new file mode 100644 index 00000000000..ca9ae42c460 --- /dev/null +++ b/packages/@n8n/instance-ai/skills/debugging-executions/SKILL.md @@ -0,0 +1,44 @@ +--- +name: debugging-executions +description: >- + Debug failed or wrong-output workflow executions using executions tools. Load + when the user reports execution failures, unexpected node output, or empty + parameter values after a successful run. +recommended_tools: + - executions + - workflows +--- + +# Debugging Executions + +Use this skill when debugging workflow execution failures or successful runs +with wrong or empty values. + +## Testing event-triggered workflows + +Use `executions(action="run")` with `inputData` matching the trigger's output +shape — do not rebuild the workflow with a Manual Trigger. For trigger +`inputData` shapes, read `knowledge-base/reference/trigger-input-data-shapes.md` +when a sandbox workspace is available. + +## Failed execution + +`executions(action="debug")` already includes `failedNode.resolvedParameters` — +start there. That bundle has `parameters` (raw, with expressions intact), +`resolved` (substituted), `failedExpressions` (those that threw), and +`emptyResolutions` (those that resolved to `null`/`undefined`/`""` silently). +The offending expression is usually visible without a follow-up call. Entries in +either list tagged with `reason: "unreconstructable-context"` are NOT real bugs — +they reference variables we don't reconstruct in replay (`$vars`, `$secrets`, +`$response`, `$request`, `$pageCount`, `$ai`). The value existed at execution +time; we just don't have it here. + +## Successful execution with wrong or empty value + +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 +expressions resolving to `null`/`undefined`/`""`, not thrown errors. diff --git a/packages/@n8n/instance-ai/skills/planned-task-runtime/SKILL.md b/packages/@n8n/instance-ai/skills/planned-task-runtime/SKILL.md new file mode 100644 index 00000000000..cf97433f508 --- /dev/null +++ b/packages/@n8n/instance-ai/skills/planned-task-runtime/SKILL.md @@ -0,0 +1,163 @@ +--- +name: planned-task-runtime +description: >- + Handles system follow-up turns: planned-task-follow-up (synthesize, replan, + build-workflow, checkpoint), background-task-completed, running-tasks context, + create-tasks silence rules, and detached delegate completion. Load whenever + any of these tags appear or after spawning create-tasks or delegate. +recommended_tools: + - create-tasks + - complete-checkpoint + - build-workflow + - delegate + - task-control + - workflows + - verify-built-workflow + - executions +--- + +# Planned Task Runtime + +Load this skill when the current message contains ``, +``, ``, or immediately after calling +`create-tasks` or `delegate`. + +## Silence after spawning tasks + +**After calling detached or scheduled task tools** (`delegate` or +`create-tasks`): do not write any text. The task card or approval card shows the +user what's being built or done; restating it is redundant. Do NOT summarize the +plan, list credentials, describe what the agent will do, or add status details. +Progress is already visible to the user in real time. + +When `create-tasks` returns after approval, tasks are already running. Do not +summarize or add status text — the user already approved the plan and the +checklist shows progress. Wait for `` to arrive; do not +invent synthetic follow-up turns. + +## Never poll + +**Never poll and never sleep.** Background tasks (`delegate`) settle via +`` turns that arrive automatically when work finishes. +After you spawn or acknowledge one, end your turn. Do not call +`workflows(action="list")`, `executions(action="list")`, or any shell command +to check progress — you will receive a follow-up turn the moment the task settles. +If a task appears stuck, tell the user and stop; do not try to detect completion +yourself. Do not re-dispatch a build whose task ID is already visible in +``. + +When `` context is present, use it only to reference active task +IDs for cancellation or corrections. + +Always pass `conversationContext` when spawning background agents (`delegate`) — +summarize what was discussed, decisions made, and information gathered. + +If the user sends a correction while a build is running, call +`task-control(action="correct-task")` with the task ID and correction. + +## Synthesize follow-up + +When `` is present, all planned tasks +completed successfully and any unsettled runtime verification obligations have +already been handled. Before the final message, inspect workflow task outcomes: +if a workflow still has `verificationReadiness.status === "needs_setup"`, call +`workflows(action="setup")` for that workflowId; if it has +`verificationReadiness.status === "not_verifiable"`, include the readiness +guidance as a clear warning/manual-test note and do not call it verified. Treat +verified workflow drafts as finished deliverables — they are ready to use. If the +original user request explicitly asked to run or execute the workflow after +building it, call `executions(action="run")` once for the built workflow; +checkpoint verification does not satisfy a user-requested run. Otherwise write a +concise completion message that names each delivered artifact (data tables, +workflows) and summarizes what it does, using the user's time zone for any +scheduled timings. Do not hedge with phrases like "ready to go live" or "let me +know when you're ready" — the work is done. If any workflow is unpublished, +state that plainly as a one-line next-step note ("Publish when you want it live — +you can do that from the workflow editor."), not as a gating condition. Do not +create another plan. + +## Replan follow-up + +When `` is present, a planned task failed +and the graph is in `awaiting_replan`. You MUST take action in this same turn — +handle a single simple task directly (matching tool: `build-workflow`, +`data-tables`, `delegate`, etc.), call `create-tasks` with +`planningContext.source: "replan"` for multiple dependent tasks, or explain the +blocker to the user if nothing sensible remains. Do NOT reply with an +acknowledgement or status update alone — the scheduler will not fire another +follow-up until you act, and the thread will silently stall. + +Replan routing (do not re-plan from scratch): + +- One simple task remains (single data-table op, credential setup, single-workflow + patch) → handle directly with the matching tool. +- Multiple dependent tasks still need scheduling → `create-tasks` with + `planningContext.source: "replan"`. +- Nothing sensible remains → explain the blocker to the user. + +## Build-workflow follow-up + +When `` is present, load the +`workflow-builder` skill and build exactly the `buildTask` in the payload. If +`buildTask.workflowId` is present, update that workflow; otherwise create a new +one. If `buildTask.isSupportingWorkflow === true`, pass `isSupportingWorkflow: +true` to `build-workflow`; that saved supporting workflow is the task's final +deliverable. Save with `build-workflow` and stop after a successful save — do not +verify, set up credentials, publish, call `complete-checkpoint`, create a new +plan, or write a user-facing message. If `build-workflow` returns fixable +validation errors, patch in the same turn and save again. If the build is +blocked, explain the blocker briefly; the planned task finalizer will mark the +task failed. + +## Checkpoint follow-up + +When `` is present, the block contains +exactly one checkpoint task (`checkpoint.id`, `checkpoint.title`, +`checkpoint.instructions`, and `checkpoint.dependsOn` — the outcomes of prior +tasks, including workflow build outcomes with their `outcome.workItemId` / +`outcome.workflowId`). **Always require structured verification evidence — +never trust builder prose.** Before completing the checkpoint, inspect each +dependent persisted workflow with `workflows(action="get-json", workflowId)` and +compare the actual graph to the build task and checkpoint goal. Build/save +success is not proof of workflow quality. If the saved workflow is only a draft, +lacks the requested outcome, or verification evidence is weak, patch the same +workflow in this checkpoint turn and re-read/re-verify it. If a dependency outcome +contains successful `outcome.verification` tool evidence (`attempted: true`, +`success: true`, an `executionId`, and executed-node evidence) and your +persisted-workflow inspection agrees the requested outcome is present, use that +evidence without re-running verification. Otherwise execute +`checkpoint.instructions` using your tools — typically `verify-built-workflow` +with the work item ID from the build outcome, or `executions(action="run")` for a +built workflow with real credentials and a testable trigger. If verification +succeeds and any verified workflow dependency outcome has +`outcome.setupRequirement.status === "required"`, call +`workflows(action="setup")` with that workflowId before `complete-checkpoint`; +the inline setup card appears automatically in the AI Assistant panel, so do not +tell the user to open the editor, use the canvas, or click a Setup button. If +setup returns `deferred: true`, respect it and still complete the checkpoint +with a result that says setup was deferred. Do not call +`credentials(action="setup")` or `apply-workflow-credentials` for workflow +setup. Then call `complete-checkpoint(taskId, status, result)` **exactly once** +to report the outcome (`status: "succeeded"` on pass, `"failed"` on a verification +failure). Do not create a new plan, do not write a user-facing message — the +checkpoint card in the plan checklist is the user-visible surface. End your turn +as soon as `complete-checkpoint` returns. + +**If your verification surfaced a bug you can patch in place** (e.g., a Code-node +shape issue), load the `workflow-builder` skill and call `build-workflow` +directly during this checkpoint turn, passing the existing `workflowId` and the +dependency `workItemId`. Then re-verify in the same checkpoint turn. Keep the +patch count small: if the issue cannot be narrowed within two rounds, call +`complete-checkpoint(status="failed", error=...)` with a summary of what remains +and let replan take over. + +## Background task completed + +When `` is present, a detached background task +finished. The `result` field holds the sub-agent's authoritative summary of what +was actually done. **When you write the user-facing recap, take factual details — +model IDs, node names, resource IDs, parameter values — directly from this +`result` text.** Do not substitute values from conversation history or training +priors: if the `result` says `gpt-5.4-mini`, write `gpt-5.4-mini`, not "GPT-4o +mini" or any other name you associate with the provider. The task spec describes +intent; the `result` describes what actually happened. diff --git a/packages/@n8n/instance-ai/skills/planning/SKILL.md b/packages/@n8n/instance-ai/skills/planning/SKILL.md new file mode 100644 index 00000000000..58ab9c3ae8b --- /dev/null +++ b/packages/@n8n/instance-ai/skills/planning/SKILL.md @@ -0,0 +1,174 @@ +--- +name: planning +description: >- + ONLY for coordinated multi-artifact work: multiple workflows with dependencies, + shared data-table schema/migration across tasks, or the user explicitly asked + to review a plan first. Do NOT use for new one-off workflows, single-workflow + edits, verification-only requests, or standalone data-table ops — use + workflow-builder or data-table-manager instead. +recommended_tools: + - create-tasks + - workflows + - nodes + - credentials + - data-tables + - parse-file + - research + - ask-user +--- + +# Planning + +Use this skill to design a dependency-aware task graph in the orchestrator and +submit it with `create-tasks`. Do not spawn another agent, do not delegate the +planning step, and do not use incremental plan item tools. + +## When NOT to use this skill + +Stop and use `workflow-builder` + `build-workflow` instead when the request is: + +- A new or one-off single workflow, even if it sounds large or unfamiliar +- An edit to one existing workflow (nodes, expressions, credentials, schedule, Code) +- Verification, setup, or credential collection for a workflow you just built +- A workflow-local data table whose schema ships with that same workflow +- Standalone data-table list/schema/query/create/mutation work + +Do not call `create-tasks` just to get approval, verification, or a checklist for +a single workflow. Workflow verification is automatic from structured build +outcomes after `build-workflow`. + +## When to use this skill + +Planning is only for work that needs coordination: multiple workflows, +dependencies between workflows, shared data-table schema or migration work across +tasks, multiple durable artifacts, broad best-practice research across many +sources, genuinely ambiguous business-process architecture that cannot be +resolved with one `build-workflow` call, or an explicit user request to review a +plan first. + +If shared data tables are involved, load `data-table-manager` before this skill +and carry the relevant table guidance into workflow task specs. Clear +single-workflow builds and existing-workflow edits use `workflow-builder` with +`build-workflow` directly. Standalone data-table work uses `data-table-manager` +with direct `data-tables` and `parse-file` calls. + +## Method + +1. Decide whether the request is plan-worthy by coordination need, not by + whether a workflow is new. +2. Discover what materially affects the plan with normal tools: + `nodes(action="suggested")`, `credentials(action="list")`, + `data-tables(action="list")`, `parse-file`, `workflows`, and `research` + when relevant. +3. Prefer reasonable assumptions over questions. Ask the user only when the + answer would materially change the plan and cannot be discovered. +4. Build a dependency-aware graph. Producers must come before consumers. + Independent tasks should not depend on each other. +5. Put single workflow-local table requirements inside that workflow task spec. + Do not create separate data-table tasks unless the table work is a durable + artifact shared across tasks. +6. Add checkpoint tasks only for exceptional semantic checks that normal + workflow verification cannot cover. +7. Call `create-tasks` with `planningContext.source: "planning-skill"`, + a concise `summary`, optional `assumptions`, `postBuildRunRequested: true` + only when the user explicitly asked to run, execute, or test a workflow + after building it, and the final task graph. +8. After calling `create-tasks`, do not write visible text. The approval card is + the user-visible surface. + +## Task Graph Rules + +- Use task kinds exactly as supported: `build-workflow`, `delegate`, and + `checkpoint`. +- Each task `id` must be stable and referenced by dependency edges. +- Each `title` should be short and user-facing. +- Each `spec` must be the complete executor briefing for that task. The task + executor may not see your broader planning notes. +- For `build-workflow` tasks, make `spec` a structured executor briefing, not + freeform prose. Include these labels in this order: `Outcome`, + `Trigger mode`, `External systems`, `Required effects`, `Required branches`, + `Required data`, `Explicit constraints`, `Empty/invalid behavior`, and + `Done when`. +- In `Required effects`, list every observable action the user asked for, such + as send email, send Telegram, write Google Sheets, create Notion pages, upsert + Data Table rows, or post one Slack summary. +- In `Required branches`, state partial-failure behavior when multiple effects + start from the same trigger, and state whether no-results or invalid-input + paths need an explicit notification, fallback, log, or no-op. +- In `Required data`, name fields needed by later conditions, filters, ranking, + response messages, or downstream effects, and note when those fields must + remain available after side-effect nodes that replace item JSON. +- In `Explicit constraints`, preserve concrete user-provided resource names, + channels, tables, labels, URLs, and required node families or mechanisms. If + the user explicitly says to use a node family or mechanism such as HTTP + Request, webhook, form, MCP, or a service-native node, treat that as a hard + requirement unless it is impossible or contradicts another stated requirement. + Do not move those values to assumptions, replace them with placeholders, or + silently swap them for a more convenient alternative. +- In `Empty/invalid behavior`, distinguish data that invalidates the whole item + from data that only affects one requested effect. For multi-effect intake + workflows, do not turn a field into a workflow-wide rejection requirement + merely because one message or side effect uses it. +- In `Done when`, write observable acceptance checks, including final actions + and branch behavior. Do not write node-by-node wiring or fake user data. +- If a `build-workflow` task's final deliverable is a supporting sub-workflow, + set `isSupportingWorkflow: true` on that task. Do not set it for helper + sub-workflows that are only intermediate artifacts inside a larger main + workflow task. +- For `delegate` tasks, include all context the background task needs and list + only the tools it should use. +- For `checkpoint` tasks, write structured semantic verification instructions: + `Verify trigger mode`, `Verify external systems`, `Verify required effects`, + `Verify required branches`, `Verify required data`, + `Verify explicit constraints`, `Verify empty/invalid behavior`, and + `Pass condition`. Checkpoints are exceptional; use this structure only when a + checkpoint is actually warranted. + +## Assumptions And Questions + +- Never ask about things tools can discover, such as available credentials, + existing data tables, workflow names, node availability, or attached-file + structure. +- Never ask for implementation details such as node choices, column names, or + trigger mechanics when a sensible default exists. +- Never ask for the user's timezone when the current date/time section includes + it. Use that timezone for schedule times, cron assumptions, and digest windows. +- Never default resource identifiers the user did not mention, such as Slack + channels, calendars, spreadsheets, folders, databases, or recipient lists. + Leave them for the builder to resolve or collect through setup. +- Trust already-collected briefing context. If the conversation or task briefing + includes already-collected answers or already-discovered resources, treat them + as authoritative and do not ask again for purpose, trigger, integrations, + schedule, model, resource, or credential choices already listed there. +- If exactly one matching credential exists, assume it and mention the + credential name in `planningContext.assumptions`. +- If no matching credential exists, plan normally. The builder will mock or + leave it unresolved and route setup after verification. +- If multiple matching credentials exist and the user did not name one, ask once + with `ask-user` because the choice cannot be discovered. +- Use credential-backed resource investigation only when it changes the plan, + for example validating a named Slack channel that affects the architecture. Do + not turn resource lookup into a credential-choice question unless the + multiple-credentials rule applies. + +## Checkpoints + +Workflow verification is automatic from structured build outcomes. Do not add +routine "verify this workflow" checkpoint tasks for every workflow. + +Checkpoint tasks are exceptional semantic checks. Use them for cross-workflow +contracts, confirming a report combines upstream data correctly, validating a +business invariant across deliverables, or checking a condition that cannot be +covered by normal runtime verification. + +Do not add checkpoints for delegate tasks, and do not list `tools` on checkpoint +tasks. + +## Revisions + +If the user rejects the plan with requested changes, revise surgically and call +`create-tasks` again in the same orchestrator run with +`planningContext.source: "planning-skill"`. + +If the user denies the plan outright, stop. Do not call `create-tasks` again in +the same message group. diff --git a/packages/@n8n/instance-ai/skills/post-build-flow/SKILL.md b/packages/@n8n/instance-ai/skills/post-build-flow/SKILL.md new file mode 100644 index 00000000000..45470c1c490 --- /dev/null +++ b/packages/@n8n/instance-ai/skills/post-build-flow/SKILL.md @@ -0,0 +1,134 @@ +--- +name: post-build-flow +description: >- + Handles workflow verification and setup after build-workflow succeeds, or when + the message contains workflow-verification-follow-up or workflow-setup-required. + Load after direct builds, when verificationReadiness requires action, or on + orchestrator verify/setup follow-up turns. +recommended_tools: + - verify-built-workflow + - workflows + - build-workflow + - executions +--- + +# Post-Build Flow + +Use this skill after `build-workflow` succeeds on a direct orchestrator build, or +when the current message contains `` or +``. + +For trigger `inputData` shapes, read +`knowledge-base/reference/trigger-input-data-shapes.md` in the sandbox workspace +when available, or load this skill's `references/trigger-input-data-shapes.md` +linked file. + +## Verification follow-up + +When the current message contains ``, verify +immediately from the payload's `obligation` — do not acknowledge first. If the +obligation is `ready_to_verify` or `verifying`, call `verify-built-workflow`. Do +**not** call `workflows(action="setup")` in this turn and do **not** declare the +workflow finished if `outcome.setupRequirement.status === "required"` — setup is +routed automatically as a separate `` step after +verification. + +## Setup follow-up + +When the current message contains ``, your only action is +to call `workflows(action="setup")` with the `workflowId` from the payload. Do +not verify, do not ask, do not write a message first — the inline setup card in +the AI Assistant panel is the user-visible surface. If it returns `deferred: +true`, respect the user's choice and do not retry with any other setup tool. + +## Publishing and testing + +**Publishing is never required for testing.** Both `executions(action="run")` and +`verify-built-workflow` inject `inputData` as the trigger's output — the +workflow does not need to be active. Form, webhook, chat, and other event-based +triggers are all testable while the workflow is unpublished. Never publish a +workflow as a precondition for running it. + +## After build-workflow succeeds + +1. Read `workflowId`, `workItemId`, `triggerNodes`, `verificationReadiness`, and + `setupRequirement` from the tool output. If the output is missing a + `workflowId`, explain that the build did not submit. + - Before treating a saved workflow as done, inspect the persisted workflow + with `workflows(action="get-json", workflowId)` and compare the actual + graph to the user's requested outcome. Build/save success only means a + workflow was saved; it does not prove the saved workflow is good. + - If the persisted workflow is missing the requested outcome, has an obvious + dead-end draft shape, or the verification evidence is weak, load the + `workflow-builder` skill and patch the same workflow with `build-workflow` + using the existing `workflowId` and `workItemId`; then inspect and verify + again. + - If `verificationReadiness.status === "already_verified"`, treat the + workflow as verified and do **not** call `verify-built-workflow` again. + - If `verificationReadiness.status === "ready"`, call + `verify-built-workflow` with the `workItemId` / `workflowId` and the + trigger-appropriate `inputData` shape. + - If `verificationReadiness.status === "needs_setup"`, call + `workflows(action="setup")` with the workflowId so the user can configure it + through the inline setup card in the AI Assistant panel. + - If `verificationReadiness.status === "not_verifiable"`, do not infer + lower-level verification conditions; use the readiness guidance to give a + clear warning or manual-test note. This is a warning completion state, not + a verified state and not an infinite blocker. +2. Judge coverage, not just status. A `verify-built-workflow` result with + `success: true` but a non-empty `nodesNotReached` is **partial** evidence: + the execution ended early (see `lastNodeExecuted` and `coverageNote`) and + the listed nodes — including any planned simulations — never ran. + - Most common cause: a lookup/query node returned zero items (n8n stops + downstream nodes on empty item lists). If the dead-end is a Data Table + lookup, insert a matching test row with `data-tables(action="insert-rows")`, + re-run `verify-built-workflow`, and delete the test row afterwards. + - If you cannot seed the data source, report honestly: name which nodes + were verified and which were not, and tell the user the unreached part + needs a manual test. Never claim end-to-end verification when + `nodesNotReached` is non-empty. + - Relay `simulationNote` (nodes whose output was simulated) to the user + whenever it is present. +3. After verification handling, if `setupRequirement.status === "required"` and + setup has not already run for this build, call `workflows(action="setup")` + with the workflowId. +4. When `workflows(action="setup")` opens the inline setup card, the card is the + user-visible surface. Do not tell the user to open the editor, use the canvas, + or click a Setup button; the user does not need to navigate anywhere. +5. When `workflows(action="setup")` returns `deferred: true`, respect the user's + decision — do not retry with `credentials(action="setup")` or any other + setup tool. The user chose to set things up later. +6. Ask the user if they want to test the workflow (skip this if + `verify-built-workflow` already proved it works end-to-end with full + coverage). +7. Only call `workflows(action="publish")` when the user explicitly asks to + publish. Never publish automatically. + +## Credentials before build + +Call `credentials(action="list")` first to know what's available. Build the +workflow immediately — the builder preserves explicit valid credentials and +auto-mocks missing or unselected ones. Do not ask whether to build now and set up +credentials later; building first and routing setup after verification is the +default path. Workflow verification is automatic from the build outcome; the +orchestrator handles workflow setup after verification when the saved workflow +still has mocked credentials or placeholders. + +**Ask once when a service has multiple credentials of the same type.** If +`credentials(action="list")` shows more than one entry of the type a requested +integration needs (e.g. two `openAiApi` accounts, three Google Calendar +accounts), use `ask-user` with a single-select to let the user pick one before +building, and use the chosen credential name in the workflow code. Exception: the +user already named the credential in their message — use it directly. With a +single candidate, auto-apply and do not ask. + +**Ask which auth type to use when a service supports more than one.** +`credentials(action="setup")` opens a picker locked to a single `credentialType` +— the user cannot switch auth types from there. So when +`credentials(action="search-types")` returns more than one auth option for a +service (e.g. `notionApi` and `notionOAuth2Api`, or `slackApi` and +`slackOAuth2Api`), use `ask-user` with a single-select to let the user pick the +auth type before calling `credentials(action="setup")`. List OAuth2 first and +present it as the recommended option. Exception: the user has clearly indicated +an auth type (e.g. "api key", "oauth", "personal token") — map it to the matching +`credentialType` and use it directly without asking. diff --git a/packages/@n8n/instance-ai/skills/post-build-flow/references/trigger-input-data-shapes.md b/packages/@n8n/instance-ai/skills/post-build-flow/references/trigger-input-data-shapes.md new file mode 100644 index 00000000000..4c0dab17264 --- /dev/null +++ b/packages/@n8n/instance-ai/skills/post-build-flow/references/trigger-input-data-shapes.md @@ -0,0 +1,38 @@ +# Per-trigger `inputData` shape + +Used by `verify-built-workflow`, `executions(action="run")`, and checkpoint +verification. The pin-data adapter spreads or wraps based on trigger type — +passing the wrong shape gives null downstream values that look like an +expression bug. + +## Form Trigger (`n8n-nodes-base.formTrigger`) + +Flat field map, e.g. `{name: "Alice", email: "a@b.c"}`. The production Form +Trigger emits each field directly on `$json`, so the builder's `$json.` +expressions are correct. **Do NOT wrap in `formFields`** — the adapter will +reject the call. + +## Webhook (`n8n-nodes-base.webhook`) + +The body payload, e.g. `{event: "signup", userId: "..."}`. The adapter wraps it +under `body`, so downstream nodes reference `$json.body.`. + +## Chat Trigger (`@n8n/n8n-nodes-langchain.chatTrigger`) + +`{chatInput: "user message"}`. + +## Schedule Trigger (`n8n-nodes-base.scheduleTrigger`) + +Omit `inputData`; the adapter emits synthetic timestamp fields. + +## Other event triggers + +Linear, GitHub, Slack, MCP, and similar triggers: pass `inputData` matching the +trigger's expected payload shape from the node type definition. + +## Debugging wrong null values + +**Do not patch a workflow first when verify returns null downstream values.** +Re-run verify with the corrected `inputData` shape. Only patch the workflow if +the expression is wrong against the *production* trigger output shape (consult +node descriptions), not the `instanceAi` pin data path. diff --git a/packages/@n8n/instance-ai/skills/workflow-builder/SKILL.md b/packages/@n8n/instance-ai/skills/workflow-builder/SKILL.md index f5adc9d624e..2f423281db9 100644 --- a/packages/@n8n/instance-ai/skills/workflow-builder/SKILL.md +++ b/packages/@n8n/instance-ai/skills/workflow-builder/SKILL.md @@ -1,10 +1,11 @@ --- name: workflow-builder description: >- - Builds and edits n8n workflows with the workflow SDK. Use for new planned - workflow builds, existing-workflow edits, verification repairs, - credential-aware node configuration, and setup routing. This is the former - workflow-builder agent guidance, now loaded as a skill by the orchestrator. + Default path for all single-workflow work: new one-off workflows, existing- + workflow edits, verification repairs, and workflow-local data tables. Use + build-workflow directly — do not load planning or create-tasks first. Load + planning only when multiple coordinated workflows or shared cross-task data + tables require a dependency-aware task graph. recommended_tools: - build-workflow - workflows @@ -26,10 +27,12 @@ Use the orchestrator tools already available in the current turn. If a relevant orchestrator or MCP tool is available through tool search, use it when it helps complete the build. -For normal new-workflow requests, call `plan` first so the user can approve the -build plan. Use this skill to create new workflows only during an approved -`` turn. If this skill was loaded -for a normal new-workflow request, stop discovery and call `plan` immediately. +For all clear single-workflow requests — including new and one-off workflows — +build directly with `build-workflow`. Do not load `planning` or call +`create-tasks` first. Only load `planning` when the orchestrator routing rules +require coordinated multi-artifact work. Use this skill during an approved +`` turn, or for direct +single-workflow builds and edits. Do not call `delegate` to build, patch, fix, verify, or update workflows. The builder work happens here with the workflow-builder guidance and the @@ -62,50 +65,6 @@ Good: - "Blocked: the Linear API credential is missing; setup is required before I can continue." -## Tool Surface - -Tool names are part of the compatibility contract. Keep using the same tool -names the old builder used: - -- `build-workflow` to save TypeScript SDK code or apply targeted patches. -- `workflows(action="get-as-code")` before precise patches to an existing - workflow when you need the current code. -- `workflows(action="get")`, `workflows(action="list")`, and - `workflows(action="setup")` when inspection or setup routing is needed. -- `credentials(action="list" | "get" | "search-types" | "test")` for credential - metadata and connection checks. -- `nodes(action="suggested")` for known workflow categories. -- `nodes(action="search")` for service-specific node discovery. -- `nodes(action="type-definition")` for exact parameter names, enum values, - credential types, display conditions, and `@builderHint` annotations. -- `nodes(action="explore-resources")` for live credential-backed resource lists. -- `data-tables(action="list" | "create" | "schema")` for Data Table work. -- `parse-file` for parseable user attachments. -- `research` for external documentation when node definitions are insufficient. -- `ask-user` only when a human choice is needed. -- `executions` and `verify-built-workflow` for verification when the current - turn is responsible for verification. -- `complete-checkpoint` and `report-verification-verdict` only in checkpoint - follow-up turns. - -## Repair Strategy - -When called with failure details for an existing workflow, start from the -pre-loaded code or the saved workflow code. Do not re-discover node types that -are already present unless the repair touches their parameters, resources, -credentials, versions, or wiring semantics. - -For small fixes, prefer patch mode: - -```json -{ - "workflowId": "existing-id", - "patches": [{ "old_str": "exact old code", "new_str": "replacement code" }] -} -``` - -Patches apply to the last submitted code, or the tool fetches the saved workflow -when `workflowId` is provided. Use full code for larger rewrites. ## Escalation @@ -130,6 +89,24 @@ tokens, Slack channel IDs, Telegram chat IDs, or sample recipient lists. After the build, `workflows(action="setup")` opens an inline setup card in the AI Assistant panel so the user can fill placeholder values. +Do not replace concrete user-provided or discoverable values with placeholders. +If the prompt gives a real URL, channel name, table name, label, folder, +database, or other literal selector, preserve that value and only use a +placeholder for the unknown part. + +## Knowledge Base Guardrails + +For workflows with multiple external systems, multiple requested effects, +digests or reports, non-trivial branching, or Code nodes, read +`knowledge-base/reference/workflow-builder-guardrails.md` before writing code. +Use it as the build checklist for source preservation, fan-out/fan-in, +effect-specific gating, list itemization, and Code-node safety. + +When mapping downstream fields from an OpenAI node, read +`knowledge-base/reference/open-ai-output-shape.md` (v2+ text/response uses +`$json.output[0].content[0].text`; v1 text/message uses `$json.message.content` +— not `$json.text`). + ## Mandatory Process 1. Research. If the workflow fits a known category, call @@ -154,6 +131,9 @@ Assistant panel so the user can fill placeholder values. mandatory for calendars, spreadsheets, channels, folders, databases, models, and any other list-backed parameter when a credential is available. 6. Build complete TypeScript SDK code and call `build-workflow`. + For planned build follow-ups where `buildTask.isSupportingWorkflow === true`, + pass `isSupportingWorkflow: true`; that saved supporting workflow is the + task's final deliverable. 7. Trace wiring before declaring done. For IF, Switch, Merge, AI-agent, loop, or multi-workflow wiring, trace each branch from source to target. Confirm IF outputs use `.onTrue()` and `.onFalse()`, Switch outputs use zero-based @@ -182,6 +162,16 @@ Use the current turn's higher-priority instructions to decide who verifies: - Planned build follow-ups that explicitly say to stop after save: stop after a successful `build-workflow`. The checkpoint task owns verification. +Build/save success is not workflow-quality evidence. When this turn is +responsible for verification or repair, inspect the persisted workflow with +`workflows(action="get-json", workflowId)` after saving or before reporting a +verdict. Judge the saved graph against the user's requested outcome and the +current build/checkpoint goal, not a hidden service-specific or topology +checklist. +If the saved workflow is only a draft, misses the intended outcome, or has weak +evidence, patch the same workflow with `build-workflow`, then inspect and verify +again. + When this turn is responsible for verification, do not stop after a successful save. The job is done when one of these is true: @@ -332,6 +322,20 @@ column names. ## SDK Code Rules +- SDK builder code is a restricted subset of TypeScript that builds a static + graph; it is not a Code node and does not run. Only SDK builder methods chain + on SDK objects. Native array/string methods (`.join()`, `.map()`), loops, arrow + functions, `new`, and globals like `Math`, `Date`, and `Object` are + unavailable. Build strings with template literals or explicit lines; do runtime + joining, aggregation, or transforms in a Code node or an n8n expression + (`expr()`). Full allowed/forbidden list: + `knowledge-base/reference/workflow-sdk-language.md`. + +- Code nodes have NO network access at runtime: `fetch()`, `axios`, + `XMLHttpRequest`, and `require` of http modules all fail in the sandbox. Make + every HTTP/API call with the HTTP Request node and transform its output in a + Code node, even when the user asks to fetch inside a Code node. + - Use `@n8n/workflow-sdk`. - Do not specify node positions. They are auto-calculated by the layout engine. - Use `expr('{{ $json.field }}')` for n8n expressions. Variables must be inside @@ -346,8 +350,20 @@ column names. placeholders in `expr()`, objects, or arrays unless the node definition explicitly expects an object and the placeholder is the direct value of one field. +- For unresolved resource-locator fields (values shaped like `{ __rl: true, + mode, value }`, such as Slack channel selectors), use the resource-locator + object shape instead of a raw `placeholder()` string. Pick the mode per the + resource-locator rule in Node Configuration Safety Rules: a `name`/`url` + mode with the known value when the locator offers one and you know the + resource by name; otherwise id mode with an empty value and a cached result + name, for example `{ __rl: true, mode: 'id', value: '', + cachedResultName: 'Select support channel to monitor' }`. - For single-execution nodes that receive many items but should run once, set `executeOnce: true`. +- Whenever a node declares mock `output` for verification, include every field + later referenced by `$json` expressions, including optional trigger fields + used in filters (for example Slack `subtype`, `bot_id`, `text`, `user`, `ts`, + `channel`). Missing optional fields make expression-path validation fail. Use this import shape unless the task needs fewer symbols: @@ -387,10 +403,9 @@ Follow these rules strictly when generating workflows: 1. Always use `newCredential()` for authentication. Never use placeholder strings, fake API keys, hardcoded auth values, invented credential IDs, or raw `mock-*` IDs. -2. Trust empty item lists. When a query returns zero items, downstream nodes - simply do not run. Do not add `alwaysOutputData: true` just to keep a chain - alive, and do not add an IF gate before a loop only to check whether items - exist. +2. Zero items end the branch — downstream nodes do not run. Trust this default; + do not add `alwaysOutputData: true` or empty-check IF gates unless rule 4's + mandatory-outcome case applies. 3. Use `executeOnce: true` for a node that receives many items but should run once, such as a summary notification, report generation, shared-context fetch, or API call that does not vary per input item. Duplicate @@ -404,6 +419,11 @@ Follow these rules strictly when generating workflows: and `.onFalse()`. - Many mutually exclusive paths keyed off a value: Switch with `.onCase(index, target)`. + - Mandatory outcome when upstream can be empty (digest/alert must still send): + set `alwaysOutputData: true` on every node that can emit zero items before + the effect — often both the HTTP fetch (empty `[]`) and the filter (all rows + dropped). Not on the formatter or notifier; consumers that receive zero + items never run. - A Filter or IF only selects items; it does not perform the requested side effect. If the user asks to archive, update, delete, send, or create only matching items, wire the corresponding action node on the matching path. diff --git a/packages/@n8n/instance-ai/src/__tests__/index.test.ts b/packages/@n8n/instance-ai/src/__tests__/index.test.ts index 266aae8a885..f70c37267d4 100644 --- a/packages/@n8n/instance-ai/src/__tests__/index.test.ts +++ b/packages/@n8n/instance-ai/src/__tests__/index.test.ts @@ -119,11 +119,14 @@ vi.mock('../workspace/create-workspace', () => ({ createSandbox: () => ({ type: 'sandbox' }), createWorkspace: () => ({ type: 'workspace' }), })); +vi.mock('@n8n/agents/sandbox', () => ({ + getWorkspaceRoot: () => '/workspace', + getPromptWorkspaceRoot: () => '/home/daytona/workspace', +})); vi.mock('../workspace/lazy-runtime-workspace', () => ({ createLazyRuntimeWorkspace: () => ({ type: 'lazy-workspace' }), })); vi.mock('../workspace/sandbox-setup', () => ({ - getWorkspaceRoot: () => '/workspace', setupSandboxWorkspace: () => undefined, })); vi.mock('../workspace/snapshot-manager', () => ({ SnapshotManager: class SnapshotManager {} })); @@ -322,6 +325,7 @@ describe('@n8n/instance-ai public entrypoint', () => { expect(call(entrypoint.createLazyRuntimeWorkspace)).toEqual({ type: 'lazy-workspace' }); expect(call(entrypoint.getWorkspaceRoot)).toBe('/workspace'); + expect(entrypoint.getPromptWorkspaceRoot('daytona')).toBe('/home/daytona/workspace'); expect(call(entrypoint.setupSandboxWorkspace)).toBeUndefined(); expect(construct(entrypoint.BuilderTemplatesService)).toBeInstanceOf( entrypoint.BuilderTemplatesService, diff --git a/packages/@n8n/instance-ai/src/agent/__tests__/instance-agent.test.ts b/packages/@n8n/instance-ai/src/agent/__tests__/instance-agent.test.ts index 422b5bd8f5b..6a224956f7a 100644 --- a/packages/@n8n/instance-ai/src/agent/__tests__/instance-agent.test.ts +++ b/packages/@n8n/instance-ai/src/agent/__tests__/instance-agent.test.ts @@ -19,6 +19,8 @@ const mockMemoryBuilder = { build: vi.fn(), }; +const mockLogger = { info: vi.fn(), warn: vi.fn(), error: vi.fn(), debug: vi.fn() }; + vi.mock('@n8n/agents', () => ({ Agent: vi.fn().mockImplementation(function Agent(this: (typeof mockAgentInstances)[number]) { this.model = vi.fn().mockReturnThis(); @@ -68,7 +70,6 @@ vi.mock('../../tools', () => ({ createOrchestrationTools: vi.fn( (context: { runId: string }) => new Map([ - ['plan', mockBuiltTool(`plan-${context.runId}`)], ['create-tasks', mockBuiltTool(`create-tasks-${context.runId}`)], ['complete-checkpoint', mockBuiltTool(`complete-checkpoint-${context.runId}`)], ['verify-built-workflow', mockBuiltTool(`verify-built-workflow-${context.runId}`)], @@ -173,7 +174,8 @@ describe('createInstanceAgent', () => { expect(Agent).toHaveBeenCalledTimes(2); const attachedTools = getAttachedTools(); const secondRunAttachedTools = getAttachedTools(1); - expect(attachedTools['plan-run-1']).toMatchObject({ name: 'plan-run-1' }); + expect(attachedTools['create-tasks-run-1']).toMatchObject({ name: 'create-tasks-run-1' }); + expect(attachedTools['plan-run-1']).toBeUndefined(); expect(attachedTools['research-run-1']).toMatchObject({ name: 'research-run-1' }); expect(attachedTools['build-workflow-run-1']).toMatchObject({ name: 'build-workflow-run-1', @@ -412,6 +414,7 @@ describe('createInstanceAgent', () => { localGatewayStatus: undefined, licenseHints: undefined, localMcpServer, + logger: mockLogger, }, orchestrationContext, memoryConfig, diff --git a/packages/@n8n/instance-ai/src/agent/__tests__/mcp-tool-name-validation.test.ts b/packages/@n8n/instance-ai/src/agent/__tests__/mcp-tool-name-validation.test.ts index 9b4818ae584..d9d67977786 100644 --- a/packages/@n8n/instance-ai/src/agent/__tests__/mcp-tool-name-validation.test.ts +++ b/packages/@n8n/instance-ai/src/agent/__tests__/mcp-tool-name-validation.test.ts @@ -15,7 +15,7 @@ describe('MCP tool name validation', () => { addSafeMcpTools(target, makeTools(['github_workflows', 'custom_plan']), { source: 'external MCP', - claimedToolNames: createClaimedToolNames(['workflows', 'plan']), + claimedToolNames: createClaimedToolNames(['workflows', 'create-tasks']), }); expect(target.get('github_workflows')).toBeDefined(); diff --git a/packages/@n8n/instance-ai/src/agent/__tests__/system-prompt.test.ts b/packages/@n8n/instance-ai/src/agent/__tests__/system-prompt.test.ts index e24dbff9d77..361a234a0dd 100644 --- a/packages/@n8n/instance-ai/src/agent/__tests__/system-prompt.test.ts +++ b/packages/@n8n/instance-ai/src/agent/__tests__/system-prompt.test.ts @@ -1,6 +1,37 @@ -import { getSystemPrompt } from '../system-prompt'; +import { getDateTimeSection, getSystemPrompt } from '../system-prompt'; + +describe('getDateTimeSection', () => { + afterEach(() => vi.useRealTimers()); + + it('renders the current time at minute precision (no seconds/milliseconds)', () => { + vi.useFakeTimers().setSystemTime(new Date('2026-06-16T14:59:11.396Z')); + + const section = getDateTimeSection('UTC'); + + expect(section).toContain('2026-06-16T14:59'); + // The sub-minute portion must be dropped so the cached prefix stays stable. + expect(section).not.toContain('14:59:11'); + expect(section).not.toContain('.396'); + }); + + it('is byte-stable across sub-minute calls', () => { + vi.useFakeTimers().setSystemTime(new Date('2026-06-16T14:59:01.000Z')); + const first = getDateTimeSection('UTC'); + + vi.setSystemTime(new Date('2026-06-16T14:59:58.999Z')); + const second = getDateTimeSection('UTC'); + + expect(second).toBe(first); + }); +}); describe('getSystemPrompt', () => { + it('keeps the cached prefix free of the current date/time so it stays cacheable', () => { + const prompt = getSystemPrompt({}); + + expect(prompt).not.toContain('## Current Date and Time'); + }); + describe('first visible turn guidance', () => { it('instructs the agent to send a concise sentence before the first tool call', () => { const prompt = getSystemPrompt({}); @@ -83,200 +114,86 @@ describe('getSystemPrompt', () => { }); }); - describe('replan branch — must take action', () => { - it('requires the orchestrator to take action rather than just acknowledge', () => { + describe('routing index', () => { + it('allows multiple skill loads per turn instead of a single best-match load', () => { const prompt = getSystemPrompt({}); - expect(prompt).toMatch(/You MUST take action in this same turn/); - expect(prompt).toContain('awaiting_replan'); - expect(prompt).toMatch(/Do NOT reply with an acknowledgement or status update alone/); - expect(prompt).toContain('the thread will silently stall'); + expect(prompt).not.toMatch(/load_skill.*once/i); + expect(prompt).toContain('more than one skill'); }); - it('lists both single-task (direct tool) and multi-task (create-tasks) routes', () => { + it('routes workflow builds through the workflow-builder skill', () => { const prompt = getSystemPrompt({}); - expect(prompt).toMatch(/handle a single simple task directly/); - expect(prompt).toMatch(/call `create-tasks` for multiple dependent tasks/); - }); - }); - - describe('When to Plan — what-am-I-touching axis', () => { - it('routes new and multi-workflow work through plan', () => { - const prompt = getSystemPrompt({}); - - expect(prompt).toContain('## When to Plan'); - expect(prompt).toMatch(/New workflow \(no `workflowId`\) or multi-workflow build/); - expect(prompt).toContain('call `plan` immediately'); - expect(prompt).toContain('Do not load the `workflow-builder` skill'); - expect(prompt).toContain('workflow tasks include any data table names'); - expect(prompt).toContain('The planner sub-agent discovers credentials and data tables'); - expect(prompt).not.toContain('discovers credentials, data tables, and best practices'); + expect(prompt).toContain("Match the user's request against skill descriptions"); + expect(prompt).toContain('**Single workflow build or edit**'); + expect(prompt).toContain('`workflow-builder`'); + expect(prompt).toContain('`build-workflow`'); + expect(prompt).toContain('**Multi-workflow or coordinated architecture**'); + expect(prompt).toContain('`planning`'); + expect(prompt).toContain('planningContext.source: "planning-skill"'); + expect(prompt).toContain('multiple durable artifacts'); + expect(prompt).toContain('shared data-table schema/migration'); + expect(prompt).not.toContain('build-workflow-with-agent'); }); - it('routes standalone data-table work through direct tools and the skill', () => { + it('routes standalone data-table work through the data-table-manager skill', () => { const prompt = getSystemPrompt({}); expect(prompt).toMatch(/Standalone data-table work/); - expect(prompt).toContain('`data-table-manager` skill'); - expect(prompt).toContain('Natural requests like "what data tables do I have?"'); - expect(prompt).toContain('Do not call `plan`, `create-tasks`, or `delegate`'); + expect(prompt).toContain('`data-table-manager`'); + expect(prompt).toContain('what data tables do I have?'); + expect(prompt).toContain( + 'never call `data-tables` or `parse-file` without loading `data-table-manager` first', + ); + expect(prompt).toContain('Do not call `create-tasks` or `delegate`'); }); - it('loads the data-table skill before planning workflows that use tables', () => { + it('loads data-table-manager before workflow-builder when tables are involved', () => { const prompt = getSystemPrompt({}); + expect(prompt).toContain('workflows that create or write to Data Tables'); expect(prompt).toContain( - 'If the workflow will create, read, update, seed, import, or store records in n8n Data Tables, load the `data-table-manager` skill before `plan`', + '`data-table-manager` when tables are involved, then `workflow-builder`', ); }); - it('routes existing-workflow edits through the workflow-builder skill', () => { - const prompt = getSystemPrompt({}); - - expect(prompt).toMatch(/Any edit to an existing workflow that runs the builder/); - expect(prompt).toContain('load the `workflow-builder` skill'); - expect(prompt).toContain('call `build-workflow` directly'); - expect(prompt).toContain('existing `workflowId`'); - expect(prompt).toContain('approval before saving'); - }); - - it('routes non-build ops through direct tools', () => { - const prompt = getSystemPrompt({}); - - expect(prompt).toMatch(/Non-build ops on an existing workflow/); - expect(prompt).toContain('The builder does not run.'); - }); - - it('routes replan follow-ups as routing, not re-planning', () => { - const prompt = getSystemPrompt({}); - - expect(prompt).toMatch(/Replan follow-up/); - expect(prompt).toMatch(/route, don't re-plan/); - }); - }); - - describe('post-build verify for direct workflow builds', () => { - it('uses verificationReadiness as the post-build routing signal', () => { - const prompt = getSystemPrompt({}); - - expect(prompt).toContain('Post-build flow'); - expect(prompt).toContain('verify-built-workflow'); - expect(prompt).toContain('`verificationReadiness`'); - expect(prompt).toContain('`setupRequirement`'); - expect(prompt).toContain('verificationReadiness.status === "ready"'); - expect(prompt).toContain('verificationReadiness.status === "needs_setup"'); - expect(prompt).toContain('verificationReadiness.status === "not_verifiable"'); - expect(prompt).toContain('setupRequirement.status === "required"'); - expect(prompt).toContain('`triggerNodes`'); - expect(prompt).not.toContain('outcome.usesWorkflowPinDataForVerification'); - expect(prompt).not.toContain('outcome.verificationPinData'); - }); - - it('grounds workflow setup in the inline assistant card', () => { - const prompt = getSystemPrompt({}); - - expect(prompt).toContain('inline setup card in the AI Assistant panel'); - expect(prompt).toContain( - 'Do not tell the user to open the editor, use the canvas, or click a Setup button', - ); - expect(prompt).not.toMatch(/setup wizard/i); - }); - - it('makes post-build credential setup the default path', () => { - const prompt = getSystemPrompt({}); - - expect(prompt).toContain('Do not ask whether to build now and set up credentials later'); - expect(prompt).toContain('building first and routing setup after verification'); - }); - - it('reads workflowId/workItemId from build-workflow output', () => { - const prompt = getSystemPrompt({}); - - expect(prompt).toContain('read `workflowId`, `workItemId`, `triggerNodes`'); - expect(prompt).toContain('`verificationReadiness`'); - expect(prompt).toContain('`setupRequirement`'); - }); - - it('reuses deterministic already-verified readiness instead of re-running verify', () => { - const prompt = getSystemPrompt({}); - - expect(prompt).toContain('verificationReadiness.status === "already_verified"'); - expect(prompt).toContain('do **not** call `verify-built-workflow` again'); - }); - - it('leaves publish dependency ordering to the workflows tool', () => { + it('loads data-table-manager before planning when shared tables are involved', () => { const prompt = getSystemPrompt({}); expect(prompt).toContain( - 'Only call `workflows(action="publish")` when the user explicitly asks', - ); - expect(prompt).not.toContain('outcome.supportingWorkflowIds'); - }); - }); - - describe('checkpoint branch — in-turn patch rule + retry carve-out', () => { - it('allows checkpoints to reuse successful structured verification evidence', () => { - const prompt = getSystemPrompt({}); - - expect(prompt).toContain('Always require structured verification evidence'); - expect(prompt).toContain('never trust builder prose'); - expect(prompt).toContain('without re-running verification'); - expect(prompt).not.toContain('Always run your own verification'); - }); - - it('routes verified checkpoint workflows with setup needs through workflow setup before completion', () => { - const prompt = getSystemPrompt({}); - - expect(prompt).toContain('workflows(action="setup")'); - expect(prompt).toContain('outcome.setupRequirement.status === "required"'); - expect(prompt).toContain('before `complete-checkpoint`'); - expect(prompt).toContain('deferred: true'); - expect(prompt).toContain( - 'Do not call `credentials(action="setup")` or `apply-workflow-credentials`', + '`data-table-manager` first when shared tables are involved → `planning`', ); }); - it('does not treat checkpoint verification as a user-requested run', () => { + it('does not plan just for verification', () => { const prompt = getSystemPrompt({}); - expect(prompt).toContain('explicitly asked to run or execute the workflow'); - expect(prompt).toContain('checkpoint verification does not satisfy a user-requested run'); - expect(prompt).toContain('executions(action="run")'); + expect(prompt).toContain('Do not create a plan just for verification'); }); - it('tells the orchestrator it may patch during a checkpoint and re-verify in place', () => { + it('points post-build and follow-up work at dedicated skills', () => { const prompt = getSystemPrompt({}); - expect(prompt).toContain('patch in place'); - expect(prompt).toContain('call `build-workflow` directly during this checkpoint turn'); - expect(prompt).toContain('re-verify'); - expect(prompt).toContain('complete-checkpoint'); + expect(prompt).toContain('`post-build-flow`'); + expect(prompt).toContain('`planned-task-runtime`'); + expect(prompt).toContain('`debugging-executions`'); }); - it('keeps in-checkpoint patch attempts bounded', () => { + it('keeps replan stall prevention in the core follow-up triggers', () => { const prompt = getSystemPrompt({}); - expect(prompt).toMatch(/Keep the patch count small/); - expect(prompt).toMatch(/within two rounds/); - }); - }); - - describe('multi-credential disambiguation guidance', () => { - it('instructs the orchestrator to ask once when a service has more than one credential of the same type', () => { - const prompt = getSystemPrompt({}); - - expect(prompt).toContain('Ask once when a service has multiple credentials of the same type'); - expect(prompt).toContain('more than one entry of the type'); - expect(prompt).toContain('single-select'); - expect(prompt).toContain('With a single candidate, auto-apply and do not ask'); + expect(prompt).toContain(''); + expect(prompt).toContain('you MUST take action in this turn'); + expect(prompt).toContain('the thread will silently stall'); }); - it('instructs the orchestrator to ask which auth type to use when a service supports more than one', () => { + it('routes browser credential setup through the Computer Use skill', () => { const prompt = getSystemPrompt({}); - expect(prompt).toContain('Ask which auth type to use when a service supports more than one'); - expect(prompt).toContain('List OAuth2 first'); + expect(prompt).toContain('needsBrowserSetup=true'); + expect(prompt).toContain('credential-setup-with-computer-use'); + expect(prompt).toMatch(/use Computer Use `browser_\*` tools directly \(not `delegate`\)/); }); }); @@ -298,6 +215,7 @@ describe('getSystemPrompt', () => { expect(prompt).toContain('knowledge-base/index.json'); expect(prompt).toContain('knowledge-base/best-practices/index.json'); expect(prompt).toContain('knowledge-base/templates/index.json'); + expect(prompt).toContain('knowledge-base/reference/index.json'); expect(prompt).not.toContain('knowledge-base/templates/index.txt'); expect(prompt).toContain('workspace_execute_command'); expect(prompt).toContain('Consult the knowledge base before planning or building'); @@ -335,9 +253,6 @@ describe('getSystemPrompt', () => { }); it('directs the agent to the Open chat button when Chat Trigger is private', () => { - // Regression: agent was sharing the public webhook URL for private chat - // triggers, then offering to flip `public: true` for testing instead of - // pointing the user at the workflow's built-in Open chat button. const prompt = getSystemPrompt({ webhookBaseUrl, formBaseUrl }); expect(prompt).toContain('**Open chat** button on the workflow canvas'); diff --git a/packages/@n8n/instance-ai/src/agent/instance-agent.ts b/packages/@n8n/instance-ai/src/agent/instance-agent.ts index 824f9ef320d..bba4f0f13fb 100644 --- a/packages/@n8n/instance-ai/src/agent/instance-agent.ts +++ b/packages/@n8n/instance-ai/src/agent/instance-agent.ts @@ -64,7 +64,7 @@ export async function createInstanceAgent(options: CreateInstanceAgentOptions): ); const warnSkippedMcpTool = (error: McpToolNameValidationError) => { - context.logger?.warn('Skipped MCP tool with unsafe name', { + context.logger.warn('Skipped MCP tool with unsafe name', { toolName: error.toolName, source: error.source, reason: error.message, @@ -132,7 +132,6 @@ export async function createInstanceAgent(options: CreateInstanceAgentOptions): localGateway: context.localGatewayStatus, toolSearchEnabled: hasDeferrableTools, licenseHints: context.licenseHints, - timeZone: options.timeZone, browserAvailable: browserToolNames.size > 0, branchReadOnly: context.branchReadOnly, workspaceRoot: diff --git a/packages/@n8n/instance-ai/src/agent/shared-prompts.ts b/packages/@n8n/instance-ai/src/agent/shared-prompts.ts index 0f73be04c7f..ef4cd08c6c4 100644 --- a/packages/@n8n/instance-ai/src/agent/shared-prompts.ts +++ b/packages/@n8n/instance-ai/src/agent/shared-prompts.ts @@ -35,9 +35,10 @@ export function getSandboxWorkspaceSection(workspaceRoot?: string): string { ${pathHint} A thread-scoped sandbox workspace is available via \`workspace_read_file\`, \`workspace_list_files\`, and \`workspace_execute_command\` (use \`grep\` or \`rg\` to search). The workspace is created on first use and includes baked-in reference material: -- \`/knowledge-base/index.json\` — combined catalog of technique guides and curated workflow templates +- \`/knowledge-base/index.json\` — combined catalog of technique guides, curated workflow templates, and orchestration reference docs - \`/knowledge-base/best-practices/index.json\` — workflow technique guides (read the linked \`.md\` files) - \`/knowledge-base/templates/index.json\` — curated SDK workflow examples (read the linked \`.ts\` source files) +- \`/knowledge-base/reference/index.json\` — orchestration reference docs (e.g. trigger \`inputData\` shapes for verification) - \`/node-types/index.txt\` — searchable catalog of available n8n nodes - \`/workflows/*.json\` — existing workflows on this instance (when synced) @@ -45,10 +46,3 @@ A thread-scoped sandbox workspace is available via \`workspace_read_file\`, \`wo return substituteWorkspaceRoot(section, workspaceRoot); } - -export const PLACEHOLDERS_RULE = `## Placeholders -Use \`placeholder('descriptive hint')\` for values that cannot be safely picked without the user: -- **User-provided values that cannot be discovered** — email recipients, phone numbers, custom URLs, notification targets. -- **Resource IDs with more than one candidate** — when \`nodes(action="explore-resources")\` returns multiple matches (e.g. several calendars, spreadsheets, channels, folders) and the user did not name a specific one, use \`placeholder('Select ')\` rather than guessing. When there is exactly one match, use it directly. - -Never hardcode fake values like \`user@example.com\` or \`YOUR_API_KEY\`. When the user says "send me" / "email me" / "notify me" and their address isn't known, use \`placeholder('Your email address')\` rather than any hardcoded address. After the build, \`workflows(action="setup")\` opens an inline setup card in the AI Assistant panel so the user can fill placeholder values.`; diff --git a/packages/@n8n/instance-ai/src/agent/system-prompt.ts b/packages/@n8n/instance-ai/src/agent/system-prompt.ts index a5959650bbe..6b2c99c215d 100644 --- a/packages/@n8n/instance-ai/src/agent/system-prompt.ts +++ b/packages/@n8n/instance-ai/src/agent/system-prompt.ts @@ -12,18 +12,19 @@ interface SystemPromptOptions { toolSearchEnabled?: boolean; /** Human-readable hints about licensed features that are NOT available on this instance. */ licenseHints?: string[]; - /** IANA time zone identifier for the current user (e.g. "Europe/Helsinki"). */ - timeZone?: string; browserAvailable?: boolean; /** When true, the instance is in read-only mode (source control branchReadOnly). */ branchReadOnly?: boolean; + projectId?: string; /** Absolute or host-relative sandbox workspace root for `` paths in prompts. */ workspaceRoot?: string; } export function getDateTimeSection(timeZone?: string): string { const now = timeZone ? DateTime.now().setZone(timeZone) : DateTime.now(); - const isoTime = now.toISO({ includeOffset: true }); + const isoTime = now + .startOf('minute') + .toISO({ includeOffset: true, suppressSeconds: true, suppressMilliseconds: true }); const tzLabel = timeZone ? ` (timezone: ${timeZone})` : ''; return ` ## Current Date and Time @@ -51,6 +52,32 @@ Some trigger nodes expose HTTP endpoints. Always share the full production URL w **These URLs are for sharing with the user only.** Do NOT hardcode them into workflow code or build specs unless the workflow actually needs to send or store its own public endpoint.`; } +function getProjectScopeSection(projectId?: string): string { + if (!projectId) return ''; + return ` +## Project Scope + +This conversation is scoped to a single n8n project. Reads and writes differ: + +- **Writes are locked to this project.** Workflows and data tables you create or + modify belong to this project, and you can only use credentials available + within it — you cannot wire in credentials from other projects. +- **Credentials are always this project's.** The credential list is exactly the + credentials usable in this project, and you cannot widen it. Report them as + "in this project", never "on this instance" or "across the instance". +- **Looking things up defaults to this project, but you can search wider.** + Workflow, data table, and other resource lookups return this project's items by + default; widen a search to the whole instance when the user needs something + that may live in another project (e.g. researching a data table or workflow in + another project). Describe results by what you actually searched — "in this + project" for the default, "across the instance" when you widened. + +If the user asks you to create something in, move something to, or use a +credential from a different project, explain that this conversation is locked to +its project and they should start a new conversation in the project they want to +work in.`; +} + function getReadOnlySection(branchReadOnly?: boolean): string { if (!branchReadOnly) return ''; return ` @@ -80,88 +107,53 @@ export function getSystemPrompt(options: SystemPromptOptions = {}): string { localGateway, toolSearchEnabled, licenseHints, - timeZone, browserAvailable, branchReadOnly, + projectId, workspaceRoot, } = options; return `You are the n8n Instance Agent — an AI assistant embedded in an n8n instance. You help users build, run, debug, and manage workflows through natural language. -${getDateTimeSection(timeZone)} ${webhookBaseUrl && formBaseUrl ? getInstanceInfoSection(webhookBaseUrl, formBaseUrl) : ''} ${workspaceRoot ? `\n${getSandboxWorkspaceSection(workspaceRoot)}\n` : ''} -You have access to workflow, execution, and credential tools plus a specialized workflow-builder skill. You also have delegation capabilities for complex tasks, and may have access to MCP tools for extended capabilities. +You have access to workflow, execution, and credential tools plus runtime skills (see the skill catalog). You also have delegation capabilities for complex tasks, and may have access to MCP tools for extended capabilities. +${getProjectScopeSection(projectId)} -## When to Plan +Match the user's request against skill descriptions in the catalog. Call \`load_skill\` before acting on a matched skill's guidance — never call \`data-tables\` or \`parse-file\` without loading \`data-table-manager\` first, and never call \`build-workflow\` without loading \`workflow-builder\` first. A single turn may need more than one skill when routing requires it (e.g. \`data-table-manager\` then \`workflow-builder\`). -Route by **what you are touching**, not by how risky the change feels: - -1. **New workflow (no \`workflowId\`) or multi-workflow build** → call \`plan\` immediately. Do not load the \`workflow-builder\` skill, look up node schemas, or call \`build-workflow\` before planning. If the workflow will create, read, update, seed, import, or store records in n8n Data Tables, load the \`data-table-manager\` skill before \`plan\` and carry the relevant table guidance into \`guidance\` or \`conversationContext\`. The planner sub-agent discovers credentials and data tables; workflow tasks include any data table names, columns, seed/import needs, or existing-table requirements in the workflow spec, and the builder creates/uses them. The orchestrator-run checkpoint independently proves every workflow deliverable works. Do NOT ask the user questions first — the planner asks targeted questions itself if needed. Only pass \`guidance\` when the conversation is ambiguous or when you need to pass loaded skill guidance. When \`plan\` returns, tasks are already dispatched. - -2. **Any edit to an existing workflow that runs the builder** (add/remove/rewire a node, change an expression, swap a credential, change a schedule, fix a Code node) → load the \`workflow-builder\` skill and call \`build-workflow\` directly with the existing \`workflowId\`. The tool asks for approval before saving when required. A plan-for-every-edit is too slow; run the lightweight post-build verify afterwards (see **Post-build flow**). - -3. **Non-build ops on an existing workflow** (rename, toggle active, duplicate, move to folder, describe, read executions, publish, delete) → use the specific direct tool (\`workflows\`, \`executions\`, etc.). The builder does not run. - -4. **Standalone data-table work** (list/show/inspect/schema/query/create/import/seed/insert/update/delete/rename columns/clean up rows without building a workflow) → load the \`data-table-manager\` skill, then call \`data-tables\` and \`parse-file\` directly. Natural requests like "what data tables do I have?", "show/list my tables", "what columns are in this table?", "query this table", and "insert/update/delete rows" all count as standalone data-table work. Do not call \`plan\`, \`create-tasks\`, or \`delegate\` for standalone data-table work. - -5. **Replan follow-up** (\`\`) → route, don't re-plan. If one simple task remains (e.g. a single data-table op, credential setup, or single-workflow patch), handle it directly with the matching tool. If multiple dependent tasks still need scheduling, call \`create-tasks\` (a runtime guard rejects \`create-tasks\` outside a replan context). If nothing sensible remains, explain the blocker to the user. **Never end a replan turn with only an acknowledgement** — the scheduler will not fire another follow-up until you act, and the thread will silently stall. +- **Single workflow build or edit** (new workflow, add/remove/rewire nodes, expression/credential/schedule/Code fixes, including workflows that create or write to Data Tables) → \`data-table-manager\` when tables are involved, then \`workflow-builder\` → \`build-workflow\`. After save, load \`post-build-flow\` when verification or setup is needed. Do not create a plan just for verification. +- **Multi-workflow or coordinated architecture** (dependencies between workflows, shared data-table schema/migration, multiple durable artifacts, broad research, ambiguous business process, user asks to review a plan) → \`data-table-manager\` first when shared tables are involved → \`planning\` → \`create-tasks\` with \`planningContext.source: "planning-skill"\`. +- **Non-build workflow ops** (rename, toggle active, duplicate, move, describe, list executions, publish, delete) → direct \`workflows\` / \`executions\` tools. Do not run the builder. +- **Standalone data-table work** (list, schema, query, create, import, mutate rows/columns without building a workflow) → \`data-table-manager\` → \`data-tables\` / \`parse-file\`. Natural requests like "what data tables do I have?", "show/list my tables", and "what columns are in this table?" count as standalone data-table work. Do not call \`create-tasks\` or \`delegate\`. +- **Execution debugging** (failed runs, wrong/empty node output) → \`debugging-executions\`. +- **Browser credential setup** when \`credentials(action="setup")\` returns \`needsBrowserSetup=true\` → \`credential-setup-with-computer-use\`, then use Computer Use \`browser_*\` tools directly (not \`delegate\`). Use \`task-control(action="update-checklist")\` only for lightweight visible checklists that do not need scheduler-driven execution. +Never use \`delegate\` to build, patch, fix, or update workflows — workflow building runs in the orchestrator with \`workflow-builder\` and \`build-workflow\`. + +## System follow-ups + +Load the matching skill **before acting** when the current message contains: + +- \`\` or \`\` → \`post-build-flow\` +- \`\`, \`\`, or \`\` → \`planned-task-runtime\` +- \`\` → \`planned-task-runtime\` — you MUST take action in this turn; never end with acknowledgement alone or the thread will silently stall + +After calling \`create-tasks\` or \`delegate\`, load \`planned-task-runtime\` guidance for silence rules — do not write visible text; the task or approval card is the user-visible surface. + ## Delegation -Use \`delegate\` when a task benefits from focused context. Sub-agents are stateless — include all relevant context in the briefing (IDs, error messages, credential names). +Use \`delegate\` when a task benefits from focused context. Sub-agents are stateless — include all relevant context in the briefing (IDs, error messages, credential names). Always pass \`conversationContext\` summarizing what was discussed, decisions made, and information gathered. -When \`credentials(action="setup")\` returns \`needsBrowserSetup=true\`, load the \`credential-setup-with-computer-use\` skill and use Computer Use \`browser_*\` tools directly (not \`delegate\`). After the credential is created or captured, call \`credentials(action="setup")\` again. +## Tool conventions -## Workflow Building - -Never use \`delegate\` to build, patch, fix, or update workflows — workflow building happens in the orchestrator with the \`workflow-builder\` skill and the workflow build tools. - -To edit an existing workflow, load the \`workflow-builder\` skill, read the current workflow code when needed with \`workflows(action="get-as-code")\`, and call \`build-workflow\` with the existing \`workflowId\`. The tool handles edit approval before saving when permissions require it. Verify the result afterwards via \`verify-built-workflow\` when the build output says verification is ready (see **Post-build flow**). Use \`plan\` when the change spans multiple workflows, creates new workflows, or a workflow build needs new or changed data-table schemas — then the orchestrator-run checkpoint drives verification. - -The \`workflow-builder\` skill handles node discovery, schema lookups, resource discovery, code generation, validation, repair, and saving. It runs in you, the orchestrator, with the native orchestrator tools directly available; it is not a delegated sub-agent or a separate sandbox lifecycle. For planned workflow builds, follow the build task spec exactly. For direct edits, describe the user goal in your own working notes, then implement it with SDK code or targeted \`build-workflow\` patches. - -**Parameter-value precedence: user > builder > you.** If the user named a concrete value (model ID, resource ID, enum choice, version), pass it through verbatim. Otherwise leave the slot unspecified — the builder resolves it from each node's \`@builderHint\` / \`@default\`, which are more current than your training data. Your own "sensible default" is never the right answer. Describe integrations at the category level — "OpenAI chat model", "hourly scheduler", "lookup spreadsheet". - -**Never hardcode fake user data in the task spec** — no \`user@example.com\`, \`YOUR_API_KEY\`, \`Bearer YOUR_TOKEN\`, sample Slack channel IDs, fake Telegram chat IDs, fake Teams thread IDs, sample recipient lists (\`alice@company.com\`, etc.). When the user hasn't provided a specific value, describe the slot generically ("user's email address", "target Slack channel", "API bearer token") and let the builder wrap it with \`placeholder()\` so \`workflows(action="setup")\` can collect it after the build through the inline setup card in the AI Assistant panel. - -Always pass \`conversationContext\` when spawning background agents (\`delegate\`) — summarize what was discussed, decisions made, and information gathered. Exception: \`plan\` reads the conversation history directly — only pass \`guidance\` if the context is ambiguous. - -**After spawning any background agent** (\`delegate\`, \`plan\`, or \`create-tasks\`): do not write any text. The task card shows the user what's being built or done; restating it (e.g. the workflow name, what the agent will do) is redundant. Do NOT summarize the plan, list credentials, describe what the agent will do, or add status details. The agent's progress is already visible to the user in real time. - -**Credentials**: Call \`credentials(action="list")\` first to know what's available. Build the workflow immediately — the builder preserves explicit valid credentials and auto-mocks missing or unselected ones. Do not ask whether to build now and set up credentials later; building first and routing setup after verification is the default path. Planned builder tasks verify through checkpoints; the orchestrator handles workflow setup after verification when the saved workflow still has mocked credentials or placeholders. - -**Ask once when a service has multiple credentials of the same type.** If \`credentials(action="list")\` shows more than one entry of the type a requested integration needs (e.g. two \`openAiApi\` accounts, three Google Calendar accounts), use \`ask-user\` with a single-select to let the user pick one before building, and use the chosen credential name in the workflow code. Exception: the user already named the credential in their message — use it directly. With a single candidate, auto-apply and do not ask. - -**Ask which auth type to use when a service supports more than one.** \`credentials(action="setup")\` opens a picker locked to a single \`credentialType\` — the user cannot switch auth types from there. So when \`credentials(action="search-types")\` returns more than one auth option for a service (e.g. \`notionApi\` and \`notionOAuth2Api\`, or \`slackApi\` and \`slackOAuth2Api\`), use \`ask-user\` with a single-select to let the user pick the auth type before calling \`credentials(action="setup")\`. List OAuth2 first and present it as the recommended option. Exception: the user has clearly indicated an auth type (e.g. "api key", "oauth", "personal token") — map it to the matching \`credentialType\` and use it directly without asking. +- **Include entity names** — when a tool accepts an optional name parameter (e.g. \`workflowName\`, \`folderName\`, \`credentialName\`), always pass it. The name is shown to the user in confirmation dialogs. +- **Web research** — use \`research\` directly for most questions. Load \`planning\` and \`create-tasks\` only for broad detached synthesis across many sources. ${SECRET_ASK_GUARDRAIL} -**Post-build flow** (for direct \`build-workflow\` calls — planned build follow-ups hand off verification to checkpoint tasks): - -**Publishing is never required for testing.** Both \`executions(action="run")\` and \`verify-built-workflow\` inject \`inputData\` as the trigger's output — the workflow does not need to be active. Form, webhook, chat, and other event-based triggers are all testable while the workflow is unpublished. Never publish a workflow as a precondition for running it. - -1. \`build-workflow\` succeeds → read \`workflowId\`, \`workItemId\`, \`triggerNodes\`, \`verificationReadiness\`, and \`setupRequirement\` from the tool output. If the output is missing a \`workflowId\`, explain that the build did not submit. - - If \`verificationReadiness.status === "already_verified"\`, treat the workflow as verified and do **not** call \`verify-built-workflow\` again. - - If \`verificationReadiness.status === "ready"\`, call \`verify-built-workflow\` with the \`workItemId\` / \`workflowId\` and the trigger-appropriate \`inputData\` shape (see **Per-trigger \`inputData\` shape** below). - - If \`verificationReadiness.status === "needs_setup"\`, call \`workflows(action="setup")\` with the workflowId so the user can configure it through the inline setup card in the AI Assistant panel. - - If \`verificationReadiness.status === "not_verifiable"\`, do not infer lower-level verification conditions; use the readiness guidance to decide whether to explain the blocker or ask the user to test manually. -2. After verification handling, if \`setupRequirement.status === "required"\` and setup has not already run for this build, call \`workflows(action="setup")\` with the workflowId. -3. When \`workflows(action="setup")\` opens the inline setup card, the card is the user-visible surface. Do not tell the user to open the editor, use the canvas, or click a Setup button; the user does not need to navigate anywhere. -4. When \`workflows(action="setup")\` returns \`deferred: true\`, respect the user's decision — do not retry with \`credentials(action="setup")\` or any other setup tool. The user chose to set things up later. -5. Ask the user if they want to test the workflow (skip this if \`verify-built-workflow\` already proved it works end-to-end). -6. Only call \`workflows(action="publish")\` when the user explicitly asks to publish. Never publish automatically. - -## Tool Usage - -- **Testing event-triggered workflows**: use \`executions(action="run")\` with \`inputData\` matching the trigger's output shape — do not rebuild the workflow with a Manual Trigger. -- **Debugging a failed execution**: \`executions(action="debug")\` already includes \`failedNode.resolvedParameters\` — start there. That bundle has \`parameters\` (raw, with expressions intact), \`resolved\` (substituted), \`failedExpressions\` (those that threw), and \`emptyResolutions\` (those that resolved to \`null\`/\`undefined\`/\`""\` silently). The offending expression is usually visible without a follow-up call. Entries in either list tagged with \`reason: "unreconstructable-context"\` are NOT real bugs — they reference variables we don't reconstruct in replay (\`$vars\`, \`$secrets\`, \`$response\`, \`$request\`, \`$pageCount\`, \`$ai\`). The value existed at execution time; we just don't have it here. -- **Debugging a successful execution with a wrong/empty value**: 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 expressions resolving to \`null\`/\`undefined\`/\`""\`, not thrown errors. -- **Include entity names** — when a tool accepts an optional name parameter (e.g. \`workflowName\`, \`folderName\`, \`credentialName\`), always pass it. The name is shown to the user in confirmation dialogs. -- **Data tables**: load the \`data-table-manager\` skill before standalone list/schema/query/create/delete/add-column/delete-column/rename-column/insert-rows/update-rows/delete-rows work, then call \`data-tables\` directly; use \`parse-file\` for attached CSV/XLSX/JSON inputs. Always pass \`dataTableName\` and \`projectId\` after a list/lookup reveals them so previews and approval cards can target the right table. Do not call \`plan\`, \`create-tasks\`, or \`delegate\` for standalone data-table work. When building workflows that need tables, load the skill before planning/building and describe table requirements in the workflow task spec — the builder creates/uses them. - ${ toolSearchEnabled ? `## Tool Discovery @@ -180,7 +172,7 @@ Examples: search "credential" for the credentials tool, search "file" for filesy - No emojis unless the user explicitly requests them. - At the beginning of a normal user-visible turn, before your first tool call, write one short sentence explaining what you are about to do or what decision you need. Keep it tied to the user's goal, not the tool name. For system-generated background or checkpoint follow-up turns, follow the follow-up instructions. - Never let an empty assistant message or a \`[Calling tools: ...]\` placeholder be the first visible response. -- End every tool call sequence with a brief text summary — the user cannot see raw tool output. Do not end your turn silently after tool calls. Exception: after spawning a background agent (\`plan\`, \`create-tasks\`, \`delegate\`) or during planned-task build/checkpoint follow-ups, the task card or checklist replaces your reply — do not write text. +- End every tool call sequence with a brief text summary — the user cannot see raw tool output. Do not end your turn silently after tool calls. Exception: after calling \`create-tasks\` or \`delegate\`, or during planned-task build/checkpoint follow-ups, the task card, approval card, or checklist replaces your reply — do not write text. ## Safety @@ -188,10 +180,6 @@ Examples: search "credential" for the credentials tool, search "file" for filesy - **Credential setup** uses \`workflows(action="setup")\` when a workflowId is available — it opens the inline setup card in the AI Assistant panel and handles credentials, parameters, and triggers in one step. Use \`credentials(action="setup")\` only when the user explicitly asks to create a credential outside of any workflow context. Never call both tools for the same workflow. Never describe workflow setup as something the user starts from the canvas or editor. - **Never expose credential secrets** — metadata only. -### Web research - -You have the \`research\` tool with \`web-search\` and \`fetch-url\` actions. Use them directly for most questions. Use \`plan\` with \`research\` tasks only for broad detached synthesis (comparing services, broad surveys across 3+ doc pages). - ${UNTRUSTED_CONTENT_DOCTRINE} ${getComputerUsePrompt({ browserAvailable, localGateway })} @@ -205,44 +193,5 @@ ${licenseHints.map((h) => `- ${h}`).join('\n')} ` : '' -}${getReadOnlySection(branchReadOnly)}## Working Memory - -Working memory persists across all your conversations with this user. Keep it focused and useful: - -- **User Context & Workflow Preferences**: Update when you learn stable facts (name, role, preferred integrations). These rarely change. -- **Active Project**: Track ONLY the currently active project. When a project is completed or the user moves on, replace it — do not accumulate a history of past projects. -- **Instance Knowledge**: Do not store credential IDs or workflow IDs — you can look these up via tools. Only note custom node types if the user has them. -- **General principle**: Working memory should be a concise snapshot of the user's current state, not a historical log. If a section grows beyond a few lines, prune older entries that are no longer relevant. - -## After Planning - -When \`plan\` or \`create-tasks\` returns, tasks are already running. Write one short sentence acknowledging the work, then end your turn. Do not summarize — the user already approved the plan. Wait for \`\` to arrive; do not invent synthetic follow-up turns. - -**Never poll and never sleep.** Background tasks (\`delegate\`) settle via \`\` turns that arrive automatically when work finishes. After you spawn or acknowledge one, end your turn. Do not call \`workflows(action="list")\`, \`executions(action="list")\`, or any shell command to check progress — you will receive a follow-up turn the moment the task settles. If a task appears stuck, tell the user and stop; do not try to detect completion yourself. Do not re-dispatch a build whose task ID is already visible in \`\`. - -When \`\` context is present, use it only to reference active task IDs for cancellation or corrections. - -When \`\` is present, all planned tasks completed successfully. Treat verified workflow drafts as finished deliverables — they are ready to use. If the original user request explicitly asked to run or execute the workflow after building it, call \`executions(action="run")\` once for the built workflow; checkpoint verification does not satisfy a user-requested run. Otherwise write a concise completion message that names each delivered artifact (data tables, workflows) and summarizes what it does, using the user's time zone for any scheduled timings. Do not hedge with phrases like "ready to go live" or "let me know when you're ready" — the work is done. If any workflow is unpublished, state that plainly as a one-line next-step note ("Publish when you want it live — you can do that from the workflow editor."), not as a gating condition. Do not create another plan. - -When \`\` is present, a planned task failed and the graph is in \`awaiting_replan\`. You MUST take action in this same turn — handle a single simple task directly (matching tool: \`build-workflow\`, \`data-tables\`, \`delegate\`, etc.), call \`create-tasks\` for multiple dependent tasks, or explain the blocker to the user if nothing sensible remains. Do NOT reply with an acknowledgement or status update alone — the scheduler will not fire another follow-up until you act, and the thread will silently stall. Apply the replan branch from \`## When to Plan\` above. - -When \`\` is present, load the \`workflow-builder\` skill and build exactly the \`buildTask\` in the payload. If \`buildTask.workflowId\` is present, update that workflow; otherwise create a new one. Save with \`build-workflow\` and stop after a successful save — do not verify, set up credentials, publish, call \`complete-checkpoint\`, create a new plan, or write a user-facing message. If \`build-workflow\` returns fixable validation errors, patch in the same turn and save again. If the build is blocked, explain the blocker briefly; the planned task finalizer will mark the task failed. - -When \`\` is present, the block contains exactly one checkpoint task (\`checkpoint.id\`, \`checkpoint.title\`, \`checkpoint.instructions\`, and \`checkpoint.dependsOn\` — the outcomes of prior tasks, including workflow build outcomes with their \`outcome.workItemId\` / \`outcome.workflowId\`). **Always require structured verification evidence — never trust builder prose.** If a dependency outcome contains successful \`outcome.verification\` tool evidence (\`attempted: true\`, \`success: true\`, an \`executionId\`, and executed-node evidence), use that evidence without re-running verification. Otherwise execute \`checkpoint.instructions\` using your tools — typically \`verify-built-workflow\` with the work item ID from the dependency outcome, or \`executions(action="run")\` for a built workflow with real credentials and a testable trigger. If verification succeeds and any verified workflow dependency outcome has \`outcome.setupRequirement.status === "required"\`, call \`workflows(action="setup")\` with that workflowId before \`complete-checkpoint\`; the inline setup card appears automatically in the AI Assistant panel, so do not tell the user to open the editor, use the canvas, or click a Setup button. If setup returns \`deferred: true\`, respect it and still complete the checkpoint with a result that says setup was deferred. Do not call \`credentials(action="setup")\` or \`apply-workflow-credentials\` for workflow setup. Then call \`complete-checkpoint(taskId, status, result)\` **exactly once** to report the outcome (\`status: "succeeded"\` on pass, \`"failed"\` on a verification failure). Do not create a new plan, do not write a user-facing message — the checkpoint card in the plan checklist is the user-visible surface. End your turn as soon as \`complete-checkpoint\` returns. - -When \`\` is present, a detached background task finished. The \`result\` field holds the sub-agent's authoritative summary of what was actually done. **When you write the user-facing recap, take factual details — model IDs, node names, resource IDs, parameter values — directly from this \`result\` text.** Do not substitute values from conversation history or training priors: if the \`result\` says \`gpt-5.4-mini\`, write \`gpt-5.4-mini\`, not "GPT-4o mini" or any other name you associate with the provider. The task spec describes intent; the \`result\` describes what actually happened. - -**If your verification surfaced a bug you can patch in place** (e.g., a Code-node shape issue), load the \`workflow-builder\` skill and call \`build-workflow\` directly during this checkpoint turn, passing the existing \`workflowId\` and the dependency \`workItemId\`. Then re-verify in the same checkpoint turn. Keep the patch count small: if the issue cannot be narrowed within two rounds, call \`complete-checkpoint(status="failed", error=...)\` with a summary of what remains and let replan take over. - -### Per-trigger \`inputData\` shape - -Used by both the checkpoint verification path and the direct post-build verify step. The pin-data adapter spreads / wraps based on trigger type — passing the wrong shape gives null downstream values that look like an expression bug: -- **Form Trigger** (\`n8n-nodes-base.formTrigger\`) — flat field map, e.g. \`{name: "Alice", email: "a@b.c"}\`. The production Form Trigger emits each field directly on \`$json\`, so the builder's \`$json.\` expressions are correct. **Do NOT wrap in \`formFields\`** — the adapter will reject the call. -- **Webhook** (\`n8n-nodes-base.webhook\`) — the body payload, e.g. \`{event: "signup", userId: "..."}\`. The adapter wraps it under \`body\`, so downstream nodes reference \`$json.body.\`. -- **Chat Trigger** (\`@n8n/n8n-nodes-langchain.chatTrigger\`) — \`{chatInput: "user message"}\`. -- **Schedule Trigger** (\`n8n-nodes-base.scheduleTrigger\`) — omit \`inputData\`; the adapter emits synthetic timestamp fields. - -**Do not patch a workflow first when verify returns null downstream values.** Re-run verify with the corrected \`inputData\` shape. Only patch the workflow if the expression is wrong against the *production* trigger output shape (consult node descriptions), not the \`instanceAi\` pin data path. - -If the user sends a correction while a build is running, call \`task-control(action="correct-task")\` with the task ID and correction.`; +}${getReadOnlySection(branchReadOnly)}`; } diff --git a/packages/@n8n/instance-ai/src/constants/max-steps.ts b/packages/@n8n/instance-ai/src/constants/max-steps.ts index 265fe0737b3..03a3f8d9916 100644 --- a/packages/@n8n/instance-ai/src/constants/max-steps.ts +++ b/packages/@n8n/instance-ai/src/constants/max-steps.ts @@ -13,8 +13,6 @@ export const MAX_STEPS = { BUILDER: 60, /** Eval setup sub-agent — reads workflow, creates DataTable, patches eval nodes + validates. */ EVAL_SETUP: 30, - /** Planning sub-agent — breaks down multi-step tasks. */ - PLANNER: 30, /** Research sub-agent — web search and synthesis. */ RESEARCH: 25, /** Generic delegate fallback when no specific limit is configured. */ diff --git a/packages/@n8n/instance-ai/src/debug/__tests__/run-debug-buffer.test.ts b/packages/@n8n/instance-ai/src/debug/__tests__/run-debug-buffer.test.ts new file mode 100644 index 00000000000..0fb83103f22 --- /dev/null +++ b/packages/@n8n/instance-ai/src/debug/__tests__/run-debug-buffer.test.ts @@ -0,0 +1,222 @@ +import type { OnStepFinishEvent, OnStepStartEvent } from 'ai'; +import { describe, expect, it } from 'vitest'; +import { mock } from 'vitest-mock-extended'; + +import type { Logger } from '../../logger'; +import { + RunDebugBuffer, + buildRunDebugLabel, + createRunDebugStepHooks, + sanitizeStepFinish, + sanitizeStepStart, +} from '../run-debug-buffer'; +import { sanitizeDebugSnapshotValue } from '../sanitize-debug-snapshot'; + +function makeFinishEvent(text: string): OnStepFinishEvent { + return { + stepNumber: 0, + text, + toolCalls: [], + finishReason: 'tool-calls', + usage: { inputTokens: 1, outputTokens: 2, totalTokens: 3 }, + response: { + modelId: 'test-model', + timestamp: new Date('2026-01-01T00:00:00.000Z'), + messages: [{ role: 'assistant', content: text }], + }, + } as unknown as OnStepFinishEvent; +} + +function makeStartEvent(): OnStepStartEvent { + return { + stepNumber: 0, + system: 'You are helpful', + messages: [{ role: 'user', content: 'hello' }], + tools: { search: { description: 'search', inputSchema: { type: 'object' } } }, + toolChoice: 'auto', + activeTools: ['search'], + abortSignal: new AbortController().signal, + } as unknown as OnStepStartEvent; +} + +describe('RunDebugBuffer', () => { + it('pairs step start and finish by run-scoped step index', () => { + const buffer = new RunDebugBuffer(); + buffer.ensure('run-1', 'thread-1'); + + buffer.recordStepStart('run-1', 0, makeStartEvent()); + buffer.recordStepFinish('run-1', 0, makeFinishEvent('done')); + + const record = buffer.get('run-1'); + expect(record?.steps).toHaveLength(1); + expect(record?.steps[0]?.stepNumber).toBe(0); + expect(record?.steps[0]?.input?.messages).toBeDefined(); + expect(record?.steps[0]?.output?.text).toBe('done'); + }); + + it('records multiple orchestrator iterations even when SDK stepNumber stays 0', () => { + const buffer = new RunDebugBuffer(); + buffer.ensure('run-1', 'thread-1'); + const hooks = createRunDebugStepHooks(buffer, { runId: 'run-1', threadId: 'thread-1' }); + + for (const label of ['first', 'second', 'third']) { + hooks.onStepStart(makeStartEvent()); + hooks.onStepFinish(makeFinishEvent(label)); + } + + const record = buffer.get('run-1'); + expect(record?.steps).toHaveLength(3); + expect(record?.steps.map((step) => step.stepNumber)).toEqual([0, 1, 2]); + expect(record?.steps.map((step) => step.output?.text)).toEqual(['first', 'second', 'third']); + }); + + it('continues step numbering after resume hooks are recreated', () => { + const buffer = new RunDebugBuffer(); + buffer.ensure('run-1', 'thread-1'); + + const firstPass = createRunDebugStepHooks(buffer, { runId: 'run-1', threadId: 'thread-1' }); + firstPass.onStepStart(makeStartEvent()); + firstPass.onStepFinish(makeFinishEvent('before suspend')); + + const resumePass = createRunDebugStepHooks(buffer, { runId: 'run-1', threadId: 'thread-1' }); + resumePass.onStepStart(makeStartEvent()); + resumePass.onStepFinish(makeFinishEvent('after resume')); + + const record = buffer.get('run-1'); + expect(record?.steps).toHaveLength(2); + expect(record?.steps[1]?.stepNumber).toBe(1); + expect(record?.steps[1]?.output?.text).toBe('after resume'); + }); + + it('keeps full tool definitions and strips abortSignal from step start', () => { + const sanitized = sanitizeStepStart( + { + stepNumber: 1, + system: 'system prompt', + messages: [{ role: 'user', content: 'hello' }], + tools: { + search: { description: 'search', inputSchema: { type: 'object', properties: { q: {} } } }, + }, + toolChoice: 'auto', + activeTools: ['search'], + abortSignal: new AbortController().signal, + } as unknown as OnStepStartEvent, + 4, + ); + + expect(sanitized.stepNumber).toBe(4); + expect(sanitized.sdkStepNumber).toBe(1); + expect(sanitized.activeTools).toEqual(['search']); + expect(sanitized.tools).toEqual({ + search: { description: 'search', inputSchema: { type: 'object', properties: { q: {} } } }, + }); + expect(sanitized).not.toHaveProperty('abortSignal'); + }); + + it('does not truncate long captured strings', () => { + const longSystem = 'x'.repeat(5_000); + const sanitized = sanitizeDebugSnapshotValue(longSystem); + expect(sanitized).toHaveLength(5_000); + }); + + it('captures full tool call inputs and outputs on step finish', () => { + const sanitized = sanitizeStepFinish( + { + stepNumber: 0, + text: '', + toolCalls: [ + { + toolCallId: 'tc-1', + toolName: 'build-workflow', + input: { code: 'full workflow code payload' }, + }, + ], + toolResults: [ + { + toolCallId: 'tc-1', + toolName: 'build-workflow', + output: { success: true, workflowId: 'wf-1' }, + }, + ], + finishReason: 'tool-calls', + usage: { inputTokens: 1, outputTokens: 2, totalTokens: 3 }, + response: { + modelId: 'test-model', + timestamp: new Date('2026-01-01T00:00:00.000Z'), + messages: [{ role: 'assistant', content: '' }], + body: { secret: 'raw-provider-body' }, + }, + } as unknown as OnStepFinishEvent, + 0, + ); + + expect(sanitized.toolCalls).toEqual([ + { + toolCallId: 'tc-1', + toolName: 'build-workflow', + input: { code: 'full workflow code payload' }, + }, + ]); + expect(sanitized.toolResults).toEqual([ + { + toolCallId: 'tc-1', + toolName: 'build-workflow', + output: { success: true, workflowId: 'wf-1' }, + }, + ]); + expect(sanitized.response).not.toHaveProperty('body'); + }); + + it('evicts oldest run when cap is exceeded', () => { + const logger = mock(); + const buffer = new RunDebugBuffer(logger); + + for (let index = 0; index < 51; index++) { + const runId = `run-${index}`; + buffer.ensure(runId, 'thread-1'); + buffer.recordStepStart(runId, 0, { + stepNumber: 0, + messages: [], + } as unknown as OnStepStartEvent); + } + + expect(buffer.get('run-0')).toBeUndefined(); + expect(buffer.get('run-50')).toBeDefined(); + expect(logger.warn).toHaveBeenCalled(); + }); + + it('createRunDebugStepHooks writes into the buffer', () => { + const buffer = new RunDebugBuffer(); + buffer.ensure('run-1', 'thread-1'); + const hooks = createRunDebugStepHooks(buffer, { runId: 'run-1', threadId: 'thread-1' }); + + hooks.onStepStart({ + stepNumber: 2, + messages: [{ role: 'user', content: 'ping' }], + } as unknown as OnStepStartEvent); + + expect(buffer.get('run-1')?.steps[0]?.stepNumber).toBe(0); + expect(buffer.get('run-1')?.steps[0]?.input?.sdkStepNumber).toBe(2); + }); + + it('stores a run label on first ensure', () => { + const buffer = new RunDebugBuffer(); + buffer.ensure('run-1', 'thread-1', 'build a weather workflow'); + expect(buffer.get('run-1')?.label).toBe('build a weather workflow'); + buffer.ensure('run-1', 'thread-1', 'ignored'); + expect(buffer.get('run-1')?.label).toBe('build a weather workflow'); + }); +}); + +describe('buildRunDebugLabel', () => { + it('uses the user message when no resume reason is provided', () => { + expect(buildRunDebugLabel({ message: 'build a simple workflow' })).toBe( + 'build a simple workflow', + ); + }); + + it('maps resume reasons to action labels', () => { + expect(buildRunDebugLabel({ resumeReason: 'approval' })).toBe('Resume · approval'); + expect(buildRunDebugLabel({ resumeReason: 'replan' })).toBe('Follow-up · replan'); + }); +}); diff --git a/packages/@n8n/instance-ai/src/debug/run-debug-buffer.ts b/packages/@n8n/instance-ai/src/debug/run-debug-buffer.ts new file mode 100644 index 00000000000..9128602cc03 --- /dev/null +++ b/packages/@n8n/instance-ai/src/debug/run-debug-buffer.ts @@ -0,0 +1,251 @@ +import { scrubSecretsInText } from '@n8n/utils'; +import type { OnStepFinishEvent, OnStepStartEvent } from 'ai'; + +import type { Logger } from '../logger'; +import { sanitizeDebugSnapshotRecord, sanitizeDebugSnapshotValue } from './sanitize-debug-snapshot'; + +const MAX_RUNS = 50; +const MAX_STEPS_PER_RUN = 200; +const MAX_WORKFLOW_SNAPSHOTS_PER_RUN = 100; + +export interface WorkflowCodeSnapshotInput { + code: string; + source: 'full-code' | 'patch'; + patches?: unknown; + workflowId?: string; + toolCallId?: string; + success: boolean; + errors?: string[]; + capturedAt: number; +} + +export type SanitizedStepStart = { + stepNumber: number; + sdkStepNumber?: number; +} & Record; + +export type SanitizedStepFinish = { + stepNumber: number; + sdkStepNumber?: number; +} & Record; + +export type WorkflowCodeSnapshot = WorkflowCodeSnapshotInput; + +export interface RunDebugStep { + stepNumber: number; + input?: SanitizedStepStart; + output?: SanitizedStepFinish; +} + +export interface RunDebugRecord { + threadId: string; + runId: string; + startedAt: number; + label?: string; + /** Next run-scoped step index; survives step-cap eviction. */ + nextStepIndex: number; + steps: RunDebugStep[]; + workflowCode: WorkflowCodeSnapshot[]; +} + +export interface RunDebugStepHookOptions { + runId: string; + threadId: string; +} + +function captureStepStartPayload(event: OnStepStartEvent): Record { + const { abortSignal: _abortSignal, ...capturable } = event; + return sanitizeDebugSnapshotRecord(capturable); +} + +function captureStepFinishPayload(event: OnStepFinishEvent): Record { + return sanitizeDebugSnapshotRecord(event); +} + +export function sanitizeStepStart(event: OnStepStartEvent, stepNumber: number): SanitizedStepStart { + return { + ...captureStepStartPayload(event), + stepNumber, + sdkStepNumber: event.stepNumber, + }; +} + +export function sanitizeStepFinish( + event: OnStepFinishEvent, + stepNumber: number, +): SanitizedStepFinish { + return { + ...captureStepFinishPayload(event), + stepNumber, + sdkStepNumber: event.stepNumber, + }; +} + +export function createRunDebugStepHooks( + buffer: RunDebugBuffer, + options: RunDebugStepHookOptions, +): { + onStepStart: (event: OnStepStartEvent) => void; + onStepFinish: (event: OnStepFinishEvent) => void; +} { + // The agent runtime calls streamText/generateText once per loop iteration. The AI SDK + // resets stepNumber to 0 on each call, so we allocate a run-scoped sequence instead. + let stepIndex = buffer.getNextStepIndex(options.runId); + + return { + onStepStart: (event) => { + buffer.recordStepStart(options.runId, stepIndex, event); + }, + onStepFinish: (event) => { + buffer.recordStepFinish(options.runId, stepIndex, event); + stepIndex++; + }, + }; +} + +export function buildRunDebugLabel(options: { + message?: string; + resumeReason?: string; +}): string { + const resumeLabels: Record = { + approval: 'Resume · approval', + background_task_completed: 'Follow-up · background task completed', + workflow_verification: 'Follow-up · workflow verification', + workflow_setup: 'Follow-up · workflow setup', + planned_checkpoint: 'Follow-up · planned checkpoint', + replan: 'Follow-up · replan', + synthesize: 'Follow-up · synthesize', + }; + + if (options.resumeReason && resumeLabels[options.resumeReason]) { + return resumeLabels[options.resumeReason]; + } + + const trimmed = options.message?.trim(); + if (trimmed) { + return trimmed.length > 80 ? `${trimmed.slice(0, 80)}…` : trimmed; + } + + return 'Orchestrator run'; +} + +export class RunDebugBuffer { + private readonly records = new Map(); + + constructor(private readonly logger?: Logger) {} + + ensure(runId: string, threadId: string, label?: string): void { + if (this.records.has(runId)) return; + + this.evictOldestRunIfNeeded(); + this.records.set(runId, { + threadId, + runId, + startedAt: Date.now(), + label: label ? scrubSecretsInText(label.trim()) : undefined, + nextStepIndex: 0, + steps: [], + workflowCode: [], + }); + } + + getNextStepIndex(runId: string): number { + return this.records.get(runId)?.nextStepIndex ?? 0; + } + + recordStepStart(runId: string, stepIndex: number, event: OnStepStartEvent): void { + const record = this.records.get(runId); + if (!record) return; + + const existing = record.steps.find((step) => step.stepNumber === stepIndex); + if (existing) { + existing.input = sanitizeStepStart(event, stepIndex); + return; + } + + this.evictOldestStepIfNeeded(record); + record.steps.push({ + stepNumber: stepIndex, + input: sanitizeStepStart(event, stepIndex), + }); + record.steps.sort((a, b) => a.stepNumber - b.stepNumber); + } + + recordStepFinish(runId: string, stepIndex: number, event: OnStepFinishEvent): void { + const record = this.records.get(runId); + if (!record) return; + + const existing = record.steps.find((step) => step.stepNumber === stepIndex); + if (existing) { + existing.output = sanitizeStepFinish(event, stepIndex); + record.nextStepIndex = stepIndex + 1; + return; + } + + this.evictOldestStepIfNeeded(record); + record.steps.push({ + stepNumber: stepIndex, + output: sanitizeStepFinish(event, stepIndex), + }); + record.steps.sort((a, b) => a.stepNumber - b.stepNumber); + record.nextStepIndex = stepIndex + 1; + } + + recordWorkflowCode(runId: string, snapshot: WorkflowCodeSnapshotInput): void { + const record = this.records.get(runId); + if (!record) return; + + if (record.workflowCode.length >= MAX_WORKFLOW_SNAPSHOTS_PER_RUN) { + record.workflowCode.shift(); + this.logger?.warn('Evicted oldest workflow code snapshot from run debug buffer', { + runId, + maxSnapshots: MAX_WORKFLOW_SNAPSHOTS_PER_RUN, + }); + } + + record.workflowCode.push({ + ...snapshot, + code: scrubSecretsInText(snapshot.code), + patches: sanitizeDebugSnapshotValue(snapshot.patches), + errors: snapshot.errors?.map((error) => scrubSecretsInText(error)), + }); + } + + get(runId: string): RunDebugRecord | undefined { + const record = this.records.get(runId); + if (!record) return undefined; + return structuredClone(record); + } + + listByThread(threadId: string): RunDebugRecord[] { + return [...this.records.values()] + .filter((record) => record.threadId === threadId) + .sort((a, b) => a.startedAt - b.startedAt) + .map((record) => structuredClone(record)); + } + + private evictOldestRunIfNeeded(): void { + if (this.records.size < MAX_RUNS) return; + + const oldest = [...this.records.values()].sort((a, b) => a.startedAt - b.startedAt)[0]; + if (!oldest) return; + + this.records.delete(oldest.runId); + this.logger?.warn('Evicted oldest run from debug buffer', { + runId: oldest.runId, + threadId: oldest.threadId, + maxRuns: MAX_RUNS, + }); + } + + private evictOldestStepIfNeeded(record: RunDebugRecord): void { + if (record.steps.length < MAX_STEPS_PER_RUN) return; + + const removed = record.steps.shift(); + this.logger?.warn('Evicted oldest step from run debug buffer', { + runId: record.runId, + stepNumber: removed?.stepNumber, + maxSteps: MAX_STEPS_PER_RUN, + }); + } +} diff --git a/packages/@n8n/instance-ai/src/debug/sanitize-debug-snapshot.ts b/packages/@n8n/instance-ai/src/debug/sanitize-debug-snapshot.ts new file mode 100644 index 00000000000..c576f8558bd --- /dev/null +++ b/packages/@n8n/instance-ai/src/debug/sanitize-debug-snapshot.ts @@ -0,0 +1,116 @@ +import { scrubSecretsInText } from '@n8n/utils'; + +import { isRecord } from '../utils/stream-helpers'; + +const OMIT_KEYS = new Set(['abortSignal']); +const SENSITIVE_KEY_PATTERN = + /(api[_-]?key|authorization|bearer|cookie|credentials?|password|secret|access[_-]?token|refresh[_-]?token|id[_-]?token|session[_-]?token|auth[_-]?token|(?:^|[._-])token$)/i; + +function shouldOmitKey(key: string, parentKey?: string): boolean { + if (OMIT_KEYS.has(key)) { + return true; + } + + // Raw provider HTTP payloads are not useful in the debug buffer. + if (key === 'body' && parentKey === 'response') { + return true; + } + + return false; +} + +function redactSensitiveKey(key: string, value: unknown, seen: WeakSet): unknown { + if (SENSITIVE_KEY_PATTERN.test(key) && typeof value === 'string') { + return '[redacted]'; + } + + return sanitizeDebugSnapshotValue(value, key, seen); +} + +/** + * Full-fidelity JSON-safe snapshot for the in-memory run debug buffer. + * Unlike trace sanitization, this does not truncate strings, arrays, or object keys. + */ +export function sanitizeDebugSnapshotValue( + value: unknown, + keyHint?: string, + seen?: WeakSet, +): unknown { + const seenObjects = seen ?? new WeakSet(); + + if (value === undefined || value === null) { + return value; + } + + if (typeof value === 'string') { + if (keyHint && SENSITIVE_KEY_PATTERN.test(keyHint)) { + return '[redacted]'; + } + return scrubSecretsInText(value); + } + + if (typeof value === 'number' || typeof value === 'boolean') { + return value; + } + + if (typeof value === 'bigint') { + return value.toString(); + } + + if (typeof value === 'function') { + return `[function ${value.name || 'anonymous'}]`; + } + + if (value instanceof AbortSignal) { + return '[AbortSignal]'; + } + + if (value instanceof Date) { + return value.toISOString(); + } + + if (value instanceof Error) { + return { + name: value.name, + message: scrubSecretsInText(value.message), + }; + } + + if (value instanceof Uint8Array) { + return `[binary ${value.byteLength} bytes]`; + } + + if (Array.isArray(value)) { + if (seenObjects.has(value)) { + return '[Circular]'; + } + seenObjects.add(value); + return value.map((entry) => sanitizeDebugSnapshotValue(entry, keyHint, seenObjects)); + } + + if (isRecord(value)) { + if (seenObjects.has(value)) { + return '[Circular]'; + } + seenObjects.add(value); + const sanitized: Record = {}; + for (const [key, entryValue] of Object.entries(value)) { + if (shouldOmitKey(key, keyHint)) { + continue; + } + sanitized[key] = redactSensitiveKey(key, entryValue, seenObjects); + } + return sanitized; + } + + if (typeof value === 'symbol') { + return value.toString(); + } + + return '[unsupported value]'; +} + +export function sanitizeDebugSnapshotRecord(value: unknown): Record { + const sanitized = sanitizeDebugSnapshotValue(value); + return isRecord(sanitized) ? sanitized : { value: sanitized }; +} diff --git a/packages/@n8n/instance-ai/src/index.ts b/packages/@n8n/instance-ai/src/index.ts index 40619322f6c..db54830ca68 100644 --- a/packages/@n8n/instance-ai/src/index.ts +++ b/packages/@n8n/instance-ai/src/index.ts @@ -1,8 +1,11 @@ /* eslint-disable @typescript-eslint/no-require-imports */ +import type * as SharedSandboxMod from '@n8n/agents/sandbox'; + import './source-map-filter'; import type * as InstanceAgentMod from './agent/instance-agent'; import type * as SubAgentFactoryMod from './agent/sub-agent-factory'; +import type * as SystemPromptMod from './agent/system-prompt'; import type * as DomainAccessMod from './domain-access'; import type * as McpClientManagerMod from './mcp/mcp-client-manager'; import type * as TitleUtilsMod from './memory/title-utils'; @@ -35,6 +38,7 @@ import type * as BuilderTemplatesServiceMod from './workspace/builder-templates- import type * as CreateWorkspaceMod from './workspace/create-workspace'; import type * as LazyRuntimeWorkspaceMod from './workspace/lazy-runtime-workspace'; import type * as SandboxSetupMod from './workspace/sandbox-setup'; +import type * as ScopedWorkspaceMod from './workspace/scoped-workspace'; import type * as SnapshotManagerMod from './workspace/snapshot-manager'; type LazyFunction = (...args: never[]) => unknown; @@ -91,6 +95,9 @@ const loadDomainAccess = lazyModule(() => require('./domain-access') as typeof D const loadSubAgentFactory = lazyModule( () => require('./agent/sub-agent-factory') as typeof SubAgentFactoryMod, ); +const loadSystemPrompt = lazyModule( + () => require('./agent/system-prompt') as typeof SystemPromptMod, +); const loadSanitizeWebContent = lazyModule( () => require('./tools/web-research/sanitize-web-content') as typeof SanitizeWebContentMod, ); @@ -124,12 +131,18 @@ const loadBuilderTemplatesService = lazyModule( const loadCreateWorkspace = lazyModule( () => require('./workspace/create-workspace') as typeof CreateWorkspaceMod, ); +const loadSharedSandbox = lazyModule( + () => require('@n8n/agents/sandbox') as typeof SharedSandboxMod, +); const loadLazyRuntimeWorkspace = lazyModule( () => require('./workspace/lazy-runtime-workspace') as typeof LazyRuntimeWorkspaceMod, ); const loadSandboxSetup = lazyModule( () => require('./workspace/sandbox-setup') as typeof SandboxSetupMod, ); +const loadScopedWorkspace = lazyModule( + () => require('./workspace/scoped-workspace') as typeof ScopedWorkspaceMod, +); const loadSnapshotManager = lazyModule( () => require('./workspace/snapshot-manager') as typeof SnapshotManagerMod, ); @@ -276,6 +289,9 @@ export const createInstanceAgent: typeof InstanceAgentMod.createInstanceAgent = export const createSubAgent: typeof SubAgentFactoryMod.createSubAgent = lazyFunction( () => loadSubAgentFactory().createSubAgent, ); +export const getDateTimeSection: typeof SystemPromptMod.getDateTimeSection = lazyFunction( + () => loadSystemPrompt().getDateTimeSection, +); export const createAllTools: typeof ToolsMod.createAllTools = lazyFunction( () => loadTools().createAllTools, ); @@ -325,6 +341,7 @@ export type { PatchableThreadMemory, ThreadPatch, TerminalOutcome, + WorkflowSetupRoutingClaim, WorkflowLoopWorkItemRecord, } from './storage'; export const truncateToTitle: typeof TitleUtilsMod.truncateToTitle = lazyFunction( @@ -395,6 +412,10 @@ defineLazyExport( () => loadLivenessPolicy().INSTANCE_AI_DEFAULT_LIVENESS_POLICY_CONFIG, ); defineLazyExport('workflowBuildOutcomeSchema', () => loadWorkflowLoop().workflowBuildOutcomeSchema); +defineLazyExport( + 'workflowVerificationEvidenceSchema', + () => loadWorkflowLoop().workflowVerificationEvidenceSchema, +); defineLazyExport('attemptRecordSchema', () => loadWorkflowLoop().attemptRecordSchema); defineLazyExport('workflowLoopStateSchema', () => loadWorkflowLoop().workflowLoopStateSchema); defineLazyExport('verificationResultSchema', () => loadWorkflowLoop().verificationResultSchema); @@ -413,15 +434,19 @@ export type { SandboxConfig } from './workspace/create-workspace'; export const createLazyRuntimeWorkspace: typeof LazyRuntimeWorkspaceMod.createLazyRuntimeWorkspace = lazyFunction(() => loadLazyRuntimeWorkspace().createLazyRuntimeWorkspace); export type { RuntimeWorkspaceResolver } from './workspace/lazy-runtime-workspace'; -export const getWorkspaceRoot: typeof SandboxSetupMod.getWorkspaceRoot = lazyFunction( - () => loadSandboxSetup().getWorkspaceRoot, +export const getWorkspaceRoot: typeof SharedSandboxMod.getWorkspaceRoot = lazyFunction( + () => loadSharedSandbox().getWorkspaceRoot, +); +export const getPromptWorkspaceRoot: typeof SharedSandboxMod.getPromptWorkspaceRoot = lazyFunction( + () => loadSharedSandbox().getPromptWorkspaceRoot, ); export const setupSandboxWorkspace: typeof SandboxSetupMod.setupSandboxWorkspace = lazyFunction( () => loadSandboxSetup().setupSandboxWorkspace, ); export type BuilderTemplatesService = BuilderTemplatesServiceMod.BuilderTemplatesService; -export { createScopedWorkspace } from './workspace/scoped-workspace'; -export { getPromptWorkspaceRoot } from './workspace/sandbox-setup'; +export const createScopedWorkspace: typeof ScopedWorkspaceMod.createScopedWorkspace = lazyFunction( + () => loadScopedWorkspace().createScopedWorkspace, +); export const BuilderTemplatesService: typeof BuilderTemplatesServiceMod.BuilderTemplatesService = lazyClass(() => loadBuilderTemplatesService().BuilderTemplatesService); export const builderTemplatesOptionsFromEnv: typeof BuilderTemplatesServiceMod.builderTemplatesOptionsFromEnv = @@ -453,10 +478,16 @@ export type { ManagedBackgroundTask, SpawnManagedBackgroundTaskOptions, } from './runtime/background-task-manager'; -export type RunStateRegistry = RunStateRegistryMod.RunStateRegistry; +export type RunStateRegistry = RunStateRegistryMod.RunStateRegistry; export const RunStateRegistry: typeof RunStateRegistryMod.RunStateRegistry = lazyClass( () => loadRunStateRegistry().RunStateRegistry, ); +export type { RunDebugRecord } from './debug/run-debug-buffer'; +export { + RunDebugBuffer, + buildRunDebugLabel, + createRunDebugStepHooks, +} from './debug/run-debug-buffer'; export type { ActiveRunState, BackgroundTaskStatusSnapshot, @@ -487,6 +518,7 @@ export type { ResumableStreamSource, } from './runtime/resumable-stream-executor'; export type { WorkSummary } from './stream/work-summary-accumulator'; +export type { RunTokenUsage } from './stream/usage-accumulator'; export const resumeAgentRun: typeof StreamRunnerMod.resumeAgentRun = lazyFunction( () => loadStreamRunner().resumeAgentRun, ); @@ -528,16 +560,33 @@ export type WorkflowTaskCoordinator = WorkflowLoopMod.WorkflowTaskCoordinator; export const WorkflowTaskCoordinator: typeof WorkflowLoopMod.WorkflowTaskCoordinator = lazyClass( () => loadWorkflowLoop().WorkflowTaskCoordinator, ); +export const deriveWorkflowVerificationObligation: typeof WorkflowLoopMod.deriveWorkflowVerificationObligation = + lazyFunction(() => loadWorkflowLoop().deriveWorkflowVerificationObligation); +export const deriveWorkflowVerificationObligationFromOutcome: typeof WorkflowLoopMod.deriveWorkflowVerificationObligationFromOutcome = + lazyFunction(() => loadWorkflowLoop().deriveWorkflowVerificationObligationFromOutcome); +export const isWorkflowVerificationObligationUnsettled: typeof WorkflowLoopMod.isWorkflowVerificationObligationUnsettled = + lazyFunction(() => loadWorkflowLoop().isWorkflowVerificationObligationUnsettled); +export const resolveWorkflowBuildOwner: typeof WorkflowLoopMod.resolveWorkflowBuildOwner = + lazyFunction(() => loadWorkflowLoop().resolveWorkflowBuildOwner); +export const plannedTaskIdFromWorkflowBuildOwner: typeof WorkflowLoopMod.plannedTaskIdFromWorkflowBuildOwner = + lazyFunction(() => loadWorkflowLoop().plannedTaskIdFromWorkflowBuildOwner); +export const isPlannedWorkflowBuildOwner: typeof WorkflowLoopMod.isPlannedWorkflowBuildOwner = + lazyFunction(() => loadWorkflowLoop().isPlannedWorkflowBuildOwner); export declare const workflowBuildOutcomeSchema: typeof WorkflowLoopMod.workflowBuildOutcomeSchema; +export declare const workflowVerificationEvidenceSchema: typeof WorkflowLoopMod.workflowVerificationEvidenceSchema; export declare const attemptRecordSchema: typeof WorkflowLoopMod.attemptRecordSchema; export declare const workflowLoopStateSchema: typeof WorkflowLoopMod.workflowLoopStateSchema; export declare const verificationResultSchema: typeof WorkflowLoopMod.verificationResultSchema; export type { WorkflowLoopState, WorkflowLoopAction, + WorkflowBuildOwner, WorkflowBuildOutcome, VerificationResult, AttemptRecord, + WorkflowVerificationEvidence, + WorkflowVerificationObligation, + WorkflowVerificationObligationSource, } from './workflow-loop'; export type WorkflowLoopRuntime = WorkflowLoopRuntimeMod.WorkflowLoopRuntime; export const WorkflowLoopRuntime: typeof WorkflowLoopRuntimeMod.WorkflowLoopRuntime = lazyClass( @@ -571,6 +620,7 @@ export type { PlannedTaskRecord, PlannedTaskGraph, PlannedTaskGraphStatus, + PlannedWorkflowVerification, PlannedTaskSchedulerAction, PlannedTaskService, OrchestrationContext, 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 dc1fcd92132..657aaefe7c3 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 @@ -14,6 +14,8 @@ import { makeBuilderTemplatesTarGz } from './builder-templates-archive.fixtures' 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; @@ -49,8 +51,8 @@ function createSandboxWorkspace(files: Map): { } describe('buildKnowledgeBaseWorkspaceBundle', () => { - it('builds best-practice markdown files, section indexes, root index, and manifest v4', () => { - const bundle = buildKnowledgeBaseWorkspaceBundle({ root: ROOT }); + it('builds best-practice markdown files, section indexes, root index, and manifest v4', async () => { + const bundle = await buildKnowledgeBaseWorkspaceBundle({ root: ROOT, logger: mockLogger }); expect(bundle.rootDir).toBe(`${ROOT}/${SANDBOX_KNOWLEDGE_BASE_DIR}`); expect( @@ -87,27 +89,66 @@ describe('buildKnowledgeBaseWorkspaceBundle', () => { ), ).toBe(true); + expect( + bundle.files.get( + `${ROOT}/${SANDBOX_KNOWLEDGE_BASE_DIR}/reference/trigger-input-data-shapes.md`, + ), + ).toContain('# Per-trigger `inputData` shape'); + expect( + bundle.files.get(`${ROOT}/${SANDBOX_KNOWLEDGE_BASE_DIR}/reference/open-ai-output-shape.md`), + ).toContain('# OpenAI node output shape'); + expect( + bundle.files.get( + `${ROOT}/${SANDBOX_KNOWLEDGE_BASE_DIR}/reference/workflow-builder-guardrails.md`, + ), + ).toContain('# Workflow Builder Guardrails'); + + expect( + bundle.files.get(`${ROOT}/${SANDBOX_KNOWLEDGE_BASE_DIR}/reference/workflow-sdk-language.md`), + ).toContain('# Workflow SDK language reference'); + const rootIndex = jsonParse<{ bestPractices: { indexFile: string; entries: Array<{ id: string }> }; templates: { indexFile: string; entries: unknown[] }; + reference: { indexFile: string; entries: Array<{ id: string; file: string }> }; }>( bundle.files.get(`${ROOT}/${SANDBOX_KNOWLEDGE_BASE_DIR}/${KNOWLEDGE_BASE_INDEX_FILE}`) ?? '', ); expect(rootIndex.bestPractices.indexFile).toBe('best-practices/index.json'); expect(rootIndex.templates.indexFile).toBe('templates/index.json'); + expect(rootIndex.reference.indexFile).toBe('reference/index.json'); expect(rootIndex.templates.entries).toEqual([]); + expect(rootIndex.reference.entries).toEqual([ + expect.objectContaining({ + id: 'trigger-input-data-shapes', + file: 'reference/trigger-input-data-shapes.md', + }), + expect.objectContaining({ + id: 'open-ai-output-shape', + file: 'reference/open-ai-output-shape.md', + }), + expect.objectContaining({ + id: 'workflow-builder-guardrails', + file: 'reference/workflow-builder-guardrails.md', + }), + expect.objectContaining({ + id: 'workflow-sdk-language', + file: 'reference/workflow-sdk-language.md', + }), + ]); expect(rootIndex.bestPractices.entries.some((entry) => entry.id === 'scheduling')).toBe(true); expect(bundle.indexPath).toBe( `${ROOT}/${SANDBOX_KNOWLEDGE_BASE_DIR}/${KNOWLEDGE_BASE_INDEX_FILE}`, ); }); - it('materializes CDN index.txt archives as templates/index.json', () => { + it('materializes CDN index.txt archives as templates/index.json', async () => { const archive = makeBuilderTemplatesTarGz([ { name: 'index.txt', content: 'example.ts | Example template' }, { name: 'example.ts', content: 'export default {};' }, ]); - const bundle = buildKnowledgeBaseWorkspaceBundle({ + const bundle = await buildKnowledgeBaseWorkspaceBundle({ + logger: mockLogger, root: ROOT, templatesArchive: archive, }); @@ -131,8 +172,11 @@ describe('buildKnowledgeBaseWorkspaceBundle', () => { ).toBe(false); }); - it('materializes templates as index.json and includes them in the root index', () => { - const withoutTemplates = buildKnowledgeBaseWorkspaceBundle({ root: ROOT }); + it('materializes templates as index.json and includes them in the root index', async () => { + const withoutTemplates = await buildKnowledgeBaseWorkspaceBundle({ + root: ROOT, + logger: mockLogger, + }); const archive = makeBuilderTemplatesTarGz([ { name: 'index.json', @@ -148,7 +192,8 @@ describe('buildKnowledgeBaseWorkspaceBundle', () => { }, { name: 'example.ts', content: 'export default {};' }, ]); - const withTemplates = buildKnowledgeBaseWorkspaceBundle({ + const withTemplates = await buildKnowledgeBaseWorkspaceBundle({ + logger: mockLogger, root: ROOT, templatesArchive: archive, }); @@ -201,6 +246,7 @@ describe('materializeKnowledgeBaseIntoWorkspace', () => { const { workspace, writes } = createSandboxWorkspace(new Map()); const bundle = await materializeKnowledgeBaseIntoWorkspace({ + logger: mockLogger, workspace, root: ROOT, }); @@ -211,7 +257,7 @@ describe('materializeKnowledgeBaseIntoWorkspace', () => { }); it('reuses prebaked knowledge base when the manifest hash matches', async () => { - const bundle = buildKnowledgeBaseWorkspaceBundle({ root: ROOT }); + const bundle = await buildKnowledgeBaseWorkspaceBundle({ root: ROOT, logger: mockLogger }); const files = new Map(); for (const [path, content] of bundle.files) { files.set(path, content); @@ -219,10 +265,12 @@ describe('materializeKnowledgeBaseIntoWorkspace', () => { const { workspace, writes } = createSandboxWorkspace(files); const prebaked = await loadPrebakedKnowledgeBaseBundle({ + logger: mockLogger, workspace, root: ROOT, }); const materialized = await materializeKnowledgeBaseIntoWorkspace({ + logger: mockLogger, workspace, root: ROOT, }); @@ -233,13 +281,14 @@ describe('materializeKnowledgeBaseIntoWorkspace', () => { }); it('rematerializes when prebaked manifest exists but payload is incomplete', async () => { - const bundle = buildKnowledgeBaseWorkspaceBundle({ root: ROOT }); + const bundle = await buildKnowledgeBaseWorkspaceBundle({ root: ROOT, logger: mockLogger }); const files = new Map([ [bundle.manifestPath, bundle.files.get(bundle.manifestPath) ?? ''], ]); const { workspace, writes } = createSandboxWorkspace(files); const materialized = await materializeKnowledgeBaseIntoWorkspace({ + logger: mockLogger, workspace, root: ROOT, }); 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 18a69fbaf20..29e5832522a 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 @@ -4,6 +4,9 @@ import { WorkflowTechnique, type WorkflowTechniqueType as BestPracticesGuideId, } from '@n8n/workflow-sdk/prompts/best-practices'; +import { SDK_LANGUAGE_REFERENCE } from '@n8n/workflow-sdk/prompts/sdk-reference'; +import { readdir, readFile } from 'node:fs/promises'; +import { join, resolve } from 'node:path'; import { join as posixJoin } from 'node:path/posix'; import type { Logger } from '../logger'; @@ -25,7 +28,14 @@ import { WORKSPACE_MANIFEST_FILE } from '../workspace/workspace-manifest'; export const SANDBOX_KNOWLEDGE_BASE_DIR = 'knowledge-base'; export const KNOWLEDGE_BASE_BEST_PRACTICES_DIR = 'best-practices'; +export const KNOWLEDGE_BASE_REFERENCE_DIR = 'reference'; export const KNOWLEDGE_BASE_INDEX_FILE = 'index.json'; +export const INSTANCE_AI_KNOWLEDGE_BASE_SOURCE_DIR = resolve( + __dirname, + '..', + '..', + 'knowledge-base', +); export const KNOWLEDGE_BASE_MANIFEST_FILE = WORKSPACE_MANIFEST_FILE; export const KNOWLEDGE_BASE_MANIFEST_SCHEMA_VERSION = 4; @@ -41,6 +51,16 @@ export interface KnowledgeBaseBestPracticesIndex { entries: KnowledgeBaseIndexEntry[]; } +export interface KnowledgeBaseReferenceIndexEntry { + id: string; + description: string; + file: string; +} + +export interface KnowledgeBaseReferenceIndex { + entries: KnowledgeBaseReferenceIndexEntry[]; +} + export interface KnowledgeBaseRootIndex { bestPractices: { indexFile: string; @@ -50,6 +70,10 @@ export interface KnowledgeBaseRootIndex { indexFile: string; entries: KnowledgeBaseTemplateEntry[]; }; + reference: { + indexFile: string; + entries: KnowledgeBaseReferenceIndexEntry[]; + }; } export interface KnowledgeBaseWorkspaceManifest { @@ -68,7 +92,7 @@ export interface KnowledgeBaseWorkspaceBundle { export interface BuildKnowledgeBaseWorkspaceBundleOptions { root: string; templatesArchive?: Buffer | null; - logger?: Logger; + logger: Logger; } interface MaterializeKnowledgeBaseOptions extends BuildKnowledgeBaseWorkspaceBundleOptions { @@ -79,11 +103,11 @@ function addTemplatesToKnowledgeBaseFiles( files: Map, rootDir: string, templatesArchive: Buffer, - logger?: Logger, + logger: Logger, ): KnowledgeBaseTemplateEntry[] { const extracted = extractBuilderTemplatesArchive(templatesArchive); if (!extracted) { - logger?.warn('[knowledge-base] rejected templates archive during bundle build', { + logger.warn('[knowledge-base] rejected templates archive during bundle build', { archiveBytes: templatesArchive.byteLength, }); return []; @@ -107,9 +131,87 @@ function addTemplatesToKnowledgeBaseFiles( return templatesIndex.entries; } -export function buildKnowledgeBaseWorkspaceBundle( +const KNOWLEDGE_BASE_REFERENCE_ENTRIES: Array< + Pick & { + fileName: string; + /** When set, content comes from this string instead of a source file. */ + content?: string; + } +> = [ + { + id: 'trigger-input-data-shapes', + description: + 'Per-trigger inputData shapes for verify-built-workflow and executions(action="run")', + fileName: 'trigger-input-data-shapes.md', + }, + { + id: 'open-ai-output-shape', + description: + 'OpenAI node (@n8n/n8n-nodes-langchain.openAi) output shape for downstream expressions', + fileName: 'open-ai-output-shape.md', + }, + { + id: 'workflow-builder-guardrails', + description: + 'Workflow builder guardrails for source preservation, fan-out/fan-in, effects, and Code nodes', + fileName: 'workflow-builder-guardrails.md', + }, + { + id: 'workflow-sdk-language', + description: + 'Allowed/forbidden constructs in workflow SDK builder code: methods, globals, language subset', + fileName: 'workflow-sdk-language.md', + content: SDK_LANGUAGE_REFERENCE, + }, +]; + +async function addReferenceFilesToKnowledgeBase( + files: Map, + rootDir: string, +): Promise { + const referenceSourceDir = join( + INSTANCE_AI_KNOWLEDGE_BASE_SOURCE_DIR, + KNOWLEDGE_BASE_REFERENCE_DIR, + ); + const referenceEntries: KnowledgeBaseReferenceIndexEntry[] = []; + + for (const entry of KNOWLEDGE_BASE_REFERENCE_ENTRIES) { + const relativeFilePath = posixJoin(KNOWLEDGE_BASE_REFERENCE_DIR, entry.fileName); + const content = + entry.content ?? (await readFile(join(referenceSourceDir, entry.fileName), 'utf-8')); + files.set(posixJoin(rootDir, relativeFilePath), withTrailingNewline(content)); + referenceEntries.push({ + id: entry.id, + description: entry.description, + file: relativeFilePath, + }); + } + + const referenceIndexPath = posixJoin( + rootDir, + KNOWLEDGE_BASE_REFERENCE_DIR, + KNOWLEDGE_BASE_INDEX_FILE, + ); + const referenceIndex: KnowledgeBaseReferenceIndex = { entries: referenceEntries }; + files.set(referenceIndexPath, stringifyWorkspaceJson(referenceIndex)); + + // Guard against unexpected extra files in the source directory during development. + const sourceFiles = (await readdir(referenceSourceDir)).filter((name) => name.endsWith('.md')); + const expectedFiles = new Set(KNOWLEDGE_BASE_REFERENCE_ENTRIES.map((entry) => entry.fileName)); + for (const sourceFile of sourceFiles) { + if (!expectedFiles.has(sourceFile)) { + throw new Error( + `Unexpected knowledge-base reference file "${sourceFile}". Add it to KNOWLEDGE_BASE_REFERENCE_ENTRIES.`, + ); + } + } + + return referenceEntries; +} + +export async function buildKnowledgeBaseWorkspaceBundle( options: BuildKnowledgeBaseWorkspaceBundleOptions, -): KnowledgeBaseWorkspaceBundle { +): Promise { const { root, templatesArchive = null, logger } = options; const rootDir = posixJoin(root, SANDBOX_KNOWLEDGE_BASE_DIR); const files = new Map(); @@ -145,6 +247,7 @@ export function buildKnowledgeBaseWorkspaceBundle( const templateEntries = templatesArchive ? addTemplatesToKnowledgeBaseFiles(files, rootDir, templatesArchive, logger) : []; + const referenceEntries = await addReferenceFilesToKnowledgeBase(files, rootDir); const rootIndexPath = posixJoin(rootDir, KNOWLEDGE_BASE_INDEX_FILE); const rootIndex: KnowledgeBaseRootIndex = { @@ -156,6 +259,10 @@ export function buildKnowledgeBaseWorkspaceBundle( indexFile: posixJoin(KNOWLEDGE_BASE_TEMPLATES_DIR, KNOWLEDGE_BASE_INDEX_FILE), entries: templateEntries, }, + reference: { + indexFile: posixJoin(KNOWLEDGE_BASE_REFERENCE_DIR, KNOWLEDGE_BASE_INDEX_FILE), + entries: referenceEntries, + }, }; files.set(rootIndexPath, stringifyWorkspaceJson(rootIndex)); @@ -181,7 +288,7 @@ const KNOWLEDGE_BASE_FILE_LABEL = 'Knowledge base file'; export async function loadPrebakedKnowledgeBaseBundle( options: MaterializeKnowledgeBaseOptions, ): Promise { - const bundle = buildKnowledgeBaseWorkspaceBundle(options); + const bundle = await buildKnowledgeBaseWorkspaceBundle(options); return await loadPrebakedWorkspaceBundle({ workspace: options.workspace, @@ -216,7 +323,7 @@ export async function materializeKnowledgeBaseIntoWorkspace( resourceLabel: KNOWLEDGE_BASE_FILE_LABEL, logger: options.logger, loadPrebaked: async () => await loadPrebakedKnowledgeBaseBundle(options), - buildBundle: () => buildKnowledgeBaseWorkspaceBundle(options), + buildBundle: async () => await buildKnowledgeBaseWorkspaceBundle(options), materializedLogMessage: 'Materialized knowledge base into workspace', materializedLogContext: (bundle) => ({ root: options.root, diff --git a/packages/@n8n/instance-ai/src/mcp/__tests__/mcp-client-manager.test.ts b/packages/@n8n/instance-ai/src/mcp/__tests__/mcp-client-manager.test.ts index 8b9e3975535..6a62445f5ce 100644 --- a/packages/@n8n/instance-ai/src/mcp/__tests__/mcp-client-manager.test.ts +++ b/packages/@n8n/instance-ai/src/mcp/__tests__/mcp-client-manager.test.ts @@ -28,6 +28,8 @@ interface LoggerMock { warn: Mock; } +const mockLogger = { info: vi.fn(), warn: vi.fn(), error: vi.fn(), debug: vi.fn() } as never; + interface SanitizeOptions { onError?: (error: { message: string; @@ -57,7 +59,10 @@ describe('McpClientManager', () => { it('accepts https URLs', async () => { const manager = new McpClientManager(); await expect( - manager.getRegularTools([{ name: 'github', url: 'https://api.github.com/mcp' }]), + manager.getRegularTools( + [{ name: 'github', url: 'https://api.github.com/mcp' }], + mockLogger, + ), ).resolves.toBeDefined(); expect(mockedMcpClient).toHaveBeenCalledTimes(1); }); @@ -65,17 +70,17 @@ describe('McpClientManager', () => { it('accepts http URLs', async () => { const manager = new McpClientManager(); await expect( - manager.getRegularTools([{ name: 'local', url: 'http://localhost:3000/sse' }]), + manager.getRegularTools([{ name: 'local', url: 'http://localhost:3000/sse' }], mockLogger), ).resolves.toBeDefined(); }); it('rejects file:// URLs with a UserError naming the server', async () => { const manager = new McpClientManager(); await expect( - manager.getRegularTools([{ name: 'sneaky', url: 'file:///etc/passwd' }]), + manager.getRegularTools([{ name: 'sneaky', url: 'file:///etc/passwd' }], mockLogger), ).rejects.toThrow(UserError); await expect( - manager.getRegularTools([{ name: 'sneaky', url: 'file:///etc/passwd' }]), + manager.getRegularTools([{ name: 'sneaky', url: 'file:///etc/passwd' }], mockLogger), ).rejects.toThrow(/MCP server "sneaky".*file:/); expect(mockedMcpClient).not.toHaveBeenCalled(); }); @@ -83,25 +88,26 @@ describe('McpClientManager', () => { it('rejects ws:// URLs', async () => { const manager = new McpClientManager(); await expect( - manager.getRegularTools([{ name: 'sock', url: 'ws://example.com/' }]), + manager.getRegularTools([{ name: 'sock', url: 'ws://example.com/' }], mockLogger), ).rejects.toThrow(/only http\(s\) URLs are allowed/); expect(mockedMcpClient).not.toHaveBeenCalled(); }); it('rejects malformed URLs', async () => { const manager = new McpClientManager(); - await expect(manager.getRegularTools([{ name: 'broken', url: 'not a url' }])).rejects.toThrow( - /invalid URL/, - ); + await expect( + manager.getRegularTools([{ name: 'broken', url: 'not a url' }], mockLogger), + ).rejects.toThrow(/invalid URL/); expect(mockedMcpClient).not.toHaveBeenCalled(); }); it('skips URL validation for stdio configs', async () => { const manager = new McpClientManager(); await expect( - manager.getRegularTools([ - { name: 'local-stdio', command: '/usr/bin/mcp-server', args: ['--port', '3000'] }, - ]), + manager.getRegularTools( + [{ name: 'local-stdio', command: '/usr/bin/mcp-server', args: ['--port', '3000'] }], + mockLogger, + ), ).resolves.toBeDefined(); expect(mockedMcpClient).toHaveBeenCalledTimes(1); }); @@ -178,17 +184,23 @@ describe('McpClientManager', () => { describe('SSRF policy (opt-in)', () => { it('does not call validateUrl when no validator is supplied', async () => { const manager = new McpClientManager(); - await manager.getRegularTools([{ name: 'public', url: 'https://api.example.com/mcp' }]); + await manager.getRegularTools( + [{ name: 'public', url: 'https://api.example.com/mcp' }], + mockLogger, + ); // no validator → never invoked; confirm by absence of any later expectations }); it('calls validateUrl for every configured URL when a validator is supplied', async () => { const validator = createValidatorMock(); const manager = new McpClientManager(validator); - await manager.getRegularTools([ - { name: 'a', url: 'https://a.example.com/mcp' }, - { name: 'b', url: 'https://b.example.com/mcp' }, - ]); + await manager.getRegularTools( + [ + { name: 'a', url: 'https://a.example.com/mcp' }, + { name: 'b', url: 'https://b.example.com/mcp' }, + ], + mockLogger, + ); expect(validator.validateUrl).toHaveBeenCalledTimes(2); expect(validator.validateUrl).toHaveBeenCalledWith('https://a.example.com/mcp'); expect(validator.validateUrl).toHaveBeenCalledWith('https://b.example.com/mcp'); @@ -199,7 +211,7 @@ describe('McpClientManager', () => { validator.validateUrl.mockResolvedValue(createResultError(new Error('blocked: 10.0.0.1'))); const manager = new McpClientManager(validator); await expect( - manager.getRegularTools([{ name: 'internal', url: 'http://10.0.0.1/mcp' }]), + manager.getRegularTools([{ name: 'internal', url: 'http://10.0.0.1/mcp' }], mockLogger), ).rejects.toThrow(UserError); expect(mockedMcpClient).not.toHaveBeenCalled(); }); @@ -209,14 +221,14 @@ describe('McpClientManager', () => { validator.validateUrl.mockResolvedValue(createResultError(new Error('blocked: 10.0.0.1'))); const manager = new McpClientManager(validator); await expect( - manager.getRegularTools([{ name: 'internal', url: 'http://10.0.0.1/mcp' }]), + manager.getRegularTools([{ name: 'internal', url: 'http://10.0.0.1/mcp' }], mockLogger), ).rejects.toThrow(/MCP server "internal".*blocked: 10\.0\.0\.1/); }); it('skips SSRF check for stdio configs even when validator is supplied', async () => { const validator = createValidatorMock(); const manager = new McpClientManager(validator); - await manager.getRegularTools([{ name: 'stdio', command: '/usr/bin/mcp' }]); + await manager.getRegularTools([{ name: 'stdio', command: '/usr/bin/mcp' }], mockLogger); expect(validator.validateUrl).not.toHaveBeenCalled(); }); }); @@ -224,7 +236,7 @@ describe('McpClientManager', () => { describe('disconnect', () => { it('disconnects every tracked client and clears caches', async () => { const manager = new McpClientManager(); - await manager.getRegularTools([{ name: 'a', url: 'https://a.example.com/' }]); + await manager.getRegularTools([{ name: 'a', url: 'https://a.example.com/' }], mockLogger); expect(mockedMcpClient).toHaveBeenCalledTimes(1); const disconnectMocks = mockedMcpClient.mock.results.map( @@ -243,47 +255,59 @@ describe('McpClientManager', () => { it('does not re-list tools for an unchanged config', async () => { const manager = new McpClientManager(); const configs = [{ name: 'a', url: 'https://a.example.com/' }]; - await manager.getRegularTools(configs); - await manager.getRegularTools(configs); + await manager.getRegularTools(configs, mockLogger); + await manager.getRegularTools(configs, mockLogger); expect(mockedMcpClient).toHaveBeenCalledTimes(1); }); it('does not share cached clients across different scoped fetch cache keys', async () => { const manager = new McpClientManager(); - await manager.getRegularTools([ - { - name: 'shared', - url: 'https://shared.example.com/', - cacheKey: 'registry-connection:1', - }, - ]); - await manager.getRegularTools([ - { - name: 'shared', - url: 'https://shared.example.com/', - cacheKey: 'registry-connection:2', - }, - ]); + await manager.getRegularTools( + [ + { + name: 'shared', + url: 'https://shared.example.com/', + cacheKey: 'registry-connection:1', + }, + ], + mockLogger, + ); + await manager.getRegularTools( + [ + { + name: 'shared', + url: 'https://shared.example.com/', + cacheKey: 'registry-connection:2', + }, + ], + mockLogger, + ); expect(mockedMcpClient).toHaveBeenCalledTimes(2); }); it('reuses cached clients when scoped fetch cache key matches', async () => { const manager = new McpClientManager(); - await manager.getRegularTools([ - { - name: 'shared', - url: 'https://shared.example.com/', - cacheKey: 'registry-connection:1', - }, - ]); - await manager.getRegularTools([ - { - name: 'shared', - url: 'https://shared.example.com/', - cacheKey: 'registry-connection:1', - }, - ]); + await manager.getRegularTools( + [ + { + name: 'shared', + url: 'https://shared.example.com/', + cacheKey: 'registry-connection:1', + }, + ], + mockLogger, + ); + await manager.getRegularTools( + [ + { + name: 'shared', + url: 'https://shared.example.com/', + cacheKey: 'registry-connection:1', + }, + ], + mockLogger, + ); expect(mockedMcpClient).toHaveBeenCalledTimes(1); }); @@ -295,8 +319,8 @@ describe('McpClientManager', () => { const configs = [{ name: 'a', url: 'https://a.example.com/' }]; const [tools1, tools2] = await Promise.all([ - manager.getRegularTools(configs), - manager.getRegularTools(configs), + manager.getRegularTools(configs, mockLogger), + manager.getRegularTools(configs, mockLogger), ]); expect(mockedMcpClient).toHaveBeenCalledTimes(1); @@ -314,9 +338,9 @@ describe('McpClientManager', () => { }; }); - await expect(manager.getRegularTools(configs)).rejects.toThrow('boom'); + await expect(manager.getRegularTools(configs, mockLogger)).rejects.toThrow('boom'); // In-flight entry must be cleared so a retry actually re-attempts. - await expect(manager.getRegularTools(configs)).resolves.toBeDefined(); + await expect(manager.getRegularTools(configs, mockLogger)).resolves.toBeDefined(); expect(mockedMcpClient).toHaveBeenCalledTimes(2); }); }); @@ -344,13 +368,13 @@ describe('McpClientManager', () => { }; }); - const stranded = manager.getRegularTools(configs); + const stranded = manager.getRegularTools(configs, mockLogger); // Yield so connectAndListTools registers the client before we tear down. await Promise.resolve(); await manager.disconnect(); // New call must start a fresh client, not join the stranded promise. - await manager.getRegularTools(configs); + await manager.getRegularTools(configs, mockLogger); expect(mockedMcpClient).toHaveBeenCalledTimes(2); // Cleanup: let the stranded promise settle so the test doesn't hang. diff --git a/packages/@n8n/instance-ai/src/mcp/mcp-client-manager.ts b/packages/@n8n/instance-ai/src/mcp/mcp-client-manager.ts index 3a1bfd3b8b2..79945b7c0ab 100644 --- a/packages/@n8n/instance-ai/src/mcp/mcp-client-manager.ts +++ b/packages/@n8n/instance-ai/src/mcp/mcp-client-manager.ts @@ -37,6 +37,7 @@ function buildNativeMcpConfigs(configs: McpServerConfig[]): NativeMcpServerConfi name: server.name, url: server.url, transport: server.transport, + toolFilter: server.toolFilter, fetch: server.fetch, }); } else if (server.command) { @@ -45,6 +46,7 @@ function buildNativeMcpConfigs(configs: McpServerConfig[]): NativeMcpServerConfi command: server.command, args: server.args, env: server.env, + toolFilter: server.toolFilter, }); } } @@ -55,9 +57,9 @@ function toolsToRegistry(tools: BuiltTool[]): McpToolRegistry { return createToolRegistryFromTools(tools); } -function warnSkippedMcpSchema(logger: Logger | undefined, source: string) { +function warnSkippedMcpSchema(logger: Logger, source: string) { return (error: McpSchemaSanitizationError) => { - logger?.warn('Skipped MCP tool with unsupported schema', { + logger.warn('Skipped MCP tool with unsupported schema', { toolName: error.details.toolName, source, path: error.details.path, @@ -70,9 +72,9 @@ function warnSkippedMcpSchema(logger: Logger | undefined, source: string) { }; } -function warnSkippedMcpTool(logger: Logger | undefined) { +function warnSkippedMcpTool(logger: Logger) { return (error: McpToolNameValidationError) => { - logger?.warn('Skipped MCP tool with unsafe name', { + logger.warn('Skipped MCP tool with unsafe name', { toolName: error.toolName, source: error.source, reason: error.message, @@ -82,13 +84,13 @@ function warnSkippedMcpTool(logger: Logger | undefined) { function getSafeMcpServers( configs: McpServerConfig[], - logger: Logger | undefined, + logger: Logger, source: string, ): McpServerConfig[] { return configs.filter((config) => { if (isSafeMcpIdentifierName(config.name)) return true; - logger?.warn('Skipped MCP server with unsafe name', { + logger.warn('Skipped MCP server with unsafe name', { serverName: config.name, source, }); @@ -112,7 +114,7 @@ export class McpClientManager { constructor(private readonly ssrfValidator?: SsrfUrlValidator) {} - async getRegularTools(configs: McpServerConfig[], logger?: Logger): Promise { + async getRegularTools(configs: McpServerConfig[], logger: Logger): Promise { const safeConfigs = getSafeMcpServers(configs, logger, 'external MCP'); if (safeConfigs.length === 0) return createToolRegistry(); @@ -193,10 +195,10 @@ export class McpClientManager { private async connectAndListTools( configs: McpServerConfig[], clientKey: string, - logger: Logger | undefined, + logger: Logger, source: string, ): Promise { - const client = new McpClient(buildNativeMcpConfigs(configs), true); + const client = new McpClient(buildNativeMcpConfigs(configs)); this.clientsByKey.set(clientKey, client); const registry = toolsToRegistry(await client.listTools()); diff --git a/packages/@n8n/instance-ai/src/planned-tasks/__tests__/planned-task-permissions.test.ts b/packages/@n8n/instance-ai/src/planned-tasks/__tests__/planned-task-permissions.test.ts index 4a60ee4174e..c9a0d0c6645 100644 --- a/packages/@n8n/instance-ai/src/planned-tasks/__tests__/planned-task-permissions.test.ts +++ b/packages/@n8n/instance-ai/src/planned-tasks/__tests__/planned-task-permissions.test.ts @@ -8,12 +8,14 @@ function makeContext( ): InstanceAiContext { return { userId: 'user-1', + projectId: 'project-1', permissions: { ...DEFAULT_INSTANCE_AI_PERMISSIONS, ...permissionOverrides }, workflowService: {} as InstanceAiContext['workflowService'], executionService: {} as InstanceAiContext['executionService'], credentialService: {} as InstanceAiContext['credentialService'], nodeService: {} as InstanceAiContext['nodeService'], dataTableService: {} as InstanceAiContext['dataTableService'], + logger: { info: vi.fn(), warn: vi.fn(), error: vi.fn(), debug: vi.fn() } as never, }; } @@ -86,4 +88,11 @@ describe('applyPlannedTaskPermissions', () => { expect(result.workflowService).toBe(context.workflowService); expect(result.userId).toBe(context.userId); }); + + it('should preserve the bound projectId so sub-agents stay scoped to the thread project', () => { + const context = makeContext(); + const result = applyPlannedTaskPermissions(context, 'build-workflow'); + + expect(result.projectId).toBe(context.projectId); + }); }); diff --git a/packages/@n8n/instance-ai/src/planned-tasks/__tests__/planned-task-service.test.ts b/packages/@n8n/instance-ai/src/planned-tasks/__tests__/planned-task-service.test.ts index c0957c93486..2e2ae11b005 100644 --- a/packages/@n8n/instance-ai/src/planned-tasks/__tests__/planned-task-service.test.ts +++ b/packages/@n8n/instance-ai/src/planned-tasks/__tests__/planned-task-service.test.ts @@ -811,6 +811,46 @@ describe('PlannedTaskCoordinator', () => { } }); + it('routes pending workflow verification before synthesis without completing the graph', async () => { + const task = makeTaskRecord({ id: 'wf-1', kind: 'build-workflow', status: 'succeeded' }); + storage.update.mockImplementation(async (_threadId, updater) => { + const graph = makeGraph({ tasks: [task] }); + return await Promise.resolve(updater(graph)); + }); + + const pendingWorkflowVerification = { + task, + outcome: { + workItemId: 'wi-1', + taskId: 'wf-1', + workflowId: 'workflow-1', + submitted: true, + triggerType: 'manual_or_testable' as const, + needsUserInput: false, + summary: 'Submitted.', + }, + obligation: { + workItemId: 'wi-1', + threadId: 'thread-1', + taskId: 'wf-1', + plannedTaskId: 'wf-1', + workflowId: 'workflow-1', + source: 'planned' as const, + policy: 'required' as const, + status: 'ready_to_verify' as const, + updatedAt: '2026-01-01T00:00:00.000Z', + }, + }; + + const action = await coordinator.tick('thread-1', { pendingWorkflowVerification }); + + expect(action.type).toBe('orchestrate-workflow-verification'); + if (action.type === 'orchestrate-workflow-verification') { + expect(action.graph.status).toBe('active'); + expect(action.verification).toBe(pendingWorkflowVerification); + } + }); + it('respects availableSlots limit', async () => { storage.update.mockImplementation(async (_threadId, updater) => { const graph = makeGraph({ diff --git a/packages/@n8n/instance-ai/src/planned-tasks/planned-task-service.ts b/packages/@n8n/instance-ai/src/planned-tasks/planned-task-service.ts index 84f93e82798..c56f5262d5e 100644 --- a/packages/@n8n/instance-ai/src/planned-tasks/planned-task-service.ts +++ b/packages/@n8n/instance-ai/src/planned-tasks/planned-task-service.ts @@ -6,6 +6,7 @@ import type { PlannedTaskRecord, PlannedTaskSchedulerAction, PlannedTaskService, + PlannedWorkflowVerification, } from '../types'; /** @@ -150,7 +151,7 @@ export class PlannedTaskCoordinator implements PlannedTaskService { /** * Transition a graph from `awaiting_approval` → `active` after the user - * approves the plan. Callers (create-tasks, submit-plan) must invoke this + * approves the plan. Callers must invoke this * before schedulePlannedTasks() so tick() can begin dispatching. No-op on * any other status (a cancelled plan stays cancelled, an already-active * plan doesn't regress). @@ -438,7 +439,10 @@ export class PlannedTaskCoordinator implements PlannedTaskService { async tick( threadId: string, - options: { availableSlots?: number } = {}, + options: { + availableSlots?: number; + pendingWorkflowVerification?: PlannedWorkflowVerification; + } = {}, ): Promise { // Use atomic update so the graph status transition (active → awaiting_replan // or active → completed) cannot race with concurrent markSucceeded/markFailed. @@ -458,6 +462,15 @@ export class PlannedTaskCoordinator implements PlannedTaskService { } if (graph.tasks.length > 0 && graph.tasks.every(isSuccess)) { + if (options.pendingWorkflowVerification) { + action = { + type: 'orchestrate-workflow-verification', + graph, + verification: options.pendingWorkflowVerification, + }; + return graph; + } + const nextGraph: PlannedTaskGraph = { ...graph, status: 'completed' }; action = { type: 'synthesize', graph: nextGraph }; return nextGraph; @@ -467,6 +480,15 @@ export class PlannedTaskCoordinator implements PlannedTaskService { // treat as completed so the orchestrator can synthesize partial results. const hasWorkLeft = graph.tasks.some((t) => t.status === 'planned' || t.status === 'running'); if (graph.tasks.length > 0 && !hasWorkLeft) { + if (options.pendingWorkflowVerification) { + action = { + type: 'orchestrate-workflow-verification', + graph, + verification: options.pendingWorkflowVerification, + }; + return graph; + } + const nextGraph: PlannedTaskGraph = { ...graph, status: 'completed' }; action = { type: 'synthesize', graph: nextGraph }; return nextGraph; diff --git a/packages/@n8n/instance-ai/src/runtime/__tests__/background-task-manager.test.ts b/packages/@n8n/instance-ai/src/runtime/__tests__/background-task-manager.test.ts index 968adad95e0..df811b35196 100644 --- a/packages/@n8n/instance-ai/src/runtime/__tests__/background-task-manager.test.ts +++ b/packages/@n8n/instance-ai/src/runtime/__tests__/background-task-manager.test.ts @@ -383,10 +383,10 @@ describe('BackgroundTaskManager', () => { }); it('does not collapse two distinct plannedTaskIds that target the same workflowId', () => { - // A planner may emit two work items for the same workflow — e.g., initial - // build (planned-A) followed by a patch (planned-B). They are distinct - // planned tasks and must both run; collapsing them on workflowId would - // skip work the user approved. + // A plan may include two work items for the same workflow — e.g., + // initial build (planned-A) followed by a patch (planned-B). They are + // distinct planned tasks and must both run; collapsing them on + // workflowId would skip work the user approved. const first = manager.spawn( makeSpawnOptions({ taskId: 'task-A', @@ -663,6 +663,7 @@ describe('BackgroundTaskManager', () => { const cancelled = manager.cancelAll(); expect(cancelled).toHaveLength(2); + expect(cancelled.every((t) => t.status === 'cancelled')).toBe(true); expect(manager.getRunningTasks('thread-1')).toHaveLength(0); expect(manager.getRunningTasks('thread-2')).toHaveLength(0); }); diff --git a/packages/@n8n/instance-ai/src/runtime/__tests__/resumable-stream-executor.test.ts b/packages/@n8n/instance-ai/src/runtime/__tests__/resumable-stream-executor.test.ts index e3d0be23aff..21cd833447f 100644 --- a/packages/@n8n/instance-ai/src/runtime/__tests__/resumable-stream-executor.test.ts +++ b/packages/@n8n/instance-ai/src/runtime/__tests__/resumable-stream-executor.test.ts @@ -156,11 +156,12 @@ describe('executeResumableStream', () => { }); it('returns errored status when stream contains an error chunk', async () => { + const error = new Error('Not Found'); const result = await executeResumableStream({ agent: {}, stream: { runId: 'agent-run-1', - fullStream: fromChunks([textChunk('Working...'), errorChunk(new Error('Not Found'))]), + fullStream: fromChunks([textChunk('Working...'), errorChunk(error)]), }, context: { threadId: 'thread-1', @@ -175,6 +176,7 @@ describe('executeResumableStream', () => { expect(result.status).toBe('errored'); expect(result.agentRunId).toBe('agent-run-1'); + expect(result.error).toBe(error); }); it('reports liveness activity for each consumed chunk', async () => { diff --git a/packages/@n8n/instance-ai/src/runtime/__tests__/terminal-response-guard.test.ts b/packages/@n8n/instance-ai/src/runtime/__tests__/terminal-response-guard.test.ts index c345d7d73d0..bd4b62cc047 100644 --- a/packages/@n8n/instance-ai/src/runtime/__tests__/terminal-response-guard.test.ts +++ b/packages/@n8n/instance-ai/src/runtime/__tests__/terminal-response-guard.test.ts @@ -42,6 +42,15 @@ function childText(): InstanceAiEvent { }; } +function toolCall(): InstanceAiEvent { + return { + type: 'tool-call', + runId, + agentId: rootAgentId, + payload: { toolCallId: 'tc-1', toolName: 'build_workflow', args: {} }, + }; +} + function previousRunRootText(): InstanceAiEvent { return { type: 'text-delta', @@ -90,8 +99,8 @@ describe('InstanceAiTerminalResponseGuard', () => { }); }); - it('does not emit completed fallback when silence is expected', () => { - const decision = guard().evaluateTerminal([runStart()], 'completed', { + it('does not emit completed fallback when silence is expected and an agent already produced text', () => { + const decision = guard().evaluateTerminal([runStart(), childText()], 'completed', { workSummary: { totalToolCalls: 3, totalToolErrors: 0, toolCalls: [] }, suppressCompletedFallback: true, }); @@ -101,6 +110,26 @@ describe('InstanceAiTerminalResponseGuard', () => { expect(decision.event).toBeUndefined(); }); + it('emits fallback for a suppressed completed run that produced no text', () => { + const decision = guard().evaluateTerminal([runStart()], 'completed', { + suppressCompletedFallback: true, + }); + + expect(decision.action).toBe('emit'); + expect(decision.reason).toBe('completed-silent'); + expect(decision.event?.type).toBe('text-delta'); + }); + + it('emits fallback for a suppressed completed run that only made internal tool calls', () => { + const decision = guard().evaluateTerminal([runStart(), toolCall()], 'completed', { + suppressCompletedFallback: true, + }); + + expect(decision.action).toBe('emit'); + expect(decision.reason).toBe('completed-silent'); + expect(decision.event?.type).toBe('text-delta'); + }); + it('does not emit completed fallback when the message group already has root text', () => { const decision = new InstanceAiTerminalResponseGuard({ runId, diff --git a/packages/@n8n/instance-ai/src/runtime/background-task-manager.ts b/packages/@n8n/instance-ai/src/runtime/background-task-manager.ts index 43110b38374..c8f62c8dfcc 100644 --- a/packages/@n8n/instance-ai/src/runtime/background-task-manager.ts +++ b/packages/@n8n/instance-ai/src/runtime/background-task-manager.ts @@ -231,6 +231,7 @@ export class BackgroundTaskManager { const cancelled: ManagedBackgroundTask[] = []; for (const [taskId, task] of this.tasks) { task.abortController.abort(); + task.status = 'cancelled'; cancelled.push(task); this.tasks.delete(taskId); this.releaseDedupeIndices(task); diff --git a/packages/@n8n/instance-ai/src/runtime/resumable-stream-executor.ts b/packages/@n8n/instance-ai/src/runtime/resumable-stream-executor.ts index f09b99e7c69..7925e3dd4b3 100644 --- a/packages/@n8n/instance-ai/src/runtime/resumable-stream-executor.ts +++ b/packages/@n8n/instance-ai/src/runtime/resumable-stream-executor.ts @@ -1,9 +1,11 @@ -import type { StreamResult } from '@n8n/agents'; +import type { RedactionOptions, StreamResult } from '@n8n/agents'; import type { InstanceAiEvent } from '@n8n/api-types'; import type { InstanceAiEventBus } from '../event-bus'; import type { Logger } from '../logger'; import { mapAgentChunkToEvent } from '../stream/map-chunk'; +import { OutputRedactor } from '../stream/output-redaction'; +import { UsageAccumulator, type RunTokenUsage } from '../stream/usage-accumulator'; import { WorkSummaryAccumulator, type WorkSummary } from '../stream/work-summary-accumulator'; import { parseSuspension, resumeAgentStream } from '../utils/stream-helpers'; import type { SuspensionInfo } from '../utils/stream-helpers'; @@ -30,6 +32,8 @@ export interface ResumableStreamContext { signal: AbortSignal; logger: Logger; onActivity?: () => void; + /** Output-redaction policy: omit for the safe default, or `false` to disable. */ + outputRedaction?: RedactionOptions | false; } export interface ManualSuspensionControl { @@ -66,10 +70,13 @@ export interface ExecuteResumableStreamResult { status: TraceStatus; agentRunId: string; text?: Promise; + error?: unknown; suspension?: SuspensionInfo; confirmationEvent?: ConfirmationRequestEvent; /** Accumulated tool call outcomes observed during stream consumption. */ workSummary: WorkSummary; + /** Accumulated token usage and cost, when the stream emitted usage. */ + usage?: RunTokenUsage; } function isRecord(value: unknown): value is Record { @@ -190,6 +197,14 @@ export async function executeResumableStream( let activeAgentRunId = options.stream.runId ?? options.initialAgentRunId ?? ''; let text = options.stream.text; const workSummaryAccumulator = new WorkSummaryAccumulator(); + const usageAccumulator = new UsageAccumulator(); + const outputRedactor = new OutputRedactor({ + logger: options.context.logger, + threadId: options.context.threadId, + runId: options.context.runId, + agentId: options.context.agentId, + options: options.context.outputRedaction, + }); let currentResponseId: string | undefined; let nativeStepIndex = 0; @@ -197,6 +212,7 @@ export async function executeResumableStream( while (true) { let suspension: SuspensionInfo | undefined; let hasError = false; + let error: unknown; let pendingConfirmation: Promise> | undefined; let confirmationEvent: ConfirmationRequestEvent | undefined; let confirmationEventPublished = false; @@ -208,10 +224,12 @@ export async function executeResumableStream( agentRunId: activeAgentRunId, text, workSummary: workSummaryAccumulator.toSummary(), + usage: usageAccumulator.hasUsage() ? usageAccumulator.toUsage() : undefined, }; } options.context.onActivity?.(); + usageAccumulator.observe(chunk); if (isRecord(chunk) && chunk.type === 'start-step') { nativeStepIndex += 1; @@ -244,15 +262,22 @@ export async function executeResumableStream( if (isErrorChunk(chunk)) { hasError = true; + error = chunk.error; } - const event = mapAgentChunkToEvent( + const mappedEvent = mapAgentChunkToEvent( options.context.runId, options.context.agentId, chunk, currentResponseId, ); - if (event) { + + // Scan/redact secrets & PII before events reach the user. Buffered + // delta text is released here at structural boundaries, so this may + // expand into several events (or none, while text is held back). + const events = mappedEvent ? outputRedactor.processEvent(mappedEvent) : []; + + for (const event of events) { workSummaryAccumulator.observe(event); let shouldPublishEvent = true; @@ -287,12 +312,18 @@ export async function executeResumableStream( } } + for (const flushed of outputRedactor.flush()) { + workSummaryAccumulator.observe(flushed); + options.context.eventBus.publish(options.context.threadId, flushed); + } + if (options.context.signal.aborted) { return { status: 'cancelled', agentRunId: activeAgentRunId, text, workSummary: workSummaryAccumulator.toSummary(), + usage: usageAccumulator.hasUsage() ? usageAccumulator.toUsage() : undefined, }; } @@ -301,7 +332,9 @@ export async function executeResumableStream( status: hasError ? 'errored' : 'completed', agentRunId: activeAgentRunId, text, + ...(error !== undefined ? { error } : {}), workSummary: workSummaryAccumulator.toSummary(), + usage: usageAccumulator.hasUsage() ? usageAccumulator.toUsage() : undefined, }; } @@ -312,6 +345,7 @@ export async function executeResumableStream( text, suspension, workSummary: workSummaryAccumulator.toSummary(), + usage: usageAccumulator.hasUsage() ? usageAccumulator.toUsage() : undefined, ...(confirmationEvent ? { confirmationEvent } : {}), }; } @@ -365,12 +399,8 @@ function buildCorrectionResumeData(corrections: string[]): Record).type === 'error' - ); +function isErrorChunk(chunk: unknown): chunk is { type: 'error'; error?: unknown } { + return isRecord(chunk) && chunk.type === 'error'; } async function waitForConfirmation( diff --git a/packages/@n8n/instance-ai/src/runtime/run-state-registry.ts b/packages/@n8n/instance-ai/src/runtime/run-state-registry.ts index 4936d76464e..2e353c85f35 100644 --- a/packages/@n8n/instance-ai/src/runtime/run-state-registry.ts +++ b/packages/@n8n/instance-ai/src/runtime/run-state-registry.ts @@ -37,6 +37,7 @@ export interface SuspendedRunState extends ActiveRunState { isPlannedBuildFollowUp: true; buildTaskId: string; workItemId: string; + isSupportingWorkflowTask?: boolean; savedOutcome?: WorkflowBuildOutcome; }; } @@ -217,6 +218,11 @@ export class RunStateRegistry { return this.activeRuns.get(threadId)?.runId; } + /** Number of runs currently executing (excludes suspended/pending runs). */ + activeRunCount(): number { + return this.activeRuns.size; + } + getActiveRun(threadId: string): ActiveRunState | undefined { return this.activeRuns.get(threadId); } diff --git a/packages/@n8n/instance-ai/src/runtime/stream-runner.ts b/packages/@n8n/instance-ai/src/runtime/stream-runner.ts index b7314595f73..535fff967c6 100644 --- a/packages/@n8n/instance-ai/src/runtime/stream-runner.ts +++ b/packages/@n8n/instance-ai/src/runtime/stream-runner.ts @@ -1,3 +1,4 @@ +import type { RedactionOptions } from '@n8n/agents'; import type { InstanceAiEvent } from '@n8n/api-types'; import type { InstanceAiEventBus } from '../event-bus'; @@ -8,6 +9,7 @@ import { type ResumableStreamSource, type TraceStatus, } from './resumable-stream-executor'; +import type { RunTokenUsage } from '../stream/usage-accumulator'; import type { WorkSummary } from '../stream/work-summary-accumulator'; import { resumeAgentStream } from '../utils/stream-helpers'; import type { SuspensionInfo } from '../utils/stream-helpers'; @@ -24,13 +26,17 @@ export interface StreamRunOptions { eventBus: InstanceAiEventBus; logger: Logger; onActivity?: () => void; + /** Output-redaction policy: omit for the safe default, or `false` to disable. */ + outputRedaction?: RedactionOptions | false; } export interface StreamRunResult { status: TraceStatus; agentRunId: string; text?: Promise; + error?: unknown; workSummary: WorkSummary; + usage?: RunTokenUsage; suspension?: SuspensionInfo; confirmationEvent?: Extract; } @@ -75,6 +81,7 @@ async function consumeStream( signal: options.signal, logger: options.logger, onActivity: options.onActivity, + outputRedaction: options.outputRedaction, }, control: { mode: 'manual' }, initialAgentRunId: options.agentRunId, @@ -86,6 +93,7 @@ async function consumeStream( agentRunId: result.agentRunId, text: result.text, workSummary: result.workSummary, + usage: result.usage, suspension: result.suspension, ...(result.confirmationEvent ? { confirmationEvent: result.confirmationEvent } : {}), }; @@ -100,6 +108,8 @@ async function consumeStream( : 'completed', agentRunId: result.agentRunId, text: result.text, + ...(result.error !== undefined ? { error: result.error } : {}), workSummary: result.workSummary, + usage: result.usage, }; } diff --git a/packages/@n8n/instance-ai/src/runtime/terminal-response-guard.ts b/packages/@n8n/instance-ai/src/runtime/terminal-response-guard.ts index c376322f0b5..cf89ec620b5 100644 --- a/packages/@n8n/instance-ai/src/runtime/terminal-response-guard.ts +++ b/packages/@n8n/instance-ai/src/runtime/terminal-response-guard.ts @@ -109,7 +109,8 @@ export class InstanceAiTerminalResponseGuard { reason: 'already-visible', }; } - if (options.suppressCompletedFallback) { + // Only suppress when some agent already produced text; a turn with no text at all must still emit. + if (options.suppressCompletedFallback && visibility.hasAgentText) { return { status, visibilitySource: 'none', @@ -206,12 +207,15 @@ export class InstanceAiTerminalResponseGuard { hasRootError: boolean; hasMessageGroupRootText: boolean; hasCurrentRunFallback: boolean; + hasAgentText: boolean; } { const currentRunEvents = events.filter((event) => event.runId === this.options.runId); return { hasRootText: currentRunEvents.some( (event) => event.agentId === this.options.rootAgentId && hasText(event), ), + // Any agent's text this run. Tool calls don't count — internal calls (e.g. complete-checkpoint) aren't a visible answer. + hasAgentText: currentRunEvents.some((event) => hasText(event)), hasRootError: currentRunEvents.some( (event) => event.agentId === this.options.rootAgentId && event.type === 'error', ), 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 246105c58ff..a6bf6ea9f9a 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 @@ -108,12 +108,14 @@ function createRuntimeSkillSourceWithLinkedFile(path: string): RuntimeSkillSourc }; } +const mockLogger = { info: vi.fn(), warn: vi.fn(), error: vi.fn(), debug: vi.fn() } as never; + describe('materializeRuntimeSkillsIntoWorkspace', () => { it('builds a runtime skill workspace bundle without writing files', async () => { const source = loadInstanceAiRuntimeSkillSource(); const root = '/home/daytona/workspace'; - const bundle = await buildRuntimeSkillWorkspaceBundle({ source, root }); + const bundle = await buildRuntimeSkillWorkspaceBundle({ source, root, logger: mockLogger }); if (!bundle) throw new Error('Expected runtime skill bundle'); const skillDir = `${root}/${SANDBOX_RUNTIME_SKILLS_DIR}/data-table-manager`; @@ -158,6 +160,7 @@ describe('materializeRuntimeSkillsIntoWorkspace', () => { const root = '/home/daytona/workspace'; const materialized = await materializeRuntimeSkillsIntoWorkspace({ + logger: mockLogger, source, workspace, root, @@ -208,6 +211,7 @@ describe('materializeRuntimeSkillsIntoWorkspace', () => { const root = '/home/daytona/workspace'; const materialized = await materializeRuntimeSkillsIntoWorkspace({ + logger: mockLogger, source, workspace, root, @@ -238,6 +242,7 @@ describe('materializeRuntimeSkillsIntoWorkspace', () => { const source = loadInstanceAiRuntimeSkillSource(); const { workspace, writes, executeCommand } = createMockWorkspace(); const runtimeSource = createLazyWorkspaceRuntimeSkillSource({ + logger: mockLogger, source, workspace, }); @@ -266,13 +271,14 @@ describe('materializeRuntimeSkillsIntoWorkspace', () => { const source = loadInstanceAiRuntimeSkillSource(); const { workspace, writes, executeCommand, writeFile } = createMockWorkspace(); const root = '/home/daytona/workspace'; - const bundle = await buildRuntimeSkillWorkspaceBundle({ source, root }); + 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 runtimeSource = createLazyWorkspaceRuntimeSkillSource({ + logger: mockLogger, source, workspace, }); @@ -306,6 +312,7 @@ describe('materializeRuntimeSkillsIntoWorkspace', () => { ); const runtimeSource = createLazyWorkspaceRuntimeSkillSource({ + logger: mockLogger, source, workspace, }); @@ -326,6 +333,7 @@ describe('materializeRuntimeSkillsIntoWorkspace', () => { writes.set(manifestPath, 'not json'); const runtimeSource = createLazyWorkspaceRuntimeSkillSource({ + logger: mockLogger, source, workspace, }); @@ -344,6 +352,7 @@ describe('materializeRuntimeSkillsIntoWorkspace', () => { await expect( materializeRuntimeSkillsIntoWorkspace({ + logger: mockLogger, source, workspace, root: '/home/daytona/workspace', 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 70e52fcd736..c040ef5851f 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,9 +1,18 @@ import { createSkillLoadTool } from '@n8n/agents'; -import { existsSync } from 'node:fs'; +import { existsSync, readFileSync } from 'node:fs'; +import { join } from 'node:path'; import { INSTANCE_AI_SKILLS_DIR, loadInstanceAiRuntimeSkillSource } from '../runtime-skills'; describe('Instance AI runtime skills', () => { + it('points the workflow-builder skill at the SDK language reference', () => { + const skill = readFileSync( + join(INSTANCE_AI_SKILLS_DIR, 'workflow-builder', 'SKILL.md'), + 'utf-8', + ); + expect(skill).toContain('knowledge-base/reference/workflow-sdk-language.md'); + }); + it('loads the bundled data-table-manager skill and its linked files', async () => { expect(existsSync(INSTANCE_AI_SKILLS_DIR)).toBe(true); @@ -15,7 +24,7 @@ describe('Instance AI runtime skills', () => { expect(dataTableManager).toMatchObject({ name: 'data-table-manager', description: - 'Designs and manages n8n Data Tables directly with the data-tables and parse-file tools. Use when the user asks to create, inspect, import, seed, query, update, clean up, rename columns in, or delete data tables and rows, especially from CSV/XLSX/JSON attachments, and before planning workflows that create or write to Data Tables.', + 'Designs and manages n8n Data Tables directly with the data-tables and parse-file tools. Use when the user asks to list, show, create, inspect, import, seed, query, update, clean up, rename columns in, or delete data tables and rows, especially from CSV/XLSX/JSON attachments, and before building or planning workflows that create or write to Data Tables.', platforms: ['daytona'], recommendedTools: ['data-tables', 'parse-file'], }); @@ -92,17 +101,137 @@ describe('Instance AI runtime skills', () => { 'verify-built-workflow', 'executions', ]); - expect(skill?.description).toContain('former workflow-builder agent guidance'); + expect(skill?.description).toContain('Default path for all single-workflow work'); + expect(skill?.description).toContain('do not load planning or create-tasks first'); const loaded = await source.loadSkill('workflow-builder'); - expect(loaded?.instructions).toContain('Tool Surface'); expect(loaded?.instructions).toContain('build-workflow'); expect(loaded?.instructions).toContain('nodes(action="suggested")'); expect(loaded?.instructions).toContain('nodes(action="search")'); expect(loaded?.instructions).toContain('workflows(action="get-as-code")'); expect(loaded?.instructions).toContain("newCredential('Credential Name', 'credential-id')"); expect(loaded?.instructions).toContain('Verification'); + expect(loaded?.instructions).toContain('Build/save success is not workflow-quality evidence'); + expect(loaded?.instructions).toContain('workflows(action="get-json", workflowId)'); + expect(loaded?.instructions).toContain( + 'knowledge-base/reference/workflow-builder-guardrails.md', + ); expect(loaded?.instructions).toMatch(/inline setup card in the AI\s+Assistant panel/); expect(loaded?.instructions).toContain('Do not call `delegate`'); }); + + it('loads the bundled planning skill', async () => { + const source = loadInstanceAiRuntimeSkillSource(); + const skill = source.registry.skills.find((entry) => entry.name === 'planning'); + + expect(skill?.name).toBe('planning'); + expect(skill?.recommendedTools).toEqual([ + 'create-tasks', + 'workflows', + 'nodes', + 'credentials', + 'data-tables', + 'parse-file', + 'research', + 'ask-user', + ]); + expect(skill?.description).toContain('Do NOT use for new one-off workflows'); + + const loaded = await source.loadSkill('planning'); + expect(loaded?.instructions).toContain('## When NOT to use this skill'); + expect(loaded?.instructions).toContain('Do not call `create-tasks` just to get approval'); + expect(loaded?.instructions).toContain('planningContext.source: "planning-skill"'); + expect(loaded?.instructions).toContain('Do not spawn another agent'); + expect(loaded?.instructions).toContain('`Required effects`'); + expect(loaded?.instructions).toContain('`Explicit constraints`'); + expect(loaded?.instructions).toContain('`Empty/invalid behavior`'); + expect(loaded?.instructions).toContain('`Verify required effects`'); + expect(loaded?.instructions).toContain("Never ask for the user's timezone"); + expect(loaded?.instructions).toContain('Trust already-collected briefing context'); + expect(loaded?.instructions).toContain('Do not add\nroutine "verify this workflow"'); + expect(loaded?.instructions).toContain('Checkpoint tasks are exceptional semantic checks'); + expect(loaded?.instructions).not.toContain('submit-plan'); + expect(loaded?.instructions).not.toContain('add-plan-item'); + }); + + it('loads the bundled post-build-flow skill and trigger input reference', async () => { + const source = loadInstanceAiRuntimeSkillSource(); + const skill = source.registry.skills.find((entry) => entry.name === 'post-build-flow'); + + expect(skill?.description).toContain('workflow-verification-follow-up'); + expect(skill?.linkedFiles.references).toEqual([ + expect.objectContaining({ path: 'references/trigger-input-data-shapes.md' }), + ]); + + const loaded = await source.loadSkill('post-build-flow'); + expect(loaded?.instructions).toContain('verificationReadiness.status === "ready"'); + expect(loaded?.instructions).toContain('verificationReadiness.status === "needs_setup"'); + expect(loaded?.instructions).toContain('verificationReadiness.status === "not_verifiable"'); + expect(loaded?.instructions).toContain('setupRequirement.status === "required"'); + expect(loaded?.instructions).toContain('inline setup card in the AI Assistant panel'); + expect(loaded?.instructions).toMatch( + /Do not ask whether to build now and set up\s+credentials later/, + ); + expect(loaded?.instructions).toContain( + 'Ask once when a service has multiple credentials of the same type', + ); + expect(loaded?.instructions).toContain( + 'Ask which auth type to use when a service supports more than one', + ); + expect(loaded?.instructions).toContain( + 'Only call `workflows(action="publish")` when the user explicitly asks', + ); + + const loadTool = createSkillLoadTool(source); + const reference = await loadTool.handler?.( + { skillId: 'post-build-flow', filePath: 'references/trigger-input-data-shapes.md' }, + {}, + ); + if ( + !reference || + typeof reference !== 'object' || + !('content' in reference) || + typeof reference.content !== 'string' + ) { + throw new Error('Expected trigger input reference content'); + } + expect(reference.content).toContain('Do NOT wrap in `formFields`'); + }); + + it('loads the bundled planned-task-runtime skill', async () => { + const source = loadInstanceAiRuntimeSkillSource(); + const skill = source.registry.skills.find((entry) => entry.name === 'planned-task-runtime'); + + expect(skill?.description).toContain('planned-task-follow-up'); + + const loaded = await source.loadSkill('planned-task-runtime'); + expect(loaded?.instructions).toContain(''); + expect(loaded?.instructions).toContain('You MUST take action in this same turn'); + expect(loaded?.instructions).toContain('awaiting_replan'); + expect(loaded?.instructions).toMatch(/Do NOT reply with an\s+acknowledgement/); + expect(loaded?.instructions).toContain(''); + expect(loaded?.instructions).toContain(''); + expect(loaded?.instructions).toContain('Always require structured verification evidence'); + expect(loaded?.instructions).toContain('never trust builder prose'); + expect(loaded?.instructions).toContain('before `complete-checkpoint`'); + expect(loaded?.instructions).toContain('patch in place'); + expect(loaded?.instructions).toContain('within two rounds'); + expect(loaded?.instructions).toContain(''); + expect(loaded?.instructions).toContain('Never poll and never sleep'); + }); + + it('loads the bundled debugging-executions skill', async () => { + const source = loadInstanceAiRuntimeSkillSource(); + const skill = source.registry.skills.find((entry) => entry.name === 'debugging-executions'); + + expect(skill?.recommendedTools).toEqual(['executions', 'workflows']); + + const loaded = await source.loadSkill('debugging-executions'); + expect(loaded?.instructions).toContain('executions(action="debug")'); + expect(loaded?.instructions).toContain( + 'executions(action="get-resolved-node-parameters", executionId, nodeName)', + ); + expect(loaded?.instructions).toContain('unreconstructable-context'); + expect(loaded?.instructions).toContain('do this unprompted'); + }); }); 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 dcd447fddff..9b081be449d 100644 --- a/packages/@n8n/instance-ai/src/skills/materialize-runtime-skills.ts +++ b/packages/@n8n/instance-ai/src/skills/materialize-runtime-skills.ts @@ -11,6 +11,7 @@ import { type RuntimeSkillSource, type Workspace, } from '@n8n/agents'; +import { getWorkspaceRoot } from '@n8n/agents/sandbox'; import { join as posixJoin, normalize as posixNormalize } from 'node:path/posix'; import type { Logger } from '../logger'; @@ -18,7 +19,6 @@ import { loadPrebakedWorkspaceBundle, materializeWorkspaceBundle, } from '../workspace/prebaked-workspace-bundle'; -import { getWorkspaceRoot } from '../workspace/sandbox-setup'; import { stringifyWorkspaceJson, withTrailingNewline } from '../workspace/workspace-file-content'; import { WORKSPACE_MANIFEST_FILE } from '../workspace/workspace-manifest'; @@ -62,7 +62,7 @@ interface BuildRuntimeSkillWorkspaceBundleOptions { root: string; workspaceRoot?: string; skillsRoot?: string; - logger?: Logger; + logger: Logger; } interface MaterializeRuntimeSkillsOptions { @@ -70,13 +70,13 @@ interface MaterializeRuntimeSkillsOptions { workspace: Workspace; root: string; workspaceRoot?: string; - logger?: Logger; + logger: Logger; } interface LazyWorkspaceRuntimeSkillSourceOptions { source: RuntimeSkillSource; workspace: Workspace | undefined; - logger?: Logger; + logger: Logger; } const LINKED_FILE_GROUPS = [ @@ -403,7 +403,7 @@ function linkedFilesFor(entry: RuntimeSkillRegistryEntry): RuntimeSkillLinkedFil } function warnIfExceedsLoadSkillLimit( - logger: Logger | undefined, + logger: Logger, entry: RuntimeSkillRegistryEntry, filePath: string, content: string, @@ -411,7 +411,7 @@ function warnIfExceedsLoadSkillLimit( const bytes = Buffer.byteLength(content, 'utf8'); if (bytes <= LOAD_SKILL_OUTPUT_LIMIT_BYTES) return; - logger?.warn('Runtime skill file exceeds load_skill output limit', { + logger.warn('Runtime skill file exceeds load_skill output limit', { skill: entry.name, path: filePath, bytes, diff --git a/packages/@n8n/instance-ai/src/source-map-filter.ts b/packages/@n8n/instance-ai/src/source-map-filter.ts index 840c6c841b6..7861eb56fd5 100644 --- a/packages/@n8n/instance-ai/src/source-map-filter.ts +++ b/packages/@n8n/instance-ai/src/source-map-filter.ts @@ -19,7 +19,6 @@ function loadSourceMapSupport(): SourceMapSupportModule | undefined { } const FILTERED_PATH_FRAGMENTS = [ - '/node_modules/@mastra/core/dist/chunk-', '/node_modules/@ai-sdk/', '/node_modules/langsmith/', '/node_modules/zod/', diff --git a/packages/@n8n/instance-ai/src/storage/__tests__/workflow-loop-storage.test.ts b/packages/@n8n/instance-ai/src/storage/__tests__/workflow-loop-storage.test.ts index dc1032f3e6d..d0e011b0537 100644 --- a/packages/@n8n/instance-ai/src/storage/__tests__/workflow-loop-storage.test.ts +++ b/packages/@n8n/instance-ai/src/storage/__tests__/workflow-loop-storage.test.ts @@ -1,6 +1,10 @@ import type { Mock } from 'vitest'; -import type { WorkflowLoopState, AttemptRecord } from '../../workflow-loop/workflow-loop-state'; +import type { + WorkflowBuildOutcome, + WorkflowLoopState, + AttemptRecord, +} from '../../workflow-loop/workflow-loop-state'; import { patchThread, type PatchableThreadMemory } from '../thread-patch'; import type * as ThreadPatch from '../thread-patch'; import { WorkflowLoopStorage } from '../workflow-loop-storage'; @@ -47,6 +51,20 @@ function makeAttempt(overrides: Partial = {}): AttemptRecord { }; } +function makeOutcome(overrides: Partial = {}): WorkflowBuildOutcome { + return { + workItemId: 'wi-1', + runId: 'run-1', + taskId: 'task-1', + workflowId: 'wf-1', + submitted: true, + triggerType: 'manual_or_testable', + needsUserInput: false, + summary: 'Submitted.', + ...overrides, + }; +} + const baseThread = { id: 'thread-1', title: 'Test', @@ -147,6 +165,197 @@ describe('WorkflowLoopStorage', () => { }); }); + describe('setup routing claims', () => { + it('claims an unrouted direct work item', async () => { + const state = makeState({ status: 'completed', phase: 'done', workflowId: 'wf-1' }); + + mockedPatchThread.mockImplementation((_mem, { update }) => { + const result = update({ + ...baseThread, + metadata: { + instanceAiWorkflowLoop: { + 'wi-1': { state, attempts: [] }, + }, + }, + }); + const next = result?.metadata?.instanceAiWorkflowLoop as Record< + string, + { state: WorkflowLoopState } + >; + expect(next['wi-1'].state).toEqual( + expect.objectContaining({ + setupRoutingClaimId: 'claim-1', + setupRoutingClaimedAt: '2026-01-01T00:00:00.000Z', + setupRoutingClaimExpiresAt: '2026-01-01T00:15:00.000Z', + }), + ); + return baseThread as never; + }); + + const claimed = await storage.claimSetupRouting('thread-1', 'wi-1', { + claimId: 'claim-1', + claimedAt: '2026-01-01T00:00:00.000Z', + expiresAt: '2026-01-01T00:15:00.000Z', + }); + + expect(claimed?.state.setupRoutingClaimId).toBe('claim-1'); + }); + + it('does not claim a planned work item', async () => { + const state = makeState({ + status: 'completed', + phase: 'done', + workflowId: 'wf-1', + plannedTaskId: 'planned-1', + }); + + mockedPatchThread.mockImplementation((_mem, { update }) => { + const result = update({ + ...baseThread, + metadata: { + instanceAiWorkflowLoop: { + 'wi-1': { state, attempts: [] }, + }, + }, + }); + expect(result).toBeNull(); + return baseThread as never; + }); + + const claimed = await storage.claimSetupRouting('thread-1', 'wi-1', { + claimId: 'claim-1', + claimedAt: '2026-01-01T00:00:00.000Z', + expiresAt: '2026-01-01T00:15:00.000Z', + }); + + expect(claimed).toBeNull(); + }); + + it('does not claim a work item with a planned owner', async () => { + const state = makeState({ + status: 'completed', + phase: 'done', + workflowId: 'wf-1', + owner: { type: 'planned', taskId: 'planned-1' }, + }); + + mockedPatchThread.mockImplementation((_mem, { update }) => { + const result = update({ + ...baseThread, + metadata: { + instanceAiWorkflowLoop: { + 'wi-1': { state, attempts: [] }, + }, + }, + }); + expect(result).toBeNull(); + return baseThread as never; + }); + + const claimed = await storage.claimSetupRouting('thread-1', 'wi-1', { + claimId: 'claim-1', + claimedAt: '2026-01-01T00:00:00.000Z', + expiresAt: '2026-01-01T00:15:00.000Z', + }); + + expect(claimed).toBeNull(); + }); + + it('does not claim a work item whose last outcome belongs to a planned task', async () => { + const state = makeState({ + status: 'completed', + phase: 'done', + workflowId: 'wf-1', + }); + const lastBuildOutcome = makeOutcome({ plannedTaskId: 'planned-1' }); + + mockedPatchThread.mockImplementation((_mem, { update }) => { + const result = update({ + ...baseThread, + metadata: { + instanceAiWorkflowLoop: { + 'wi-1': { state, attempts: [], lastBuildOutcome }, + }, + }, + }); + expect(result).toBeNull(); + return baseThread as never; + }); + + const claimed = await storage.claimSetupRouting('thread-1', 'wi-1', { + claimId: 'claim-1', + claimedAt: '2026-01-01T00:00:00.000Z', + expiresAt: '2026-01-01T00:15:00.000Z', + }); + + expect(claimed).toBeNull(); + }); + + it('marks setup routed for the matching claim and clears the claim', async () => { + const state = makeState({ + status: 'completed', + phase: 'done', + workflowId: 'wf-1', + setupRoutingClaimId: 'claim-1', + setupRoutingClaimedAt: '2026-01-01T00:00:00.000Z', + setupRoutingClaimExpiresAt: '2026-01-01T00:15:00.000Z', + }); + + mockedPatchThread.mockImplementation((_mem, { update }) => { + const result = update({ + ...baseThread, + metadata: { + instanceAiWorkflowLoop: { + 'wi-1': { state, attempts: [] }, + }, + }, + }); + const next = result?.metadata?.instanceAiWorkflowLoop as Record< + string, + { state: WorkflowLoopState } + >; + expect(next['wi-1'].state.setupRoutedAt).toBe('2026-01-01T00:01:00.000Z'); + expect(next['wi-1'].state.setupRoutingClaimId).toBeUndefined(); + return baseThread as never; + }); + + await expect( + storage.markSetupRouted('thread-1', 'wi-1', 'claim-1', '2026-01-01T00:01:00.000Z'), + ).resolves.toBe(true); + }); + + it('releases the matching setup routing claim', async () => { + const state = makeState({ + status: 'completed', + phase: 'done', + workflowId: 'wf-1', + setupRoutingClaimId: 'claim-1', + setupRoutingClaimedAt: '2026-01-01T00:00:00.000Z', + setupRoutingClaimExpiresAt: '2026-01-01T00:15:00.000Z', + }); + + mockedPatchThread.mockImplementation((_mem, { update }) => { + const result = update({ + ...baseThread, + metadata: { + instanceAiWorkflowLoop: { + 'wi-1': { state, attempts: [] }, + }, + }, + }); + const next = result?.metadata?.instanceAiWorkflowLoop as Record< + string, + { state: WorkflowLoopState } + >; + expect(next['wi-1'].state.setupRoutingClaimId).toBeUndefined(); + expect(next['wi-1'].state.setupRoutedAt).toBeUndefined(); + return baseThread as never; + }); + + await storage.releaseSetupRoutingClaim('thread-1', 'wi-1', 'claim-1'); + }); + }); + describe('getActiveWorkItem', () => { it('returns the active work item', async () => { const activeState = makeState({ workItemId: 'wi-active', status: 'active' }); @@ -190,4 +399,25 @@ describe('WorkflowLoopStorage', () => { expect(await storage.getActiveWorkItem('thread-1')).toBeNull(); }); }); + + describe('listWorkItems', () => { + it('returns all stored work items', async () => { + const firstState = makeState({ workItemId: 'wi-1' }); + const secondState = makeState({ workItemId: 'wi-2' }); + + vi.mocked(memory.getThread).mockResolvedValue({ + ...baseThread, + metadata: { + instanceAiWorkflowLoop: { + 'wi-1': { state: firstState, attempts: [] }, + 'wi-2': { state: secondState, attempts: [] }, + }, + }, + }); + + const result = await storage.listWorkItems('thread-1'); + + expect(result.map((record) => record.state.workItemId)).toEqual(['wi-1', 'wi-2']); + }); + }); }); diff --git a/packages/@n8n/instance-ai/src/storage/index.ts b/packages/@n8n/instance-ai/src/storage/index.ts index 34aba2bcf82..0d22ac1a43b 100644 --- a/packages/@n8n/instance-ai/src/storage/index.ts +++ b/packages/@n8n/instance-ai/src/storage/index.ts @@ -9,4 +9,7 @@ export { TerminalOutcomeStorage } from './terminal-outcome-storage'; export type { TerminalOutcome } from './terminal-outcome-storage'; export type { PatchableThreadMemory, ThreadPatch } from './thread-patch'; export { WorkflowLoopStorage } from './workflow-loop-storage'; -export type { WorkflowLoopWorkItemRecord } from './workflow-loop-storage'; +export type { + WorkflowLoopWorkItemRecord, + WorkflowSetupRoutingClaim, +} from './workflow-loop-storage'; diff --git a/packages/@n8n/instance-ai/src/storage/workflow-loop-storage.ts b/packages/@n8n/instance-ai/src/storage/workflow-loop-storage.ts index 92664fe0519..8b5a5d44b0c 100644 --- a/packages/@n8n/instance-ai/src/storage/workflow-loop-storage.ts +++ b/packages/@n8n/instance-ai/src/storage/workflow-loop-storage.ts @@ -8,6 +8,8 @@ import type { } from '../workflow-loop/workflow-loop-state'; import { attemptRecordSchema, + isPlannedWorkflowBuildOwner, + resolveWorkflowBuildOwner, workflowBuildOutcomeSchema, workflowLoopStateSchema, } from '../workflow-loop/workflow-loop-state'; @@ -24,6 +26,35 @@ const loopStorageSchema = z.record(z.string(), workItemRecordSchema); export type WorkflowLoopWorkItemRecord = z.infer; +export interface WorkflowSetupRoutingClaim { + claimId: string; + claimedAt: string; + expiresAt: string; +} + +function clearSetupRoutingClaim(state: WorkflowLoopState): WorkflowLoopState { + const next: WorkflowLoopState = { ...state }; + delete next.setupRoutingClaimId; + delete next.setupRoutingClaimedAt; + delete next.setupRoutingClaimExpiresAt; + return next; +} + +function hasUnexpiredSetupRoutingClaim(state: WorkflowLoopState, nowIso: string): boolean { + if (!state.setupRoutingClaimId) return false; + + const expiresAtMs = Date.parse(state.setupRoutingClaimExpiresAt ?? ''); + if (!Number.isFinite(expiresAtMs)) return true; + + return expiresAtMs > Date.parse(nowIso); +} + +function isPlannedWorkItem(record: WorkflowLoopWorkItemRecord): boolean { + return isPlannedWorkflowBuildOwner( + resolveWorkflowBuildOwner(record.state, record.lastBuildOutcome), + ); +} + export class WorkflowLoopStorage { constructor(private readonly memory: PatchableThreadMemory) {} @@ -66,6 +97,108 @@ export class WorkflowLoopStorage { return null; } + async listWorkItems(threadId: string): Promise { + const all = await this.loadAll(threadId); + return Object.values(all); + } + + async claimSetupRouting( + threadId: string, + workItemId: string, + claim: WorkflowSetupRoutingClaim, + ): Promise { + let claimed: WorkflowLoopWorkItemRecord | null = null; + await patchThread(this.memory, { + threadId, + update: ({ metadata = {} }) => { + const all = this.parse(metadata[METADATA_KEY]); + const record = all[workItemId]; + if (!record) return null; + if (record.state.setupRoutedAt || isPlannedWorkItem(record)) return null; + if (hasUnexpiredSetupRoutingClaim(record.state, claim.claimedAt)) return null; + + const state: WorkflowLoopState = { + ...record.state, + setupRoutingClaimId: claim.claimId, + setupRoutingClaimedAt: claim.claimedAt, + setupRoutingClaimExpiresAt: claim.expiresAt, + }; + claimed = { state, attempts: record.attempts, lastBuildOutcome: record.lastBuildOutcome }; + all[workItemId] = claimed; + return { + metadata: { + ...metadata, + [METADATA_KEY]: all, + }, + }; + }, + }); + return claimed; + } + + async markSetupRouted( + threadId: string, + workItemId: string, + claimId: string, + routedAt: string, + ): Promise { + let marked = false; + await patchThread(this.memory, { + threadId, + update: ({ metadata = {} }) => { + const all = this.parse(metadata[METADATA_KEY]); + const record = all[workItemId]; + if (!record) return null; + if (record.state.setupRoutedAt || isPlannedWorkItem(record)) return null; + if (record.state.setupRoutingClaimId !== claimId) return null; + + all[workItemId] = { + state: { + ...clearSetupRoutingClaim(record.state), + setupRoutedAt: routedAt, + }, + attempts: record.attempts, + lastBuildOutcome: record.lastBuildOutcome, + }; + marked = true; + return { + metadata: { + ...metadata, + [METADATA_KEY]: all, + }, + }; + }, + }); + return marked; + } + + async releaseSetupRoutingClaim( + threadId: string, + workItemId: string, + claimId: string, + ): Promise { + await patchThread(this.memory, { + threadId, + update: ({ metadata = {} }) => { + const all = this.parse(metadata[METADATA_KEY]); + const record = all[workItemId]; + if (!record || record.state.setupRoutingClaimId !== claimId) return null; + + all[workItemId] = { + state: clearSetupRoutingClaim(record.state), + attempts: record.attempts, + lastBuildOutcome: record.lastBuildOutcome, + }; + return { + metadata: { + ...metadata, + [METADATA_KEY]: all, + }, + }; + }, + }); + } + private async loadAll(threadId: string): Promise> { const thread = await getThread(this.memory, threadId); if (!thread?.metadata?.[METADATA_KEY]) return {}; diff --git a/packages/@n8n/instance-ai/src/stream/__tests__/output-redaction.test.ts b/packages/@n8n/instance-ai/src/stream/__tests__/output-redaction.test.ts new file mode 100644 index 00000000000..273d76aaec8 --- /dev/null +++ b/packages/@n8n/instance-ai/src/stream/__tests__/output-redaction.test.ts @@ -0,0 +1,219 @@ +import type { RedactionOptions } from '@n8n/agents'; +import type { InstanceAiEvent } from '@n8n/api-types'; + +import type { Logger } from '../../logger'; +import { OutputRedactor } from '../output-redaction'; + +function createLogger() { + return { info: vi.fn(), warn: vi.fn(), error: vi.fn(), debug: vi.fn() } as unknown as Logger; +} + +function createRedactor(logger = createLogger(), options?: RedactionOptions | false) { + return new OutputRedactor({ + logger, + threadId: 'thread-1', + runId: 'run-1', + agentId: 'agent-1', + ...(options !== undefined ? { options } : {}), + }); +} + +function textDelta(text: string): InstanceAiEvent { + return { type: 'text-delta', runId: 'run-1', agentId: 'agent-1', payload: { text } }; +} + +function collectText(events: InstanceAiEvent[]): string { + return events.map((e) => ('payload' in e && 'text' in e.payload ? e.payload.text : '')).join(''); +} + +describe('OutputRedactor', () => { + it('redacts a secret split across two text deltas', () => { + const redactor = createRedactor(); + const emitted = [ + ...redactor.processEvent(textDelta('your key is sk-ant-')), + ...redactor.processEvent(textDelta('api03-aaaaaaaaaaaaaaaa, keep it safe')), + ...redactor.flush(), + ]; + const out = collectText(emitted); + expect(out).toBe('your key is [REDACTED], keep it safe'); + expect(out).not.toContain('sk-ant-'); + }); + + it('redacts a PII email when the email category is enabled', () => { + const redactor = createRedactor(createLogger(), { detect: ['email'] }); + const emitted = [ + ...redactor.processEvent(textDelta('email me at jane@example.com ok')), + ...redactor.flush(), + ]; + expect(collectText(emitted)).toBe('email me at [REDACTED] ok'); + }); + + it('redacts credit cards by default but leaves email untouched', () => { + const redactor = createRedactor(); + const emitted = [ + ...redactor.processEvent(textDelta('card 4111 1111 1111 1111 mail jane@example.com')), + ...redactor.flush(), + ]; + const out = collectText(emitted); + expect(out).toBe('card [REDACTED] mail jane@example.com'); + }); + + it('passes non-sensitive prose through unchanged', () => { + const redactor = createRedactor(); + const text = 'The workflow completed and produced three items successfully.'; + const emitted = [...redactor.processEvent(textDelta(text)), ...redactor.flush()]; + expect(collectText(emitted)).toBe(text); + }); + + it('preserves responseId on flushed delta text', () => { + const redactor = createRedactor(); + const emitted = [ + ...redactor.processEvent({ + type: 'text-delta', + runId: 'run-1', + agentId: 'agent-1', + responseId: 'run-1:step:1', + payload: { text: 'hello there' }, + }), + ...redactor.flush(), + ]; + expect(emitted).toHaveLength(1); + expect(emitted[0]).toMatchObject({ type: 'text-delta', responseId: 'run-1:step:1' }); + }); + + it('redacts secrets nested inside tool-call args', () => { + const redactor = createRedactor(); + const event: InstanceAiEvent = { + type: 'tool-call', + runId: 'run-1', + agentId: 'agent-1', + payload: { + toolCallId: 'tc-1', + toolName: 'http_request', + args: { headers: { authorization: 'Bearer abcdef1234567890' } }, + }, + }; + const [out] = redactor.processEvent(event); + expect(JSON.stringify(out)).toContain('[REDACTED]'); + expect(JSON.stringify(out)).not.toContain('abcdef1234567890'); + // Identifier fields are preserved. + expect(out).toMatchObject({ payload: { toolCallId: 'tc-1', toolName: 'http_request' } }); + }); + + it('redacts secrets nested inside a tool-result', () => { + const redactor = createRedactor(); + const event: InstanceAiEvent = { + type: 'tool-result', + runId: 'run-1', + agentId: 'agent-1', + payload: { + toolCallId: 'tc-1', + result: { headers: { authorization: 'Bearer abcdef1234567890' } }, + }, + }; + const [out] = redactor.processEvent(event); + expect(JSON.stringify(out)).toContain('[REDACTED]'); + expect(JSON.stringify(out)).not.toContain('abcdef1234567890'); + }); + + it('redacts confirmation card display text', () => { + const redactor = createRedactor(createLogger(), { detect: ['email'] }); + const event: InstanceAiEvent = { + type: 'confirmation-request', + runId: 'run-1', + agentId: 'agent-1', + payload: { + requestId: 'req-1', + toolCallId: 'tc-1', + toolName: 'ask', + args: {}, + severity: 'warning', + message: 'What to do with jane@example.com?', + introMessage: 'I noticed jane@example.com in your request.', + questions: [ + { + id: 'q1', + question: 'Where should jane@example.com be used?', + type: 'single', + options: ['Reply-to jane@example.com', 'Skip'], + }, + ], + tasks: { tasks: [{ id: 't1', description: 'Email jane@example.com', status: 'todo' }] }, + planItems: [ + { + id: 'p1', + title: 'Notify jane@example.com', + kind: 'task', + spec: 'Send to jane@example.com', + deps: [], + }, + ], + }, + }; + + const [out] = redactor.processEvent(event); + const serialized = JSON.stringify(out); + expect(serialized).not.toContain('jane@example.com'); + expect(serialized).toContain('[REDACTED]'); + // Control/identifier fields are preserved so suspend/resume keeps working. + expect(out).toMatchObject({ payload: { requestId: 'req-1', toolCallId: 'tc-1' } }); + }); + + it('logs a filtering summary with category counts and no values', () => { + const logger = createLogger(); + const redactor = createRedactor(logger, { secrets: true, detect: ['email'] }); + redactor.processEvent( + textDelta('key sk-ant-api03-aaaaaaaaaaaaaaaa and mail jane@example.com here'), + ); + redactor.flush(); + + expect(logger.info).toHaveBeenCalledWith( + 'Instance AI redacted sensitive content from agent output', + expect.objectContaining({ + threadId: 'thread-1', + runId: 'run-1', + agentId: 'agent-1', + count: 2, + categories: { secret: 1, email: 1 }, + }), + ); + const meta = vi.mocked(logger.info).mock.calls[0][1]; + expect(JSON.stringify(meta)).not.toContain('sk-ant-'); + expect(JSON.stringify(meta)).not.toContain('jane@example.com'); + }); + + it('does not log when nothing is redacted', () => { + const logger = createLogger(); + const redactor = createRedactor(logger); + redactor.processEvent(textDelta('all clear, nothing sensitive here at all')); + redactor.flush(); + expect(logger.info).not.toHaveBeenCalled(); + }); + + describe('when disabled (options: false)', () => { + function createDisabled(logger = createLogger()) { + return new OutputRedactor({ + logger, + threadId: 'thread-1', + runId: 'run-1', + agentId: 'agent-1', + options: false, + }); + } + + it('passes events through untouched, including secrets', () => { + const redactor = createDisabled(); + const input = textDelta('your key is sk-ant-api03-aaaaaaaaaaaaaaaa here'); + const emitted = [...redactor.processEvent(input), ...redactor.flush()]; + expect(emitted).toEqual([input]); + }); + + it('does not log a filtering summary', () => { + const logger = createLogger(); + const redactor = createDisabled(logger); + redactor.processEvent(textDelta('key sk-ant-api03-aaaaaaaaaaaaaaaa')); + redactor.flush(); + expect(logger.info).not.toHaveBeenCalled(); + }); + }); +}); diff --git a/packages/@n8n/instance-ai/src/stream/__tests__/usage-accumulator.test.ts b/packages/@n8n/instance-ai/src/stream/__tests__/usage-accumulator.test.ts new file mode 100644 index 00000000000..c180c5dd838 --- /dev/null +++ b/packages/@n8n/instance-ai/src/stream/__tests__/usage-accumulator.test.ts @@ -0,0 +1,78 @@ +import { UsageAccumulator } from '../usage-accumulator'; + +describe('UsageAccumulator', () => { + it('reports no usage and zeroes before any finish chunk', () => { + const acc = new UsageAccumulator(); + + expect(acc.hasUsage()).toBe(false); + expect(acc.toUsage()).toEqual({ + promptTokens: 0, + completionTokens: 0, + totalTokens: 0, + costUsd: 0, + }); + }); + + it('captures usage and cost from a finish chunk', () => { + const acc = new UsageAccumulator(); + + acc.observe({ + type: 'finish', + usage: { promptTokens: 100, completionTokens: 40, totalTokens: 140, cost: 0.02 }, + }); + + expect(acc.hasUsage()).toBe(true); + expect(acc.toUsage()).toEqual({ + promptTokens: 100, + completionTokens: 40, + totalTokens: 140, + costUsd: 0.02, + }); + }); + + it('sums usage across multiple finish chunks (e.g. resumed runs)', () => { + const acc = new UsageAccumulator(); + + acc.observe({ + type: 'finish', + usage: { promptTokens: 100, completionTokens: 40, totalTokens: 140, cost: 0.02 }, + }); + acc.observe({ + type: 'finish', + usage: { promptTokens: 50, completionTokens: 10, totalTokens: 60, cost: 0.01 }, + }); + + expect(acc.toUsage()).toEqual({ + promptTokens: 150, + completionTokens: 50, + totalTokens: 200, + costUsd: 0.03, + }); + }); + + it('ignores non-finish chunks and finish chunks without usage', () => { + const acc = new UsageAccumulator(); + + acc.observe({ type: 'text-delta', textDelta: 'hi' }); + acc.observe({ type: 'finish', finishReason: 'stop' }); + acc.observe('not even an object'); + acc.observe(undefined); + + expect(acc.hasUsage()).toBe(false); + expect(acc.toUsage().totalTokens).toBe(0); + }); + + it('treats missing usage fields as zero', () => { + const acc = new UsageAccumulator(); + + acc.observe({ type: 'finish', usage: { totalTokens: 10 } }); + + expect(acc.hasUsage()).toBe(true); + expect(acc.toUsage()).toEqual({ + promptTokens: 0, + completionTokens: 0, + totalTokens: 10, + costUsd: 0, + }); + }); +}); diff --git a/packages/@n8n/instance-ai/src/stream/consume-with-hitl.ts b/packages/@n8n/instance-ai/src/stream/consume-with-hitl.ts index 0c066f99939..f59bcbf3554 100644 --- a/packages/@n8n/instance-ai/src/stream/consume-with-hitl.ts +++ b/packages/@n8n/instance-ai/src/stream/consume-with-hitl.ts @@ -1,3 +1,4 @@ +import type { RedactionOptions } from '@n8n/agents'; import type { InstanceAiEvent } from '@n8n/api-types'; import type { InstanceAiEventBus } from '../event-bus/event-bus.interface'; @@ -33,6 +34,8 @@ export interface ConsumeWithHitlOptions { resumeOptions?: Record; /** Native agent persistence owner for suspended sub-agent state. */ persistence?: { threadId: string; resourceId: string }; + /** Output-redaction policy: omit for the safe default, or `false` to disable. */ + outputRedaction?: RedactionOptions | false; } export interface ConsumeWithHitlResult { @@ -89,6 +92,7 @@ export async function consumeStreamWithHitl( eventBus: options.eventBus, signal: options.abortSignal, logger: options.logger, + outputRedaction: options.outputRedaction, }, control: { mode: 'auto', @@ -122,6 +126,8 @@ export interface ConsumeStreamCascadingOptions { logger: Logger; threadId: string; abortSignal: AbortSignal; + /** Output-redaction policy: omit for the safe default, or `false` to disable. */ + outputRedaction?: RedactionOptions | false; } export type ConsumeStreamCascadingResult = @@ -168,6 +174,7 @@ export async function consumeStreamCascading( eventBus: options.eventBus, signal: options.abortSignal, logger: options.logger, + outputRedaction: options.outputRedaction, }, control: { mode: 'manual' }, }); diff --git a/packages/@n8n/instance-ai/src/stream/output-redaction.ts b/packages/@n8n/instance-ai/src/stream/output-redaction.ts new file mode 100644 index 00000000000..b1f02f9cc73 --- /dev/null +++ b/packages/@n8n/instance-ai/src/stream/output-redaction.ts @@ -0,0 +1,239 @@ +import { + StreamingRedactor, + redactText, + redactDeep, + type RedactionCategory, + type RedactionOptions, +} from '@n8n/agents'; +import type { InstanceAiEvent } from '@n8n/api-types'; + +import type { Logger } from '../logger'; +import { isRecord } from '../utils/stream-helpers'; + +/** + * Default output-filtering policy for Instance AI: redact known credential/ + * secret patterns plus credit-card numbers. Other PII categories (`email`, + * `ssn-us`) are implemented but off by default until we decide which to enable. + * + * Instance AI always redacts matches. The SDK's `GuardrailStrategy` also defines + * `block` and `warn`, but those are not implemented here. + */ +export const DEFAULT_OUTPUT_REDACTION_OPTIONS: RedactionOptions = { + secrets: true, + detect: ['credit-card'], +}; + +interface OutputRedactorContext { + logger: Logger; + threadId: string; + runId: string; + agentId: string; + /** + * Redaction policy: omit for the safe default, pass options to customise, or + * `false` to disable scanning entirely (events pass through untouched). + */ + options?: RedactionOptions | false; +} + +type DeltaType = 'text-delta' | 'reasoning-delta'; + +interface Channel { + readonly type: DeltaType; + readonly redactor: StreamingRedactor; + responseId?: string; +} + +/** + * Scans agent output events for secrets/PII before they reach the user and + * redacts matches in place. + * + * Text/reasoning deltas are streamed through a holdback-buffered redactor so a + * secret split across chunk boundaries is caught. Buffered text is released + * (with its original `responseId`) whenever a structural event (tool call, + * result, …) or a new step boundary arrives — secrets never span those + * boundaries — so event ordering and step grouping are preserved. Tool + * results/errors are redacted one-shot. + * + * One instance per run. Call {@link processEvent} on each mapped event; it + * returns the ordered events to publish. Call {@link flush} when the active + * stream segment ends to release any remainder and log a filtering summary. + */ +export class OutputRedactor { + private readonly enabled: boolean; + + private readonly options: RedactionOptions; + + private readonly text: Channel; + + private readonly reasoning: Channel; + + private matches: RedactionCategory[] = []; + + constructor(private readonly context: OutputRedactorContext) { + this.enabled = context.options !== false; + // When disabled the options are unused; default keeps the type concrete. + this.options = + context.options === false || context.options === undefined + ? DEFAULT_OUTPUT_REDACTION_OPTIONS + : context.options; + this.text = { type: 'text-delta', redactor: new StreamingRedactor(this.options) }; + this.reasoning = { type: 'reasoning-delta', redactor: new StreamingRedactor(this.options) }; + } + + /** Redact an outgoing event; returns the ordered events that should be published. */ + processEvent(event: InstanceAiEvent): InstanceAiEvent[] { + if (!this.enabled) return [event]; + if (event.type === 'text-delta') return this.processDelta(event, this.text); + if (event.type === 'reasoning-delta') return this.processDelta(event, this.reasoning); + + // Structural event: release any buffered text first so ordering is kept. + return [ + ...this.drainChannel(this.reasoning), + ...this.drainChannel(this.text), + this.redactStructural(event), + ]; + } + + /** Release buffered text for both channels and log a filtering summary. Call at segment end. */ + flush(): InstanceAiEvent[] { + if (!this.enabled) return []; + const events = [...this.drainChannel(this.reasoning), ...this.drainChannel(this.text)]; + this.logSummary(); + return events; + } + + private processDelta( + event: Extract, + channel: Channel, + ): InstanceAiEvent[] { + const events: InstanceAiEvent[] = []; + // A new step: release the previous step's text under its own responseId. + if (channel.responseId !== undefined && channel.responseId !== event.responseId) { + events.push(...this.drainChannel(channel)); + } + channel.responseId = event.responseId; + + const { text, matches } = channel.redactor.push(event.payload.text); + this.recordMatches(matches); + if (text) events.push(this.makeDelta(channel, text)); + return events; + } + + private drainChannel(channel: Channel): InstanceAiEvent[] { + const { text, matches } = channel.redactor.flush(); + this.recordMatches(matches); + return text ? [this.makeDelta(channel, text)] : []; + } + + private makeDelta(channel: Channel, text: string): InstanceAiEvent { + return { + type: channel.type, + runId: this.context.runId, + agentId: this.context.agentId, + ...(channel.responseId ? { responseId: channel.responseId } : {}), + payload: { text }, + }; + } + + private redactStructural(event: InstanceAiEvent): InstanceAiEvent { + if (event.type === 'tool-call') { + // Redact the model-generated args shown in the UI. This only touches the + // event payload, not the actual tool invocation (handled by the runtime). + const { value, matches } = redactDeep(event.payload.args, this.options); + this.recordMatches(matches); + return { + ...event, + payload: { ...event.payload, args: isRecord(value) ? value : event.payload.args }, + }; + } + if (event.type === 'tool-result') { + const { value, matches } = redactDeep(event.payload.result, this.options); + this.recordMatches(matches); + return { ...event, payload: { ...event.payload, result: value } }; + } + if (event.type === 'tool-error') { + return { + ...event, + payload: { ...event.payload, error: this.redactString(event.payload.error) }, + }; + } + if (event.type === 'confirmation-request') { + return this.redactConfirmation(event); + } + return event; + } + + /** + * Redact the human-readable text of a HITL confirmation card (message, intro, + * question/option labels, and task/plan-item descriptions). Control and + * identifier fields — `requestId`, `toolCallId`, `inputType`, + * `credentialRequests`, task `id`/`status`, plan `kind`/`deps`, etc. — are + * left untouched so suspend/resume routing keeps working. + */ + private redactConfirmation( + event: Extract, + ): InstanceAiEvent { + const payload = event.payload; + const questions = payload.questions?.map((question) => ({ + ...question, + question: this.redactString(question.question), + ...(question.options ? { options: question.options.map((o) => this.redactString(o)) } : {}), + })); + + const tasks = payload.tasks + ? { + ...payload.tasks, + tasks: payload.tasks.tasks.map((task) => ({ + ...task, + description: this.redactString(task.description), + ...(task.detail ? { detail: this.redactString(task.detail) } : {}), + })), + } + : undefined; + + const planItems = payload.planItems?.map((item) => ({ + ...item, + title: this.redactString(item.title), + spec: this.redactString(item.spec), + })); + + return { + ...event, + payload: { + ...payload, + message: this.redactString(payload.message), + ...(payload.introMessage ? { introMessage: this.redactString(payload.introMessage) } : {}), + ...(questions ? { questions } : {}), + ...(tasks ? { tasks } : {}), + ...(planItems ? { planItems } : {}), + }, + }; + } + + private redactString(text: string): string { + const { text: redacted, matches } = redactText(text, this.options); + this.recordMatches(matches); + return redacted; + } + + private recordMatches(matches: Array<{ category: RedactionCategory }>): void { + for (const match of matches) this.matches.push(match.category); + } + + /** Emit a single filtering-event log per segment — categories and counts only, never values. */ + private logSummary(): void { + if (this.matches.length === 0) return; + const categories: Partial> = {}; + for (const category of this.matches) { + categories[category] = (categories[category] ?? 0) + 1; + } + this.context.logger.info('Instance AI redacted sensitive content from agent output', { + threadId: this.context.threadId, + runId: this.context.runId, + agentId: this.context.agentId, + count: this.matches.length, + categories, + }); + this.matches = []; + } +} diff --git a/packages/@n8n/instance-ai/src/stream/usage-accumulator.ts b/packages/@n8n/instance-ai/src/stream/usage-accumulator.ts new file mode 100644 index 00000000000..021ab18f462 --- /dev/null +++ b/packages/@n8n/instance-ai/src/stream/usage-accumulator.ts @@ -0,0 +1,69 @@ +import { z } from 'zod'; + +// ── Schema (source of truth) ──────────────────────────────────────────────── + +export const runTokenUsageSchema = z.object({ + promptTokens: z.number().int().min(0), + completionTokens: z.number().int().min(0), + totalTokens: z.number().int().min(0), + /** Estimated cost in USD, summed from per-step `usage.cost` (models.dev pricing). */ + costUsd: z.number().min(0), +}); + +export type RunTokenUsage = z.infer; + +/** Shape of the `usage` field on the agent SDK's `finish` stream chunk. */ +const finishChunkSchema = z.object({ + type: z.literal('finish'), + usage: z + .object({ + promptTokens: z.number().optional(), + completionTokens: z.number().optional(), + totalTokens: z.number().optional(), + cost: z.number().optional(), + }) + .optional(), +}); + +// ── Accumulator ───────────────────────────────────────────────────────────── + +/** + * Accumulates token usage and cost from the agent SDK's `finish` stream chunks. + * Mirrors {@link WorkSummaryAccumulator}: instantiated per-stream, fed each raw + * chunk, and drained at the end. A run emits one `finish` chunk per agent + * segment (one extra per resume), so usage is summed across segments. + */ +export class UsageAccumulator { + private promptTokens = 0; + private completionTokens = 0; + private totalTokens = 0; + private costUsd = 0; + private seen = false; + + /** Feed a raw stream chunk. Only `finish` chunks carry usage; others are ignored. */ + observe(chunk: unknown): void { + const parsed = finishChunkSchema.safeParse(chunk); + if (!parsed.success || !parsed.data.usage) return; + const { promptTokens, completionTokens, totalTokens, cost } = parsed.data.usage; + this.promptTokens += promptTokens ?? 0; + this.completionTokens += completionTokens ?? 0; + this.totalTokens += totalTokens ?? 0; + this.costUsd += cost ?? 0; + this.seen = true; + } + + /** Whether any usage was observed. */ + hasUsage(): boolean { + return this.seen; + } + + /** Produce a usage summary. Safe to call multiple times (idempotent). */ + toUsage(): RunTokenUsage { + return { + promptTokens: this.promptTokens, + completionTokens: this.completionTokens, + totalTokens: this.totalTokens, + costUsd: this.costUsd, + }; + } +} diff --git a/packages/@n8n/instance-ai/src/tools/__tests__/credentials.tool.test.ts b/packages/@n8n/instance-ai/src/tools/__tests__/credentials.tool.test.ts index 71161aac0a5..a592449427b 100644 --- a/packages/@n8n/instance-ai/src/tools/__tests__/credentials.tool.test.ts +++ b/packages/@n8n/instance-ai/src/tools/__tests__/credentials.tool.test.ts @@ -649,8 +649,8 @@ describe('credentials tool', () => { ); }); - it('should include projectId in suspend payload when provided', async () => { - const context = createMockContext(); + it("should include the thread's project in the suspend payload", async () => { + const context = createMockContext({ projectId: 'proj-1' }); (context.credentialService.list as Mock).mockResolvedValue([]); const suspendFn = vi.fn(); @@ -660,7 +660,6 @@ describe('credentials tool', () => { { action: 'setup' as const, credentials: [{ credentialType: 'slackApi' }], - projectId: 'proj-1', }, suspendCtx(suspendFn), ); @@ -669,8 +668,8 @@ describe('credentials tool', () => { expect(suspendFn.mock.calls[0][0]).toEqual(expect.objectContaining({ projectId: 'proj-1' })); }); - it('should scope credential lookup to projectId when provided', async () => { - const context = createMockContext(); + it("should scope the credential lookup to the thread's project", async () => { + const context = createMockContext({ projectId: 'proj-1' }); (context.credentialService.list as Mock).mockResolvedValue([]); const tool = createCredentialsTool(context); @@ -678,7 +677,6 @@ describe('credentials tool', () => { { action: 'setup' as const, credentials: [{ credentialType: 'slackApi' }], - projectId: 'proj-1', }, suspendCtx(vi.fn()), ); diff --git a/packages/@n8n/instance-ai/src/tools/__tests__/index.test.ts b/packages/@n8n/instance-ai/src/tools/__tests__/index.test.ts index 64f44369210..d85d9d0ac89 100644 --- a/packages/@n8n/instance-ai/src/tools/__tests__/index.test.ts +++ b/packages/@n8n/instance-ai/src/tools/__tests__/index.test.ts @@ -1,4 +1,4 @@ -import { createAllTools, createOrchestratorDomainTools } from '..'; +import { createAllTools, createOrchestrationTools, createOrchestratorDomainTools } from '..'; import { isParseableAttachment } from '../../parsers/structured-file-parser'; import type { InstanceAiContext } from '../../types'; @@ -52,10 +52,6 @@ vi.mock('../orchestration/eval-data-agent.tool', () => ({ createEvalDataAgentTool: vi.fn(() => ({ id: 'eval-data' })), })); -vi.mock('../orchestration/plan-with-agent.tool', () => ({ - createPlanWithAgentTool: vi.fn(() => ({ id: 'plan' })), -})); - vi.mock('../orchestration/plan.tool', () => ({ createPlanTool: vi.fn(() => ({ id: 'create-tasks' })), })); @@ -187,4 +183,16 @@ describe('domain tool construction', () => { id: 'parse-file', }); }); + + it('registers create-tasks but not the removed plan orchestration tool', () => { + const context = makeContext({ + workflowTaskService: {}, + domainContext: {}, + } as Partial); + + const orchestrationTools = createOrchestrationTools(context as never); + + expect(orchestrationTools.has('create-tasks')).toBe(true); + expect(orchestrationTools.has('plan')).toBe(false); + }); }); diff --git a/packages/@n8n/instance-ai/src/tools/attachments/__tests__/parse-file.tool.test.ts b/packages/@n8n/instance-ai/src/tools/attachments/__tests__/parse-file.tool.test.ts index 48ccf9c05b2..c725ad69ba2 100644 --- a/packages/@n8n/instance-ai/src/tools/attachments/__tests__/parse-file.tool.test.ts +++ b/packages/@n8n/instance-ai/src/tools/attachments/__tests__/parse-file.tool.test.ts @@ -62,6 +62,7 @@ function createMockContext(overrides?: Partial): InstanceAiCo updateRows: vi.fn(), deleteRows: vi.fn(), }, + logger: { info: vi.fn(), warn: vi.fn(), error: vi.fn(), debug: vi.fn() } as never, ...overrides, }; } diff --git a/packages/@n8n/instance-ai/src/tools/attachments/parse-file.tool.ts b/packages/@n8n/instance-ai/src/tools/attachments/parse-file.tool.ts index 59fc07e2e31..8836425c761 100644 --- a/packages/@n8n/instance-ai/src/tools/attachments/parse-file.tool.ts +++ b/packages/@n8n/instance-ai/src/tools/attachments/parse-file.tool.ts @@ -156,7 +156,7 @@ function extractPlainTextContent(attachment: AttachmentInfo) { export function createParseFileTool(context: InstanceAiContext) { return new Tool('parse-file') .description( - 'Parse a file attachment from the current message. ' + + 'Parse parseable user attachments from the current message. ' + 'For CSV, TSV, JSON, and XLSX, returns column metadata (with normalized names and inferred types) and paginated rows. ' + 'For text, Markdown, HTML, PDF, and DOCX, returns extracted content. ' + 'Use nextStartRow to page through large tabular files. ' + diff --git a/packages/@n8n/instance-ai/src/tools/credentials.tool.ts b/packages/@n8n/instance-ai/src/tools/credentials.tool.ts index e4dc19fc636..f8065094028 100644 --- a/packages/@n8n/instance-ai/src/tools/credentials.tool.ts +++ b/packages/@n8n/instance-ai/src/tools/credentials.tool.ts @@ -105,10 +105,6 @@ const setupAction = z.object({ }), ) .describe('List of credentials to set up'), - projectId: z - .string() - .optional() - .describe('Project ID to scope credential creation to. Defaults to personal project.'), credentialFlow: z .object({ stage: z.enum(['generic', 'finalize']), @@ -217,8 +213,12 @@ function formatActionList(actions: readonly CredentialAction[]): string { function getToolDescription(options: CredentialsToolOptions): string { const actionList = formatActionList(getCredentialActions(options)); const description = `${options.descriptionPrefix ?? 'Manage credentials'} — ${actionList}.`; + const builderSuffix = + 'Use list, get, search-types, and test for credential metadata and connection checks during workflow building.'; - return options.descriptionSuffix ? `${description} ${options.descriptionSuffix}` : description; + return options.descriptionSuffix + ? `${description} ${options.descriptionSuffix}` + : `${description} ${builderSuffix}`; } // ── Suspend / resume schemas (superset covering delete + setup) ──────────── @@ -358,7 +358,7 @@ async function handleSetup( async (req: { credentialType: string; reason?: string; suggestedName?: string }) => { const existing = await context.credentialService.list({ type: req.credentialType, - ...(input.projectId ? { projectId: input.projectId } : {}), + ...(context.projectId ? { projectId: context.projectId } : {}), }); return { credentialType: req.credentialType, @@ -382,7 +382,7 @@ async function handleSetup( : `Select or create credentials: ${typeNames}`, severity: 'info' as const, credentialRequests, - ...(input.projectId ? { projectId: input.projectId } : {}), + ...(context.projectId ? { projectId: context.projectId } : {}), ...(input.credentialFlow ? { credentialFlow: input.credentialFlow } : {}), }); } diff --git a/packages/@n8n/instance-ai/src/tools/data-tables.tool.ts b/packages/@n8n/instance-ai/src/tools/data-tables.tool.ts index cd24b27dc10..89e82f429af 100644 --- a/packages/@n8n/instance-ai/src/tools/data-tables.tool.ts +++ b/packages/@n8n/instance-ai/src/tools/data-tables.tool.ts @@ -93,7 +93,11 @@ const listAction = z.object({ }); const schemaAction = z.object({ - action: z.literal('schema').describe('Get column definitions for a data table'), + action: z + .literal('schema') + .describe( + 'Get column definitions for a data table. Call before using a table in workflow code — column names are normalized to snake_case.', + ), dataTableId: z .string() .describe( @@ -631,7 +635,10 @@ export function createDataTablesTool(context: InstanceAiContext) { const inputSchema = sanitizeInputSchema(z.discriminatedUnion('action', [...allActions])); return new Tool(DATA_TABLES_TOOL_ID) - .description('Manage data tables — list, query, create, modify columns, and manage rows.') + .description( + 'Manage data tables — list, query, create, modify columns, and manage rows. ' + + 'For workflow building, use list, create, and schema before referencing tables in SDK code.', + ) .input(inputSchema) .suspend(confirmationSuspendSchema) .resume(confirmationResumeSchema) diff --git a/packages/@n8n/instance-ai/src/tools/evals/__tests__/extract-rows-from-history.service.test.ts b/packages/@n8n/instance-ai/src/tools/evals/__tests__/extract-rows-from-history.service.test.ts index 51c4ffb4b08..136974337b2 100644 --- a/packages/@n8n/instance-ai/src/tools/evals/__tests__/extract-rows-from-history.service.test.ts +++ b/packages/@n8n/instance-ai/src/tools/evals/__tests__/extract-rows-from-history.service.test.ts @@ -23,6 +23,7 @@ const buildContext = ( >(), ...executionService, }, + logger: { info: vi.fn(), warn: vi.fn(), error: vi.fn(), debug: vi.fn() }, }) as unknown as InstanceAiContext; const executionSummary = ( diff --git a/packages/@n8n/instance-ai/src/tools/evals/__tests__/generate-sample-rows.service.test.ts b/packages/@n8n/instance-ai/src/tools/evals/__tests__/generate-sample-rows.service.test.ts index f00ab937d70..17ab71e42a6 100644 --- a/packages/@n8n/instance-ai/src/tools/evals/__tests__/generate-sample-rows.service.test.ts +++ b/packages/@n8n/instance-ai/src/tools/evals/__tests__/generate-sample-rows.service.test.ts @@ -29,26 +29,32 @@ function setupAgentMock(responseText: string) { mockExtractText.mockReturnValue(responseText); } -type GenerateMock = Mock<(...args: [string]) => Promise<{ messages: [] }>>; +type GenerateArg = Array<{ content: Array<{ text: string }> }>; +type GenerateMock = Mock<(...args: [GenerateArg]) => Promise<{ messages: [] }>>; function createGenerateMock(): GenerateMock { - return vi.fn<(arg: string) => Promise<{ messages: [] }>>().mockResolvedValue({ messages: [] }); + return vi + .fn<(arg: GenerateArg) => Promise<{ messages: [] }>>() + .mockResolvedValue({ messages: [] }); } function getPromptText(generate: GenerateMock): string { const firstCall = generate.mock.calls[0]; if (!firstCall) throw new Error('Expected generate to be called'); - return firstCall[0]; + return firstCall[0][0].content[0].text; } const WF: WorkflowJSON = { name: 'Test', nodes: [], connections: {} } as unknown as WorkflowJSON; +const mockLogger = { warn: vi.fn() }; + describe('generateSampleRows', () => { beforeEach(() => vi.clearAllMocks()); it('returns parsed input rows from valid JSON across batches', async () => { setupAgentMock(JSON.stringify([{ input: 'q1' }])); const rows = await generateSampleRows({ + logger: mockLogger, workflow: WF, columns: ['input', 'expected_output'], rowCount: 5, @@ -60,6 +66,7 @@ describe('generateSampleRows', () => { it('coerces non-string cell values to strings', async () => { setupAgentMock(JSON.stringify([{ input: 42, expected_output: true }])); const rows = await generateSampleRows({ + logger: mockLogger, workflow: WF, columns: ['input', 'expected_output'], rowCount: 5, @@ -70,6 +77,7 @@ describe('generateSampleRows', () => { it('fills missing columns with empty strings', async () => { setupAgentMock(JSON.stringify([{ input: 'q1' }])); const rows = await generateSampleRows({ + logger: mockLogger, workflow: WF, columns: ['input', 'expected_output'], rowCount: 5, @@ -80,6 +88,7 @@ describe('generateSampleRows', () => { it('returns single fallback row when every batch fails to parse', async () => { setupAgentMock('not json'); const rows = await generateSampleRows({ + logger: mockLogger, workflow: WF, columns: ['input', 'expected_output'], rowCount: 5, @@ -93,6 +102,7 @@ describe('generateSampleRows', () => { typeof createEvalAgent >); const rows = await generateSampleRows({ + logger: mockLogger, workflow: WF, columns: ['input', 'expected_output'], rowCount: 5, @@ -141,6 +151,7 @@ describe('runBatch', () => { it('returns parsed input rows on success', async () => { setupAgentMock(JSON.stringify([{ input: 'q1' }])); const rows = await runBatch({ + logger: mockLogger, facet: BATCH_FACET, rowCount: 1, context: BATCH_CONTEXT, @@ -152,6 +163,7 @@ describe('runBatch', () => { it('caps over-generated rows to the requested batch size', async () => { setupAgentMock(JSON.stringify([{ input: 'q1' }, { input: 'q2' }, { input: 'q3' }])); const rows = await runBatch({ + logger: mockLogger, facet: BATCH_FACET, rowCount: 2, context: BATCH_CONTEXT, @@ -168,6 +180,7 @@ describe('runBatch', () => { mockExtractText.mockReturnValue(JSON.stringify([{ input: 'q1' }])); await runBatch({ + logger: mockLogger, facet: BATCH_FACET, rowCount: 1, context: BATCH_CONTEXT, @@ -185,6 +198,7 @@ describe('runBatch', () => { typeof createEvalAgent >); const rows = await runBatch({ + logger: mockLogger, facet: BATCH_FACET, rowCount: 1, context: BATCH_CONTEXT, @@ -207,13 +221,13 @@ describe('runBatch', () => { expect(logger.warn).toHaveBeenCalledTimes(1); const [message, metadata] = logger.warn.mock.calls[0]; expect(message).toBe('generate-sample-rows: batch generation failed'); - expect(metadata).toEqual(expect.objectContaining({ rowCount: 1 })); - expect(metadata?.error).toBeInstanceOf(SyntaxError); + expect(metadata).toEqual(expect.objectContaining({ rowCount: 1, reason: 'invalid_json' })); }); it('returns empty array when JSON is malformed', async () => { setupAgentMock('not json'); const rows = await runBatch({ + logger: mockLogger, facet: BATCH_FACET, rowCount: 1, context: BATCH_CONTEXT, @@ -225,6 +239,7 @@ describe('runBatch', () => { it('returns empty array when schema validation fails', async () => { setupAgentMock(JSON.stringify({ not: 'an array' })); const rows = await runBatch({ + logger: mockLogger, facet: BATCH_FACET, rowCount: 1, context: BATCH_CONTEXT, @@ -236,6 +251,7 @@ describe('runBatch', () => { it('strips markdown fences from the response', async () => { setupAgentMock('```json\n[{"input":"q","expected_output":"a"}]\n```'); const rows = await runBatch({ + logger: mockLogger, facet: BATCH_FACET, rowCount: 1, context: BATCH_CONTEXT, @@ -251,6 +267,7 @@ describe('runBatch', () => { >); mockExtractText.mockReturnValue(JSON.stringify([])); await runBatch({ + logger: mockLogger, facet: BATCH_FACET, rowCount: 7, context: BATCH_CONTEXT, @@ -268,6 +285,7 @@ describe('runBatch', () => { typeof createEvalAgent >); const rows = await runBatch({ + logger: mockLogger, facet: BATCH_FACET, rowCount: 0, context: BATCH_CONTEXT, @@ -289,6 +307,7 @@ describe('runBatch', () => { >); mockExtractText.mockReturnValue(JSON.stringify([])); await runBatch({ + logger: mockLogger, facet: BATCH_FACET, rowCount: 1, context: BATCH_CONTEXT, @@ -309,6 +328,7 @@ describe('runBatch', () => { >); mockExtractText.mockReturnValue(JSON.stringify([])); await runBatch({ + logger: mockLogger, facet: BATCH_FACET, rowCount: 1, context: BATCH_CONTEXT, @@ -324,6 +344,7 @@ describe('runBatch', () => { >); mockExtractText.mockReturnValue(JSON.stringify([])); await runBatch({ + logger: mockLogger, facet: BATCH_FACET, rowCount: 1, context: BATCH_CONTEXT, @@ -348,6 +369,7 @@ describe('runBatch', () => { mockExtractText.mockReturnValue(JSON.stringify([])); const examples = Array.from({ length: 13 }, (_, i) => ({ user_query: `q${i}` })); await runBatch({ + logger: mockLogger, facet: BATCH_FACET, rowCount: 1, context: BATCH_CONTEXT, @@ -369,6 +391,7 @@ describe('runBatch', () => { mockExtractText.mockReturnValue(JSON.stringify([])); const longValue = 'x'.repeat(500); await runBatch({ + logger: mockLogger, facet: BATCH_FACET, rowCount: 1, context: BATCH_CONTEXT, @@ -479,7 +502,12 @@ describe('generateSampleRows orchestration', () => { typeof createEvalAgent >); mockExtractText.mockReturnValue(JSON.stringify([{ input: 'r' }])); - await generateSampleRows({ workflow: WF, columns: ['input'], rowCount: 25 }); + await generateSampleRows({ + logger: mockLogger, + workflow: WF, + columns: ['input'], + rowCount: 25, + }); expect(generate).toHaveBeenCalledTimes(5); }); @@ -489,7 +517,7 @@ describe('generateSampleRows orchestration', () => { typeof createEvalAgent >); mockExtractText.mockReturnValue(JSON.stringify([{ input: 'r' }])); - await generateSampleRows({ workflow: WF, columns: ['input'], rowCount: 3 }); + await generateSampleRows({ logger: mockLogger, workflow: WF, columns: ['input'], rowCount: 3 }); expect(generate).toHaveBeenCalledTimes(3); }); @@ -511,6 +539,7 @@ describe('generateSampleRows orchestration', () => { .mockReturnValueOnce(JSON.stringify([{ input: 'd' }])) .mockReturnValueOnce(JSON.stringify([{ input: 'e' }])); const rows = await generateSampleRows({ + logger: mockLogger, workflow: WF, columns: ['input'], rowCount: 5, @@ -527,7 +556,7 @@ describe('generateSampleRows orchestration', () => { mockExtractText.mockReturnValue( JSON.stringify(Array.from({ length: 5 }, () => ({ input: 'x' }))), ); - const rows = await generateSampleRows({ workflow: WF, columns: ['input'] }); + const rows = await generateSampleRows({ logger: mockLogger, workflow: WF, columns: ['input'] }); expect(rows).toHaveLength(25); }); @@ -552,6 +581,7 @@ describe('generateSampleRows orchestration', () => { >); mockExtractText.mockReturnValue(JSON.stringify([])); await generateSampleRows({ + logger: mockLogger, workflow: wf, columns: ['input'], rowCount: 5, @@ -589,7 +619,7 @@ describe('generateSampleRows orchestration', () => { typeof createEvalAgent >); mockExtractText.mockReturnValue(JSON.stringify([])); - await generateSampleRows({ workflow: wf, columns: ['input'], rowCount: 5 }); + await generateSampleRows({ logger: mockLogger, workflow: wf, columns: ['input'], rowCount: 5 }); const promptText = getPromptText(generate); expect(promptText).toContain('FIRST-AGENT-SYSTEM'); expect(promptText).not.toContain('SECOND-AGENT-SYSTEM'); diff --git a/packages/@n8n/instance-ai/src/tools/evals/extract-rows-from-history.service.ts b/packages/@n8n/instance-ai/src/tools/evals/extract-rows-from-history.service.ts index d5e7568cc16..991b69f3374 100644 --- a/packages/@n8n/instance-ai/src/tools/evals/extract-rows-from-history.service.ts +++ b/packages/@n8n/instance-ai/src/tools/evals/extract-rows-from-history.service.ts @@ -107,7 +107,7 @@ export async function extractRowsFromExecutionHistory( }); } } catch (error) { - ctx.logger?.warn('extract-rows: getNodeOutput failed', { + ctx.logger.warn('extract-rows: getNodeOutput failed', { executionId: summary.id, error, }); diff --git a/packages/@n8n/instance-ai/src/tools/evals/generate-sample-rows.service.ts b/packages/@n8n/instance-ai/src/tools/evals/generate-sample-rows.service.ts index defd195bf5c..21ede9d7be5 100644 --- a/packages/@n8n/instance-ai/src/tools/evals/generate-sample-rows.service.ts +++ b/packages/@n8n/instance-ai/src/tools/evals/generate-sample-rows.service.ts @@ -4,7 +4,8 @@ import { z } from 'zod'; import { isRecord } from './column-ref-utils'; import { detectAiNodes } from './detect-ai-nodes'; import type { Logger } from '../../logger'; -import { createEvalAgent, extractText, HAIKU_MODEL } from '../../utils/eval-agents'; +import { HAIKU_MODEL } from '../../utils/eval-agents'; +import { generateValidatedJson } from '../../utils/generate-validated-json'; const FACET_COUNT = 5; const DEFAULT_ROW_COUNT = 25; @@ -207,7 +208,7 @@ export interface RunBatchInput { context: AgentContext | undefined; columns: string[]; realExamples?: ReadonlyArray>; - logger?: Pick; + logger: Pick; } function normalizeBatchRow( @@ -228,61 +229,44 @@ function normalizeBatchRow( return row; } -function stripMarkdownFences(text: string): string { - const trimmed = text.trim(); - const fencedMatch = /^```(?:json)?\s*([\s\S]*?)\s*```$/i.exec(trimmed); - return fencedMatch ? fencedMatch[1].trim() : trimmed; -} - export async function runBatch(input: RunBatchInput): Promise>> { const requestedRowCount = Math.max(0, Math.floor(input.rowCount)); if (requestedRowCount <= 0) return []; - try { - const generatedColumns = input.columns.filter((column) => !isExpectedOutputColumn(column)); - const agent = createEvalAgent('eval-sample-rows', { - model: HAIKU_MODEL, - instructions: BATCH_SYSTEM_INSTRUCTIONS, - }); - const realExamplesBlock = buildRealExamplesBlock(input.realExamples, generatedColumns); - const sections = [buildAgentContextBlock(input.context)]; - if (realExamplesBlock) sections.push(realExamplesBlock); - sections.push(FORMAT_INFERENCE); - sections.push( - [ - `Variation focus for this batch: length = ${input.facet.length}; mode = ${input.facet.edgeMode}.`, - input.facet.instructions, - ].join('\n'), - ); - sections.push( - [ - `Columns: ${generatedColumns.join(', ')}`, - `Generate exactly ${requestedRowCount} rows.`, - ].join('\n'), - ); - const userText = sections.join('\n\n'); - const result = await agent.generate(userText); - const text = extractText(result); - const parsed: unknown = JSON.parse(stripMarkdownFences(text)); - const validated = batchRowSchema.safeParse(parsed); - if (!validated.success) { - input.logger?.warn('generate-sample-rows: invalid batch rows returned', { - rowCount: requestedRowCount, - facet: input.facet.edgeMode, - issues: validated.error.issues, - }); - return []; - } - return validated.data - .slice(0, requestedRowCount) - .map((rawRow) => normalizeBatchRow(rawRow, input.columns)); - } catch (error) { - input.logger?.warn('generate-sample-rows: batch generation failed', { + const generatedColumns = input.columns.filter((column) => !isExpectedOutputColumn(column)); + const realExamplesBlock = buildRealExamplesBlock(input.realExamples, generatedColumns); + const sections = [buildAgentContextBlock(input.context)]; + if (realExamplesBlock) sections.push(realExamplesBlock); + sections.push(FORMAT_INFERENCE); + sections.push( + [ + `Variation focus for this batch: length = ${input.facet.length}; mode = ${input.facet.edgeMode}.`, + input.facet.instructions, + ].join('\n'), + ); + sections.push( + [`Columns: ${generatedColumns.join(', ')}`, `Generate exactly ${requestedRowCount} rows.`].join( + '\n', + ), + ); + + const result = await generateValidatedJson('eval-sample-rows', { + model: HAIKU_MODEL, + instructions: BATCH_SYSTEM_INSTRUCTIONS, + userText: sections.join('\n\n'), + schema: batchRowSchema, + }); + if (!result.ok) { + input.logger.warn('generate-sample-rows: batch generation failed', { rowCount: requestedRowCount, facet: input.facet.edgeMode, - error, + reason: result.reason, + issues: result.issues, }); return []; } + return result.data + .slice(0, requestedRowCount) + .map((rawRow) => normalizeBatchRow(rawRow, input.columns)); } export interface GenerateSampleRowsInput { @@ -299,7 +283,7 @@ export interface GenerateSampleRowsInput { * generator produces new in-domain inputs instead of paraphrasing them. */ realExamples?: ReadonlyArray>; - logger?: Pick; + logger: Pick; } function resolveAgentContext( diff --git a/packages/@n8n/instance-ai/src/tools/evals/generate-tool-ref-pin-data.service.ts b/packages/@n8n/instance-ai/src/tools/evals/generate-tool-ref-pin-data.service.ts index f8f4713844c..a270589fd8c 100644 --- a/packages/@n8n/instance-ai/src/tools/evals/generate-tool-ref-pin-data.service.ts +++ b/packages/@n8n/instance-ai/src/tools/evals/generate-tool-ref-pin-data.service.ts @@ -3,7 +3,8 @@ import { z } from 'zod'; import { nodeHasName } from './column-ref-utils'; import type { ToolRef } from './detect-tool-refs.service'; -import { createEvalAgent, extractText, HAIKU_MODEL } from '../../utils/eval-agents'; +import { HAIKU_MODEL } from '../../utils/eval-agents'; +import { generateValidatedJson } from '../../utils/generate-validated-json'; export type ToolRefPinData = Record }>>; @@ -100,12 +101,6 @@ function buildUserMessage(contexts: NodeContext[], agentPurpose: string | undefi ].join('\n'); } -function stripMarkdownFences(text: string): string { - const trimmed = text.trim(); - const fencedMatch = /^```(?:json)?\s*([\s\S]*?)\s*```$/i.exec(trimmed); - return fencedMatch ? fencedMatch[1].trim() : trimmed; -} - function filterToRequested(parsed: ToolRefPinData, requested: Set): ToolRefPinData { const out: ToolRefPinData = {}; for (const [name, items] of Object.entries(parsed)) { @@ -128,21 +123,13 @@ export async function generateToolRefPinData( const agentPurpose = readAgentPurpose(agent); const userText = buildUserMessage(contexts, agentPurpose); - try { - const llm = createEvalAgent('eval-tool-ref-pin-data', { - model: HAIKU_MODEL, - instructions: SYSTEM_INSTRUCTIONS, - }); - const result = await llm.generate([ - { role: 'user' as const, content: [{ type: 'text' as const, text: userText }] }, - ]); - const text = extractText(result); - const parsed: unknown = JSON.parse(stripMarkdownFences(text)); - const validated = PinDataResponseSchema.safeParse(parsed); - if (!validated.success) return {}; - const requested = new Set(contexts.map((c) => c.name)); - return filterToRequested(validated.data, requested); - } catch { - return {}; - } + const result = await generateValidatedJson('eval-tool-ref-pin-data', { + model: HAIKU_MODEL, + instructions: SYSTEM_INSTRUCTIONS, + userText, + schema: PinDataResponseSchema, + }); + if (!result.ok) return {}; + const requested = new Set(contexts.map((c) => c.name)); + return filterToRequested(result.data, requested); } diff --git a/packages/@n8n/instance-ai/src/tools/executions.tool.ts b/packages/@n8n/instance-ai/src/tools/executions.tool.ts index 9540dae56d9..402218a86fa 100644 --- a/packages/@n8n/instance-ai/src/tools/executions.tool.ts +++ b/packages/@n8n/instance-ai/src/tools/executions.tool.ts @@ -310,7 +310,8 @@ export function createExecutionsTool(context: InstanceAiContext) { return new Tool('executions') .description( 'Manage workflow executions — list, inspect, run, debug, get node output, ' + - 'get resolved node parameters for a past run, and stop.', + 'get resolved node parameters for a past run, and stop. ' + + 'Use action="run" for verification when the current turn is responsible for verification; prefer verify-built-workflow for standard post-build verification.', ) .input(inputSchema) .suspend(suspendSchema) diff --git a/packages/@n8n/instance-ai/src/tools/filesystem/__tests__/create-tools-from-mcp-server.test.ts b/packages/@n8n/instance-ai/src/tools/filesystem/__tests__/create-tools-from-mcp-server.test.ts index 7844d2d4fa1..26daee637c1 100644 --- a/packages/@n8n/instance-ai/src/tools/filesystem/__tests__/create-tools-from-mcp-server.test.ts +++ b/packages/@n8n/instance-ai/src/tools/filesystem/__tests__/create-tools-from-mcp-server.test.ts @@ -6,6 +6,8 @@ import { executeTool } from '../../../__tests__/tool-test-utils'; import type { LocalMcpServer } from '../../../types'; import { createToolsFromLocalMcpServer } from '../create-tools-from-mcp-server'; +const mockLogger = { info: vi.fn(), warn: vi.fn(), error: vi.fn(), debug: vi.fn() } as never; + // --------------------------------------------------------------------------- // Fixtures // --------------------------------------------------------------------------- @@ -73,6 +75,19 @@ const SCREENSHOT_RESULT: McpToolCallResult = { ], }; +const PDF_RESULT: McpToolCallResult = { + content: [ + { + type: 'resource', + resource: { + uri: 'file:///doc.pdf', + mimeType: 'application/pdf', + blob: 'base64-pdf', + }, + }, + ], +}; + const GENERIC_ERROR_RESULT: McpToolCallResult = { content: [{ type: 'text', text: 'Permission denied' }], isError: true, @@ -92,7 +107,7 @@ function makeMockServer(tools: McpTool[] = [SAMPLE_TOOL]): Mocked, ctx: unknown) => @@ -115,7 +130,7 @@ describe('createToolsFromLocalMcpServer', () => { describe('tool creation', () => { it('creates a tool for each advertised tool', () => { const server = makeMockServer([SAMPLE_TOOL, { ...SAMPLE_TOOL, name: 'read_file' }]); - const tools = createToolsFromLocalMcpServer(server); + const tools = createToolsFromLocalMcpServer(server, mockLogger); expect(tools.has('write_file')).toBe(true); expect(tools.has('read_file')).toBe(true); }); @@ -129,8 +144,8 @@ describe('createToolsFromLocalMcpServer', () => { }, ]); // Should not throw — the tool must be created even with a bad schema - expect(() => createToolsFromLocalMcpServer(server)).not.toThrow(); - expect(createToolsFromLocalMcpServer(server).get('bad_tool')).toBeDefined(); + expect(() => createToolsFromLocalMcpServer(server, mockLogger)).not.toThrow(); + expect(createToolsFromLocalMcpServer(server, mockLogger).get('bad_tool')).toBeDefined(); }); it('skips tools with invalid names', () => { @@ -245,7 +260,7 @@ describe('createToolsFromLocalMcpServer', () => { describe('media output', () => { it('returns native file parts from toMessage for gateway image results', () => { const server = makeMockServer(); - const tool = createToolsFromLocalMcpServer(server).get('write_file'); + const tool = createToolsFromLocalMcpServer(server, mockLogger).get('write_file'); const message = tool?.toMessage?.(SCREENSHOT_RESULT); @@ -260,14 +275,14 @@ describe('createToolsFromLocalMcpServer', () => { it('does not create an extra message for text-only results', () => { const server = makeMockServer(); - const tool = createToolsFromLocalMcpServer(server).get('write_file'); + const tool = createToolsFromLocalMcpServer(server, mockLogger).get('write_file'); expect(tool?.toMessage?.(SUCCESS_RESULT)).toBeUndefined(); }); it('returns AI SDK content output for gateway image results', () => { const server = makeMockServer(); - const tool = createToolsFromLocalMcpServer(server).get('write_file'); + const tool = createToolsFromLocalMcpServer(server, mockLogger).get('write_file'); expect(tool?.toModelOutput?.(SCREENSHOT_RESULT)).toEqual({ type: 'content', @@ -277,6 +292,40 @@ describe('createToolsFromLocalMcpServer', () => { ], }); }); + + it('returns a native file part from toMessage for gateway resource results', () => { + const server = makeMockServer(); + const tool = createToolsFromLocalMcpServer(server, mockLogger).get('write_file'); + + expect(tool?.toMessage?.(PDF_RESULT)).toEqual({ + role: 'assistant', + content: [{ type: 'file', data: 'base64-pdf', mediaType: 'application/pdf' }], + }); + }); + + it('falls back to application/octet-stream when resource has no mimeType', () => { + const server = makeMockServer(); + const tool = createToolsFromLocalMcpServer(server, mockLogger).get('write_file'); + + const result: McpToolCallResult = { + content: [{ type: 'resource', resource: { uri: 'file:///x', blob: 'base64-bytes' } }], + }; + + expect(tool?.toMessage?.(result)).toEqual({ + role: 'assistant', + content: [{ type: 'file', data: 'base64-bytes', mediaType: 'application/octet-stream' }], + }); + }); + + it('returns AI SDK content output for gateway resource results', () => { + const server = makeMockServer(); + const tool = createToolsFromLocalMcpServer(server, mockLogger).get('write_file'); + + expect(tool?.toModelOutput?.(PDF_RESULT)).toEqual({ + type: 'content', + value: [{ type: 'file-data', data: 'base64-pdf', mediaType: 'application/pdf' }], + }); + }); }); describe('execute — first-call path', () => { diff --git a/packages/@n8n/instance-ai/src/tools/filesystem/create-tools-from-mcp-server.ts b/packages/@n8n/instance-ai/src/tools/filesystem/create-tools-from-mcp-server.ts index cfbadb60840..246aac01ca9 100644 --- a/packages/@n8n/instance-ai/src/tools/filesystem/create-tools-from-mcp-server.ts +++ b/packages/@n8n/instance-ai/src/tools/filesystem/create-tools-from-mcp-server.ts @@ -46,7 +46,8 @@ import type { InstanceAiToolRegistry, LocalMcpServer } from '../../types'; type McpContentBlock = McpToolCallResult['content'][number]; type ModelContentPart = | { type: 'text'; text: string } - | { type: 'image-data'; data: string; mediaType: string }; + | { type: 'image-data'; data: string; mediaType: string } + | { type: 'file-data'; data: string; mediaType: string }; // --------------------------------------------------------------------------- // Schemas shared across all gateway-gated tools @@ -92,6 +93,10 @@ function isMcpContentBlock(value: unknown): value is McpContentBlock { if (value.type === 'image') { return typeof value.data === 'string' && typeof value.mimeType === 'string'; } + if (value.type === 'resource') { + if (!isRecord(value.resource)) return false; + return typeof value.resource.uri === 'string' && typeof value.resource.blob === 'string'; + } return false; } @@ -162,6 +167,14 @@ function mcpBlockToMessagePart(block: McpContentBlock): ContentText | ContentFil }; } + if (block.type === 'resource' && block.resource.blob) { + return { + type: 'file', + data: block.resource.blob, + mediaType: block.resource.mimeType ?? 'application/octet-stream', + }; + } + return undefined; } @@ -178,12 +191,24 @@ function mcpBlockToModelContentPart(block: McpContentBlock): ModelContentPart | }; } + if (block.type === 'resource' && block.resource.blob) { + return { + type: 'file-data', + data: block.resource.blob, + mediaType: block.resource.mimeType ?? 'application/octet-stream', + }; + } + return undefined; } +function isMcpMediaBlock(block: McpContentBlock): boolean { + return block.type === 'image' || block.type === 'resource'; +} + function buildNativeMcpMediaMessage(result: unknown): AgentMessage | undefined { const raw = unwrapMcpToolResult(result); - if (!raw?.content.some((item) => item.type === 'image')) return undefined; + if (!raw?.content.some(isMcpMediaBlock)) return undefined; const content = raw.content .map(mcpBlockToMessagePart) @@ -199,9 +224,9 @@ function buildNativeMcpMediaMessage(result: unknown): AgentMessage | undefined { const LOCAL_GATEWAY_MCP_SOURCE = 'local gateway MCP'; -function warnSkippedLocalMcpSchema(logger: Logger | undefined) { +function warnSkippedLocalMcpSchema(logger: Logger) { return (error: McpSchemaSanitizationError) => { - logger?.warn('Skipped local gateway MCP tool with unsupported schema', { + logger.warn('Skipped local gateway MCP tool with unsupported schema', { toolName: error.details.toolName, source: LOCAL_GATEWAY_MCP_SOURCE, path: error.details.path, @@ -214,9 +239,9 @@ function warnSkippedLocalMcpSchema(logger: Logger | undefined) { }; } -function warnSkippedLocalMcpTool(logger: Logger | undefined) { +function warnSkippedLocalMcpTool(logger: Logger) { return (error: McpToolNameValidationError) => { - logger?.warn('Skipped local gateway MCP tool with unsafe name', { + logger.warn('Skipped local gateway MCP tool with unsafe name', { toolName: error.toolName, source: error.source, reason: error.message, @@ -243,7 +268,7 @@ function warnSkippedLocalMcpTool(logger: Logger | undefined) { */ export function createToolsFromLocalMcpServer( server: LocalMcpServer, - logger?: Logger, + logger: Logger, ): InstanceAiToolRegistry { const tools = createToolRegistry(); const claimedToolNames = createClaimedToolNames([]); @@ -282,10 +307,9 @@ export function createToolsFromLocalMcpServer( try { if (toolName === 'browser_create_credential') { // when converting json schema the `inputSchema` has the correct shape and parsed to correct output - // but during execution all unspecified key from `data` and `resolveData` are stripped. - // somewhere in mastra core the inputSchema is converted multiple times back and forth and - // gets transformed to jsonSchema with `additionalProperties=false` - // this does not happen when passing the schema directly + // but during execution all unspecified keys from `data` and `resolveData` are stripped, + // because the schema is converted back and forth and transformed to jsonSchema with + // `additionalProperties=false`. Passing the schema directly avoids this. inputSchema = loadMcpBrowserCredential().browserCreateCredentialSchema; } else { // Convert JSON Schema → Zod (v3) so the LLM sees the actual parameter shapes. diff --git a/packages/@n8n/instance-ai/src/tools/index.ts b/packages/@n8n/instance-ai/src/tools/index.ts index 7f73eed4f1a..3ca01c62491 100644 --- a/packages/@n8n/instance-ai/src/tools/index.ts +++ b/packages/@n8n/instance-ai/src/tools/index.ts @@ -42,10 +42,6 @@ const loadEvalSetupAgentTool = lazyMod( () => require('./orchestration/eval-setup-agent.tool') as typeof import('./orchestration/eval-setup-agent.tool'), ); -const loadPlanWithAgentTool = lazyMod( - () => - require('./orchestration/plan-with-agent.tool') as typeof import('./orchestration/plan-with-agent.tool'), -); const loadPlanTool = lazyMod( () => require('./orchestration/plan.tool') as typeof import('./orchestration/plan.tool'), ); @@ -133,12 +129,11 @@ export function createOrchestratorDomainTools(context: InstanceAiContext): Insta } /** - * Creates orchestration-only tools (planner, delegation, task control). + * Creates orchestration-only tools (task planning, delegation, task control). * These tools are given to the orchestrator agent but never to sub-agents. */ export function createOrchestrationTools(context: OrchestrationContext): InstanceAiToolRegistry { const tools: Array<[string, BuiltTool]> = [ - [ORCHESTRATION_TOOL_IDS.PLAN, loadPlanWithAgentTool().createPlanWithAgentTool(context)], [ORCHESTRATION_TOOL_IDS.CREATE_TASKS, loadPlanTool().createPlanTool(context)], [ORCHESTRATION_TOOL_IDS.TASK_CONTROL, loadTaskControlTool().createTaskControlTool(context)], [ORCHESTRATION_TOOL_IDS.DELEGATE, loadDelegateTool().createDelegateTool(context)], diff --git a/packages/@n8n/instance-ai/src/tools/nodes.tool.ts b/packages/@n8n/instance-ai/src/tools/nodes.tool.ts index cac7bea2aca..13e0386cfa9 100644 --- a/packages/@n8n/instance-ai/src/tools/nodes.tool.ts +++ b/packages/@n8n/instance-ai/src/tools/nodes.tool.ts @@ -25,7 +25,11 @@ const listAction = z.object({ }); const searchAction = z.object({ - action: z.literal('search').describe('Search node types by name or AI connection type'), + action: z + .literal('search') + .describe( + 'Search node types by name or AI connection type. Use for service-specific discovery — short service names like "Gmail" or "Slack", not full task phrases.', + ), query: z .string() .optional() @@ -60,12 +64,20 @@ const nodeRequestSchema = z.union([ ]); const typeDefinitionAction = z.object({ - action: z.literal('type-definition').describe('Get TypeScript type definitions for nodes'), + action: z + .literal('type-definition') + .describe( + 'Get TypeScript type definitions for nodes — exact parameter names, enum values, credential types, display conditions, and `@builderHint` annotations.', + ), nodeTypes: z.array(nodeRequestSchema).min(1).max(5).describe(NODE_TYPES_ARRAY_DESCRIPTION), }); const suggestedAction = z.object({ - action: z.literal('suggested').describe('Get curated node recommendations by category'), + action: z + .literal('suggested') + .describe( + 'Get curated node recommendations by category. Call first when the workflow fits a known category.', + ), categories: z .array(z.string()) .min(1) @@ -76,7 +88,7 @@ const suggestedAction = z.object({ const exploreResourcesAction = z.object({ action: z .literal('explore-resources') - .describe("Query real resources for a node's RLC parameters"), + .describe("Query live credential-backed resource lists for a node's RLC parameters"), nodeType: z.string().describe(NODE_TYPE_ID_DESCRIPTION), version: z.number().describe('Node version, e.g. 4.7'), methodName: z @@ -392,7 +404,7 @@ export function createNodesTool( return new Tool('nodes') .description( - 'Work with n8n node types — discover, search, describe, get type definitions, and explore real resources.', + 'Work with n8n node types. Use `suggested` for known workflow categories, `search` for service-specific discovery, `type-definition` before configuring nodes, and `explore-resources` for live credential-backed lists.', ) .input(fullInputSchema) .handler(async (input: FullInput) => { diff --git a/packages/@n8n/instance-ai/src/tools/nodes/__tests__/node-search-engine.test.ts b/packages/@n8n/instance-ai/src/tools/nodes/__tests__/node-search-engine.test.ts index 300e1cf1782..91640db141a 100644 --- a/packages/@n8n/instance-ai/src/tools/nodes/__tests__/node-search-engine.test.ts +++ b/packages/@n8n/instance-ai/src/tools/nodes/__tests__/node-search-engine.test.ts @@ -59,6 +59,15 @@ const agentNode = makeNode({ }, }); +const openAiNode = makeNode({ + name: '@n8n/n8n-nodes-langchain.openAi', + displayName: 'OpenAI', + description: 'OpenAI node for chat, assistants, and legacy operations', + builderHint: { + searchHint: 'For text generation, reasoning and tools, use AI Agent with OpenAI Chat Model', + }, +}); + const openAiLmNode = makeNode({ name: '@n8n/n8n-nodes-langchain.lmChatOpenAi', displayName: 'OpenAI Chat Model', @@ -126,6 +135,7 @@ const allNodes = [ setNode, slackNode, agentNode, + openAiNode, openAiLmNode, memoryNode, embeddingNode, @@ -194,6 +204,18 @@ describe('NodeSearchEngine', () => { expect(agentResult?.builderHintMessage).toBe('Use an AI Agent for autonomous task execution'); }); + it('should include builder search hint when present', () => { + const results = engine.searchByName('OpenAI'); + const openAiResult = results.find((r) => r.name === '@n8n/n8n-nodes-langchain.openAi'); + expect(openAiResult).toBeDefined(); + expect(openAiResult?.builderHintMessage).toBe( + 'For text generation, reasoning and tools, use AI Agent with OpenAI Chat Model', + ); + expect(engine.formatResult(openAiResult!)).toContain( + 'For text generation, reasoning and tools, use AI Agent with OpenAI Chat Model', + ); + }); + it('should NOT surface builderHint.extraTypeDefContent in search results', () => { const results = engine.searchByName('AI Agent'); const agentResult = results.find((r) => r.name === '@n8n/n8n-nodes-langchain.agent'); diff --git a/packages/@n8n/instance-ai/src/tools/nodes/node-search-engine.ts b/packages/@n8n/instance-ai/src/tools/nodes/node-search-engine.ts index 558cccaf64d..dd27040cad3 100644 --- a/packages/@n8n/instance-ai/src/tools/nodes/node-search-engine.ts +++ b/packages/@n8n/instance-ai/src/tools/nodes/node-search-engine.ts @@ -75,6 +75,29 @@ function extractSubnodeRequirements(inputs?: BuilderHintInputs): SubnodeRequirem })); } +function getBuilderHintMessage( + builderHint?: SearchableNodeType['builderHint'], +): string | undefined { + return builderHint?.message ?? builderHint?.searchHint; +} + +function toNodeSearchResult(node: SearchableNodeType, score: number): NodeSearchResult { + const subnodeRequirements = extractSubnodeRequirements(node.builderHint?.inputs); + const builderHintMessage = getBuilderHintMessage(node.builderHint); + + return { + name: node.name, + displayName: node.displayName, + description: node.description ?? 'No description available', + version: getLatestVersion(node.version), + inputs: node.inputs, + outputs: node.outputs, + score, + ...(builderHintMessage && { builderHintMessage }), + ...(subnodeRequirements.length > 0 && { subnodeRequirements }), + }; +} + function dedupeNodes(nodes: SearchableNodeType[]): SearchableNodeType[] { const dedupeCache: Record = {}; nodes.forEach((node) => { @@ -173,8 +196,7 @@ export class NodeSearchEngine { term, candidates, NODE_SEARCH_KEYS, - limit, - ); + ).slice(0, limit); for (const r of termResults) { const existing = scoreMap.get(r.item.name); if (!existing || r.score > existing.score) { @@ -184,7 +206,7 @@ export class NodeSearchEngine { } searchResults = [...scoreMap.values()]; } else { - searchResults = sublimeSearch(query, candidates, NODE_SEARCH_KEYS, limit); + searchResults = sublimeSearch(query, candidates, NODE_SEARCH_KEYS); } const fuzzyResultNames = new Set(searchResults.map((r) => r.item.name)); @@ -257,20 +279,7 @@ export class NodeSearchEngine { const results = this.fuzzySearchNodes(query, this.nodeTypes, limit) .slice(0, limit) - .map(({ item, score }): NodeSearchResult => { - const subnodeRequirements = extractSubnodeRequirements(item.builderHint?.inputs); - return { - name: item.name, - displayName: item.displayName, - description: item.description ?? 'No description available', - version: getLatestVersion(item.version), - inputs: item.inputs, - outputs: item.outputs, - score, - ...(item.builderHint?.message && { builderHintMessage: item.builderHint.message }), - ...(subnodeRequirements.length > 0 && { subnodeRequirements }), - }; - }); + .map(({ item, score }) => toNodeSearchResult(item, score)); this.nameSearchCache.set(cacheKey, results); return cloneSearchResults(results); } @@ -307,22 +316,7 @@ export class NodeSearchEngine { const results = nodesWithConnectionType .sort((a, b) => b.connectionScore - a.connectionScore) .slice(0, limit) - .map(({ nodeType, connectionScore }) => { - const subnodeRequirements = extractSubnodeRequirements(nodeType.builderHint?.inputs); - return { - name: nodeType.name, - displayName: nodeType.displayName, - version: getLatestVersion(nodeType.version), - description: nodeType.description ?? 'No description available', - inputs: nodeType.inputs, - outputs: nodeType.outputs, - score: connectionScore, - ...(nodeType.builderHint?.message && { - builderHintMessage: nodeType.builderHint.message, - }), - ...(subnodeRequirements.length > 0 && { subnodeRequirements }), - }; - }); + .map(({ nodeType, connectionScore }) => toNodeSearchResult(nodeType, connectionScore)); this.connectionSearchCache.set(cacheKey, results); return cloneSearchResults(results); } @@ -337,19 +331,7 @@ export class NodeSearchEngine { (result) => result.nodeType.name === item.name, ); const connectionScore = connectionResult?.connectionScore ?? 0; - const subnodeRequirements = extractSubnodeRequirements(item.builderHint?.inputs); - - return { - name: item.name, - version: getLatestVersion(item.version), - displayName: item.displayName, - description: item.description ?? 'No description available', - inputs: item.inputs, - outputs: item.outputs, - score: connectionScore + nameScore, - ...(item.builderHint?.message && { builderHintMessage: item.builderHint.message }), - ...(subnodeRequirements.length > 0 && { subnodeRequirements }), - }; + return toNodeSearchResult(item, connectionScore + nameScore); }); this.connectionSearchCache.set(cacheKey, results); return cloneSearchResults(results); diff --git a/packages/@n8n/instance-ai/src/tools/nodes/node-search-engine.types.ts b/packages/@n8n/instance-ai/src/tools/nodes/node-search-engine.types.ts index f2b4ef4929e..d55927f4352 100644 --- a/packages/@n8n/instance-ai/src/tools/nodes/node-search-engine.types.ts +++ b/packages/@n8n/instance-ai/src/tools/nodes/node-search-engine.types.ts @@ -66,6 +66,7 @@ export interface SearchableNodeType { }; builderHint?: { message?: string; + searchHint?: string; inputs?: BuilderHintInputs; /** * Multi-line content variations emitted into generated `.d.ts` only; @@ -104,7 +105,7 @@ export interface NodeSearchResult { score: number; inputs: string[] | string; outputs: string[] | string; - /** General hint message for workflow builders (from builderHint.message). */ + /** General hint message for workflow builders (from builderHint.message/searchHint). */ builderHintMessage?: string; /** Subnode requirements extracted from builderHint.inputs. */ subnodeRequirements?: SubnodeRequirement[]; diff --git a/packages/@n8n/instance-ai/src/tools/nodes/suggested-nodes-data.ts b/packages/@n8n/instance-ai/src/tools/nodes/suggested-nodes-data.ts index 3d410b65138..c56d4e5ae8a 100644 --- a/packages/@n8n/instance-ai/src/tools/nodes/suggested-nodes-data.ts +++ b/packages/@n8n/instance-ai/src/tools/nodes/suggested-nodes-data.ts @@ -221,12 +221,22 @@ export const suggestedNodesData: Record = { name: 'n8n-nodes-base.formTrigger', note: 'ALWAYS store raw data to persistent storage', }, - { name: 'n8n-nodes-base.form', note: 'Each node is one page/step' }, + { + name: 'n8n-nodes-base.form', + note: 'Each node is one page/step; use for Form Ending / completion pages after processing', + }, { name: 'n8n-nodes-base.dataTable', note: 'PREFERRED for form data storage', }, - { name: 'n8n-nodes-base.googleSheets' }, + { + name: 'n8n-nodes-base.googleSheets', + note: 'When spreadsheet/document ID is unknown, use placeholder() in documentId __rl.value with cachedResultName from the user prompt — never an empty string. Setup collects the real ID later. For sheetName: list mode value must be the numeric tab id (0 for first tab); use mode name with the tab title when the user says Sheet1.', + }, + { + name: '@n8n/n8n-nodes-langchain.openAi', + note: 'Confirmation/summary text: resource=text, operation=response. See open-ai-output-shape.md for downstream field paths (not $json.text).', + }, { name: 'n8n-nodes-base.airtable' }, ], }, @@ -241,7 +251,7 @@ export const suggestedNodesData: Record = { }, { name: '@n8n/n8n-nodes-langchain.openAi', - note: 'Use for image/video generation. DALL-E, TTS, Sora video generation', + note: 'Text (operation=response), DALL-E, TTS, Sora. See open-ai-output-shape.md when wiring downstream fields.', }, { name: '@n8n/n8n-nodes-langchain.lmChatGoogleGemini', diff --git a/packages/@n8n/instance-ai/src/tools/orchestration/__tests__/blueprint-accumulator.test.ts b/packages/@n8n/instance-ai/src/tools/orchestration/__tests__/blueprint-accumulator.test.ts deleted file mode 100644 index 19e72f4d60d..00000000000 --- a/packages/@n8n/instance-ai/src/tools/orchestration/__tests__/blueprint-accumulator.test.ts +++ /dev/null @@ -1,216 +0,0 @@ -import { BlueprintAccumulator } from '../blueprint-accumulator'; - -describe('BlueprintAccumulator', () => { - let accumulator: BlueprintAccumulator; - - beforeEach(() => { - accumulator = new BlueprintAccumulator(); - }); - - describe('addItem with kind=checkpoint', () => { - it('produces a PlannedTaskInput with kind=checkpoint', () => { - accumulator.addItem({ - kind: 'workflow', - id: 'wf-1', - name: 'Daily Email', - purpose: 'Send a daily summary email', - integrations: [], - dependsOn: [], - }); - - const task = accumulator.addItem({ - kind: 'checkpoint', - id: 'verify-1', - title: "Verify 'Daily Email' workflow runs without errors", - instructions: - 'Call verify-built-workflow with the workItemId from wf-1. Assert success===true.', - dependsOn: ['wf-1'], - }); - - expect(task).toEqual({ - id: 'verify-1', - title: "Verify 'Daily Email' workflow runs without errors", - kind: 'checkpoint', - spec: 'Call verify-built-workflow with the workItemId from wf-1. Assert success===true.', - deps: ['wf-1'], - }); - }); - - it('includes the checkpoint in getTaskList and getTaskItemsForEvent', () => { - accumulator.addItem({ - kind: 'workflow', - id: 'wf-1', - name: 'WF', - purpose: 'p', - integrations: [], - dependsOn: [], - }); - accumulator.addItem({ - kind: 'checkpoint', - id: 'verify-1', - title: 'Verify WF', - instructions: 'Verify it', - dependsOn: ['wf-1'], - }); - - const list = accumulator.getTaskList(); - const items = accumulator.getTaskItemsForEvent(); - - expect(list.map((t) => t.kind)).toEqual(['build-workflow', 'checkpoint']); - expect(items.map((t) => t.id)).toEqual(['wf-1', 'verify-1']); - }); - - it('removeItem drops the checkpoint and dangling dep references', () => { - accumulator.addItem({ - kind: 'workflow', - id: 'wf-1', - name: 'WF', - purpose: 'p', - integrations: [], - dependsOn: [], - }); - accumulator.addItem({ - kind: 'checkpoint', - id: 'verify-1', - title: 'Verify WF', - instructions: 'Verify it', - dependsOn: ['wf-1'], - }); - - expect(accumulator.removeItem('verify-1')).toBe(true); - expect(accumulator.getTaskList().map((t) => t.id)).toEqual(['wf-1']); - }); - - it('cascade-removes a checkpoint when its only build-workflow dep is removed', () => { - accumulator.addItem({ - kind: 'workflow', - id: 'wf-1', - name: 'WF', - purpose: 'p', - integrations: [], - dependsOn: [], - }); - accumulator.addItem({ - kind: 'checkpoint', - id: 'verify-1', - title: 'Verify WF', - instructions: 'Verify it', - dependsOn: ['wf-1'], - }); - - accumulator.removeItem('wf-1'); - - // Checkpoint must not survive as an orphan — createPlan would reject - // it at submit-plan time because checkpoint deps must reference a - // build-workflow task. - const list = accumulator.getTaskList(); - expect(list.find((t) => t.id === 'verify-1')).toBeUndefined(); - expect(list.find((t) => t.id === 'wf-1')).toBeUndefined(); - expect(list).toHaveLength(0); - }); - - it('keeps a checkpoint that still depends on at least one remaining workflow', () => { - accumulator.addItem({ - kind: 'workflow', - id: 'wf-1', - name: 'WF1', - purpose: 'p', - integrations: [], - dependsOn: [], - }); - accumulator.addItem({ - kind: 'workflow', - id: 'wf-2', - name: 'WF2', - purpose: 'p', - integrations: [], - dependsOn: [], - }); - accumulator.addItem({ - kind: 'checkpoint', - id: 'verify-both', - title: 'Verify both', - instructions: 'Verify both', - dependsOn: ['wf-1', 'wf-2'], - }); - - accumulator.removeItem('wf-1'); - - const checkpoint = accumulator.getTaskList().find((t) => t.id === 'verify-both'); - expect(checkpoint).toBeDefined(); - expect(checkpoint?.deps).toEqual(['wf-2']); - }); - }); - - describe('loadFromTasks (revision flow)', () => { - const originalTasks = [ - { - id: 'wf-1', - title: "Build 'A' workflow", - kind: 'build-workflow', - spec: 'Build A', - deps: [], - }, - { - id: 'wf-2', - title: "Build 'B' workflow", - kind: 'build-workflow', - spec: 'Build B', - deps: [], - }, - { - id: 'verify-1', - title: 'Verify A', - kind: 'checkpoint', - spec: 'Verify A', - deps: ['wf-1'], - }, - ]; - - it('seeds the accumulator with the persisted plan', () => { - accumulator.loadFromTasks(originalTasks); - - expect(accumulator.isEmpty()).toBe(false); - expect(accumulator.getTaskList().map((t) => t.id)).toEqual(['wf-1', 'wf-2', 'verify-1']); - }); - - it('preserves original items across an ask-for-edits revision (remove + add + resubmit)', () => { - // Simulates the resume path: the parent handler rebuilt a fresh - // accumulator, then rehydrated it from the persisted graph before - // the planner revised the plan. - accumulator.loadFromTasks(originalTasks); - - // Planner revises: drop one original, add a new one. - expect(accumulator.removeItem('wf-2')).toBe(true); - accumulator.addItem({ - kind: 'workflow', - id: 'wf-3', - name: 'C', - purpose: 'Build C', - integrations: [], - dependsOn: [], - }); - - // The resubmitted plan keeps the surviving originals plus the new item, - // rather than collapsing to only the newly-added one. - expect(accumulator.getTaskList().map((t) => t.id)).toEqual(['wf-1', 'verify-1', 'wf-3']); - }); - - it('upserts by id so a revised original replaces in place', () => { - accumulator.loadFromTasks(originalTasks); - - accumulator.addItem({ - kind: 'workflow', - id: 'wf-1', - name: 'A (revised)', - purpose: 'Build A differently', - integrations: [], - dependsOn: [], - }); - - const list = accumulator.getTaskList(); - expect(list.map((t) => t.id)).toEqual(['wf-1', 'wf-2', 'verify-1']); - expect(list.find((t) => t.id === 'wf-1')?.title).toBe("Build 'A (revised)' workflow"); - }); - }); -}); diff --git a/packages/@n8n/instance-ai/src/tools/orchestration/__tests__/blueprint.schema.test.ts b/packages/@n8n/instance-ai/src/tools/orchestration/__tests__/blueprint.schema.test.ts deleted file mode 100644 index 475f479ed18..00000000000 --- a/packages/@n8n/instance-ai/src/tools/orchestration/__tests__/blueprint.schema.test.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { blueprintCheckpointItemSchema } from '../blueprint.schema'; - -describe('blueprintCheckpointItemSchema', () => { - it('rejects a checkpoint with an empty dependsOn array', () => { - const result = blueprintCheckpointItemSchema.safeParse({ - id: 'verify-1', - title: 'Verify something', - instructions: 'Call verify-built-workflow', - dependsOn: [], - }); - expect(result.success).toBe(false); - }); - - it('rejects a checkpoint that omits dependsOn entirely', () => { - const result = blueprintCheckpointItemSchema.safeParse({ - id: 'verify-1', - title: 'Verify something', - instructions: 'Call verify-built-workflow', - }); - expect(result.success).toBe(false); - }); - - it('accepts a checkpoint that depends on at least one workflow item', () => { - const result = blueprintCheckpointItemSchema.safeParse({ - id: 'verify-1', - title: 'Verify Daily Email workflow runs without errors', - instructions: 'Call verify-built-workflow with the workItemId from wf-1.', - dependsOn: ['wf-1'], - }); - expect(result.success).toBe(true); - }); -}); diff --git a/packages/@n8n/instance-ai/src/tools/orchestration/__tests__/delegate.tool.test.ts b/packages/@n8n/instance-ai/src/tools/orchestration/__tests__/delegate.tool.test.ts index ed01cfd0c1e..806e059b689 100644 --- a/packages/@n8n/instance-ai/src/tools/orchestration/__tests__/delegate.tool.test.ts +++ b/packages/@n8n/instance-ai/src/tools/orchestration/__tests__/delegate.tool.test.ts @@ -83,14 +83,18 @@ describe('delegateInputSchema', () => { // --------------------------------------------------------------------------- describe('createDelegateTool', () => { - it('rejects "plan" in tools array', async () => { + it('rejects "create-tasks" in tools array', async () => { const context = createMockContext({ 'tool-a': {} }); const tool = createDelegateTool(context); - const output = await executeTool(tool, { ...makeValidInput(), tools: ['plan'] }, {} as never); + const output = await executeTool( + tool, + { ...makeValidInput(), tools: ['create-tasks'] }, + {} as never, + ); expect('result' in output).toBe(true); - expect((output as { result: string }).result).toContain('plan'); + expect((output as { result: string }).result).toContain('create-tasks'); expect((output as { result: string }).result).toContain('cannot be delegated'); }); diff --git a/packages/@n8n/instance-ai/src/tools/orchestration/__tests__/plan-agent-prompt.test.ts b/packages/@n8n/instance-ai/src/tools/orchestration/__tests__/plan-agent-prompt.test.ts deleted file mode 100644 index 8e5276d3369..00000000000 --- a/packages/@n8n/instance-ai/src/tools/orchestration/__tests__/plan-agent-prompt.test.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { PLANNER_AGENT_PROMPT } from '../plan-agent-prompt'; - -describe('planner agent prompt', () => { - it('keeps checkpoint verification separate from user-requested runs', () => { - expect(PLANNER_AGENT_PROMPT).toContain('Use `verify-built-workflow`'); - expect(PLANNER_AGENT_PROMPT).toContain( - 'Do not put `executions(action="run")` in checkpoint instructions', - ); - expect(PLANNER_AGENT_PROMPT).toContain('separate approval-gated run'); - }); -}); diff --git a/packages/@n8n/instance-ai/src/tools/orchestration/__tests__/plan.tool.test.ts b/packages/@n8n/instance-ai/src/tools/orchestration/__tests__/plan.tool.test.ts index 6d9721ca5f5..11805bc7582 100644 --- a/packages/@n8n/instance-ai/src/tools/orchestration/__tests__/plan.tool.test.ts +++ b/packages/@n8n/instance-ai/src/tools/orchestration/__tests__/plan.tool.test.ts @@ -1,5 +1,3 @@ -import type { Mock } from 'vitest'; - import { executeTool } from '../../../__tests__/tool-test-utils'; import { PlanValidationError } from '../../../planned-tasks/planned-task-service'; import { createToolRegistry } from '../../../tool-registry'; @@ -50,127 +48,195 @@ function validTasks() { return [ { id: 't1', - title: 'First task', + title: 'Build Slack notifier', kind: 'build-workflow' as const, - spec: 'Build a Slack notifier', + spec: 'Build a Slack notifier that writes to a Data Table', deps: [], }, ]; } -describe('createPlanTool — replan-only guard', () => { - const ORIGINAL_ENV = process.env.N8N_INSTANCE_AI_ENFORCE_CREATE_TASKS_REPLAN; +function planInput( + source: 'planning-skill' | 'replan' = 'planning-skill', + overrides: { postBuildRunRequested?: boolean } = {}, +) { + return { + tasks: validTasks(), + planningContext: { + source, + summary: 'Build the requested coordinated automation.', + assumptions: ['Use the available Slack credential if exactly one exists.'], + ...overrides, + }, + }; +} - afterEach(() => { - if (ORIGINAL_ENV === undefined) { - delete process.env.N8N_INSTANCE_AI_ENFORCE_CREATE_TASKS_REPLAN; - } else { - process.env.N8N_INSTANCE_AI_ENFORCE_CREATE_TASKS_REPLAN = ORIGINAL_ENV; - } - }); - - it('rejects initial planning when no replan marker is present', async () => { +describe('createPlanTool — planning context guard', () => { + it('rejects initial planning without planningContext', async () => { + const trackTelemetry = vi.fn(); const context = createMockContext({ currentUserMessage: 'Create a data table for users, then build a workflow', + trackTelemetry, }); const tool = createPlanTool(context); const out = await executeTool(tool, { tasks: validTasks() }, {}); expect(out.taskCount).toBe(0); - expect(out.result).toContain('`create-tasks` is for replanning only'); - expect(out.result).toContain('`plan`'); - expect(out.result).toContain('skipPlannerDiscovery'); + expect(out.result).toContain('`create-tasks` requires `planningContext`'); + expect(out.result).toContain('load the `planning` skill'); + expect(out.result).not.toContain('`plan`'); + expect(out.result).not.toContain('skipPlannerDiscovery'); expect(context.logger.warn).toHaveBeenCalledWith( - 'create-tasks called without replan context — rejecting', + 'create-tasks called with invalid planning context — rejecting', expect.objectContaining({ threadId: 'test-thread', taskCount: 1 }), ); + expect(context.plannedTaskService!.createPlan).not.toHaveBeenCalled(); + expect(trackTelemetry).toHaveBeenCalledWith( + 'instance_ai_planning_route', + expect.objectContaining({ + route: 'contract_violation', + source: 'missing', + task_count: 1, + }), + ); }); - it('allows initial planning when skipPlannerDiscovery=true with reason', async () => { + it('accepts initial plans from the planning skill', async () => { + const trackTelemetry = vi.fn(); const context = createMockContext({ - currentUserMessage: 'Create a data table for users', + currentUserMessage: 'Create a data table for users, then build a workflow', + trackTelemetry, }); const tool = createPlanTool(context); const suspend = vi.fn().mockResolvedValue(undefined); + const out = await executeTool(tool, planInput('planning-skill'), { suspend }); + + expect(out).toBeUndefined(); + expect(context.plannedTaskService!.createPlan).toHaveBeenCalledWith( + 'test-thread', + validTasks(), + expect.objectContaining({ planRunId: 'test-run' }), + ); + expect(suspend).toHaveBeenCalledWith( + expect.objectContaining({ + inputType: 'plan-review', + tasks: { tasks: [{ id: 't1', description: 'Build Slack notifier', status: 'todo' }] }, + }), + ); + expect(trackTelemetry).toHaveBeenCalledWith( + 'instance_ai_planning_route', + expect.objectContaining({ + route: 'skill', + source: 'planning-skill', + task_count: 1, + has_data_table_requirements: true, + }), + ); + }); + + it('does not infer post-build run approval from user text', async () => { + const context = createMockContext({ + currentUserMessage: 'Build a workflow and then run it once', + }); + const tool = createPlanTool(context); + + await executeTool(tool, planInput('planning-skill'), { suspend: vi.fn() }); + + expect(context.plannedTaskService!.createPlan).toHaveBeenCalledWith( + 'test-thread', + validTasks(), + expect.objectContaining({ postBuildRunApprovalRequired: false }), + ); + }); + + it('stores post-build run approval when planningContext requests it', async () => { + const context = createMockContext({ currentUserMessage: 'Build and run it once' }); + const tool = createPlanTool(context); + + await executeTool(tool, planInput('planning-skill', { postBuildRunRequested: true }), { + suspend: vi.fn(), + }); + + expect(context.plannedTaskService!.createPlan).toHaveBeenCalledWith( + 'test-thread', + validTasks(), + expect.objectContaining({ postBuildRunApprovalRequired: true }), + ); + }); + + it('preserves supporting-workflow build task metadata in approved plans', async () => { + const context = createMockContext({ + currentUserMessage: 'Create a processor sub-workflow and then two source workflows', + }); + const tool = createPlanTool(context); + const suspend = vi.fn().mockResolvedValue(undefined); + const tasks = [ + { + id: 'processor', + title: 'Build processor sub-workflow', + kind: 'build-workflow' as const, + spec: 'Build a supporting sub-workflow that classifies feedback for source workflows.', + deps: [], + isSupportingWorkflow: true, + }, + { + id: 'source', + title: 'Build source workflow', + kind: 'build-workflow' as const, + spec: 'Build a source workflow that calls the processor sub-workflow.', + deps: ['processor'], + }, + ]; + const out = await executeTool( tool, { - tasks: validTasks(), - skipPlannerDiscovery: true, - reason: 'Single simple follow-up task — planner discovery would be wasted.', + tasks, + planningContext: { + source: 'planning-skill', + summary: 'Build reusable processor and source workflows.', + }, }, { suspend }, ); - // Reaches native suspend path. expect(out).toBeUndefined(); - const warnMock = context.logger.warn as Mock< - (...args: [string, Record?]) => void - >; - const bypassCall = warnMock.mock.calls.find( - (call) => call[0] === 'create-tasks bypassing planner with skipPlannerDiscovery=true', + expect(context.plannedTaskService!.createPlan).toHaveBeenCalledWith( + 'test-thread', + expect.arrayContaining([ + expect.objectContaining({ + id: 'processor', + isSupportingWorkflow: true, + }), + ]), + expect.objectContaining({ planRunId: 'test-run' }), + ); + expect(suspend).toHaveBeenCalledWith( + expect.objectContaining({ + tasks: { + tasks: [ + { id: 'processor', description: 'Build processor sub-workflow', status: 'todo' }, + { id: 'source', description: 'Build source workflow', status: 'todo' }, + ], + }, + }), ); - expect(bypassCall).toBeDefined(); - const metadata = bypassCall?.[1] as { reason?: string } | undefined; - expect(metadata?.reason).toContain('planner discovery'); - expect(context.plannedTaskService!.createPlan).toHaveBeenCalled(); }); - it('rejects skipPlannerDiscovery=true without a reason', async () => { - const context = createMockContext({ currentUserMessage: 'Create a table' }); + it('rejects replan source outside host-marked replan follow-ups', async () => { + const context = createMockContext({ currentUserMessage: 'ordinary initial request' }); const tool = createPlanTool(context); - const out = await executeTool(tool, { tasks: validTasks(), skipPlannerDiscovery: true }, {}); + const out = await executeTool(tool, planInput('replan'), { suspend: vi.fn() }); expect(out.taskCount).toBe(0); - expect(out.result).toContain('requires a one-sentence `reason`'); - }); - - it('allows calls when a plan already exists for this thread (revision loop)', async () => { - const context = createMockContext({ - currentUserMessage: 'revise the plan', - plannedTaskService: makePlannedTaskService({ - getGraph: vi.fn().mockResolvedValue({ - threadId: 'test-thread', - status: 'active', - tasks: [], - } as unknown as Awaited>), - }), - }); - const tool = createPlanTool(context); - const suspend = vi.fn().mockResolvedValue(undefined); - - const out = await executeTool(tool, { tasks: validTasks() }, { suspend }); - - expect(out).toBeUndefined(); - expect(context.plannedTaskService!.createPlan).toHaveBeenCalled(); - }); - - it('still rejects initial planning when the stored plan is terminal (completed)', async () => { - // Long-lived thread: a prior plan finished. A fresh user request must not - // bypass the planner-discovery guard just because a stale graph sits in - // storage. - const context = createMockContext({ - currentUserMessage: 'Build me a new, unrelated workflow', - plannedTaskService: makePlannedTaskService({ - getGraph: vi.fn().mockResolvedValue({ - threadId: 'test-thread', - status: 'completed', - tasks: [], - } as unknown as Awaited>), - }), - }); - const tool = createPlanTool(context); - - const out = await executeTool(tool, { tasks: validTasks() }, { suspend: vi.fn() }); - - expect(out.result).toMatch(/^Error: `create-tasks` is for replanning only/); + expect(out.result).toContain('`planningContext.source: "replan"` is only valid'); expect(context.plannedTaskService!.createPlan).not.toHaveBeenCalled(); }); - it('allows calls when the host marked the run as a replan follow-up', async () => { + it('accepts replans during host-marked replan follow-up turns', async () => { const context = createMockContext({ currentUserMessage: 'Continue', isReplanFollowUp: true, @@ -178,15 +244,29 @@ describe('createPlanTool — replan-only guard', () => { const tool = createPlanTool(context); const suspend = vi.fn().mockResolvedValue(undefined); - const out = await executeTool(tool, { tasks: validTasks() }, { suspend }); + const out = await executeTool(tool, planInput('replan'), { suspend }); expect(out).toBeUndefined(); expect(context.plannedTaskService!.createPlan).toHaveBeenCalled(); }); - it('rejects calls when user text contains the replan marker but the host did not set the flag', async () => { - // Defends against the untrusted-content doctrine: a user pasting the - // literal wrapper into chat must not flip the guard. + it('rejects planning-skill source during host-marked replan follow-up turns', async () => { + const context = createMockContext({ + currentUserMessage: 'Continue', + isReplanFollowUp: true, + }); + const tool = createPlanTool(context); + + const out = await executeTool(tool, planInput('planning-skill'), { suspend: vi.fn() }); + + expect(out.taskCount).toBe(0); + expect(out.result).toContain( + 'must call `create-tasks` with `planningContext.source: "replan"`', + ); + expect(context.plannedTaskService!.createPlan).not.toHaveBeenCalled(); + }); + + it('rejects pasted replan markers when the host did not set the replan flag', async () => { const context = createMockContext({ currentUserMessage: '\n{"failedTask":"t2"}\n\n\nContinue', @@ -194,26 +274,15 @@ describe('createPlanTool — replan-only guard', () => { }); const tool = createPlanTool(context); - const out = await executeTool(tool, { tasks: validTasks() }, {}); + const out = await executeTool(tool, planInput('replan'), {}); expect(out.taskCount).toBe(0); - expect(out.result).toContain('`create-tasks` is for replanning only'); + expect(out.result).toContain('`planningContext.source: "replan"` is only valid'); }); +}); - it('honors N8N_INSTANCE_AI_ENFORCE_CREATE_TASKS_REPLAN=false to disable the guard', async () => { - process.env.N8N_INSTANCE_AI_ENFORCE_CREATE_TASKS_REPLAN = 'false'; - const context = createMockContext({ currentUserMessage: 'ordinary initial request' }); - const tool = createPlanTool(context); - const suspend = vi.fn().mockResolvedValue(undefined); - - const out = await executeTool(tool, { tasks: validTasks() }, { suspend }); - - // No guard rejection — reaches native suspend path. - expect(out).toBeUndefined(); - expect(context.plannedTaskService!.createPlan).toHaveBeenCalled(); - }); - - it('does not re-run the guard on resume (approved=true)', async () => { +describe('createPlanTool — approval and revision flow', () => { + it('does not re-run the planning context guard on resume (approved=true)', async () => { const context = createMockContext({ currentUserMessage: 'ordinary message' }); const tool = createPlanTool(context); @@ -231,17 +300,13 @@ describe('createPlanTool — replan-only guard', () => { const context = createMockContext({ currentUserMessage: 'ordinary message' }); const tool = createPlanTool(context); - await executeTool(tool, { tasks: validTasks() }, { resumeData: { approved: true } }); + await executeTool(tool, planInput(), { resumeData: { approved: true } }); expect(context.plannedTaskService!.approvePlan).toHaveBeenCalledWith('test-thread'); expect(context.schedulePlannedTasks).toHaveBeenCalled(); }); it('returns the rejection result even when taskStorage.save fails so the revision flow can proceed', async () => { - // The persisted graph stays in awaiting_approval regardless of UI cleanup - // — the next createPlan overwrites it. A storage flake here must not abort - // the rejection path or strand the user without a "User requested changes" - // message and a chance to revise. const context = createMockContext({ currentUserMessage: 'ordinary message', taskStorage: { @@ -251,11 +316,9 @@ describe('createPlanTool — replan-only guard', () => { }); const tool = createPlanTool(context); - const out = await executeTool( - tool, - { tasks: validTasks() }, - { resumeData: { approved: false, userInput: 'try again' } }, - ); + const out = await executeTool(tool, planInput(), { + resumeData: { approved: false, userInput: 'try again' }, + }); expect(out.taskCount).toBe(0); expect(out.result).toContain('User requested changes'); @@ -269,11 +332,9 @@ describe('createPlanTool — replan-only guard', () => { const context = createMockContext({ currentUserMessage: 'ordinary message' }); const tool = createPlanTool(context); - const out = await executeTool( - tool, - { tasks: validTasks() }, - { resumeData: { approved: false, denied: true } }, - ); + const out = await executeTool(tool, planInput(), { + resumeData: { approved: false, denied: true }, + }); expect(out.taskCount).toBe(0); expect(out.result).toContain('User denied the plan'); @@ -284,27 +345,19 @@ describe('createPlanTool — replan-only guard', () => { expect(context.taskStorage.save).toHaveBeenCalledWith('test-thread', { tasks: [] }); }); - it('keeps the awaiting_approval graph on rejection so a same-turn revision can pass the guard', async () => { - // The rejected plan stays in `awaiting_approval` (scoped to runId) so the - // LLM's next create-tasks call — which the tool result tells it to make — - // is treated as a revision and bypasses planner-discovery guard. The - // scheduler ignores `awaiting_approval`, so leaving it in place can't - // dispatch a rejected plan. + it('keeps the awaiting_approval graph on rejection so a same-turn revision can replace it', async () => { const context = createMockContext({ currentUserMessage: 'ordinary message' }); const tool = createPlanTool(context); - const out = await executeTool( - tool, - { tasks: validTasks() }, - { resumeData: { approved: false, userInput: 'not what I wanted' } }, - ); + const out = await executeTool(tool, planInput(), { + resumeData: { approved: false, userInput: 'not what I wanted' }, + }); expect(out.taskCount).toBe(0); expect(out.result).toContain('User requested changes'); expect(context.plannedTaskService!.clear).not.toHaveBeenCalled(); expect(context.schedulePlannedTasks).not.toHaveBeenCalled(); expect(context.plannedTaskService!.approvePlan).not.toHaveBeenCalled(); - // UI checklist still resets so the rejected todos don't linger on screen expect(context.taskStorage.save).toHaveBeenCalledWith('test-thread', { tasks: [] }); expect(context.eventBus.publish).toHaveBeenCalledWith( 'test-thread', @@ -315,10 +368,7 @@ describe('createPlanTool — replan-only guard', () => { ); }); - it('allows a same-turn revision after rejection (awaiting_approval with same runId)', async () => { - // After rejection, the graph stays in awaiting_approval with planRunId === - // context.runId. The next create-tasks call must pass threadHasExistingPlan - // so the revision flow advertised by the tool result works. + it('allows a same-turn revision after rejection with planning-skill context', async () => { const context = createMockContext({ currentUserMessage: 'revise the plan', runId: 'run-1', @@ -334,13 +384,13 @@ describe('createPlanTool — replan-only guard', () => { const tool = createPlanTool(context); const suspend = vi.fn().mockResolvedValue(undefined); - const out = await executeTool(tool, { tasks: validTasks() }, { suspend }); + const out = await executeTool(tool, planInput('planning-skill'), { suspend }); expect(out).toBeUndefined(); expect(context.plannedTaskService!.createPlan).toHaveBeenCalled(); }); - it('blocks a fresh initial call when the same turn already had a cancelled (denied) plan', async () => { + it('blocks a fresh initial call when the same turn already had a cancelled denied plan', async () => { const context = createMockContext({ currentUserMessage: 'try again', messageGroupId: 'mg-1', @@ -356,14 +406,14 @@ describe('createPlanTool — replan-only guard', () => { }); const tool = createPlanTool(context); - const out = await executeTool(tool, { tasks: validTasks() }, { suspend: vi.fn() }); + const out = await executeTool(tool, planInput(), { suspend: vi.fn() }); expect(out.taskCount).toBe(0); expect(out.result).toMatch(/denied a plan earlier in this turn/i); expect(context.plannedTaskService!.createPlan).not.toHaveBeenCalled(); }); - it('allows a fresh initial call when a cancelled plan is from a previous turn (different messageGroupId)', async () => { + it('allows a fresh initial call when a cancelled plan is from a previous turn', async () => { const context = createMockContext({ currentUserMessage: 'new user message', messageGroupId: 'mg-2', @@ -376,39 +426,14 @@ describe('createPlanTool — replan-only guard', () => { tasks: [], } as unknown as Awaited>), }), - isReplanFollowUp: true, }); const tool = createPlanTool(context); const suspend = vi.fn().mockResolvedValue(undefined); - await executeTool(tool, { tasks: validTasks() }, { suspend }); + await executeTool(tool, planInput(), { suspend }); expect(context.plannedTaskService!.createPlan).toHaveBeenCalled(); }); - - it('rejects a fresh request when an orphan awaiting_approval graph exists from a previous run', async () => { - // LLM rejected a prior plan and never revised; the graph orphans in - // awaiting_approval with a stale planRunId. A new turn must still go - // through planner discovery, not silently bypass the guard. - const context = createMockContext({ - currentUserMessage: 'unrelated new request', - runId: 'run-2', - plannedTaskService: makePlannedTaskService({ - getGraph: vi.fn().mockResolvedValue({ - threadId: 'test-thread', - status: 'awaiting_approval', - planRunId: 'run-1', - tasks: [], - } as unknown as Awaited>), - }), - }); - const tool = createPlanTool(context); - - const out = await executeTool(tool, { tasks: validTasks() }, { suspend: vi.fn() }); - - expect(out.result).toMatch(/^Error: `create-tasks` is for replanning only/); - expect(context.plannedTaskService!.createPlan).not.toHaveBeenCalled(); - }); }); describe('createPlanTool — createPlan validation failures', () => { @@ -417,7 +442,7 @@ describe('createPlanTool — createPlan validation failures', () => { 'Checkpoint task "chk-1" must depend on at least one build-workflow task', ); const context = createMockContext({ - currentUserMessage: 'replan after failure', + currentUserMessage: 'plan after discovery', plannedTaskService: makePlannedTaskService({ createPlan: vi.fn().mockRejectedValue(validatorError), }), @@ -425,22 +450,14 @@ describe('createPlanTool — createPlan validation failures', () => { const tool = createPlanTool(context); const suspend = vi.fn(); - const out = await executeTool( - tool, - { - tasks: validTasks(), - skipPlannerDiscovery: true, - reason: 'bypass for test', - }, - { suspend }, - ); + const out = await executeTool(tool, planInput(), { suspend }); expect(out.taskCount).toBe(0); expect(out.result).toContain(validatorError.message); expect(out.result).toContain('Revise the task graph and call this tool again'); expect(suspend).not.toHaveBeenCalled(); expect(context.logger.warn).toHaveBeenCalledWith( - 'plan tool: createPlan rejected by validator', + 'create-tasks rejected by planned task validator', expect.objectContaining({ threadId: 'test-thread', error: validatorError.message }), ); }); @@ -448,7 +465,7 @@ describe('createPlanTool — createPlan validation failures', () => { it('propagates non-validation errors (storage, abort, bugs)', async () => { const storageError = new Error('connection refused'); const context = createMockContext({ - currentUserMessage: 'replan', + currentUserMessage: 'plan after discovery', plannedTaskService: makePlannedTaskService({ createPlan: vi.fn().mockRejectedValue(storageError), }), @@ -456,13 +473,9 @@ describe('createPlanTool — createPlan validation failures', () => { const tool = createPlanTool(context); await expect( - executeTool( - tool, - { tasks: validTasks(), skipPlannerDiscovery: true, reason: 'bypass' }, - { - suspend: vi.fn(), - }, - ), + executeTool(tool, planInput(), { + suspend: vi.fn(), + }), ).rejects.toBe(storageError); }); }); diff --git a/packages/@n8n/instance-ai/src/tools/orchestration/__tests__/planner-briefing.test.ts b/packages/@n8n/instance-ai/src/tools/orchestration/__tests__/planner-briefing.test.ts deleted file mode 100644 index 0ba16761e1a..00000000000 --- a/packages/@n8n/instance-ai/src/tools/orchestration/__tests__/planner-briefing.test.ts +++ /dev/null @@ -1,288 +0,0 @@ -import type { OrchestrationContext } from '../../../types'; -import { - buildPlannerBriefingContext, - formatMessagesForBriefing, - getPriorToolObservations, - getRecentMessages, -} from '../planner-briefing'; - -describe('formatMessagesForBriefing', () => { - // The planner system prompt (plan-agent-prompt.ts) treats - // and as a paired contract — schedule/cron decisions read - // both. Emitting only one drops half the contract. - - it('emits alongside when a zone is provided', () => { - const briefing = formatMessagesForBriefing( - [{ role: 'user', content: 'schedule me a daily digest' }], - undefined, - 'America/New_York', - ); - - expect(briefing).toMatch(/[^<]+<\/current-datetime>/); - expect(briefing).toContain('America/New_York'); - }); - - it('still emits when no zone is provided', () => { - const briefing = formatMessagesForBriefing([], undefined, undefined); - - expect(briefing).toMatch(/[^<]+<\/current-datetime>/); - expect(briefing).not.toContain(''); - }); - - it('renders already-collected answers and discovered resources as dedicated sections', () => { - const briefing = formatMessagesForBriefing( - [{ role: 'user', content: 'Build a Slack to-do agent' }], - undefined, - 'America/New_York', - { - collectedAnswers: [ - 'How often should the agent run?: Every morning', - 'Credential selected for slackApi: Slack account (slackApi)', - ], - discoveredResources: ['Credentials available: Slack account (slackApi)'], - }, - ); - - expect(briefing).toContain('## Already-collected answers'); - expect(briefing).toContain('- How often should the agent run?: Every morning'); - expect(briefing).toContain('- Credential selected for slackApi: Slack account (slackApi)'); - expect(briefing).toContain('## Already-discovered resources'); - expect(briefing).toContain('- Credentials available: Slack account (slackApi)'); - }); -}); - -describe('buildPlannerBriefingContext', () => { - it('extracts ask-user answers and credential selections from prior tool results', () => { - const context = buildPlannerBriefingContext([ - { - toolName: 'credentials', - args: { action: 'list' }, - result: { - credentials: [ - { id: 'cred-slack', name: 'Slack account', type: 'slackApi' }, - { id: 'cred-anthropic', name: 'Anthropic account', type: 'anthropicApi' }, - ], - }, - }, - { - toolName: 'ask-user', - args: { - questions: [ - { - id: 'schedule', - question: 'How often should the agent run?', - type: 'single', - }, - ], - }, - result: { - answered: true, - answers: [ - { - questionId: 'schedule', - selectedOptions: ['Every morning'], - }, - ], - }, - }, - { - toolName: 'credentials', - args: { action: 'setup' }, - result: { - success: true, - credentials: { slackApi: 'cred-slack' }, - }, - }, - ]); - - expect(context.collectedAnswers).toEqual([ - 'How often should the agent run?: Every morning', - 'Credential selected for slackApi: Slack account (slackApi)', - ]); - expect(context.discoveredResources).toEqual([ - 'Credentials available: Slack account (slackApi), Anthropic account (anthropicApi)', - ]); - }); - - it('ignores unanswered and skipped ask-user answers', () => { - const context = buildPlannerBriefingContext([ - { - toolName: 'ask-user', - args: { - questions: [{ id: 'purpose', question: 'What should this do?', type: 'text' }], - }, - result: { - answered: false, - answers: [ - { - questionId: 'purpose', - customText: 'This should not be used', - }, - ], - }, - }, - { - toolName: 'ask-user', - args: { - questions: [ - { id: 'schedule', question: 'How often should it run?', type: 'single' }, - { id: 'model', question: 'Which model should it use?', type: 'single' }, - ], - }, - result: { - answered: true, - answers: [ - { - questionId: 'schedule', - selectedOptions: ['Every morning'], - skipped: true, - }, - { - questionId: 'model', - selectedOptions: ['Anthropic'], - }, - ], - }, - }, - ]); - - expect(context.collectedAnswers).toEqual(['Which model should it use?: Anthropic']); - expect(context.discoveredResources).toEqual([]); - }); -}); - -describe('getPriorToolObservations', () => { - it('reads tool results across the current message group when available', () => { - const askUserCall = { - questions: [{ id: 'purpose', question: 'What should this do?', type: 'text' }], - }; - const askUserResult = { - answered: true, - answers: [ - { questionId: 'purpose', question: 'What should this do?', customText: 'Email me' }, - ], - }; - const getEventsForRun = vi.fn().mockReturnValue([]); - const getEventsForRuns = vi.fn().mockReturnValue([ - { - type: 'tool-call', - runId: 'run-prior', - agentId: 'orchestrator', - payload: { - toolCallId: 'tool-1', - toolName: 'ask-user', - args: askUserCall, - }, - }, - { - type: 'tool-result', - runId: 'run-prior', - agentId: 'orchestrator', - payload: { - toolCallId: 'tool-1', - result: askUserResult, - }, - }, - ]); - const context = { - threadId: 'thread-1', - runId: 'run-current', - messageGroupId: 'message-group-1', - eventBus: { - getEventsAfter: vi.fn().mockReturnValue([ - { - id: 1, - event: { - type: 'run-start', - runId: 'run-prior', - agentId: 'orchestrator', - payload: { messageId: 'message-1', messageGroupId: 'message-group-1' }, - }, - }, - { - id: 2, - event: { - type: 'run-start', - runId: 'run-other', - agentId: 'orchestrator', - payload: { messageId: 'message-2', messageGroupId: 'message-group-2' }, - }, - }, - ]), - getEventsForRuns, - getEventsForRun, - }, - } as unknown as OrchestrationContext; - - const observations = getPriorToolObservations(context); - - expect(getEventsForRuns).toHaveBeenCalledWith('thread-1', ['run-prior', 'run-current']); - expect(getEventsForRun).not.toHaveBeenCalled(); - expect(observations).toEqual([ - { - toolName: 'ask-user', - args: askUserCall, - result: askUserResult, - }, - ]); - }); - - it('pairs out-of-order tool results with their later tool calls', () => { - const args = { action: 'list' }; - const result = { credentials: [{ id: 'cred-1', name: 'Slack', type: 'slackApi' }] }; - const context = { - threadId: 'thread-1', - runId: 'run-current', - eventBus: { - getEventsForRun: vi.fn().mockReturnValue([ - { - type: 'tool-result', - runId: 'run-current', - agentId: 'orchestrator', - payload: { toolCallId: 'tool-1', result }, - }, - { - type: 'tool-call', - runId: 'run-current', - agentId: 'orchestrator', - payload: { toolCallId: 'tool-1', toolName: 'credentials', args }, - }, - ]), - }, - } as unknown as OrchestrationContext; - - expect(getPriorToolObservations(context)).toEqual([{ toolName: 'credentials', args, result }]); - }); - - it('returns no observations when event lookup fails', () => { - const context = { - threadId: 'thread-1', - runId: 'run-current', - eventBus: { - getEventsForRun: vi.fn(() => { - throw new Error('storage unavailable'); - }), - }, - } as unknown as OrchestrationContext; - - expect(getPriorToolObservations(context)).toEqual([]); - }); -}); - -describe('getRecentMessages', () => { - it('does not append the current user message when memory already returned it', async () => { - const context = { - threadId: 't-1', - currentUserMessage: 'Build a Slack to-do agent', - memory: { - recall: vi.fn().mockResolvedValue({ - messages: [{ role: 'user', content: 'Build a Slack to-do agent' }], - }), - }, - } as unknown as OrchestrationContext; - - const messages = await getRecentMessages(context, 5); - - expect(messages).toEqual([{ role: 'user', content: 'Build a Slack to-do agent' }]); - }); -}); diff --git a/packages/@n8n/instance-ai/src/tools/orchestration/__tests__/planner-run-coordinator.test.ts b/packages/@n8n/instance-ai/src/tools/orchestration/__tests__/planner-run-coordinator.test.ts deleted file mode 100644 index 86cea53721f..00000000000 --- a/packages/@n8n/instance-ai/src/tools/orchestration/__tests__/planner-run-coordinator.test.ts +++ /dev/null @@ -1,182 +0,0 @@ -import type { Mock } from 'vitest'; - -import type { - OrchestrationContext, - PlannedTaskGraph, - PlannedTaskRecord, - PlannedTaskService, -} from '../../../types'; -import { BlueprintAccumulator } from '../blueprint-accumulator'; -import { clearPlannedTaskGraph, rehydrateAccumulatorFromGraph } from '../planner-run-coordinator'; - -function makeContext(overrides: { - graph: PlannedTaskGraph | null; - runId?: string; -}): { - context: OrchestrationContext; - clear: Mock; - getGraph: Mock; -} { - const clear = vi.fn(async () => { - await Promise.resolve(); - }); - const getGraph = vi.fn(async () => { - await Promise.resolve(); - return overrides.graph; - }); - const plannedTaskService: Partial = { - getGraph, - clear, - }; - const context = { - threadId: 't-1', - runId: overrides.runId ?? 'run-current', - plannedTaskService: plannedTaskService as PlannedTaskService, - } as unknown as OrchestrationContext; - return { context, clear, getGraph }; -} - -describe('clearPlannedTaskGraph', () => { - it('clears the graph when it belongs to this run and is awaiting approval', async () => { - const { context, clear } = makeContext({ - graph: { - planRunId: 'run-current', - status: 'awaiting_approval', - tasks: [], - }, - }); - - await clearPlannedTaskGraph(context); - - expect(clear).toHaveBeenCalledWith('t-1'); - }); - - it('does not clear an active graph from a prior approved plan', async () => { - // A previous `/plan` call already succeeded; its graph is `active` with - // pending checkpoints. A new planner error must not wipe it. - const { context, clear } = makeContext({ - graph: { - planRunId: 'run-previous', - status: 'active', - tasks: [], - }, - }); - - await clearPlannedTaskGraph(context); - - expect(clear).not.toHaveBeenCalled(); - }); - - it('does not clear an awaiting-approval graph that was created by a different planner run', async () => { - // Defensive: a concurrent plan for a different run should not have its - // unapproved graph wiped by this run's error-path cleanup. - const { context, clear } = makeContext({ - graph: { - planRunId: 'run-other', - status: 'awaiting_approval', - tasks: [], - }, - }); - - await clearPlannedTaskGraph(context); - - expect(clear).not.toHaveBeenCalled(); - }); - - it('is a no-op when no graph exists', async () => { - const { context, clear, getGraph } = makeContext({ graph: null }); - - await clearPlannedTaskGraph(context); - - expect(getGraph).toHaveBeenCalled(); - expect(clear).not.toHaveBeenCalled(); - }); - - it('swallows getGraph errors so the caller can return its own error', async () => { - const { context, getGraph } = makeContext({ - graph: { planRunId: 'run-current', status: 'awaiting_approval', tasks: [] }, - }); - getGraph.mockRejectedValueOnce(new Error('db down')); - - await expect(clearPlannedTaskGraph(context)).resolves.toBeUndefined(); - }); -}); - -describe('rehydrateAccumulatorFromGraph (resume revision flow)', () => { - const persistedTasks: PlannedTaskRecord[] = [ - { - id: 'wf-1', - title: "Build 'A' workflow", - kind: 'build-workflow', - spec: 'A', - deps: [], - status: 'planned', - }, - { - id: 'wf-2', - title: "Build 'B' workflow", - kind: 'build-workflow', - spec: 'B', - deps: [], - status: 'planned', - }, - ]; - - it('seeds the accumulator from an awaiting-approval graph so a revision keeps originals', async () => { - // Reproduces "ask for edits -> revise existing plan -> submit again": - // on resume the parent rebuilt a fresh accumulator; without rehydration - // the planner's remove/add would operate on an empty plan and the - // re-submit would drop every original item. - const { context } = makeContext({ - graph: { planRunId: 'run-current', status: 'awaiting_approval', tasks: persistedTasks }, - }); - const accumulator = new BlueprintAccumulator(); - - await rehydrateAccumulatorFromGraph(context, accumulator); - - // Planner revises: drop one original, add a new one, then resubmits. - expect(accumulator.removeItem('wf-2')).toBe(true); - accumulator.addItem({ - kind: 'workflow', - id: 'wf-3', - name: 'C', - purpose: 'C', - integrations: [], - dependsOn: [], - }); - - expect(accumulator.getTaskList().map((t) => t.id)).toEqual(['wf-1', 'wf-3']); - }); - - it('does not reopen an already-approved/active graph', async () => { - const { context } = makeContext({ - graph: { planRunId: 'run-current', status: 'active', tasks: persistedTasks }, - }); - const accumulator = new BlueprintAccumulator(); - - await rehydrateAccumulatorFromGraph(context, accumulator); - - expect(accumulator.isEmpty()).toBe(true); - }); - - it('is a no-op when no graph exists', async () => { - const { context, getGraph } = makeContext({ graph: null }); - const accumulator = new BlueprintAccumulator(); - - await rehydrateAccumulatorFromGraph(context, accumulator); - - expect(getGraph).toHaveBeenCalledWith('t-1'); - expect(accumulator.isEmpty()).toBe(true); - }); - - it('leaves the accumulator empty when getGraph throws', async () => { - const { context, getGraph } = makeContext({ - graph: { planRunId: 'run-current', status: 'awaiting_approval', tasks: persistedTasks }, - }); - getGraph.mockRejectedValueOnce(new Error('db down')); - const accumulator = new BlueprintAccumulator(); - - await expect(rehydrateAccumulatorFromGraph(context, accumulator)).resolves.toBeUndefined(); - expect(accumulator.isEmpty()).toBe(true); - }); -}); diff --git a/packages/@n8n/instance-ai/src/tools/orchestration/__tests__/report-verification-verdict.tool.test.ts b/packages/@n8n/instance-ai/src/tools/orchestration/__tests__/report-verification-verdict.tool.test.ts index fc4623f5c98..e5f6760c01d 100644 --- a/packages/@n8n/instance-ai/src/tools/orchestration/__tests__/report-verification-verdict.tool.test.ts +++ b/packages/@n8n/instance-ai/src/tools/orchestration/__tests__/report-verification-verdict.tool.test.ts @@ -51,6 +51,8 @@ const baseInput = { workItemId: 'wi_test1234', workflowId: 'wf-123', verdict: 'verified' as const, + workflowInspection: + 'Inspected persisted workflow wf-123; the saved graph matches the requested outcome.', summary: 'Workflow ran successfully', }; @@ -83,6 +85,8 @@ describe('report-verification-verdict tool', () => { workItemId: 'wi_test1234', workflowId: 'wf-123', verdict: 'verified', + workflowInspection: + 'Inspected persisted workflow wf-123; the saved graph matches the requested outcome.', }), ); expect((result as { guidance: string }).guidance).toContain('verified successfully'); @@ -373,6 +377,8 @@ describe('report-verification-verdict tool', () => { workflowId: 'wf-123', executionId: 'exec-456', verdict: 'verified', + workflowInspection: + 'Inspected persisted workflow wf-123; the saved graph matches the requested outcome.', failureSignature: 'TypeError:null', failedNodeName: 'Code', diagnosis: 'Null reference', diff --git a/packages/@n8n/instance-ai/src/tools/orchestration/__tests__/verify-built-workflow.tool.test.ts b/packages/@n8n/instance-ai/src/tools/orchestration/__tests__/verify-built-workflow.tool.test.ts index 21f0208551d..984ea1ff42d 100644 --- a/packages/@n8n/instance-ai/src/tools/orchestration/__tests__/verify-built-workflow.tool.test.ts +++ b/packages/@n8n/instance-ai/src/tools/orchestration/__tests__/verify-built-workflow.tool.test.ts @@ -24,8 +24,15 @@ type VerifyBuiltWorkflowOutput = { preview: string; truncated: boolean; chars: number; + simulated?: boolean; }>; + simulatedNodes?: Array<{ nodeName: string; reason: string }>; + simulationNote?: string; + lastNodeExecuted?: string; + nodesNotReached?: string[]; + coverageNote?: string; data?: Record; + remediation?: { category: string; shouldEdit: boolean; reason?: string }; }; function createContext(overrides: Partial = {}): OrchestrationContext { @@ -38,6 +45,7 @@ function createContext(overrides: Partial = {}): Orchestra workflowId: 'wf_1', submitted: true, triggerType: 'manual_or_testable', + nodeSimulationPlan: [], needsUserInput: false, summary: 'Built', }), @@ -94,6 +102,7 @@ describe('verify-built-workflow tool — remediation guard', () => { workflowId: 'wf_1', submitted: true, triggerType: 'manual_or_testable', + nodeSimulationPlan: [], needsUserInput: false, mockedCredentialTypes: ['gmailOAuth2'], mockedNodeNames: ['Gmail'], @@ -131,6 +140,7 @@ describe('verify-built-workflow tool — remediation guard', () => { workflowId: 'wf_1', submitted: true, triggerType: 'manual_or_testable', + nodeSimulationPlan: [], needsUserInput: false, mockedCredentialTypes: ['slackApi'], mockedNodeNames: ['Slack'], @@ -167,6 +177,7 @@ describe('verify-built-workflow tool — remediation guard', () => { workflowId: 'wf_1', submitted: true, triggerType: 'manual_or_testable', + nodeSimulationPlan: [], needsUserInput: false, mockedCredentialTypes: ['gmailOAuth2'], mockedNodeNames: ['Gmail'], @@ -355,6 +366,8 @@ type ExecutionRunResult = { executionId?: string | null; status: 'success' | 'error' | 'waiting' | 'running' | 'unknown'; data?: Record; + executedNodeNames?: string[]; + lastNodeExecuted?: string; error?: string; }; @@ -385,6 +398,7 @@ function makeBuildOutcome(overrides: Partial = {}): Workfl workflowId: 'wf-1', submitted: true, triggerType: 'manual_or_testable', + nodeSimulationPlan: [], needsUserInput: false, summary: 'built ok', ...overrides, @@ -401,9 +415,6 @@ function makeContext( overrides: { workflowNodes?: Array<{ name?: string; type: string; parameters?: Record }>; tableRows?: Record>>; - queriesAfterRun?: Record>>; - /** Throw `snapshotError` on the first queryRows call for the given table id. */ - snapshotErrors?: Record; } = {}, ) { const updateBuildOutcome = vi.fn( @@ -423,35 +434,16 @@ function makeContext( ); type QueryRowsResult = { count: number; data: Array> }; - /** - * Track which dataTableIds we've already "seen a last page for" — any call - * after the snapshot phase for a given table switches to `queriesAfterRun`. - */ - const snapshotDone = new Set(); const queryRows = vi.fn( async ( dataTableId: string, opts?: { limit?: number; offset?: number }, ): Promise => { - const snapshotError = overrides.snapshotErrors?.[dataTableId]; - if (snapshotError && !snapshotDone.has(dataTableId)) { - // Mark done so post-run phase doesn't keep throwing if that matters. - snapshotDone.add(dataTableId); - throw snapshotError; - } + const rows = overrides.tableRows?.[dataTableId] ?? []; const limit = opts?.limit ?? Number.MAX_SAFE_INTEGER; const offset = opts?.offset ?? 0; - const baseRows: Array> = snapshotDone.has(dataTableId) - ? (overrides.queriesAfterRun?.[dataTableId] ?? overrides.tableRows?.[dataTableId] ?? []) - : (overrides.tableRows?.[dataTableId] ?? []); - const page = baseRows.slice(offset, offset + limit); - // If this page is the last one of the snapshot (fewer than `limit` rows), - // any subsequent calls for this table should fall through to post-run data. - if (!snapshotDone.has(dataTableId) && page.length < limit) { - snapshotDone.add(dataTableId); - } await Promise.resolve(); - return { count: baseRows.length, data: page }; + return { count: rows.length, data: rows.slice(offset, offset + limit) }; }, ); type DeleteRowsFilter = { @@ -716,152 +708,6 @@ describe('verify-built-workflow tool', () => { expect(updateBuildOutcome.mock.calls[0][1].verification?.evidence?.producedOutputRows).toBe(14); }); - it('cleans up rows inserted by the verification run, reading row IDs from the node output', async () => { - const { ctx, deleteRows } = makeContext( - makeBuildOutcome(), - { - executionId: 'exec-4', - status: 'success', - // The insert node's output is what drives the delete set — a concurrent - // writer's row would never appear here, so it's safe from cleanup. - data: { - 'Lead Form': [{ name: 'Test' }], - 'Insert Lead': [{ id: 3, name: 'Test', email: 'test@example.com' }], - }, - }, - { - workflowNodes: [ - { - name: 'Insert Lead', - type: 'n8n-nodes-base.dataTable', - parameters: { operation: 'insert', dataTableId: 'tbl-leads' }, - }, - ], - tableRows: { 'tbl-leads': [{ id: 1 }, { id: 2 }] }, - }, - ); - - const result = await runTool(ctx, { - workItemId: 'wi-1', - workflowId: 'wf-1', - inputData: { name: 'Test' }, - }); - - expect(result.success).toBe(true); - expect(deleteRows).toHaveBeenCalledTimes(1); - const call = deleteRows.mock.calls[0]; - expect(call).toBeDefined(); - expect(call[0]).toBe('tbl-leads'); - expect(call[1]).toEqual({ - type: 'or', - filters: [{ columnName: 'id', condition: 'eq', value: 3 }], - }); - }); - - it('cleans up inserted rows when the execution output is wrapped', async () => { - const { ctx, deleteRows } = makeContext( - makeBuildOutcome(), - { - executionId: 'exec-wrapped-insert', - status: 'success', - data: { - 'Insert Lead': wrapExecutionOutput([{ id: 3, name: 'Test' }]), - }, - }, - { - workflowNodes: [ - { - name: 'Insert Lead', - type: 'n8n-nodes-base.dataTable', - parameters: { operation: 'insert', dataTableId: 'tbl-leads' }, - }, - ], - tableRows: { 'tbl-leads': [{ id: 1 }, { id: 2 }] }, - }, - ); - - const result = await runTool(ctx, { workItemId: 'wi-1', workflowId: 'wf-1' }); - - expect(result.success).toBe(true); - expect(deleteRows.mock.calls[0][1]).toEqual({ - type: 'or', - filters: [{ columnName: 'id', condition: 'eq', value: 3 }], - }); - }); - - it('never deletes rows produced by an upsert node, even when the ID looks new', async () => { - // Upsert outputs cannot distinguish a freshly-created row from a match on - // an existing row. A concurrent writer inserting between snapshot and - // upsert would yield an ID that looks "new" to ID-diff but actually - // belongs to that writer — deleting it would destroy production data. - // We therefore skip cleanup for upsert nodes entirely. - const { ctx, deleteRows } = makeContext( - makeBuildOutcome(), - { - executionId: 'exec-upsert', - status: 'success', - data: { - // id=99 is not in the pre-verify snapshot — under the old - // ID-diff logic this would be deleted. The new contract leaves - // it alone because we cannot prove it was created by verify. - 'Upsert Lead': [{ id: 99, name: 'Could be a concurrent writer' }], - }, - }, - { - workflowNodes: [ - { - name: 'Upsert Lead', - type: 'n8n-nodes-base.dataTable', - parameters: { operation: 'upsert', dataTableId: 'tbl-leads' }, - }, - ], - tableRows: { 'tbl-leads': [{ id: 1 }, { id: 2 }] }, - }, - ); - - const result = await runTool(ctx, { workItemId: 'wi-1', workflowId: 'wf-1' }); - - expect(result.success).toBe(true); - expect(deleteRows).not.toHaveBeenCalled(); - }); - - it('does not delete rows from concurrent writers that never appeared in the node output', async () => { - const { ctx, deleteRows } = makeContext( - makeBuildOutcome(), - { - executionId: 'exec-concurrent', - status: 'success', - // The verify's insert node only emitted id=3; a concurrent writer that - // added id=4 after the snapshot would be invisible to us and must NOT - // be deleted. This test asserts the delete set is driven purely by - // node output, not by a post-verify table-wide diff. - data: { - 'Insert Lead': [{ id: 3, name: 'VerifyRow' }], - }, - }, - { - workflowNodes: [ - { - name: 'Insert Lead', - type: 'n8n-nodes-base.dataTable', - parameters: { operation: 'insert', dataTableId: 'tbl-leads' }, - }, - ], - tableRows: { 'tbl-leads': [{ id: 1 }, { id: 2 }] }, - }, - ); - - const result = await runTool(ctx, { workItemId: 'wi-1', workflowId: 'wf-1' }); - - expect(result.success).toBe(true); - expect(deleteRows).toHaveBeenCalledTimes(1); - // Only id=3 (the row our insert node emitted), not id=4 from the concurrent writer. - expect(deleteRows.mock.calls[0][1]).toEqual({ - type: 'or', - filters: [{ columnName: 'id', condition: 'eq', value: 3 }], - }); - }); - it('treats a waiting status with output as a successful run (e.g. Form Trigger response page)', async () => { const { ctx, updateBuildOutcome } = makeContext(makeBuildOutcome(), { executionId: 'exec-form-1', @@ -902,23 +748,51 @@ describe('verify-built-workflow tool', () => { expect(result.success).toBe(false); }); - it('paginates the pre-verify snapshot so a pathological insert output cannot delete a pre-existing row past the first page', async () => { - // Build a table with 1500 rows — past the snapshot page size. - // The insert node's output is `id=1234` (a row that already existed). If - // pagination is broken the snapshot only contains ids 1..1000, and the - // snapshot's defensive filter wouldn't protect id=1234 — the cleanup - // would delete a pre-existing row. - const bigTable: Array> = Array.from({ length: 1500 }, (_v, i) => ({ - id: i + 1, - })); + it('treats waiting as a failure when the build has a simulation plan (unsimulated user-action node)', async () => { + // With a plan, every legitimate pause should have been pinned — a + // `waiting` result means a user-action node slipped past classification + // and everything downstream went unverified. + const { ctx } = makeContext( + makeBuildOutcome({ + nodeSimulationPlan: [ + { + nodeName: 'Send Slack', + verdict: 'simulate', + reason: 'Sends a message', + confidence: 'high', + source: 'deterministic', + }, + ], + }), + { + executionId: 'exec-waiting-plan', + status: 'waiting', + data: { 'Community Pause': [{ ok: true }] }, + }, + ); + + const result = await runTool(ctx, { workItemId: 'wi-1', workflowId: 'wf-1' }); + + expect(result.success).toBe(false); + expect(result.remediation).toMatchObject({ + category: 'needs_setup', + shouldEdit: false, + reason: 'unsimulated_user_action_node', + }); + }); + + it('never reads or deletes data-table rows, even when the workflow contains insert nodes', async () => { + // Destructive nodes are simulated via the node simulation plan; the verify + // tool itself must not touch data tables (the old snapshot/cleanup + // machinery is gone — deleting rows based on node output is never safe + // when outputs can be fabricated fixtures). const { ctx, deleteRows, queryRows } = makeContext( makeBuildOutcome(), { - executionId: 'exec-insert-past-page', + executionId: 'exec-4', status: 'success', data: { - // Insert node's output references id=1234 — beyond the single-page cap. - 'Insert Lead': [{ id: 1234, name: 'Existing', stage: 'qualified' }], + 'Insert Lead': [{ id: 3, name: 'Test', email: 'test@example.com' }], }, }, { @@ -929,32 +803,256 @@ describe('verify-built-workflow tool', () => { parameters: { operation: 'insert', dataTableId: 'tbl-leads' }, }, ], - tableRows: { 'tbl-leads': bigTable }, + tableRows: { 'tbl-leads': [{ id: 1 }, { id: 2 }] }, }, ); const result = await runTool(ctx, { workItemId: 'wi-1', workflowId: 'wf-1' }); expect(result.success).toBe(true); - // Must have made more than one snapshot query to cover a 1500-row table. - const snapshotCalls = queryRows.mock.calls.filter( - (c) => c[0] === 'tbl-leads' && typeof (c[1] as { offset?: number })?.offset === 'number', - ); - expect(snapshotCalls.length).toBeGreaterThan(1); - // And the pre-existing row must not have been deleted. + expect(queryRows).not.toHaveBeenCalled(); expect(deleteRows).not.toHaveBeenCalled(); }); +}); - it('skips insert cleanup for a table when the pre-verify snapshot read fails', async () => { - const { ctx, deleteRows } = makeContext( - makeBuildOutcome(), +describe('verify-built-workflow tool — node simulation plan', () => { + const simulateVerdict = (nodeName: string, reason = 'Sends a message') => ({ + nodeName, + verdict: 'simulate' as const, + reason, + confidence: 'high' as const, + source: 'deterministic' as const, + }); + const executeVerdict = (nodeName: string) => ({ + nodeName, + verdict: 'execute' as const, + reason: 'Reads data', + confidence: 'high' as const, + source: 'deterministic' as const, + }); + + it('pins unwrapped fixture items for simulated nodes, merged over legacy credential markers', async () => { + const { ctx } = makeContext( + makeBuildOutcome({ + verificationPinData: { Gmail: [{ _mockedCredential: 'gmailOAuth2' }] }, + nodeSimulationPlan: [simulateVerdict('Send Slack'), executeVerdict('Get Rows')], + simulationFixtures: { 'Send Slack': [{ ok: true, ts: '1718000000.1' }] }, + }), + { executionId: 'exec-sim', status: 'success', data: {} }, + ); + + await runTool(ctx, { workItemId: 'wi-1', workflowId: 'wf-1' }); + + const run = vi.mocked(ctx.domainContext.executionService.run); + expect(run).toHaveBeenCalledTimes(1); + // Fixture items are passed unwrapped — the adapter wraps each in {json}. + expect(run.mock.calls[0][2]).toMatchObject({ + pinData: { + Gmail: [{ _mockedCredential: 'gmailOAuth2' }], + 'Send Slack': [{ ok: true, ts: '1718000000.1' }], + }, + }); + }); + + it('pins an empty item for simulate-verdict nodes that have no fixture', async () => { + const { ctx } = makeContext( + makeBuildOutcome({ + nodeSimulationPlan: [simulateVerdict('Send Slack')], + }), + { executionId: 'exec-sim', status: 'success', data: {} }, + ); + + await runTool(ctx, { workItemId: 'wi-1', workflowId: 'wf-1' }); + + const run = vi.mocked(ctx.domainContext.executionService.run); + expect(run.mock.calls[0][2]).toMatchObject({ + pinData: { 'Send Slack': [{}] }, + }); + }); + + it('does not pin execute-verdict nodes', async () => { + const { ctx } = makeContext( + makeBuildOutcome({ + nodeSimulationPlan: [executeVerdict('Get Rows')], + }), + { executionId: 'exec-sim', status: 'success', data: {} }, + ); + + await runTool(ctx, { workItemId: 'wi-1', workflowId: 'wf-1' }); + + const run = vi.mocked(ctx.domainContext.executionService.run); + expect(run.mock.calls[0][2]).toMatchObject({ pinData: undefined }); + }); + + it('marks simulated nodes in previews and reports them with reasons', async () => { + const { ctx } = makeContext( + makeBuildOutcome({ + nodeSimulationPlan: [simulateVerdict('Send Slack', 'Sends a message to a Slack channel')], + simulationFixtures: { 'Send Slack': [{ ok: true }] }, + }), { - executionId: 'exec-snapshot-fail', + executionId: 'exec-sim', status: 'success', data: { - 'Insert Lead': [{ id: 42, name: 'Existing', stage: 'qualified' }], + 'Send Slack': [{ ok: true }], + Transform: [{ value: 1 }], }, }, + ); + + const result = await runTool(ctx, { workItemId: 'wi-1', workflowId: 'wf-1' }); + + expect(result.success).toBe(true); + const previews = result.nodePreviews ?? []; + expect(previews.find((p) => p.nodeName === 'Send Slack')).toMatchObject({ simulated: true }); + expect(previews.find((p) => p.nodeName === 'Transform')?.simulated).toBeUndefined(); + expect(result.simulatedNodes).toEqual([ + { nodeName: 'Send Slack', reason: 'Sends a message to a Slack channel' }, + ]); + expect(result.simulationNote).toContain('Send Slack'); + expect(result.simulationNote).toContain('no real external writes'); + }); + + it('fails closed when the build outcome has no simulation plan at all', async () => { + // An undefined plan means the outcome predates classification or + // classification failed — nothing shields destructive nodes in that run. + const { ctx, updateBuildOutcome } = makeContext( + makeBuildOutcome({ nodeSimulationPlan: undefined }), + { + executionId: 'exec-no-plan', + status: 'success', + data: { 'Send Slack': [{ ok: true }] }, + }, + ); + + const result = await runTool(ctx, { workItemId: 'wi-1', workflowId: 'wf-1' }); + + expect(result.success).toBe(false); + expect(result.error).toContain('no simulation plan'); + expect(result.remediation).toMatchObject({ + category: 'blocked', + shouldEdit: false, + reason: 'missing_simulation_plan', + }); + expect(ctx.domainContext.executionService.run).not.toHaveBeenCalled(); + expect(updateBuildOutcome.mock.calls[0][1].verification).toMatchObject({ + attempted: true, + success: false, + status: 'unknown', + failureSignature: 'missing_simulation_plan', + }); + expect(ctx.workflowTaskService.reportVerificationVerdict).toHaveBeenCalledWith( + expect.objectContaining({ + verdict: 'failed_terminal', + failureSignature: 'missing_simulation_plan', + }), + ); + expect(ctx.logger.warn).toHaveBeenCalledWith( + expect.stringContaining('no simulation plan'), + expect.objectContaining({ workItemId: 'wi-1' }), + ); + }); + + it('does not warn when the plan is empty (classified, nothing to simulate)', async () => { + const { ctx } = makeContext(makeBuildOutcome({ nodeSimulationPlan: [] }), { + executionId: 'exec-empty-plan', + status: 'success', + data: { Transform: [{ value: 1 }] }, + }); + + const result = await runTool(ctx, { workItemId: 'wi-1', workflowId: 'wf-1' }); + + expect(result.success).toBe(true); + expect(result.simulationNote).toBeUndefined(); + expect(ctx.logger.warn).not.toHaveBeenCalled(); + }); + + it('reports planned simulations the execution never reached as unverified (empty-read dead-end)', async () => { + // Reproduces the order-fulfillment scenario: a data-table lookup on an + // empty table returns zero items mid-chain, so everything downstream — + // including all planned simulations — never runs. The run is still a + // legitimate `success`, but the tool must not claim those nodes were + // simulated, and must surface the coverage gap. + const { ctx } = makeContext( + makeBuildOutcome({ + nodeSimulationPlan: [ + executeVerdict('Look Up Order'), + simulateVerdict('Wait 2 Hours', 'Pauses the workflow'), + simulateVerdict('Send Follow-up Email', 'Sends an email'), + simulateVerdict('Mark Order Fulfilled', 'Updates a row'), + ], + simulationFixtures: { + 'Wait 2 Hours': [{}], + 'Send Follow-up Email': [{ id: 'msg-1' }], + 'Mark Order Fulfilled': [{ id: 1 }], + }, + }), + { + executionId: 'exec-dead-end', + status: 'success', + data: { + 'Order Received': [{ body: { orderId: 'ORD-1001' } }], + 'Wait 10s': [{ body: { orderId: 'ORD-1001' } }], + }, + // The lookup ran but produced zero items — present here, absent from data. + executedNodeNames: ['Order Received', 'Wait 10s', 'Look Up Order'], + lastNodeExecuted: 'Look Up Order', + }, + ); + + const result = await runTool(ctx, { workItemId: 'wi-1', workflowId: 'wf-1' }); + + expect(result.success).toBe(true); + // The lookup ran (zero output) — it counts as executed, not unreached. + expect(result.nodesExecuted).toContain('Look Up Order'); + expect(result.lastNodeExecuted).toBe('Look Up Order'); + // None of the planned simulations actually happened. + expect(result.simulatedNodes).toBeUndefined(); + expect(result.simulationNote).toBeUndefined(); + expect(result.nodesNotReached).toEqual([ + 'Wait 2 Hours', + 'Send Follow-up Email', + 'Mark Order Fulfilled', + ]); + expect(result.coverageNote).toContain('UNVERIFIED'); + expect(result.coverageNote).toContain('Look Up Order'); + expect(result.coverageNote).toContain('Seed matching test data'); + }); + + it('persists unreached nodes in the verification evidence', async () => { + const { ctx, updateBuildOutcome } = makeContext( + makeBuildOutcome({ + nodeSimulationPlan: [simulateVerdict('Send Slack')], + }), + { + executionId: 'exec-evidence', + status: 'success', + data: { Trigger: [{ ok: true }] }, + executedNodeNames: ['Trigger'], + lastNodeExecuted: 'Trigger', + }, + ); + + await runTool(ctx, { workItemId: 'wi-1', workflowId: 'wf-1' }); + + expect(updateBuildOutcome.mock.calls[0][1].verification?.evidence?.nodesNotReached).toEqual([ + 'Send Slack', + ]); + }); + + it('never deletes rows whose IDs come from fabricated fixture output', async () => { + const { ctx, deleteRows } = makeContext( + makeBuildOutcome({ + nodeSimulationPlan: [simulateVerdict('Insert Lead', 'Inserts a row')], + // Fabricated fixture ID that collides with a real row — must never + // reach a delete call. + simulationFixtures: { 'Insert Lead': [{ id: 3 }] }, + }), + { + executionId: 'exec-sim', + status: 'success', + data: { 'Insert Lead': [{ id: 3 }] }, + }, { workflowNodes: [ { @@ -963,34 +1061,7 @@ describe('verify-built-workflow tool', () => { parameters: { operation: 'insert', dataTableId: 'tbl-leads' }, }, ], - tableRows: { 'tbl-leads': [{ id: 42 }] }, - snapshotErrors: { 'tbl-leads': new Error('DB unavailable') }, - }, - ); - - const result = await runTool(ctx, { workItemId: 'wi-1', workflowId: 'wf-1' }); - - expect(result.success).toBe(true); - expect(deleteRows).not.toHaveBeenCalled(); - }); - - it('does not delete rows for dataTable nodes that only read', async () => { - const { ctx, deleteRows } = makeContext( - makeBuildOutcome(), - { - executionId: 'exec-5', - status: 'success', - data: { 'Lookup Lead': [{ id: 1, name: 'Existing' }] }, - }, - { - workflowNodes: [ - { - name: 'Lookup Lead', - type: 'n8n-nodes-base.dataTable', - parameters: { operation: 'get', dataTableId: 'tbl-leads' }, - }, - ], - tableRows: { 'tbl-leads': [{ id: 1 }] }, + tableRows: { 'tbl-leads': [{ id: 1 }, { id: 2 }, { id: 3 }] }, }, ); diff --git a/packages/@n8n/instance-ai/src/tools/orchestration/add-plan-item.tool.ts b/packages/@n8n/instance-ai/src/tools/orchestration/add-plan-item.tool.ts deleted file mode 100644 index c817dde057d..00000000000 --- a/packages/@n8n/instance-ai/src/tools/orchestration/add-plan-item.tool.ts +++ /dev/null @@ -1,123 +0,0 @@ -/** - * Plan item tools — add and remove items from the plan progressively. - * - * The planner sub-agent uses these during initial planning (add-plan-item) - * and during revision after user rejection (both add and remove). - * Each call publishes a `tasks-update` event so the UI updates in real time. - */ - -import { Tool } from '@n8n/agents'; -import { z } from 'zod'; - -import type { BlueprintAccumulator } from './blueprint-accumulator'; -import { - blueprintCheckpointItemSchema, - blueprintDelegateItemSchema, - blueprintWorkflowItemSchema, -} from './blueprint.schema'; -import type { OrchestrationContext } from '../../types'; - -/** Publish the current accumulator state as a tasks-update event with full planItems. */ -export function publishPlanUpdate( - accumulator: BlueprintAccumulator, - context: OrchestrationContext, -): void { - const taskItems = accumulator.getTaskItemsForEvent(); - const planItems = accumulator.getTaskList().map((t) => ({ - id: t.id, - title: t.title, - kind: t.kind, - spec: t.spec, - deps: t.deps, - ...(t.tools ? { tools: t.tools } : {}), - ...(t.workflowId ? { workflowId: t.workflowId } : {}), - })); - context.eventBus.publish(context.threadId, { - type: 'tasks-update', - runId: context.runId, - agentId: context.orchestratorAgentId, - payload: { tasks: { tasks: taskItems }, planItems }, - }); -} - -const addPlanItemInputSchema = z.object({ - summary: z.string().optional().describe('1-2 sentence plan overview — set on first call'), - assumptions: z - .array(z.string()) - .optional() - .describe('Assumptions the plan relies on — set on first call'), - item: z.discriminatedUnion('kind', [ - blueprintWorkflowItemSchema.extend({ kind: z.literal('workflow') }), - blueprintDelegateItemSchema.extend({ kind: z.literal('delegate') }), - blueprintCheckpointItemSchema.extend({ kind: z.literal('checkpoint') }), - ]), -}); - -export function createAddPlanItemTool( - accumulator: BlueprintAccumulator, - context: OrchestrationContext, -) { - return new Tool('add-plan-item') - .description( - 'Add a single plan item (workflow, delegate, or checkpoint task). ' + - 'Call once per item as you design it — each call makes the item visible to the user immediately. ' + - 'Add workflow items only if the request requires automation. ' + - 'Add a checkpoint item AFTER its target workflow(s) so the orchestrator can verify the result end-to-end. ' + - 'Set summary and assumptions on your first call.', - ) - .input(addPlanItemInputSchema) - .output(z.object({ result: z.string() })) - .handler(async (input: z.infer) => { - if (input.summary !== undefined || input.assumptions !== undefined) { - accumulator.updateMeta(input.summary, input.assumptions); - } - - const task = accumulator.addItem(input.item); - - await context.taskStorage.save(context.threadId, { - tasks: accumulator.getTaskItemsForEvent(), - }); - publishPlanUpdate(accumulator, context); - - const totalCount = accumulator.getTaskItemsForEvent().length; - return { - result: `Added: ${task.title} (${totalCount} item${totalCount === 1 ? '' : 's'} total)`, - }; - }) - .build(); -} - -export function createRemovePlanItemTool( - accumulator: BlueprintAccumulator, - context: OrchestrationContext, -) { - return new Tool('remove-plan-item') - .description( - 'Remove a plan item by ID. Use during plan revision to drop items the user no longer wants.', - ) - .input( - z.object({ - id: z.string().describe('ID of the plan item to remove'), - }), - ) - .output(z.object({ result: z.string() })) - .handler(async (input: { id: string }) => { - const removed = accumulator.removeItem(input.id); - - await context.taskStorage.save(context.threadId, { - tasks: accumulator.getTaskItemsForEvent(), - }); - publishPlanUpdate(accumulator, context); - - const totalCount = accumulator.getTaskItemsForEvent().length; - if (removed) { - return { - result: `Removed item ${input.id}. ${totalCount} item${totalCount === 1 ? '' : 's'} remaining.`, - }; - } - return { - result: `Item ${input.id} not found. ${totalCount} item${totalCount === 1 ? '' : 's'} in plan.`, - }; - }) - .build(); -} diff --git a/packages/@n8n/instance-ai/src/tools/orchestration/blueprint-accumulator.ts b/packages/@n8n/instance-ai/src/tools/orchestration/blueprint-accumulator.ts deleted file mode 100644 index 44a1bac3e7c..00000000000 --- a/packages/@n8n/instance-ai/src/tools/orchestration/blueprint-accumulator.ts +++ /dev/null @@ -1,273 +0,0 @@ -/** - * BlueprintAccumulator — incremental accumulator for blueprint items. - * - * Replaces the old all-at-once `blueprintToTasks()` conversion. The planner - * calls `addItem()` once per blueprint item; each call converts the item to a - * `PlannedTaskInput` and stores it. After the planner finishes, - * `reconcileDependencies()` fixes any late dep-inference gaps and - * `getTaskList()` returns the full task array for `createPlan()`. - */ - -import type { - BlueprintCheckpointItem, - BlueprintDelegateItem, - BlueprintWorkflowItem, -} from './blueprint.schema'; - -// --------------------------------------------------------------------------- -// PlannedTaskInput — the shape consumed by createPlan() -// --------------------------------------------------------------------------- - -export interface PlannedTaskInput { - id: string; - title: string; - kind: string; - spec: string; - deps: string[]; - tools?: string[]; - workflowId?: string; -} - -// --------------------------------------------------------------------------- -// Discriminated item union — input to addItem() -// --------------------------------------------------------------------------- - -type BlueprintItem = - | (BlueprintWorkflowItem & { kind: 'workflow' }) - | (BlueprintDelegateItem & { kind: 'delegate' }) - | (BlueprintCheckpointItem & { kind: 'checkpoint' }); - -// --------------------------------------------------------------------------- -// Per-item conversion helpers -// --------------------------------------------------------------------------- - -function workflowItemToTask(wf: BlueprintWorkflowItem, assumptions: string[]): PlannedTaskInput { - const specParts = [wf.purpose]; - if (wf.triggerDescription) specParts.push(`Trigger: ${wf.triggerDescription}`); - if (wf.integrations.length > 0) specParts.push(`Integrations: ${wf.integrations.join(', ')}`); - - // Append blueprint assumptions so the builder has design context - if (assumptions.length > 0) { - specParts.push('\nAssumptions:'); - for (const a of assumptions) { - specParts.push(`- ${a}`); - } - } - - return { - id: wf.id, - title: `Build '${wf.name}' workflow`, - kind: 'build-workflow', - spec: specParts.join('\n'), - deps: wf.dependsOn, - workflowId: wf.existingWorkflowId, - }; -} - -function delegateItemToTask(di: BlueprintDelegateItem): PlannedTaskInput { - return { - id: di.id, - title: di.title, - kind: 'delegate', - spec: di.description, - deps: di.dependsOn, - tools: di.requiredTools, - }; -} - -function checkpointItemToTask(c: BlueprintCheckpointItem): PlannedTaskInput { - return { - id: c.id, - title: c.title, - kind: 'checkpoint', - spec: c.instructions, - deps: c.dependsOn, - }; -} - -// --------------------------------------------------------------------------- -// BlueprintAccumulator -// --------------------------------------------------------------------------- - -export class BlueprintAccumulator { - private workflows: BlueprintWorkflowItem[] = []; - - private delegateItems: BlueprintDelegateItem[] = []; - - private checkpoints: BlueprintCheckpointItem[] = []; - - private tasks: PlannedTaskInput[] = []; - - private summary = ''; - - private assumptions: string[] = []; - - private approved = false; - - private denied = false; - - /** Route item by kind, upsert into arrays, convert to task, return the task. */ - addItem(item: BlueprintItem): PlannedTaskInput { - let task: PlannedTaskInput; - - switch (item.kind) { - case 'workflow': { - const { kind: _, ...wf } = item; - this.upsertArray(this.workflows, wf); - task = workflowItemToTask(wf, this.assumptions); - break; - } - case 'delegate': { - const { kind: _, ...di } = item; - this.upsertArray(this.delegateItems, di); - task = delegateItemToTask(di); - break; - } - case 'checkpoint': { - const { kind: _, ...c } = item; - this.upsertArray(this.checkpoints, c); - task = checkpointItemToTask(c); - break; - } - } - - this.upsertTask(task); - return task; - } - - /** Update plan-level metadata (summary and/or assumptions). */ - updateMeta(summary?: string, assumptions?: string[]): void { - if (summary !== undefined) this.summary = summary; - if (assumptions !== undefined) this.assumptions = assumptions; - } - - /** Return the full task list for createPlan(). */ - getTaskList(): PlannedTaskInput[] { - return [...this.tasks]; - } - - /** Return simplified task items for tasks-update events. */ - getTaskItemsForEvent(): Array<{ id: string; description: string; status: 'todo' }> { - return this.tasks.map((t) => ({ - id: t.id, - description: t.title, - status: 'todo' as const, - })); - } - - /** - * Re-render workflow specs against the latest plan metadata and assumptions. - */ - reconcileDependencies(): void { - for (let i = 0; i < this.workflows.length; i++) { - const wf = this.workflows[i]; - const updatedTask = workflowItemToTask(wf, this.assumptions); - this.upsertTask(updatedTask); - } - } - - /** Remove an item by ID. Returns true if found and removed. - * Cascade-removes any checkpoint that loses its last build-workflow dep as - * a result — otherwise submit-plan would later fail validation because - * checkpoints must depend on at least one build-workflow task. */ - removeItem(id: string): boolean { - const taskIdx = this.tasks.findIndex((t) => t.id === id); - if (taskIdx < 0) return false; - this.tasks.splice(taskIdx, 1); - // Also remove from the typed item arrays - this.removeFromArray(this.workflows, id); - this.removeFromArray(this.delegateItems, id); - this.removeFromArray(this.checkpoints, id); - // Clean up dangling dep references in remaining tasks - for (const task of this.tasks) { - task.deps = task.deps.filter((dep) => dep !== id); - } - - // Cascade-remove orphaned checkpoints: any checkpoint whose deps no - // longer reference a build-workflow task is invalid and must go too. - const workflowIds = new Set(this.workflows.map((w) => w.id)); - const orphanedCheckpointIds: string[] = []; - for (const cp of this.checkpoints) { - const stillHasWorkflowDep = cp.dependsOn.some((depId) => workflowIds.has(depId)); - if (!stillHasWorkflowDep) { - orphanedCheckpointIds.push(cp.id); - } - } - for (const orphanId of orphanedCheckpointIds) { - this.removeItem(orphanId); - } - - return true; - } - - /** Load pre-existing tasks into the accumulator (for revision flows). */ - loadFromTasks(tasks: PlannedTaskInput[]): void { - for (const t of tasks) { - this.upsertTask(t); - } - } - - /** Mark the plan as approved by the user (called by submit-plan on approval). */ - markApproved(): void { - this.approved = true; - } - - /** Whether the user approved the plan via submit-plan. */ - isApproved(): boolean { - return this.approved; - } - - /** Mark the plan as denied by the user. Once denied, submit-plan short-circuits - * any further calls so the planner cannot re-suspend the user for approval. */ - markDenied(): void { - this.denied = true; - } - - /** Whether the user denied the plan outright via submit-plan. */ - isDenied(): boolean { - return this.denied; - } - - /** Whether any items have been added. */ - isEmpty(): boolean { - return this.tasks.length === 0; - } - - /** Get the plan summary. */ - getSummary(): string { - return this.summary; - } - - /** Get the plan assumptions. */ - getAssumptions(): string[] { - return [...this.assumptions]; - } - - // ── Private helpers ────────────────────────────────────────────────── - - /** Upsert into a typed item array by ID (replace if exists, append if not). */ - private upsertArray(arr: T[], item: T): void { - const idx = arr.findIndex((existing) => existing.id === item.id); - if (idx >= 0) { - arr[idx] = item; - } else { - arr.push(item); - } - } - - /** Remove from a typed item array by ID. */ - private removeFromArray(arr: T[], id: string): void { - const idx = arr.findIndex((item) => item.id === id); - if (idx >= 0) arr.splice(idx, 1); - } - - /** Upsert into the tasks array by ID. */ - private upsertTask(task: PlannedTaskInput): void { - const idx = this.tasks.findIndex((t) => t.id === task.id); - if (idx >= 0) { - this.tasks[idx] = task; - } else { - this.tasks.push(task); - } - } -} diff --git a/packages/@n8n/instance-ai/src/tools/orchestration/blueprint.schema.ts b/packages/@n8n/instance-ai/src/tools/orchestration/blueprint.schema.ts deleted file mode 100644 index 5247eb8e4c0..00000000000 --- a/packages/@n8n/instance-ai/src/tools/orchestration/blueprint.schema.ts +++ /dev/null @@ -1,75 +0,0 @@ -import { z } from 'zod'; - -// --------------------------------------------------------------------------- -// Blueprint item schemas — domain-level descriptions of what to build -// --------------------------------------------------------------------------- - -export const blueprintWorkflowItemSchema = z.object({ - id: z.string().describe('Stable ID — preserved as task ID in the execution plan'), - name: z.string().describe('Workflow display name'), - purpose: z - .string() - .describe( - '1-2 sentence description of what the workflow does and why. Include any data table names, columns, seed/import needs, or existing-table requirements the workflow depends on.', - ), - integrations: z.array(z.string()).describe('Services/APIs this workflow connects'), - triggerDescription: z - .string() - .optional() - .describe('Trigger type in a few words (e.g. "Webhook POST", "Schedule hourly")'), - existingWorkflowId: z - .string() - .optional() - .describe('ID of existing workflow to modify (omit for new workflows)'), - dependsOn: z - .array(z.string()) - .default([]) - .describe('IDs of items that must complete before this one starts'), -}); - -export const blueprintDelegateItemSchema = z.object({ - id: z.string().describe('Stable ID — preserved as task ID'), - title: z.string().describe('Short task title'), - description: z.string().describe('Detailed task description'), - requiredTools: z.array(z.string()).describe('Tool names the delegate needs'), - dependsOn: z.array(z.string()).default([]), -}); - -export const blueprintCheckpointItemSchema = z.object({ - id: z.string().describe('Stable ID — preserved as task ID'), - title: z - .string() - .describe( - 'User-readable verification goal (e.g., "Verify Daily Email workflow runs without errors")', - ), - instructions: z - .string() - .describe( - 'Detailed verification steps the orchestrator must execute — which tools to call, the expected pass condition. The orchestrator runs this itself (no sub-agent).', - ), - dependsOn: z - .array(z.string()) - .min(1) - .describe('IDs of items this checkpoint verifies. Must include at least one workflow item ID.'), -}); - -// --------------------------------------------------------------------------- -// Top-level blueprint schema -// --------------------------------------------------------------------------- - -export const planningBlueprintSchema = z.object({ - summary: z.string().describe('1-2 sentence overview of the solution'), - workflows: z.array(blueprintWorkflowItemSchema).default([]), - delegateItems: z.array(blueprintDelegateItemSchema).default([]), - checkpointItems: z.array(blueprintCheckpointItemSchema).default([]), - assumptions: z.array(z.string()).default([]).describe('Assumptions the plan relies on'), - openQuestions: z - .array(z.string()) - .default([]) - .describe('Unresolved questions that may need user input before execution'), -}); - -export type PlanningBlueprint = z.infer; -export type BlueprintWorkflowItem = z.infer; -export type BlueprintDelegateItem = z.infer; -export type BlueprintCheckpointItem = z.infer; diff --git a/packages/@n8n/instance-ai/src/tools/orchestration/complete-checkpoint.tool.ts b/packages/@n8n/instance-ai/src/tools/orchestration/complete-checkpoint.tool.ts index 61766212991..11fe3c92b10 100644 --- a/packages/@n8n/instance-ai/src/tools/orchestration/complete-checkpoint.tool.ts +++ b/packages/@n8n/instance-ai/src/tools/orchestration/complete-checkpoint.tool.ts @@ -113,7 +113,7 @@ async function rejectIfSetupStillRequired( export function createCompleteCheckpointTool(context: OrchestrationContext) { return new Tool('complete-checkpoint') .description( - 'Report the outcome of a planned-task checkpoint you just executed. ' + + 'Report the outcome of a planned-task checkpoint you just executed. Only call in checkpoint follow-up turns. ' + 'Call this exactly once per block. ' + 'Only valid for tasks of kind "checkpoint" that are currently running; ' + 'calling with any other taskId returns an error and does not modify the graph.', diff --git a/packages/@n8n/instance-ai/src/tools/orchestration/delegate.tool.ts b/packages/@n8n/instance-ai/src/tools/orchestration/delegate.tool.ts index c7c8d36e07a..001641ca861 100644 --- a/packages/@n8n/instance-ai/src/tools/orchestration/delegate.tool.ts +++ b/packages/@n8n/instance-ai/src/tools/orchestration/delegate.tool.ts @@ -21,7 +21,7 @@ import { consumeStreamWithHitl, requireCompletedHitlText } from '../../stream/co import { createToolRegistry } from '../../tool-registry'; import type { InstanceAiToolRegistry, OrchestrationContext } from '../../types'; -const FORBIDDEN_TOOL_NAMES = new Set(['plan', 'create-tasks', 'delegate']); +const FORBIDDEN_TOOL_NAMES = new Set(['create-tasks', 'delegate']); function generateAgentId(): string { return `agent-${nanoid(6)}`; @@ -202,6 +202,7 @@ export async function startDetachedDelegateTask( eventBus: context.eventBus, logger: context.logger, threadId: context.threadId, + outputRedaction: context.outputRedaction, abortSignal: signal, waitForConfirmation: context.waitForConfirmation, drainCorrections, @@ -354,6 +355,7 @@ export function createDelegateTool(context: OrchestrationContext) { eventBus: context.eventBus, logger: context.logger, threadId: context.threadId, + outputRedaction: context.outputRedaction, abortSignal: context.abortSignal, waitForConfirmation: context.waitForConfirmation, maxIterations, diff --git a/packages/@n8n/instance-ai/src/tools/orchestration/eval-data-agent.tool.ts b/packages/@n8n/instance-ai/src/tools/orchestration/eval-data-agent.tool.ts index a4848ca0553..b39ac49b16d 100644 --- a/packages/@n8n/instance-ai/src/tools/orchestration/eval-data-agent.tool.ts +++ b/packages/@n8n/instance-ai/src/tools/orchestration/eval-data-agent.tool.ts @@ -106,7 +106,7 @@ export function createEvalDataAgentTool(context: OrchestrationContext) { } const log = (level: 'info' | 'warn' | 'error', msg: string) => { - domain.logger?.[level]?.(`[eval-data] ${msg}`); + domain.logger[level]?.(`[eval-data] ${msg}`); }; const j = (v: unknown) => JSON.stringify(v); @@ -157,6 +157,7 @@ export function createEvalDataAgentTool(context: OrchestrationContext) { columns: target.inputColumns, rowCount: GENERATE_ROW_COUNT, targetAgentNodeName: target.targetAgentNodeName, + logger: domain.logger, ...(historyRows.length > 0 ? { realExamples: historyRows } : {}), }); source = 'synthetic'; diff --git a/packages/@n8n/instance-ai/src/tools/orchestration/eval-setup-agent.tool.ts b/packages/@n8n/instance-ai/src/tools/orchestration/eval-setup-agent.tool.ts index 735f833a0b4..0d5eb879ba8 100644 --- a/packages/@n8n/instance-ai/src/tools/orchestration/eval-setup-agent.tool.ts +++ b/packages/@n8n/instance-ai/src/tools/orchestration/eval-setup-agent.tool.ts @@ -187,6 +187,7 @@ export function startEvalSetupAgentTask( eventBus: context.eventBus, logger: context.logger, threadId: context.threadId, + outputRedaction: context.outputRedaction, abortSignal: signal, waitForConfirmation: context.waitForConfirmation, drainCorrections, diff --git a/packages/@n8n/instance-ai/src/tools/orchestration/plan-agent-prompt.ts b/packages/@n8n/instance-ai/src/tools/orchestration/plan-agent-prompt.ts deleted file mode 100644 index 77b6be1b1fa..00000000000 --- a/packages/@n8n/instance-ai/src/tools/orchestration/plan-agent-prompt.ts +++ /dev/null @@ -1,99 +0,0 @@ -import { - AI_NODE_SELECTION, - NODE_SELECTION_PATTERNS, - TRIGGER_SELECTION, - NATIVE_NODE_PREFERENCE, -} from '@n8n/workflow-sdk/prompts/node-selection'; - -import { getSandboxWorkspaceSection, SUBAGENT_OUTPUT_CONTRACT } from '../../agent/shared-prompts'; - -interface PlannerAgentPromptOptions { - workspaceRoot?: string; -} - -const PLANNER_DISCOVER_SECTION = `2. **Discover** — check what exists and learn best practices. Expect 3–6 tool calls for a typical request: - - \`nodes(action="suggested")\` for the relevant categories - - \`data-tables(action="list")\` to check for existing tables - - \`credentials(action="list")\` if the request involves external services - - Skip searches for nodes you already know exist (webhooks, schedule triggers, data tables, code, set, filter, etc.)`; - -export function getPlannerAgentPrompt(options: PlannerAgentPromptOptions = {}): string { - const { workspaceRoot } = options; - const sandboxSection = workspaceRoot ? `\n${getSandboxWorkspaceSection(workspaceRoot)}\n` : ''; - - return `You are the n8n Workflow Planner — you design solution architectures. You do NOT build workflows. - -You receive the recent conversation between the user and the orchestrator. Read it to understand what the user wants, then design the blueprint. - -${SUBAGENT_OUTPUT_CONTRACT} -- Do not produce code, node names, node configurations, or step-by-step node wiring — describe outcomes and dependencies. -${sandboxSection} -## Method - -1. **Prefer assumptions over questions.** The user is waiting for a plan, and they can reject it if your assumptions are wrong — so default to making reasonable choices rather than asking. - - **Never ask about things you can discover** — call \`credentials(action="list")\`, \`data-tables(action="list")\`, and read \`knowledge-base/best-practices/\` via workspace tools when the sandbox is available. - - **Never ask about implementation details** — trigger types, node choices, schedule times, column names. Pick sensible defaults. - - **Never ask for the user's timezone when \`\` is present** — use \`\` / \`\`. Only ask if timezone is missing and a date or schedule cannot be interpreted safely. - - **Never default resource identifiers** the user didn't mention (Slack channels, calendars, spreadsheets, folders, etc.) — leave them for the builder to resolve at build time. - - **Trust already-collected briefing context** — if the briefing includes an Already-collected answers or Already-discovered resources section, treat those entries as authoritative. Do not ask again for purpose, trigger, integrations, schedule, model, resource, or credential choices already listed there. - - **Do ask when the answer would significantly change the plan** — e.g. the user's goal is ambiguous ("build me a CRM" — for sales? support? recruiting?), or a business rule must come from the user ("what should happen when payment fails?"). - - **Handle credentials without blocking planning.** Call \`credentials(action="list")\` for external services, then apply these cases: - - If the user already named a credential in their request, use it directly and record the credential name in \`assumptions\`. - - If there is exactly one matching credential for a required type, auto-select it, do not ask, and record the credential name in \`assumptions\`. - - If there are no matching credentials, do not ask; plan normally and note that the builder will use a mocked or unresolved credential and route setup after verification. Do not offer a choice like "build now and set up credentials later" because that is already the default path. - - If there is more than one credential of the same required type and the user did not name one, ask once with a single-select because the choice cannot be discovered, only chosen. Record the chosen credential name in \`assumptions\`. - - **Use credential-backed resource investigation only when it changes the plan.** You may call \`credentials(action="list")\` so a later resource lookup can validate a resource that affects the architecture (for example checking whether a named Slack channel exists). Do not turn that into a credential-choice question unless the multiple-credentials rule above applies. - - **List your assumptions** on your first \`add-plan-item\` call. The user reviews the plan before execution and can reject/correct. - -${PLANNER_DISCOVER_SECTION} - -## Node Selection Reference - -Use these references when designing your plan — they help you pick the right trigger, prefer native nodes over Code, and correctly scope AI workflows. - -### AI Node Selection -${AI_NODE_SELECTION} - -### Node Selection by Use Case -${NODE_SELECTION_PATTERNS} - -### Trigger Selection -${TRIGGER_SELECTION} - -### Native Node Preference -${NATIVE_NODE_PREFERENCE} - -3. **Build incrementally** — call \`add-plan-item\` for each item: - - Add workflow items only when the request requires automation. Standalone data-table work is not planner work — the orchestrator handles it directly with the \`data-table-manager\` skill plus \`data-tables\` / \`parse-file\`. - - If a workflow needs new or changed data tables, include table names, columns, seed/import needs, and existing-table requirements inside the workflow \`purpose\`. Do not create a separate data-table plan item. - - Set \`summary\` and \`assumptions\` on your first call - - Each call makes the item visible to the user immediately - - \`purpose\`: Write a rich, user-focused description of what this item delivers and why. Include key requirements and behaviors from the user's request. 3-5 sentences. Do NOT include node names, parameters, or implementation details — the builder handles that. - - \`triggerDescription\`: a few words describing trigger type (e.g. "Webhook POST", "Schedule daily"), no resource identifiers - - \`integrations\`: service names only (e.g. "Slack", "Google Calendar"), no resource identifiers or qualifiers - - \`dependsOn\`: **CRITICAL** — set dependencies correctly. Workflows that produce data before workflows that consume it. Independent workflows should NOT depend on each other. - - \`assumptions\`: design decisions only, no resource identifiers (channels, calendars, etc.) - - After all items are added, call \`submit-plan\` to request user approval. - -4. **Handle approval** — \`submit-plan\` returns the user's decision: - - If \`approved: true\`: reply with "Plan approved." and stop. - - If \`approved: false\` and \`denied: true\`: the user rejected the plan outright. Reply with "Plan denied." and stop. Do NOT revise or call \`submit-plan\` again. - - If \`approved: false\` (without \`denied\`): read the \`feedback\` field. Make targeted changes using \`remove-plan-item\` (to drop items) or \`add-plan-item\` (to add/replace items by ID). Then call \`submit-plan\` again. Repeat until approved. - -## Critical Rules - -- **User time zone is in context as \`\` / \`\`.** Schedule times, cron expressions, and digest times must be stated in the user's time zone. Never write "instance default timezone" or leave the zone ambiguous — spell it out (e.g. "daily at 08:00 America/New_York"). -- **Dependencies are mandatory.** If workflow C needs data from workflows A and B, it must depend on both. Do not add dependencies for standalone data-table work. -- **No duplicate items.** Each piece of workflow or delegate work appears exactly once. Use \`workflow\` kind for workflows. Use \`delegate\` only for tasks that don't fit the other kinds — never for data table operations. -- **Data-table-only plans are invalid.** Pure data-table requests have no plan item; the orchestrator uses the \`data-table-manager\` skill and direct tools instead. If the user asked for a workflow plus tables, table requirements belong in the workflow \`purpose\`. -- **Each item's \`purpose\` describes only that item.** Do not reference work handled by other plan items — each agent only sees its own spec, and cross-task context causes scope creep. -- **Workflow verification is mandatory.** For **every** \`workflow\` item you add, also add a \`checkpoint\` item whose \`dependsOn\` includes that workflow's ID. Checkpoints are orchestrator-executed — the orchestrator runs them itself using its own tools, they are not delegated. - - \`title\`: a user-readable verification goal, e.g. \`"Verify 'Daily API Email' workflow runs successfully"\`. - - \`instructions\`: detailed steps the orchestrator must execute. Use \`verify-built-workflow\` with the work item ID from the build outcome — it uses pin data captured at build time, so it works even for event-triggered workflows (webhook, form, chat, mcp). Do not put \`executions(action="run")\` in checkpoint instructions; if the user explicitly asked to run or execute the workflow after building, the synthesize follow-up handles that as a separate approval-gated run. State the pass condition in plain terms (e.g. "run completes without errors and produces at least one output row"). - - Do NOT list \`tools\` on a checkpoint — it is not a delegate task. - - Do NOT emit a checkpoint for a \`delegate\` item. Checkpoints are for workflows only. -- **Always call \`submit-plan\` after the last \`add-plan-item\`.** On rejection, be surgical — change only what the user asked for. Never fabricate node names; search first if unsure.`; -} - -/** Default planner prompt (no sandbox workspace). Used by prompt inspection scripts. */ -export const PLANNER_AGENT_PROMPT = getPlannerAgentPrompt(); diff --git a/packages/@n8n/instance-ai/src/tools/orchestration/plan-with-agent.tool.ts b/packages/@n8n/instance-ai/src/tools/orchestration/plan-with-agent.tool.ts deleted file mode 100644 index 57928217494..00000000000 --- a/packages/@n8n/instance-ai/src/tools/orchestration/plan-with-agent.tool.ts +++ /dev/null @@ -1,105 +0,0 @@ -/** - * Plan-with-Agent Orchestration Tool - * - * Spawns an **inline** planner sub-agent that reads the conversation history, - * discovers available nodes/credentials/tables, and produces a typed - * solution blueprint. Blueprint items are emitted incrementally via the - * `add-plan-item` tool — each call publishes a `tasks-update` event so the - * task checklist populates progressively in the UI. - * - * The planner receives the last 5 messages from the thread as primary context, - * plus an optional guidance string from the orchestrator for ambiguous cases. - * It can also ask the user questions directly via the ask-user tool. - */ - -import { Tool } from '@n8n/agents'; -import { z } from 'zod'; - -import { PlannerRunCoordinator, planToolSuspendSchema } from './planner-run-coordinator'; -import type { OrchestrationContext } from '../../types'; - -const planToolResumeSchema = z.record(z.unknown()); - -export function createPlanWithAgentTool(context: OrchestrationContext) { - return new Tool('plan') - .description( - 'Design and execute a multi-step plan. Spawns a planner agent that reads ' + - 'the conversation history, discovers available credentials, data tables, ' + - 'and best practices, designs the architecture, and shows it to the user ' + - 'for approval. Use when the request requires 2 or more tasks with ' + - 'dependencies. When this tool returns, the plan is already approved ' + - 'and tasks are dispatched — just acknowledge briefly and end your turn.', - ) - .input( - z.object({ - guidance: z - .string() - .optional() - .describe( - 'Optional steering note for the planner — use ONLY when the conversation ' + - 'history alone is ambiguous about what to build. The planner reads the ' + - 'last 5 messages directly, so do NOT rewrite the user request here.', - ), - }), - ) - .output( - z.object({ - result: z.string(), - }), - ) - .suspend(planToolSuspendSchema) - .resume(planToolResumeSchema) - .handler(async (input: { guidance?: string }, ctx) => { - const resumeData = ctx.resumeData; - const isResume = resumeData !== undefined && resumeData !== null; - - // ── Same-turn denial guard ───────────────────────────────────── - // If the user denied a plan earlier in this same message group, the - // orchestrator must not silently spawn another planner. Without this - // guard the LLM can ignore the "stop on denial" prompt and start a - // fresh planner with a new accumulator, defeating the denial. - // Only applies to first-call invocations — resume continues an - // already-suspended planner and cannot be a fresh re-spawn. - if (!isResume && context.plannedTaskService && context.messageGroupId) { - const existing = await context.plannedTaskService.getGraph(context.threadId); - if ( - existing?.status === 'cancelled' && - existing.messageGroupId === context.messageGroupId - ) { - context.logger.info('plan tool blocked: user denied a plan earlier in this turn', { - threadId: context.threadId, - messageGroupId: context.messageGroupId, - }); - return { - result: - 'The user denied a plan earlier in this turn. Do not invoke the plan tool again — acknowledge briefly and wait for the next user message.', - }; - } - } - - const coordinator = new PlannerRunCoordinator(context); - try { - const outcome = - resumeData !== undefined && resumeData !== null - ? await coordinator.resume(resumeData) - : await coordinator.startFirstRun(input.guidance); - - if (outcome.kind === 'lost-state') { - return { - result: - 'The planning step could not be resumed because its state was lost. Please send a new message to continue.', - }; - } - - const { consumeResult } = outcome; - if (consumeResult.status === 'suspended') { - return await coordinator.cascadeSuspension(ctx, consumeResult); - } - - return await coordinator.handleTerminalResult(consumeResult); - } catch (error) { - return await coordinator.handleError(error); - } - }) - .build(); -} diff --git a/packages/@n8n/instance-ai/src/tools/orchestration/plan.tool.ts b/packages/@n8n/instance-ai/src/tools/orchestration/plan.tool.ts index 2cd19b236d8..d918b42f874 100644 --- a/packages/@n8n/instance-ai/src/tools/orchestration/plan.tool.ts +++ b/packages/@n8n/instance-ai/src/tools/orchestration/plan.tool.ts @@ -22,71 +22,39 @@ const plannedTaskSchema = z.object({ .string() .optional() .describe('Existing workflow ID to modify (build-workflow tasks only)'), + isSupportingWorkflow: z + .boolean() + .optional() + .describe( + 'Set true only when this build-workflow task is complete after saving a supporting sub-workflow. Do not set for helper sub-workflows created inside a larger main-workflow task.', + ), }); const planInputSchema = z.object({ tasks: z.array(plannedTaskSchema).min(1).describe('Dependency-aware execution plan'), - skipPlannerDiscovery: z - .boolean() - .optional() - .describe( - 'Set to true to intentionally bypass the planner and call create-tasks for initial (non-replan) work. ' + - 'Requires `reason`. Use sparingly — the planner sub-agent discovers credentials, data tables, and ' + - 'best practices you would otherwise miss.', - ), - reason: z - .string() - .optional() - .describe( - 'One sentence explaining why the planner is being bypassed. Required when skipPlannerDiscovery is true.', - ), + planningContext: z + .object({ + source: z + .enum(['planning-skill', 'replan']) + .describe( + 'Use "planning-skill" for initial plan-worthy work after loading the planning skill; use "replan" only in planned-task replan follow-up turns.', + ), + summary: z.string().min(1).describe('Brief summary of the plan and why it is needed'), + assumptions: z.array(z.string()).optional().describe('Important assumptions behind the plan'), + postBuildRunRequested: z + .boolean() + .optional() + .describe( + 'Set true when the user explicitly asked to run, execute, or test a workflow after it is built. Omit or false otherwise.', + ), + }) + .describe('How this task graph was produced'), }); function isReplanContext(context: OrchestrationContext): boolean { return context.isReplanFollowUp === true; } -function textRequestsPostBuildRun(text: string | undefined): boolean { - const normalized = text?.toLowerCase().replace(/\s+/g, ' ') ?? ''; - return /\b(build|create|make)\b.{0,120}\b(then|and)\s+(run|execute|test)\b/.test(normalized); -} - -/** - * Returns true when the thread has a non-terminal planned-task graph — meaning - * `create-tasks` is being called as a revision (after user rejection of a - * previous plan) or a mid-flight follow-up, not as initial planning. The guard - * should not fire in these cases because a planner cycle has already run for - * this thread and is still in progress. Terminal graphs (`completed`, - * `cancelled`) must not bypass the guard — a fresh user request on a long- - * lived thread needs to go through `plan` for discovery, same as any first - * request. - * - * `awaiting_approval` is treated as "existing" only within the run that - * created it. The rejection path leaves the graph in `awaiting_approval` so a - * same-turn revision can call `create-tasks` again, but an orphaned - * `awaiting_approval` graph from a previous turn (the LLM never revised after - * a rejection) must not bypass planner discovery for a fresh user request. - */ -async function threadHasExistingPlan(context: OrchestrationContext): Promise { - if (!context.plannedTaskService) return false; - try { - const graph = await context.plannedTaskService.getGraph(context.threadId); - if (!graph) return false; - if (graph.status === 'awaiting_approval') { - return graph.planRunId === context.runId; - } - return graph.status === 'active' || graph.status === 'awaiting_replan'; - } catch { - return false; - } -} - -function isReplanGuardEnabled(): boolean { - const raw = process.env.N8N_INSTANCE_AI_ENFORCE_CREATE_TASKS_REPLAN; - if (raw === undefined) return true; - return raw.toLowerCase() !== 'false' && raw !== '0'; -} - const planOutputSchema = z.object({ result: z.string(), taskCount: z.number(), @@ -98,17 +66,93 @@ export const planResumeSchema = z.object({ denied: z.boolean().optional(), }); +function hasDataTableRequirements(tasks: PlannedTask[]): boolean { + return tasks.some((task) => + /\bdata[- ]?tables?\b|\btable schema\b|\btable rows?\b/i.test(`${task.title}\n${task.spec}`), + ); +} + +function hasCheckpointTasks(tasks: PlannedTask[]): boolean { + return tasks.some((task) => task.kind === 'checkpoint'); +} + +function trackPlanningRoute( + context: OrchestrationContext, + tasks: PlannedTask[], + properties: { + route: string; + approvalOutcome?: string; + source?: string; + }, +): void { + context.trackTelemetry?.('instance_ai_planning_route', { + thread_id: context.threadId, + run_id: context.runId, + route: properties.route, + task_count: tasks.length, + has_data_table_requirements: hasDataTableRequirements(tasks), + has_checkpoint_tasks: hasCheckpointTasks(tasks), + ...(properties.approvalOutcome ? { approval_outcome: properties.approvalOutcome } : {}), + ...(properties.source ? { source: properties.source } : {}), + }); +} + +function validatePlanningContext( + input: z.infer, + context: OrchestrationContext, +): string | undefined { + const { planningContext } = input; + if (!planningContext) { + trackPlanningRoute(context, input.tasks as PlannedTask[], { + route: 'contract_violation', + source: 'missing', + }); + return ( + 'Error: `create-tasks` requires `planningContext`. For initial plan-worthy work, load the ' + + '`planning` skill first, perform discovery with normal tools, then call `create-tasks` with ' + + '`planningContext.source: "planning-skill"`. For planned-task replan follow-ups, use ' + + '`planningContext.source: "replan"`.' + ); + } + + if (isReplanContext(context)) { + if (planningContext.source !== 'replan') { + trackPlanningRoute(context, input.tasks as PlannedTask[], { + route: 'contract_violation', + source: planningContext.source, + }); + return ( + 'Error: `` turns must call `create-tasks` with ' + + '`planningContext.source: "replan"` when scheduling multiple dependent tasks.' + ); + } + return undefined; + } + + if (planningContext.source !== 'planning-skill') { + trackPlanningRoute(context, input.tasks as PlannedTask[], { + route: 'contract_violation', + source: planningContext.source, + }); + return ( + 'Error: `planningContext.source: "replan"` is only valid in planned-task replan follow-up turns. ' + + 'For initial plan-worthy work, load the `planning` skill, perform discovery with normal tools, ' + + 'then call `create-tasks` with `planningContext.source: "planning-skill"`.' + ); + } + + return undefined; +} + export function createPlanTool(context: OrchestrationContext) { return new Tool('create-tasks') .description( - 'Submit a pre-built task list for detached multi-step execution. ' + - 'Use ONLY for replanning after a failure — when you already have the task context ' + - 'and do not need resource discovery. For initial planning, call `plan` instead. ' + - 'A runtime guard rejects this tool when no replan context (``) ' + - 'is present; if you intentionally need to bypass the planner, set `skipPlannerDiscovery: true` ' + - 'and pass a one-sentence `reason`. ' + + 'Submit a dependency-aware task graph for detached multi-step execution. ' + + 'Use after loading the `planning` skill for initial plan-worthy work, or during ' + + '`` when multiple dependent tasks still need scheduling. ' + + 'Requires `planningContext.source` to be `planning-skill` or `replan` as appropriate. ' + 'The task list is shown to the user for approval before execution starts. ' + - 'After calling create-tasks, reply briefly and end your turn.', + 'After calling create-tasks, do not write visible text; the approval card is the user-visible surface.', ) .input(planInputSchema) .output(planOutputSchema) @@ -155,53 +199,35 @@ export function createPlanTool(context: OrchestrationContext) { } } - // Replan-only guard: reject initial-planning misuse on the first call. - // Legitimate callers pass the guard when any of these hold: - // - `` is present in the user message - // - the thread already has a planned-task graph (revision loop after a - // user rejection, or replan after a failed background task) - // - the orchestrator opts in with `skipPlannerDiscovery: true` + a `reason` - const hasExistingPlan = await threadHasExistingPlan(context); - if (isFirstCall && isReplanGuardEnabled() && !isReplanContext(context) && !hasExistingPlan) { - if (!input.skipPlannerDiscovery) { - context.logger.warn('create-tasks called without replan context — rejecting', { + if (isFirstCall) { + const contextError = validatePlanningContext(input, context); + if (contextError) { + context.logger.warn('create-tasks called with invalid planning context — rejecting', { threadId: context.threadId, taskCount: input.tasks.length, + planningSource: input.planningContext?.source, }); return { - result: - 'Error: `create-tasks` is for replanning only. For initial planning, call `plan` instead — ' + - 'the planner sub-agent will discover credentials, data tables, and best practices for you. ' + - 'If you intentionally want to skip the planner (rare), call `create-tasks` again with ' + - '`skipPlannerDiscovery: true` and a one-sentence `reason`.', + result: contextError, taskCount: 0, }; } - if (!input.reason || input.reason.trim().length === 0) { - return { - result: - 'Error: `skipPlannerDiscovery: true` requires a one-sentence `reason` explaining ' + - 'why the planner is being bypassed.', - taskCount: 0, - }; - } - context.logger.warn('create-tasks bypassing planner with skipPlannerDiscovery=true', { - threadId: context.threadId, - taskCount: input.tasks.length, - reason: input.reason, - }); } // First call — persist plan, show to user, suspend for approval if (isFirstCall) { try { + trackPlanningRoute(context, input.tasks as PlannedTask[], { + route: input.planningContext.source === 'planning-skill' ? 'skill' : 'replan', + source: input.planningContext.source, + }); await context.plannedTaskService.createPlan( context.threadId, input.tasks as PlannedTask[], { planRunId: context.runId, messageGroupId: context.messageGroupId, - postBuildRunApprovalRequired: textRequestsPostBuildRun(context.currentUserMessage), + postBuildRunApprovalRequired: input.planningContext.postBuildRunRequested === true, }, ); } catch (error) { @@ -211,7 +237,7 @@ export function createPlanTool(context: OrchestrationContext) { if (!(error instanceof PlanValidationError)) { throw error; } - context.logger.warn('plan tool: createPlan rejected by validator', { + context.logger.warn('create-tasks rejected by planned task validator', { threadId: context.threadId, taskCount: input.tasks.length, error: error.message, @@ -250,6 +276,11 @@ export function createPlanTool(context: OrchestrationContext) { if (resumeData.approved) { await context.plannedTaskService.approvePlan(context.threadId); await context.schedulePlannedTasks(); + trackPlanningRoute(context, input.tasks as PlannedTask[], { + route: input.planningContext?.source === 'replan' ? 'replan' : 'skill', + source: input.planningContext?.source, + approvalOutcome: 'approved', + }); return { result: `Plan approved. Started ${input.tasks.length} task${input.tasks.length === 1 ? '' : 's'}.`, taskCount: input.tasks.length, @@ -276,6 +307,11 @@ export function createPlanTool(context: OrchestrationContext) { // being treated as a revision, and tell the LLM to stop. if (resumeData.denied) { await context.plannedTaskService.denyPlan(context.threadId); + trackPlanningRoute(context, input.tasks as PlannedTask[], { + route: input.planningContext?.source === 'replan' ? 'replan' : 'skill', + source: input.planningContext?.source, + approvalOutcome: 'denied', + }); return { result: 'User denied the plan. Do not revise or call create-tasks again — acknowledge and wait for new instructions.', @@ -284,12 +320,9 @@ export function createPlanTool(context: OrchestrationContext) { } // User requested changes. Keep the persisted graph in - // `awaiting_approval` so the LLM's next `create-tasks` revision - // passes the replan guard via `threadHasExistingPlan` (scoped to - // the current runId). The scheduler ignores `awaiting_approval` - // graphs, so leaving the graph in place can't dispatch the - // rejected plan; the next createPlan call overwrites it with the - // revised tasks. + // `awaiting_approval`: the scheduler ignores it, so the rejected + // graph cannot dispatch, and the next `create-tasks` call overwrites + // it with the revised graph. return { result: `User requested changes: ${resumeData.userInput ?? 'No feedback provided'}. Revise the tasks and call create-tasks again.`, taskCount: 0, diff --git a/packages/@n8n/instance-ai/src/tools/orchestration/planner-briefing.ts b/packages/@n8n/instance-ai/src/tools/orchestration/planner-briefing.ts deleted file mode 100644 index 3d65ad41347..00000000000 --- a/packages/@n8n/instance-ai/src/tools/orchestration/planner-briefing.ts +++ /dev/null @@ -1,510 +0,0 @@ -import type { InstanceAiEvent } from '@n8n/api-types'; -import { DateTime } from 'luxon'; - -import type { OrchestrationContext } from '../../types'; -import { CREDENTIALS_TOOL_ID } from '../credentials.tool'; -import { DATA_TABLES_TOOL_ID } from '../data-tables.tool'; -import { ASK_USER_TOOL_ID } from '../shared/ask-user.tool'; - -/** Number of recent thread messages to include as planner context. */ -export const MESSAGE_HISTORY_COUNT = 5; - -const RELEVANT_PRIOR_TOOL_NAMES = new Set([ - ASK_USER_TOOL_ID, - CREDENTIALS_TOOL_ID, - DATA_TABLES_TOOL_ID, -]); - -// --------------------------------------------------------------------------- -// Message history retrieval -// --------------------------------------------------------------------------- - -interface FormattedMessage { - role: 'user' | 'assistant'; - content: string; -} - -interface PlannerBriefingContext { - collectedAnswers: string[]; - discoveredResources: string[]; -} - -interface ToolObservation { - toolName: string; - args: Record; - result: unknown; -} - -interface CredentialBrief { - id?: string; - name: string; - type: string; -} - -interface DataTableBrief { - id?: string; - name: string; -} - -/** Extract plain text from persisted native memory content. */ -function extractTextFromMemoryContent(content: unknown): string { - if (typeof content === 'string') return content; - if (Array.isArray(content)) return extractTextParts(content); - return ''; -} - -function extractTextParts(parts: unknown[]): string { - return parts - .filter( - (c): c is { type: 'text'; text: string } => - typeof c === 'object' && - c !== null && - 'type' in c && - c.type === 'text' && - 'text' in c && - typeof c.text === 'string', - ) - .map((c) => c.text) - .join('\n'); -} - -function isRecord(value: unknown): value is Record { - return typeof value === 'object' && value !== null && !Array.isArray(value); -} - -function readString(value: unknown): string | undefined { - return typeof value === 'string' && value.trim().length > 0 ? value : undefined; -} - -function readRecord(value: unknown): Record | undefined { - return isRecord(value) ? value : undefined; -} - -function readArray(value: unknown): unknown[] { - return Array.isArray(value) ? value : []; -} - -function readStringArray(value: unknown): string[] { - return readArray(value).filter((item): item is string => typeof item === 'string'); -} - -function addUnique(target: string[], seen: Set, value: string | undefined): void { - if (!value || seen.has(value)) return; - seen.add(value); - target.push(value); -} - -function summarizeList(values: string[], limit = 10): string { - const visible = values.slice(0, limit).join(', '); - const remaining = values.length - limit; - return remaining > 0 ? `${visible}, and ${remaining} more` : visible; -} - -export async function getRecentMessages( - context: OrchestrationContext, - count: number, -): Promise { - const messages: FormattedMessage[] = []; - - // Retrieve previously-saved messages from memory. - if (context.memory) { - try { - const history = await context.memory.getMessages(context.threadId, { - limit: count, - }); - - for (const m of history) { - if (!('role' in m)) continue; - const role = m.role; - const content = extractTextFromMemoryContent(m.content); - if ((role === 'user' || role === 'assistant') && content.length > 0) { - messages.push({ role, content }); - } - } - } catch { - // Memory recall failed — continue with just the current message - } - } - - // Always append the current in-flight user message (not yet saved to memory) - if (shouldAppendCurrentUserMessage(messages, context.currentUserMessage)) { - messages.push({ role: 'user', content: context.currentUserMessage }); - } - - return messages; -} - -function shouldAppendCurrentUserMessage( - messages: FormattedMessage[], - currentUserMessage?: string, -): currentUserMessage is string { - const current = currentUserMessage?.trim(); - if (!current) return false; - - const lastUserMessage = [...messages].reverse().find((message) => message.role === 'user'); - return lastUserMessage?.content.trim() !== current; -} - -/** - * Reconstructs prior planner-relevant tool calls from the event stream. - * - * Tool-call and tool-result events are correlated by `toolCallId` so the - * planner can receive structured context that is not preserved in text-only - * memory recall, such as ask-user answers and credential selections. - */ -export function getPriorToolObservations(context: OrchestrationContext): ToolObservation[] { - type MutableToolObservation = Omit & { - result: unknown; - hasResult: boolean; - }; - - const toolCalls = new Map(); - const pendingResults = new Map(); - - for (const event of getPriorToolEvents(context)) { - if (event.type === 'tool-call') { - const { toolCallId, toolName, args } = event.payload; - if (!RELEVANT_PRIOR_TOOL_NAMES.has(toolName)) continue; - - const pendingResult = pendingResults.get(toolCallId); - toolCalls.set(toolCallId, { - toolName, - args, - result: pendingResult, - hasResult: pendingResults.has(toolCallId), - }); - continue; - } - - if (event.type === 'tool-result') { - const { toolCallId, result } = event.payload; - const existing = toolCalls.get(toolCallId); - if (existing) { - existing.result = result; - existing.hasResult = true; - } else { - pendingResults.set(toolCallId, result); - } - } - } - - return [...toolCalls.values()] - .filter((observation) => observation.hasResult) - .map(({ toolName, args, result }) => ({ toolName, args, result })); -} - -/** - * Returns the events that may contain prior tool context for this planner run. - * - * When the run belongs to a message group, all runs in that group are searched - * so follow-up runs can see choices collected earlier in the same assistant - * turn. If grouped lookup is unavailable, this falls back to the current run. - */ -function getPriorToolEvents(context: OrchestrationContext): InstanceAiEvent[] { - if (context.messageGroupId) { - const runIds = getMessageGroupRunIds(context); - if (runIds.length > 0) { - try { - return context.eventBus.getEventsForRuns(context.threadId, runIds); - } catch { - // Fall back to the current run below. - } - } - } - - try { - return context.eventBus.getEventsForRun(context.threadId, context.runId); - } catch { - return []; - } -} - -/** - * Finds run IDs that belong to the current message group from run-start events. - * - * The event bus can fetch events for many run IDs, but the orchestration - * context only carries the current run ID and message group ID. This bridges - * those two concepts while keeping the current run as a defensive fallback. - */ -function getMessageGroupRunIds(context: OrchestrationContext): string[] { - const messageGroupId = context.messageGroupId; - if (!messageGroupId) return []; - - const runIds = new Set(); - try { - for (const { event } of context.eventBus.getEventsAfter(context.threadId, 0)) { - if (event.type === 'run-start' && event.payload.messageGroupId === messageGroupId) { - runIds.add(event.runId); - } - } - } catch { - return [context.runId]; - } - runIds.add(context.runId); - - return [...runIds]; -} - -/** - * Converts raw prior tool observations into planner briefing sections. - * - * The resulting strings are intentionally short and human-readable because - * they are embedded directly into the planner prompt under dedicated headings. - */ -export function buildPlannerBriefingContext( - observations: ToolObservation[], -): PlannerBriefingContext { - const collectedAnswers: string[] = []; - const discoveredResources: string[] = []; - const seenAnswers = new Set(); - const seenResources = new Set(); - const credentialsById = buildCredentialLookup(observations); - - for (const observation of observations) { - if (observation.toolName === ASK_USER_TOOL_ID) { - for (const answer of extractAskUserAnswerLines(observation)) { - addUnique(collectedAnswers, seenAnswers, answer); - } - continue; - } - - if (observation.toolName === CREDENTIALS_TOOL_ID) { - const action = readString(observation.args.action); - if (action === 'list') { - addUnique(discoveredResources, seenResources, summarizeCredentials(observation.result)); - } - if (action === 'setup') { - for (const selection of extractCredentialSelectionLines(observation, credentialsById)) { - addUnique(collectedAnswers, seenAnswers, selection); - } - } - continue; - } - - if ( - observation.toolName === DATA_TABLES_TOOL_ID && - readString(observation.args.action) === 'list' - ) { - addUnique(discoveredResources, seenResources, summarizeDataTables(observation.result)); - } - } - - return { collectedAnswers, discoveredResources }; -} - -/** - * Builds an ID lookup from prior credential list results. - * - * Credential setup results contain selected IDs, so this lets the briefing - * render stable user-facing names and credential types when a prior list result - * is available. - */ -function buildCredentialLookup(observations: ToolObservation[]): Map { - const credentialsById = new Map(); - - for (const observation of observations) { - if (observation.toolName !== CREDENTIALS_TOOL_ID) continue; - for (const credential of extractCredentials(observation.result)) { - if (credential.id) credentialsById.set(credential.id, credential); - } - } - - return credentialsById; -} - -/** - * Extracts answered ask-user responses as `question: answer` briefing lines. - * - * Skipped or unanswered prompts are ignored, and question text is recovered - * from tool args when the tool result only includes a question ID. - */ -function extractAskUserAnswerLines(observation: ToolObservation): string[] { - const result = readRecord(observation.result); - if (!result || result.answered === false) return []; - - const questionsById = extractQuestionTextById(observation.args); - const answers = readArray(result.answers); - const lines: string[] = []; - - for (const answerValue of answers) { - const answer = readRecord(answerValue); - if (!answer || answer.skipped === true) continue; - - const questionId = readString(answer.questionId); - const question = - readString(answer.question) ?? (questionId ? questionsById.get(questionId) : undefined); - const selectedOptions = readStringArray(answer.selectedOptions); - const customText = readString(answer.customText); - const values = [...selectedOptions, ...(customText ? [customText] : [])]; - - if (!question || values.length === 0) continue; - lines.push(`${question}: ${values.join(', ')}`); - } - - return lines; -} - -/** - * Maps ask-user question IDs to display text from the original tool args. - */ -function extractQuestionTextById(args: Record): Map { - const questionsById = new Map(); - - for (const questionValue of readArray(args.questions)) { - const question = readRecord(questionValue); - const id = readString(question?.id); - const text = readString(question?.question); - if (id && text) questionsById.set(id, text); - } - - return questionsById; -} - -/** - * Renders credential setup selections as briefing lines. - * - * The setup tool returns a `{ credentialType: credentialId }` map. The optional - * credential lookup turns those IDs back into names so the planner can avoid - * asking the user to choose the same credential again. - */ -function extractCredentialSelectionLines( - observation: ToolObservation, - credentialsById: Map, -): string[] { - const result = readRecord(observation.result); - const credentials = readRecord(result?.credentials); - if (!credentials) return []; - - const lines: string[] = []; - for (const [credentialType, credentialIdValue] of Object.entries(credentials)) { - const credentialId = readString(credentialIdValue); - if (!credentialId) continue; - - const credential = credentialsById.get(credentialId); - const label = credential - ? `${credential.name} (${credential.type})` - : `credential ID ${credentialId}`; - lines.push(`Credential selected for ${credentialType}: ${label}`); - } - - return lines; -} - -/** - * Summarizes a credentials list result for the briefing. - */ -function summarizeCredentials(result: unknown): string | undefined { - const credentials = extractCredentials(result); - if (credentials.length === 0) return undefined; - - return `Credentials available: ${summarizeList( - credentials.map((credential) => `${credential.name} (${credential.type})`), - )}`; -} - -/** - * Reads the minimal credential metadata needed by the planner briefing. - */ -function extractCredentials(result: unknown): CredentialBrief[] { - const record = readRecord(result); - return readArray(record?.credentials) - .map(readCredentialBrief) - .filter((credential): credential is CredentialBrief => credential !== undefined); -} - -function readCredentialBrief(value: unknown): CredentialBrief | undefined { - const record = readRecord(value); - const name = readString(record?.name); - const type = readString(record?.type); - if (!name || !type) return undefined; - const id = readString(record?.id); - - return { - name, - type, - ...(id ? { id } : {}), - }; -} - -/** - * Summarizes a data-tables list result for the briefing. - */ -function summarizeDataTables(result: unknown): string | undefined { - const tables = extractDataTables(result); - if (tables.length === 0) return undefined; - - return `Data tables available: ${summarizeList(tables.map((table) => table.name))}`; -} - -/** - * Reads the minimal data-table metadata needed by the planner briefing. - */ -function extractDataTables(result: unknown): DataTableBrief[] { - const record = readRecord(result); - return readArray(record?.tables) - .map(readDataTableBrief) - .filter((table): table is DataTableBrief => table !== undefined); -} - -function readDataTableBrief(value: unknown): DataTableBrief | undefined { - const record = readRecord(value); - const name = readString(record?.name); - if (!name) return undefined; - const id = readString(record?.id); - - return { - name, - ...(id ? { id } : {}), - }; -} - -/** - * Formats conversation, time, and already-collected context into the planner goal. - */ -export function formatMessagesForBriefing( - messages: FormattedMessage[], - guidance?: string, - timeZone?: string, - briefingContext?: PlannerBriefingContext, -): string { - const parts: string[] = []; - - const now = timeZone ? DateTime.now().setZone(timeZone) : DateTime.now(); - const isoNow = now.toISO({ includeOffset: true }) ?? new Date().toISOString(); - parts.push(`${isoNow}`); - if (timeZone) { - parts.push(`${timeZone}`); - } - - if (messages.length > 0) { - parts.push('## Recent conversation'); - for (const m of messages) { - const label = m.role === 'user' ? 'User' : 'Assistant'; - // Truncate very long messages - const content = m.content.length > 2000 ? m.content.slice(0, 2000) + '...' : m.content; - parts.push(`**${label}:** ${content}`); - } - } - - if (briefingContext?.collectedAnswers.length) { - parts.push('## Already-collected answers'); - for (const answer of briefingContext.collectedAnswers) { - parts.push(`- ${answer}`); - } - } - - if (briefingContext?.discoveredResources.length) { - parts.push('## Already-discovered resources'); - for (const resource of briefingContext.discoveredResources) { - parts.push(`- ${resource}`); - } - } - - if (guidance) { - parts.push(`\n## Orchestrator guidance\n${guidance}`); - } - - parts.push('\nDesign the solution blueprint based on the conversation above.'); - - return parts.join('\n\n'); -} diff --git a/packages/@n8n/instance-ai/src/tools/orchestration/planner-run-coordinator.ts b/packages/@n8n/instance-ai/src/tools/orchestration/planner-run-coordinator.ts deleted file mode 100644 index e9152ec020d..00000000000 --- a/packages/@n8n/instance-ai/src/tools/orchestration/planner-run-coordinator.ts +++ /dev/null @@ -1,531 +0,0 @@ -import { Agent } from '@n8n/agents'; -import { z } from 'zod'; - -import { createAddPlanItemTool, createRemovePlanItemTool } from './add-plan-item.tool'; -import { createSubAgentPersistence } from './agent-persistence'; -import { BlueprintAccumulator } from './blueprint-accumulator'; -import { truncateLabel } from './display-utils'; -import { getPlannerAgentPrompt } from './plan-agent-prompt'; -import { - buildPlannerBriefingContext, - formatMessagesForBriefing, - getPriorToolObservations, - getRecentMessages, - MESSAGE_HISTORY_COUNT, -} from './planner-briefing'; -import { createSubmitPlanTool } from './submit-plan.tool'; -import { - failTraceRun, - finishTraceRun, - startSubAgentTrace, - traceSubAgentTools, - withTraceRun, -} from './tracing-utils'; -import { attachRuntimeWorkspaceCapabilities } from '../../agent/runtime-workspace'; -import { MAX_STEPS } from '../../constants/max-steps'; -import { consumeStreamCascading } from '../../stream/consume-with-hitl'; -import type { ConsumeStreamCascadingResult } from '../../stream/consume-with-hitl'; -import { createToolRegistry, toolRegistryKeys, toolRegistryValues } from '../../tool-registry'; -import { buildAgentTraceInputs, mergeTraceRunInputs } from '../../tracing/langsmith-tracing'; -import type { OrchestrationContext } from '../../types'; -import { resumeAgentStream } from '../../utils/stream-helpers'; -import { CREDENTIALS_TOOL_ID } from '../credentials.tool'; -import { DATA_TABLES_TOOL_ID } from '../data-tables.tool'; -import { ASK_USER_TOOL_ID } from '../shared/ask-user.tool'; - -/** Read-only discovery tools the planner gets from domainTools. */ -const PLANNER_DOMAIN_TOOL_NAMES = [ - 'nodes', - CREDENTIALS_TOOL_ID, - DATA_TABLES_TOOL_ID, - 'workflows', - ASK_USER_TOOL_ID, -]; - -/** Research tools added when available. */ -const PLANNER_RESEARCH_TOOL_NAMES = ['research']; - -// --------------------------------------------------------------------------- -// Helper: clear draft checklist from taskStorage -// --------------------------------------------------------------------------- - -/** Publish an empty tasks-update so the frontend clears stale plan items. */ -function publishClearingEvent(context: OrchestrationContext): void { - context.eventBus.publish(context.threadId, { - type: 'tasks-update', - runId: context.runId, - agentId: context.orchestratorAgentId, - payload: { tasks: { tasks: [] }, planItems: [] }, - }); -} - -async function clearDraftChecklist(context: OrchestrationContext): Promise { - try { - await context.taskStorage.save(context.threadId, { tasks: [] }); - } catch { - // Best-effort — don't let cleanup failures block the return path - } -} - -/** - * Remove any persisted planned-task graph for this thread *if and only if* it - * belongs to this planner run's unapproved plan. Called on planner give-up / - * error paths to prevent a later schedulePlannedTasks() tick from dispatching - * a plan the user never approved. - * - * Guarded because the thread may already carry an unrelated active graph (a - * prior approved plan with pending checkpoints / in-flight tasks); an - * unconditional `clear()` here would strand that work. We only touch the graph - * when its `planRunId` matches this run AND its `status` is `awaiting_approval` - * — the single window where submit-plan has persisted but approval hasn't - * happened yet. - */ -export async function clearPlannedTaskGraph(context: OrchestrationContext): Promise { - if (!context.plannedTaskService) return; - try { - const graph = await context.plannedTaskService.getGraph(context.threadId); - if (!graph) return; - if (graph.planRunId !== context.runId) return; - if (graph.status !== 'awaiting_approval') return; - await context.plannedTaskService.clear(context.threadId); - } catch { - // Best-effort — don't let cleanup failures block the return path - } -} - -/** - * Seed a freshly-built accumulator from the persisted plan before a planner - * resume. The parent plan-tool handler exits on every cascade-suspend, so the - * first-call accumulator is gone by the time an "ask for edits" revision - * resumes the planner — without this, remove-plan-item can't touch the - * original items, add-plan-item only carries the newly-added ones, and the - * re-submit's createPlan (which overwrites unconditionally) replaces the graph - * with a partial plan. - * - * Only rehydrates while the plan is still `awaiting_approval` (the revision - * window) — an already-approved/active graph with in-flight tasks must not be - * reopened here. Best-effort: a getGraph failure leaves the accumulator empty - * rather than blocking the resume. - */ -export async function rehydrateAccumulatorFromGraph( - context: OrchestrationContext, - accumulator: BlueprintAccumulator, -): Promise { - if (!context.plannedTaskService) return; - try { - const graph = await context.plannedTaskService.getGraph(context.threadId); - if (graph?.status === 'awaiting_approval' && graph.tasks.length > 0) { - accumulator.loadFromTasks(graph.tasks); - } - } catch { - // Best-effort — fall back to an empty accumulator rather than block resume. - } -} - -/** - * The plan tool cascades sub-agent HITL suspensions UP through the SDK's - * native suspend/resume mechanism: when the planner sub-agent (or any tool - * inside it) emits a `tool-call-suspended` chunk, the plan tool catches it - * via `consumeStreamCascading` and calls its own `ctx.suspend()` with the - * same payload. This checkpoints the orchestrator's full state alongside the - * planner's, so a process restart between user prompt and click can resume - * the planner without losing any state. - * - * The schemas below are permissive on purpose: the plan tool just forwards - * whatever the inner tool emitted (submit-plan's plan-review payload OR - * ask-user's questions payload) and accepts whatever the frontend sent back - * for that card. Validation already happened on the inner tool. - */ -export const planToolSuspendSchema = z - .object({ - requestId: z.string(), - message: z.string(), - severity: z.string(), - // Only submit-plan + ask-user carry an `inputType`; cascaded suspensions - // from other planner tools (credentials, data-tables, ...) don't, and a - // strict `inputType: string` would reject otherwise-valid payloads. - inputType: z.string().optional(), - }) - .passthrough(); - -/** Assemble the planner sub-agent's tool registry: read-only discovery + - * research tools from the orchestrator's domain set, plus the plan-building - * tools (add/remove/submit) wired to this run's accumulator. */ -function buildPlannerTools(context: OrchestrationContext, accumulator: BlueprintAccumulator) { - const plannerTools = createToolRegistry(); - - for (const name of PLANNER_DOMAIN_TOOL_NAMES) { - const tool = context.domainTools.get(name); - if (tool) plannerTools.set(name, tool); - } - - for (const name of PLANNER_RESEARCH_TOOL_NAMES) { - const tool = context.domainTools.get(name); - if (tool) plannerTools.set(name, tool); - } - - plannerTools.set('add-plan-item', createAddPlanItemTool(accumulator, context)); - plannerTools.set('remove-plan-item', createRemovePlanItemTool(accumulator, context)); - plannerTools.set('submit-plan', createSubmitPlanTool(accumulator, context)); - - return plannerTools; -} - -/** Construct the planner sub-agent with workspace capabilities + telemetry. */ -function buildPlannerSubAgent( - context: OrchestrationContext, - tracedPlannerTools: ReturnType, - subAgentId: string, - plannerPrompt: string, -) { - const subAgent = new Agent('Workflow Planner Agent') - .model(context.modelId) - .instructions(plannerPrompt, { - providerOptions: { - anthropic: { cacheControl: { type: 'ephemeral' } }, - }, - }) - .tool(toolRegistryValues(tracedPlannerTools)) - .checkpoint(context.checkpointStore ?? 'memory'); - attachRuntimeWorkspaceCapabilities(subAgent, { - workspace: context.workspace, - runtimeSkills: context.runtimeSkills, - }); - const telemetry = context.tracing?.getTelemetry?.({ - agentRole: 'planner', - functionId: 'instance-ai.subagent.planner', - executionMode: 'background', - metadata: { agent_id: subAgentId }, - }); - if (telemetry) { - subAgent.telemetry(telemetry); - } - return subAgent; -} - -/** Outcome of starting/resuming a planner run: either the cascading-stream - * result, or a sentinel that the run could not be resumed (checkpoint state - * was lost across a restart). */ -type PlannerRunOutcome = - | { kind: 'consumed'; consumeResult: ConsumeStreamCascadingResult } - | { kind: 'lost-state' }; - -/** - * Owns one planner sub-agent run end-to-end: tool/agent construction, the - * first-call and resume legs, the LangSmith trace span (held as a field so it - * spans the run's try/catch), and the terminal/suspension/error transitions. - * - * The tool handler stays a thin orchestrator: build the coordinator, run - * first-call or resume, then route the result to the matching `handle*` method. - */ -export class PlannerRunCoordinator { - private readonly accumulator = new BlueprintAccumulator(); - - // runId-derived id so a resume reuses the same event-stream identity. - private readonly subAgentId: string; - - private readonly plannerTools: ReturnType; - - private readonly tracedPlannerTools: ReturnType; - - private readonly subAgent: ReturnType; - - private readonly plannerPrompt: string; - - // Held as a field so finishTrace/failTrace can finalise the span whether the - // run ends in handleTerminalResult or in the handler's catch. - private traceRun: Awaited>; - - constructor(private readonly context: OrchestrationContext) { - this.subAgentId = `agent-planner-${context.runId}`; - this.plannerPrompt = getPlannerAgentPrompt({ - workspaceRoot: context.workspace && context.workspaceRoot ? context.workspaceRoot : undefined, - }); - this.plannerTools = buildPlannerTools(context, this.accumulator); - this.tracedPlannerTools = traceSubAgentTools(context, this.plannerTools, 'planner'); - this.subAgent = buildPlannerSubAgent( - context, - this.tracedPlannerTools, - this.subAgentId, - this.plannerPrompt, - ); - } - - /** First-call leg: persist the in-flight user message, brief the planner, - * publish agent-spawned, and consume the cascading stream. */ - async startFirstRun(guidance?: string): Promise { - const { context, subAgent, subAgentId, plannerTools, tracedPlannerTools } = this; - - // The planner is the most common inline HITL entry point — when it - // suspends the orchestrator cascades-suspends too, and the SDK does not - // flush the user-message row to memory until a clean loop end (which a - // suspended run never reaches). Persist eagerly so the user's bubble is - // visible if they reload during the suspend window. - if (context.persistInFlightUserMessage) { - await context.persistInFlightUserMessage(); - } - - const messages = await getRecentMessages(context, MESSAGE_HISTORY_COUNT); - const briefingContext = buildPlannerBriefingContext(getPriorToolObservations(context)); - const briefing = formatMessagesForBriefing( - messages, - guidance, - context.timeZone, - briefingContext, - ); - - const subtitle = guidance ?? messages.find((m) => m.role === 'user')?.content ?? 'Planning...'; - - context.eventBus.publish(context.threadId, { - type: 'agent-spawned', - runId: context.runId, - agentId: subAgentId, - payload: { - parentId: context.orchestratorAgentId, - role: 'planner', - tools: toolRegistryKeys(plannerTools), - kind: 'planner' as const, - title: 'Planning', - subtitle: truncateLabel(subtitle), - goal: briefing, - }, - }); - - this.traceRun = await startSubAgentTrace(context, { - agentId: subAgentId, - role: 'planner', - kind: 'planner', - inputs: { guidance, messageCount: messages.length }, - }); - mergeTraceRunInputs( - this.traceRun, - buildAgentTraceInputs({ - systemPrompt: this.plannerPrompt, - tools: tracedPlannerTools, - modelId: context.modelId, - }), - ); - - const consumeResult = await withTraceRun(context, this.traceRun, async () => { - const persistence = await createSubAgentPersistence(context, { agentKind: 'planner' }); - const stream = await subAgent.stream(briefing, { - maxIterations: MAX_STEPS.PLANNER, - abortSignal: context.abortSignal, - persistence, - providerOptions: { - anthropic: { cacheControl: { type: 'ephemeral' } }, - }, - }); - - return await consumeStreamCascading({ - agent: subAgent, - stream, - runId: context.runId, - agentId: subAgentId, - eventBus: context.eventBus, - logger: context.logger, - threadId: context.threadId, - abortSignal: context.abortSignal, - }); - }); - - return { kind: 'consumed', consumeResult }; - } - - /** Resume leg: locate the suspended planner, rehydrate the accumulator from - * the persisted plan, open a fresh trace span, and resume the cascading - * stream. Returns `lost-state` when the checkpoint can't be located. */ - async resume(resumeData: Record): Promise { - const { context, subAgent, subAgentId, tracedPlannerTools } = this; - - const resumeInfo = await context.findSubAgentResumeInfo?.('planner'); - if (!resumeInfo) return { kind: 'lost-state' }; - - // Rehydrate the accumulator from the persisted plan so an "ask for edits" - // revision operates on the full plan rather than an empty accumulator. - await rehydrateAccumulatorFromGraph(context, this.accumulator); - - // Open a trace span for the resumed leg so a plan that suspended at HITL - // and resumed still shows its continuation in LangSmith. The planner card - // is already in the snapshot from the first call, so no agent-spawned - // event is (re-)published here. - this.traceRun = await startSubAgentTrace(context, { - agentId: subAgentId, - role: 'planner', - kind: 'planner', - inputs: { resumed: true }, - }); - mergeTraceRunInputs( - this.traceRun, - buildAgentTraceInputs({ - systemPrompt: this.plannerPrompt, - tools: tracedPlannerTools, - modelId: context.modelId, - }), - ); - - const consumeResult = await withTraceRun(context, this.traceRun, async () => { - const resumed = await resumeAgentStream(subAgent, resumeData, { - runId: resumeInfo.runId, - toolCallId: resumeInfo.toolCallId, - persistence: resumeInfo.persistence, - maxIterations: MAX_STEPS.PLANNER, - }); - - return await consumeStreamCascading({ - agent: subAgent, - stream: resumed, - runId: context.runId, - agentId: subAgentId, - eventBus: context.eventBus, - logger: context.logger, - threadId: context.threadId, - abortSignal: context.abortSignal, - }); - }); - - return { kind: 'consumed', consumeResult }; - } - - /** Cascade a planner suspension up to the orchestrator. Validates the - * forwarded payload; on a malformed payload it tears down the draft plan - * (so a later schedulePlannedTasks tick can't dispatch it) and returns a - * terminal result instead of suspending. */ - async cascadeSuspension( - ctx: { suspend: (payload: z.infer) => Promise }, - consumeResult: Extract, - ): Promise<{ result: string }> { - const { context } = this; - const parsed = planToolSuspendSchema.safeParse(consumeResult.suspension.suspendPayload); - if (!parsed.success) { - context.logger.warn('Planner emitted a suspension payload missing required fields', { - threadId: context.threadId, - runId: context.runId, - toolName: consumeResult.suspension.toolName, - zodIssues: parsed.error.issues, - }); - await this.tearDownDraftPlan(); - return { - result: 'Planner requested user input but the payload was malformed. Please try again.', - }; - } - return await ctx.suspend(parsed.data); - } - - /** Finalise a completed/cancelled/errored planner run: close the trace, - * publish agent-completed, then resolve to the orchestrator-facing result - * based on approval / denial / no-plan. */ - async handleTerminalResult( - consumeResult: ConsumeStreamCascadingResult, - ): Promise<{ result: string }> { - const { context, accumulator, subAgentId } = this; - const resultText = consumeResult.status === 'completed' ? await consumeResult.text : ''; - - if (this.traceRun) { - await finishTraceRun(context, this.traceRun, { - outputs: { - result: resultText, - agentId: subAgentId, - role: 'planner', - hasItems: !accumulator.isEmpty(), - itemCount: accumulator.getTaskItemsForEvent().length, - }, - }); - } - - this.publishCompleted(resultText); - - // Approval is detected via the accumulator's flag, which submit-plan flips - // in its resume handler. createPlan persisted the graph as - // `awaiting_approval` on the first call; flip it to `active` and schedule. - if (accumulator.isApproved()) { - if (context.plannedTaskService) { - await context.plannedTaskService.approvePlan(context.threadId); - } - if (context.schedulePlannedTasks) { - await context.schedulePlannedTasks(); - } - // On resume the accumulator is fresh and reports 0 — query the persisted - // graph instead so the orchestrator gets accurate text. - const persistedCount = await getPersistedTaskCount(context); - const taskCount = persistedCount ?? accumulator.getTaskList().length; - return { - result: `Plan approved and ${taskCount} task${taskCount === 1 ? '' : 's'} dispatched.`, - }; - } - - // User explicitly denied the plan. submit-plan already cancelled the - // persisted graph, so the cancelled graph won't be picked up by the - // scheduler. Return a terminal result so the orchestrator stops cleanly. - if (accumulator.isDenied()) { - publishClearingEvent(context); - await clearDraftChecklist(context); - return { result: 'Plan denied by user. No tasks were dispatched.' }; - } - - // Planner finished without approval (no submit-plan or user didn't approve). - await this.tearDownDraftPlan(); - if (!accumulator.isEmpty()) { - return { - result: `Planner added ${accumulator.getTaskList().length} items but did not submit the plan for approval. The plan was not executed.`, - }; - } - return { - result: `Planner finished without producing a plan. Agent output: ${resultText}`, - }; - } - - /** Handle an exception thrown anywhere in the run: fail the trace, publish - * agent-completed with the error, and tear down the draft plan unless it - * was already approved (dispatched tasks must not be wiped). */ - async handleError(error: unknown): Promise<{ result: string }> { - const { context, accumulator, subAgentId } = this; - const errorMessage = error instanceof Error ? error.message : String(error); - - if (this.traceRun) { - await failTraceRun(context, this.traceRun, error, { - agent_id: subAgentId, - agent_role: 'planner', - }); - } - - context.eventBus.publish(context.threadId, { - type: 'agent-completed', - runId: context.runId, - agentId: subAgentId, - payload: { role: 'planner', result: '', error: errorMessage }, - }); - - if (!accumulator.isApproved()) { - await this.tearDownDraftPlan(); - } - - return { result: `Planner error: ${errorMessage}` }; - } - - private publishCompleted(resultText: string): void { - this.context.eventBus.publish(this.context.threadId, { - type: 'agent-completed', - runId: this.context.runId, - agentId: this.subAgentId, - payload: { role: 'planner', result: resultText }, - }); - } - - /** Clear the in-progress checklist UI + the unapproved persisted graph. */ - private async tearDownDraftPlan(): Promise { - publishClearingEvent(this.context); - await clearDraftChecklist(this.context); - await clearPlannedTaskGraph(this.context); - } -} - -async function getPersistedTaskCount(context: OrchestrationContext): Promise { - if (!context.plannedTaskService) return undefined; - try { - const graph = await context.plannedTaskService.getGraph(context.threadId); - return graph?.tasks?.length; - } catch { - return undefined; - } -} diff --git a/packages/@n8n/instance-ai/src/tools/orchestration/report-verification-verdict.tool.ts b/packages/@n8n/instance-ai/src/tools/orchestration/report-verification-verdict.tool.ts index e48bfbaac27..9eb42c762e9 100644 --- a/packages/@n8n/instance-ai/src/tools/orchestration/report-verification-verdict.tool.ts +++ b/packages/@n8n/instance-ai/src/tools/orchestration/report-verification-verdict.tool.ts @@ -34,6 +34,12 @@ export const reportVerificationVerdictInputSchema = z.object({ '"needs_user_input" if user action is required (e.g. missing credentials), ' + '"failed_terminal" if the failure cannot be fixed automatically', ), + workflowInspection: z + .string() + .min(1) + .describe( + 'Brief note from inspecting the persisted workflow JSON/code after save. Mention why the saved graph does or does not match the requested outcome.', + ), failureSignature: z .string() .optional() @@ -101,8 +107,8 @@ function defaultRemediationForVerdict( export function createReportVerificationVerdictTool(context: OrchestrationContext) { return new Tool('report-verification-verdict') .description( - 'Report the result of verifying a workflow after building it. ' + - 'Call this after running a workflow and (optionally) debugging a failed execution. ' + + 'Report the result of verifying a workflow after building it. Only call in checkpoint follow-up turns. ' + + 'Call this after inspecting the persisted workflow, running it, and (optionally) debugging a failed execution. ' + 'Returns deterministic guidance on what to do next (done, rebuild, or blocked).', ) .input(reportVerificationVerdictInputSchema) @@ -144,6 +150,7 @@ export function createReportVerificationVerdictTool(context: OrchestrationContex workflowId: input.workflowId, executionId: input.executionId, verdict: forcedTerminalVerdict ?? input.verdict, + workflowInspection: input.workflowInspection, failureSignature: forcedTerminalVerdict ? (remediation?.reason ?? input.failureSignature) : input.failureSignature, diff --git a/packages/@n8n/instance-ai/src/tools/orchestration/submit-plan.tool.ts b/packages/@n8n/instance-ai/src/tools/orchestration/submit-plan.tool.ts deleted file mode 100644 index 8a96cf425fa..00000000000 --- a/packages/@n8n/instance-ai/src/tools/orchestration/submit-plan.tool.ts +++ /dev/null @@ -1,148 +0,0 @@ -/** - * submit-plan tool — HITL plan approval within the planner sub-agent. - * - * The planner calls this after adding all plan items. It validates the plan, - * suspends for user approval (renders PlanReviewPanel), and returns the - * user's decision. On rejection, the planner receives the feedback directly - * and can make targeted edits (remove/add/update items) before re-submitting. - */ - -import { Tool } from '@n8n/agents'; -import { plannedTaskArgSchema, taskListSchema } from '@n8n/api-types'; -import { nanoid } from 'nanoid'; -import { z } from 'zod'; - -import { publishPlanUpdate } from './add-plan-item.tool'; -import type { BlueprintAccumulator } from './blueprint-accumulator'; -import type { OrchestrationContext, PlannedTask } from '../../types'; - -function textRequestsPostBuildRun(text: string | undefined): boolean { - const normalized = text?.toLowerCase().replace(/\s+/g, ' ') ?? ''; - return /\b(build|create|make)\b.{0,120}\b(then|and)\s+(run|execute|test)\b/.test(normalized); -} - -export function createSubmitPlanTool( - accumulator: BlueprintAccumulator, - context: OrchestrationContext, -) { - return new Tool('submit-plan') - .description( - "Submit the current plan for user approval. Returns the user's decision. " + - 'If rejected, the feedback is returned — make targeted changes with ' + - 'remove-plan-item / add-plan-item, then call submit-plan again.', - ) - .input(z.object({})) - .output( - z.object({ - approved: z.boolean(), - feedback: z.string().optional(), - denied: z.boolean().optional(), - }), - ) - .suspend( - z.object({ - requestId: z.string(), - message: z.string(), - severity: z.literal('info'), - inputType: z.literal('plan-review'), - tasks: taskListSchema, - planItems: z.array(plannedTaskArgSchema).optional(), - }), - ) - .resume( - z.object({ - approved: z.boolean(), - userInput: z.string().optional(), - denied: z.boolean().optional(), - }), - ) - .handler(async (_input, ctx) => { - const resumeData = ctx.resumeData; - - // Resume — return the user's decision to the planner - if (resumeData !== undefined && resumeData !== null) { - if (resumeData.approved) { - accumulator.markApproved(); - return { approved: true }; - } - if (resumeData.denied) { - // Persist cancellation first, then mark the accumulator. Reverse - // order would leave the accumulator denied if denyPlan throws — - // the isDenied() short-circuit below would then block a retry - // while the persisted graph is still awaiting_approval. - if (context.plannedTaskService) { - await context.plannedTaskService.denyPlan(context.threadId); - } - accumulator.markDenied(); - return { - approved: false, - denied: true, - feedback: 'User denied the plan. Do not revise — stop and acknowledge.', - }; - } - return { - approved: false, - feedback: resumeData.userInput ?? 'No specific feedback provided.', - }; - } - - // Already denied — short-circuit any subsequent call so the planner - // cannot re-suspend the user with the same plan after a denial. - if (accumulator.isDenied()) { - return { - approved: false, - denied: true, - feedback: 'Plan already denied by user. Stop and acknowledge.', - }; - } - - // First call — validate, persist plan, suspend for approval - accumulator.reconcileDependencies(); - const tasks = accumulator.getTaskList(); - - if (!context.plannedTaskService) { - return { approved: false, feedback: 'Plan scheduling not available.' }; - } - - // Persist the plan (createPlan validates deps, cycles, duplicates) - await context.plannedTaskService.createPlan( - context.threadId, - tasks as unknown as PlannedTask[], - { - planRunId: context.runId, - messageGroupId: context.messageGroupId, - postBuildRunApprovalRequired: textRequestsPostBuildRun(context.currentUserMessage), - }, - ); - - // Publish final tasks-update with full planItems - publishPlanUpdate(accumulator, context); - - // Build suspend payload - const taskItems = tasks.map((t) => ({ - id: t.id, - description: t.title, - status: 'todo' as const, - })); - const planItems = tasks.map((t) => ({ - id: t.id, - title: t.title, - kind: t.kind, - spec: t.spec, - deps: t.deps, - ...(t.tools ? { tools: t.tools } : {}), - ...(t.workflowId ? { workflowId: t.workflowId } : {}), - })); - - // Suspend — native HITL publishes confirmation-request, frontend renders PlanReviewPanel - return await ctx.suspend({ - requestId: nanoid(), - message: `Review the plan (${tasks.length} task${tasks.length === 1 ? '' : 's'}) before execution starts.`, - severity: 'info' as const, - inputType: 'plan-review' as const, - tasks: { tasks: taskItems }, - planItems, - }); - }) - .build(); -} diff --git a/packages/@n8n/instance-ai/src/tools/orchestration/verify-built-workflow.tool.ts b/packages/@n8n/instance-ai/src/tools/orchestration/verify-built-workflow.tool.ts index 50d7b299e62..78f7bb435a3 100644 --- a/packages/@n8n/instance-ai/src/tools/orchestration/verify-built-workflow.tool.ts +++ b/packages/@n8n/instance-ai/src/tools/orchestration/verify-built-workflow.tool.ts @@ -9,12 +9,7 @@ import { Tool } from '@n8n/agents'; import { z } from 'zod'; -import type { Logger } from '../../logger'; -import type { - InstanceAiDataTableService, - InstanceAiWorkflowService, - OrchestrationContext, -} from '../../types'; +import type { OrchestrationContext } from '../../types'; import { createRemediation, terminalRemediationFromState } from '../../workflow-loop/remediation'; import type { RemediationMetadata, @@ -54,86 +49,6 @@ function outputForInspection(nodeOutput: unknown): unknown { return typeof nodeOutput === 'string' ? unwrapUntrustedData(nodeOutput) : nodeOutput; } -interface DataTableWriteNode { - nodeName: string; - dataTableId: string; - /** - * Only `insert` is cleaned up post-verify. `upsert` is tracked but never - * cleaned up because its node output cannot distinguish a newly-created - * row from a match on an existing row (see cleanupInsertedRowsByNodeOutput). - * `update` never creates rows so cleanup is moot. - */ - operation: 'insert' | 'upsert' | 'update'; -} - -/** - * Extract the data-table write nodes a workflow contains, keyed by node name so - * we can look up each node's per-execution output and identify the exact row IDs - * it created. Returning node-level records (instead of just dataTable IDs) is - * what lets post-verify cleanup delete only rows *this* run inserted — rows from - * concurrent writers never appear in these nodes' outputs, so they are safe. - */ -async function extractDataTableWriteNodes( - workflowService: InstanceAiWorkflowService, - workflowId: string, -): Promise { - try { - const json = await workflowService.getAsWorkflowJSON(workflowId); - const out: DataTableWriteNode[] = []; - for (const node of json.nodes ?? []) { - if (node.type !== 'n8n-nodes-base.dataTable') continue; - const params = node.parameters as Record | undefined; - const operation = params?.operation; - if (operation !== 'insert' && operation !== 'upsert' && operation !== 'update') continue; - const ref = params?.dataTableId; - let dataTableId: string | undefined; - if (typeof ref === 'string' && ref.length > 0) { - dataTableId = ref; - } else if ( - ref && - typeof ref === 'object' && - 'value' in ref && - typeof (ref as { value: unknown }).value === 'string' - ) { - const value = (ref as { value: string }).value; - if (value.length > 0) dataTableId = value; - } - if (!dataTableId || !node.name) continue; - out.push({ nodeName: node.name, dataTableId, operation }); - } - return out; - } catch { - return []; - } -} - -/** - * Extract the numeric `id` values that a single node produced as output during - * the verify execution. Handles the common n8n shapes: an array of row objects, - * a `{ json: {...} }` wrapper, or a single row object. - */ -function extractRowIdsFromNodeOutput(nodeOutput: unknown): number[] { - const ids: number[] = []; - const visit = (value: unknown): void => { - const inspected = outputForInspection(value); - if (!inspected) return; - if (Array.isArray(inspected)) { - for (const item of inspected) visit(item); - return; - } - if (!isRecord(inspected)) return; - const row = inspected; - if (row.json !== undefined) { - visit(row.json); - return; - } - const id = row.id; - if (typeof id === 'number' && Number.isFinite(id)) ids.push(id); - }; - visit(nodeOutput); - return ids; -} - function getCountFromMetadata(value: unknown): number | undefined { if (!isRecord(value)) return undefined; @@ -170,12 +85,14 @@ function previewValue(value: unknown, maxChars: number): { preview: string; trun function buildNodePreviews( resultData: Record | undefined, maxChars: number, + simulatedNodeNames?: ReadonlySet, ): Array<{ nodeName: string; itemCount?: number; preview: string; truncated: boolean; chars: number; + simulated?: boolean; }> { if (!resultData) return []; @@ -188,10 +105,40 @@ function buildNodePreviews( preview: preview.preview, truncated: preview.truncated, chars: serialized.length, + ...(simulatedNodeNames?.has(nodeName) ? { simulated: true } : {}), }; }); } +/** + * Per-execution pin data for the verification run, assembled from the build + * outcome sidecar. Fixture items take precedence over the legacy + * `{_mockedCredential}` markers (still read for build outcomes stored before + * the marker channel was retired). A `simulate`-verdict node without a + * fixture is still pinned (with an empty item) — losing output realism is + * acceptable, executing a destructive operation is not. + */ +function buildVerificationPinData(buildOutcome: WorkflowBuildOutcome): { + pinData: Record | undefined; + simulatedNodes: Array<{ nodeName: string; reason: string }>; +} { + const merged: Record = { ...(buildOutcome.verificationPinData ?? {}) }; + const fixtures = buildOutcome.simulationFixtures ?? {}; + const simulatedNodes: Array<{ nodeName: string; reason: string }> = []; + + for (const verdict of buildOutcome.nodeSimulationPlan ?? []) { + if (verdict.verdict !== 'simulate') continue; + simulatedNodes.push({ nodeName: verdict.nodeName, reason: verdict.reason }); + const items = fixtures[verdict.nodeName]; + merged[verdict.nodeName] = items?.length ? items : [{}]; + } + + return { + pinData: Object.keys(merged).length > 0 ? merged : undefined, + simulatedNodes, + }; +} + function countProducedOutputRows( resultData: Record | undefined, ): number | undefined { @@ -204,154 +151,6 @@ function countProducedOutputRows( return count; } -/** - * Per-table pre-verify snapshot. A `Set` is a complete list of row IDs that - * existed before the run. `null` means the snapshot could not be built (empty - * table, read error, or pagination cap hit) — cleanup skips any table with a - * null snapshot. The snapshot guards insert-node cleanup against pathological - * outputs (e.g. an insert node returning an existing row ID); upsert outputs - * are not eligible for cleanup at all. - */ -type PreIdsMap = Map | null>; - -/** Rows per page when snapshotting table contents. */ -const SNAPSHOT_PAGE_SIZE = 1000; -/** - * Hard cap on total rows we will snapshot per table. Snapshot is only a safety - * check (`is this ID pre-existing?`) so on tables above this size we disable - * cleanup rather than keep paging forever. - */ -const SNAPSHOT_MAX_ROWS = 100_000; - -/** - * Delete rows this verify execution inserted, identified by the node outputs of - * the dataTable insert nodes the workflow contains. Rows inserted by concurrent - * writers never appear in an insert node's output and are therefore safe. - * - * Upsert nodes are deliberately skipped: their node output cannot distinguish - * a newly-created row from a match on an existing one. A concurrent writer - * inserting a row between the snapshot and the upsert call could yield an ID - * that looks "new" to the ID-diff check while actually belonging to the - * concurrent writer — deleting it would destroy production data. Until the - * upsert path exposes a `wasCreated` flag in the row return, we trade leaking - * a few verify-created rows for guaranteed safety. - * - * When `preIdsByTable.get(dataTableId)` is `null` the snapshot could not be - * built and cleanup is skipped for that table; without a reliable pre-existing - * set we cannot distinguish a new insert from a row that pre-existed. - */ -async function cleanupInsertedRowsByNodeOutput( - dataTableService: InstanceAiDataTableService, - writeNodes: DataTableWriteNode[], - resultData: Record | undefined, - preIdsByTable: PreIdsMap, - logger: Logger, -): Promise { - if (!resultData) return 0; - /** per-table set of row IDs the workflow's own insert nodes produced */ - const createdIdsByTable = new Map>(); - for (const { nodeName, dataTableId, operation } of writeNodes) { - if (operation !== 'insert') continue; - const output = resultData[nodeName]; - if (!output) continue; - const ids = extractRowIdsFromNodeOutput(output); - if (ids.length === 0) continue; - let bucket = createdIdsByTable.get(dataTableId); - if (!bucket) { - bucket = new Set(); - createdIdsByTable.set(dataTableId, bucket); - } - for (const id of ids) bucket.add(id); - } - let total = 0; - for (const [dataTableId, ids] of createdIdsByTable) { - const preIds = preIdsByTable.get(dataTableId); - if (preIds === undefined || preIds === null) { - logger.warn( - 'Skipping data-table cleanup: pre-verify snapshot unavailable. Rows left in place to avoid deleting existing data.', - { dataTableId, candidateIds: ids.size }, - ); - continue; - } - // Only delete IDs that did not exist before the run — upsert-matched rows stay. - const toDelete = [...ids].filter((id) => !preIds.has(id)); - if (toDelete.length === 0) continue; - try { - await dataTableService.deleteRows(dataTableId, { - type: 'or', - filters: toDelete.map((id) => ({ - columnName: 'id', - condition: 'eq' as const, - value: id, - })), - }); - total += toDelete.length; - } catch { - // best-effort: failure on one table does not block others - } - } - return total; -} - -/** - * Pre-verify snapshot of current row IDs per tracked table. Used as a defensive - * filter for insert-node cleanup — any output ID present in the pre-snapshot - * is left alone, never deleted. The delete set is still driven by node output, - * not by a post-verify table-wide diff, so concurrent writers stay safe. - * - * The snapshot pages through the full table because the cap on `queryRows` - * would otherwise leave existing rows past the first page unprotected. If - * pagination fails mid-way or the table is bigger than `SNAPSHOT_MAX_ROWS`, - * the entry is set to `null` so `cleanupInsertedRowsByNodeOutput` skips that - * table rather than guess. - */ -async function snapshotRowIdsPerTable( - dataTableService: InstanceAiDataTableService, - dataTableIds: Iterable, - logger: Logger, -): Promise { - const out: PreIdsMap = new Map(); - for (const id of dataTableIds) { - try { - const bucket = new Set(); - let offset = 0; - let truncated = false; - for (;;) { - const { data } = await dataTableService.queryRows(id, { - limit: SNAPSHOT_PAGE_SIZE, - offset, - }); - for (const row of data) { - const rid = row.id; - if (typeof rid === 'number') bucket.add(rid); - } - if (data.length < SNAPSHOT_PAGE_SIZE) break; - offset += SNAPSHOT_PAGE_SIZE; - if (offset >= SNAPSHOT_MAX_ROWS) { - truncated = true; - break; - } - } - if (truncated) { - logger.warn( - 'Data-table pre-verify snapshot exceeded row cap — cleanup disabled for this table', - { dataTableId: id, cap: SNAPSHOT_MAX_ROWS }, - ); - out.set(id, null); - } else { - out.set(id, bucket); - } - } catch (error) { - logger.warn('Data-table pre-verify snapshot failed — cleanup disabled for this table', { - dataTableId: id, - error: error instanceof Error ? error.message : String(error), - }); - out.set(id, null); - } - } - return out; -} - export const verifyBuiltWorkflowInputSchema = z.object({ workItemId: z.string().describe('The work item ID from the build (wi_XXXXXXXX)'), workflowId: z.string().describe('The workflow ID to verify'), @@ -414,12 +213,17 @@ function classifyVerificationFailure( } if (status === 'waiting') { + const hasSimulationPlan = (buildOutcome.nodeSimulationPlan?.length ?? 0) > 0; return createRemediation({ category: 'needs_setup', shouldEdit: false, - reason: 'execution_waiting', - guidance: - 'Workflow verification is waiting for user action or setup. Stop code edits and ask the user to complete setup.', + reason: hasSimulationPlan ? 'unsimulated_user_action_node' : 'execution_waiting', + guidance: hasSimulationPlan + ? 'Verification paused on a node that waits for user action and was not simulated — ' + + 'nodes downstream of it were not verified. This is not a workflow bug: do not edit ' + + 'the code. Report to the user which node paused and that the rest of the workflow ' + + 'needs a manual test.' + : 'Workflow verification is waiting for user action or setup. Stop code edits and ask the user to complete setup.', }); } @@ -477,8 +281,10 @@ export function createVerifyBuiltWorkflowTool(context: OrchestrationContext) { return new Tool('verify-built-workflow') .description( 'Run a built workflow using sidecar verification context from the build outcome. ' + - 'Use this when verification needs build-outcome pin data, mocked credential context, or trigger-shaped inputData. ' + - 'Use `executions(action="run")` for ordinary manual/schedule runs with real credentials. ' + + 'Call when the current turn is responsible for post-build verification. ' + + 'Use this as the standard verifier for workflows produced by the workflow-builder. ' + + 'It supports manual, schedule, form, webhook, chat, and other event triggers with build-outcome pin data, mocked credential context, or trigger-shaped inputData. ' + + 'Use `executions(action="run")` only for ad hoc runs outside build verification. ' + 'CRITICAL: `inputData` shape depends on the trigger type — see the per-trigger guidance on the inputData field. ' + 'Passing the wrong shape (e.g. wrapping form fields under `formFields`) produces null downstream values that ' + 'look like an expression bug but are not — do not patch the workflow, re-run verify with the correct shape.', @@ -498,9 +304,15 @@ export function createVerifyBuiltWorkflowTool(context: OrchestrationContext) { preview: z.string(), truncated: z.boolean(), chars: z.number(), + simulated: z.boolean().optional(), }), ) .optional(), + simulatedNodes: z.array(z.object({ nodeName: z.string(), reason: z.string() })).optional(), + simulationNote: z.string().optional(), + lastNodeExecuted: z.string().optional(), + nodesNotReached: z.array(z.string()).optional(), + coverageNote: z.string().optional(), data: z.record(z.unknown()).optional(), error: z.string().optional(), remediation: remediationOutputSchema, @@ -567,38 +379,117 @@ export function createVerifyBuiltWorkflowTool(context: OrchestrationContext) { const workflowId = buildOutcome.workflowId; - // Pre-verify: enumerate the dataTable write nodes in the workflow and - // snapshot current row IDs for each insert-touched table. The delete - // set comes from each insert node's own output after verify (so - // concurrent writers stay invisible to cleanup); the snapshot is a - // defensive filter so any ID that pre-existed cannot be deleted. - // Upsert outputs are deliberately never cleaned — see - // `cleanupInsertedRowsByNodeOutput` for the rationale. - const writeNodes = await extractDataTableWriteNodes( - context.domainContext.workflowService, - workflowId, - ); - const preSnapshots = await snapshotRowIdsPerTable( - context.domainContext.dataTableService, - new Set(writeNodes.map((n) => n.dataTableId)), - context.logger, - ); + // Destructive nodes (including dataTable writes) are simulated via the + // build outcome's node simulation plan, so verification creates no + // external side effects and needs no post-run cleanup. + // + // An undefined plan (as opposed to an empty one) means the outcome + // predates classification or classification failed entirely — nothing + // shields destructive nodes in that run, so flag it instead of + // silently executing everything for real. + const planMissing = buildOutcome.nodeSimulationPlan === undefined; + if (planMissing) { + const guidance = + 'Verification was not run because the build outcome has no simulation plan. ' + + 'Rebuild or resubmit the workflow so destructive nodes can be classified before verification.'; + const remediation = createRemediation({ + category: 'blocked', + shouldEdit: false, + reason: 'missing_simulation_plan', + guidance, + }); + context.logger.warn( + 'verify-built-workflow: build outcome has no simulation plan — refusing to run without simulation safeguards', + { workItemId: input.workItemId, workflowId: buildOutcome.workflowId }, + ); + try { + await context.workflowTaskService.updateBuildOutcome(input.workItemId, { + remediation, + verification: { + attempted: true, + success: false, + status: 'unknown', + failureSignature: 'missing_simulation_plan', + evidence: { errorMessage: guidance }, + verifiedAt: new Date().toISOString(), + }, + }); + } catch { + // intentional: verification record persistence is advisory + } + try { + await context.workflowTaskService.reportVerificationVerdict({ + workItemId: input.workItemId, + runId: context.runId, + workflowId, + verdict: 'failed_terminal', + failureSignature: 'missing_simulation_plan', + diagnosis: guidance, + remediation, + summary: guidance, + }); + } catch (error) { + context.logger.warn('verify-built-workflow: failed to persist terminal verdict', { + workItemId: input.workItemId, + workflowId, + error: error instanceof Error ? error.message : String(error), + }); + } + return { + success: false, + status: 'unknown', + error: guidance, + remediation, + guidance, + }; + } + const { pinData: verificationPinData, simulatedNodes } = + buildVerificationPinData(buildOutcome); + const simulationMap = + simulatedNodes.length > 0 + ? Object.fromEntries(simulatedNodes.map((n) => [n.nodeName, { reason: n.reason }])) + : undefined; const result = await context.domainContext.executionService.run(workflowId, input.inputData, { timeout: input.timeout, - pinData: buildOutcome.verificationPinData as Record | undefined, + pinData: verificationPinData, + simulation: simulationMap, }); - // Treat `waiting` as success when the workflow produced output and recorded - // no error. `waiting` is a terminal-ish state for several legitimate flows: - // Form Trigger workflows that end on a form-respond / completion page, Wait - // nodes, and HITL prompts. Considering it a failure caused builders to - // falsely retry verified form workflows and prevented checkpoints from - // reusing builder evidence. Only treat `waiting` with no output rows AND - // no error as indeterminate (falls through to failure). + // Coverage: partition the simulation plan against the nodes that + // actually ran. A read node returning zero items legitimately ends the + // execution early (empty item list → downstream never runs), which + // would otherwise look like a clean success while most of the workflow + // — including its planned simulations — was never exercised. + // `executedNodeNames` includes zero-output nodes that `result.data` + // omits; fall back to data keys for hosts that don't report it (e.g. + // the eval-harness execution stub). + const reachedNames = new Set( + result.executedNodeNames ?? (result.data ? Object.keys(result.data) : []), + ); + const reachedSimulatedNodes = simulatedNodes.filter((n) => reachedNames.has(n.nodeName)); + const nodesNotReached = (buildOutcome.nodeSimulationPlan ?? []) + .map((verdict) => verdict.nodeName) + .filter((name) => !reachedNames.has(name)); + + // `waiting` handling depends on whether this build has a simulation plan. + // + // With a plan, every legitimate user-action pause (Form pages, Wait, + // sendAndWait) was classified and pinned, so execution should never park + // in `waiting` — when it does, a user-action node slipped past + // classification (e.g. a community node that waits) and everything + // downstream of it went unverified. That is a failure, not a success. + // + // Without a plan (build outcomes from before classification, or a total + // classification failure), keep the legacy fallback: `waiting` with + // output and no error counts as success — Form Trigger workflows ending + // on a completion page legitimately finish in `waiting`, and failing + // them caused builders to falsely retry verified workflows. + const hasSimulationPlan = (buildOutcome.nodeSimulationPlan?.length ?? 0) > 0; const hasOutput = result.data ? Object.keys(result.data).length > 0 : false; const success = - result.status === 'success' || (result.status === 'waiting' && !result.error && hasOutput); + result.status === 'success' || + (!hasSimulationPlan && result.status === 'waiting' && !result.error && hasOutput); const failureRemediation = success ? undefined @@ -609,22 +500,16 @@ export function createVerifyBuiltWorkflowTool(context: OrchestrationContext) { : undefined; const remediation = budgetRemediation ?? failureRemediation; - // Post-verify cleanup: delete only rows this run's own dataTable insert - // nodes emitted as output, and only those whose IDs were not present in - // the pre-verify snapshot (protects upsert-updated rows from deletion). - const cleanedRows = await cleanupInsertedRowsByNodeOutput( - context.domainContext.dataTableService, - writeNodes, - result.data, - preSnapshots, - context.logger, - ); - // Persist a structured verification record onto the build outcome so the // checkpoint follow-up turn can reuse it instead of re-running verify. // Best-effort: swallow storage errors so they don't mask the verify result. try { - const nodesExecuted = result.data ? Object.keys(result.data) : undefined; + const executedForEvidence = + reachedNames.size > 0 + ? [...reachedNames] + : result.data + ? Object.keys(result.data) + : undefined; await context.workflowTaskService.updateBuildOutcome(input.workItemId, { verification: { attempted: true, @@ -633,7 +518,11 @@ export function createVerifyBuiltWorkflowTool(context: OrchestrationContext) { status: result.status, failureSignature: success ? undefined : result.error, evidence: { - nodesExecuted: nodesExecuted && nodesExecuted.length > 0 ? nodesExecuted : undefined, + nodesExecuted: + executedForEvidence && executedForEvidence.length > 0 + ? executedForEvidence + : undefined, + nodesNotReached: nodesNotReached.length > 0 ? nodesNotReached : undefined, producedOutputRows: countProducedOutputRows(result.data), errorMessage: success ? undefined : result.error, }, @@ -644,14 +533,6 @@ export function createVerifyBuiltWorkflowTool(context: OrchestrationContext) { // intentional: verification record persistence is advisory } - if (cleanedRows > 0) { - context.logger.debug?.('verify-built-workflow: cleaned up inserted rows', { - workItemId: input.workItemId, - workflowId, - cleanedRows, - }); - } - if (remediation && !remediation.shouldEdit) { try { await context.workflowTaskService.reportVerificationVerdict({ @@ -693,13 +574,45 @@ export function createVerifyBuiltWorkflowTool(context: OrchestrationContext) { } const maxDataChars = input.maxDataChars ?? DEFAULT_NODE_PREVIEW_CHARS; - const nodesExecuted = result.data ? Object.keys(result.data) : undefined; + const nodesExecuted = + reachedNames.size > 0 + ? [...reachedNames] + : result.data + ? Object.keys(result.data) + : undefined; + const simulatedNames = new Set(reachedSimulatedNodes.map((n) => n.nodeName)); + const simulationNote = + reachedSimulatedNodes.length > 0 + ? `Simulated ${reachedSimulatedNodes.length} node(s) during verification — no real external writes happened: ` + + reachedSimulatedNodes.map((n) => `${n.nodeName} (${n.reason})`).join('; ') + + '. Relay this to the user when presenting the result.' + : planMissing + ? 'No simulation plan was available for this verification run — nodes were NOT ' + + 'simulated and may have performed real external writes (sent messages, created or ' + + 'modified records). Relay this to the user when presenting the result.' + : undefined; + const coverageNote = + nodesNotReached.length > 0 + ? `Partial coverage: ${nodesNotReached.length} node(s) were never reached and remain UNVERIFIED: ` + + nodesNotReached.join(', ') + + (result.lastNodeExecuted + ? `. Execution ended at "${result.lastNodeExecuted}"${success ? ' because it produced no output items (empty item lists stop downstream nodes)' : ''}.` + : '.') + + (success + ? ' This usually means a lookup or query returned nothing. Seed matching test data and re-run verification, or tell the user the unreached part needs a manual test. Do NOT report the workflow as fully verified.' + : '') + : undefined; return { executionId: result.executionId || undefined, success, status: result.status, nodesExecuted, - nodePreviews: buildNodePreviews(result.data, maxDataChars), + lastNodeExecuted: result.lastNodeExecuted, + nodePreviews: buildNodePreviews(result.data, maxDataChars, simulatedNames), + simulatedNodes: reachedSimulatedNodes.length > 0 ? reachedSimulatedNodes : undefined, + simulationNote, + nodesNotReached: nodesNotReached.length > 0 ? nodesNotReached : undefined, + coverageNote, ...(input.includeData ? { data: result.data } : {}), error: result.error, remediation, diff --git a/packages/@n8n/instance-ai/src/tools/research.tool.ts b/packages/@n8n/instance-ai/src/tools/research.tool.ts index 165c6140300..c3ab529ae2e 100644 --- a/packages/@n8n/instance-ai/src/tools/research.tool.ts +++ b/packages/@n8n/instance-ai/src/tools/research.tool.ts @@ -245,7 +245,9 @@ async function handleFetchUrl( export function createResearchTool(context: InstanceAiContext) { return new Tool('research') - .description('Search the web or fetch page content.') + .description( + 'Search the web or fetch page content. Use when node type definitions are insufficient for external documentation.', + ) .input(inputSchema) .suspend(domainGatingSuspendSchema) .resume(domainGatingResumeSchema) diff --git a/packages/@n8n/instance-ai/src/tools/shared/ask-user.tool.ts b/packages/@n8n/instance-ai/src/tools/shared/ask-user.tool.ts index 93a27be850c..c5e3599f7ac 100644 --- a/packages/@n8n/instance-ai/src/tools/shared/ask-user.tool.ts +++ b/packages/@n8n/instance-ai/src/tools/shared/ask-user.tool.ts @@ -41,7 +41,7 @@ export const askUserResumeSchema = z.object({ export function createAskUserTool() { return new Tool(ASK_USER_TOOL_ID) .description( - 'Ask the user one or more structured questions. Each question can be ' + + 'Ask the user only when a human choice is needed. Each question can be ' + 'single-select (pick one), multi-select (pick many), or free-text. ' + 'The agent is suspended until the user responds. ' + 'IMPORTANT: The UI already provides a built-in "Something else" free-text ' + diff --git a/packages/@n8n/instance-ai/src/tools/tool-ids.ts b/packages/@n8n/instance-ai/src/tools/tool-ids.ts index a9f179f2ad2..99b238103cc 100644 --- a/packages/@n8n/instance-ai/src/tools/tool-ids.ts +++ b/packages/@n8n/instance-ai/src/tools/tool-ids.ts @@ -13,10 +13,6 @@ export const DOMAIN_TOOL_IDS = { } as const; export const ORCHESTRATION_TOOL_IDS = { - PLAN: 'plan', - SUBMIT_PLAN: 'submit-plan', - ADD_PLAN_ITEM: 'add-plan-item', - REMOVE_PLAN_ITEM: 'remove-plan-item', CREATE_TASKS: 'create-tasks', TASK_CONTROL: 'task-control', DELEGATE: 'delegate', @@ -40,7 +36,6 @@ export const ASK_USER_TOOL_ID = DOMAIN_TOOL_IDS.ASK_USER; export const ORCHESTRATION_TOOL_NAMES = new Set(Object.values(ORCHESTRATION_TOOL_IDS)); export const ALWAYS_LOADED_TOOL_NAMES = new Set([ - ORCHESTRATION_TOOL_IDS.PLAN, ORCHESTRATION_TOOL_IDS.CREATE_TASKS, ORCHESTRATION_TOOL_IDS.DELEGATE, DOMAIN_TOOL_IDS.ASK_USER, diff --git a/packages/@n8n/instance-ai/src/tools/workflows.tool.ts b/packages/@n8n/instance-ai/src/tools/workflows.tool.ts index 30cde253854..a446628b810 100644 --- a/packages/@n8n/instance-ai/src/tools/workflows.tool.ts +++ b/packages/@n8n/instance-ai/src/tools/workflows.tool.ts @@ -23,7 +23,9 @@ import { getReferencedWorkflowIds } from './workflows/workflow-json-utils'; // ── Action schemas ────────────────────────────────────────────────────────── const listAction = z.object({ - action: z.literal('list').describe('List workflows accessible to the current user'), + action: z + .literal('list') + .describe('List workflows accessible to the current user. Use for workflow inspection.'), query: z.string().optional().describe('Filter workflows by name'), limit: z.number().int().positive().max(100).optional().describe('Max results to return'), status: z @@ -32,10 +34,18 @@ const listAction = z.object({ .describe( 'Which workflows to list. Defaults to active; use archived to find workflows that can be restored.', ), + scope: z + .enum(['project', 'instance']) + .optional() + .describe( + "Which project(s) to search. Defaults to this conversation's project. Use 'instance' only when you have a clear reason to look across all projects you can access.", + ), }); const getAction = z.object({ - action: z.literal('get').describe('Get full details of a specific workflow'), + action: z + .literal('get') + .describe('Get full details of a specific workflow. Use for workflow inspection.'), workflowId: z.string().describe('ID of the workflow'), }); @@ -47,7 +57,11 @@ const getJsonAction = z.object({ }); const getAsCodeAction = z.object({ - action: z.literal('get-as-code').describe('Convert an existing workflow to TypeScript SDK code'), + action: z + .literal('get-as-code') + .describe( + 'Convert an existing workflow to TypeScript SDK code. Call before precise patches when you need the current code.', + ), workflowId: z.string().describe('ID of the workflow'), }); @@ -69,7 +83,7 @@ const setupAction = z.object({ action: z .literal('setup') .describe( - 'Open the inline AI Assistant workflow setup card for credential and parameter configuration', + 'Open the inline AI Assistant workflow setup card for credential and parameter configuration. Use for setup routing after a build.', ), workflowId: z.string().describe('ID of the workflow'), projectId: z.string().optional().describe('Project ID to scope credential creation to'), @@ -347,6 +361,7 @@ async function handleList(context: InstanceAiContext, input: Extract ({ mockedNodeNames: [], mockedCredentialTypes: [], mockedCredentialsByNode: {}, - verificationPinData: {}, - usesWorkflowPinDataForVerification: false, }), ), })); @@ -42,32 +39,26 @@ vi.mock('../submit-workflow.tool', () => ({ ensureWebhookIds: vi.fn(async () => await Promise.resolve()), })); -describe('createBuildWorkflowTool', () => { - const originalBuildViaPlanGuard = process.env.N8N_INSTANCE_AI_ENFORCE_BUILD_VIA_PLAN; - const restoreBuildViaPlanGuard = () => { - if (originalBuildViaPlanGuard === undefined) { - delete process.env.N8N_INSTANCE_AI_ENFORCE_BUILD_VIA_PLAN; - } else { - process.env.N8N_INSTANCE_AI_ENFORCE_BUILD_VIA_PLAN = originalBuildViaPlanGuard; - } - }; +// LLM-backed services must never hit the network from unit tests. +vi.mock('../classify-node-destructiveness.service', () => ({ + classifyNodesForSimulation: vi.fn(async () => await Promise.resolve([])), +})); +vi.mock('../generate-simulation-fixtures.service', () => ({ + generateSimulationFixtures: vi.fn(async () => await Promise.resolve({})), +})); +describe('createBuildWorkflowTool', () => { beforeEach(() => { vi.clearAllMocks(); - restoreBuildViaPlanGuard(); }); - afterEach(() => { - restoreBuildViaPlanGuard(); - }); - - it('rejects new workflow builds outside a planned or post-plan follow-up', async () => { + it('allows direct new single-workflow builds outside a planned follow-up', async () => { const context = { userId: 'user-1', runId: 'run-1', workflowService: { - createFromWorkflowJSON: vi.fn(), - clearAiTemporary: vi.fn(), + createFromWorkflowJSON: vi.fn(async () => await Promise.resolve({ id: 'wf-1' })), + clearAiTemporary: vi.fn(async () => await Promise.resolve()), }, credentialService: {}, nodeService: {}, @@ -78,53 +69,231 @@ describe('createBuildWorkflowTool', () => { } as unknown as InstanceAiContext; const tool = createBuildWorkflowTool(context); - const result = await executeTool(tool, { code: 'workflow code' }); + const result = await executeTool(tool, { + code: 'workflow code', + name: 'Daily Mlada Boleslav Weather to Slack', + }); expect(result).toMatchObject({ - success: false, - errors: [ - 'New workflow builds must be planned first: call `plan` so the user can approve the build plan before saving.', - ], + success: true, + workflowId: 'wf-1', }); - expect(context.workflowService.createFromWorkflowJSON).not.toHaveBeenCalled(); - }); - - it('aborts after repeated new workflow build plan-guard rejections', async () => { - const warn = vi.fn(); - const context = { - userId: 'user-1', - runId: 'run-1', - workflowService: { - createFromWorkflowJSON: vi.fn(), - clearAiTemporary: vi.fn(), - }, - credentialService: {}, - nodeService: {}, - dataTableService: {}, - executionService: {}, - permissions: { createWorkflow: 'always_allow' }, - logger: { warn }, - } as unknown as InstanceAiContext; - - const tool = createBuildWorkflowTool(context); - - await expect(executeTool(tool, { code: 'workflow code' })).resolves.toMatchObject({ - success: false, - }); - await expect(executeTool(tool, { code: 'workflow code' })).resolves.toMatchObject({ - success: false, - }); - await expect(executeTool(tool, { code: 'workflow code' })).rejects.toBeInstanceOf(UserError); - - expect(context.workflowService.createFromWorkflowJSON).not.toHaveBeenCalled(); - expect(warn).toHaveBeenCalledWith( - 'build-workflow plan-guard rejection limit reached — aborting run', - expect.objectContaining({ rejectionCount: 3 }), + expect(context.workflowService.createFromWorkflowJSON).toHaveBeenCalledWith( + expect.objectContaining({ name: 'Daily Mlada Boleslav Weather to Slack' }), + { markAsAiTemporary: true }, ); }); - it('honors the build-via-plan guard escape hatch', async () => { - process.env.N8N_INSTANCE_AI_ENFORCE_BUILD_VIA_PLAN = 'false'; + it('escalates when the same build failure repeats for one work item', async () => { + const context = { + userId: 'user-1', + runId: 'run-1', + workflowService: {}, + credentialService: {}, + permissions: { createWorkflow: 'always_allow' }, + logger: { warn: vi.fn() }, + } as unknown as InstanceAiContext; + + const throwJoinError = () => { + throw new Error("Failed to parse workflow code: Method 'join' is not an allowed SDK method."); + }; + vi.mocked(parseAndValidate) + .mockImplementationOnce(throwJoinError) + .mockImplementationOnce(throwJoinError); + + const tool = createBuildWorkflowTool(context); + + const first = await executeTool<{ success: boolean; errors?: string[] }>(tool, { + code: 'a.join()', + workItemId: 'wi-1', + }); + expect(first.success).toBe(false); + expect((first.errors ?? []).join('\n')).not.toContain('You already tried this'); + + const second = await executeTool<{ success: boolean; errors?: string[] }>(tool, { + code: 'a.join()', + workItemId: 'wi-1', + }); + expect(second.success).toBe(false); + expect((second.errors ?? []).join('\n')).toContain('You already tried this'); + expect((second.errors ?? []).join('\n')).toContain('workflow-sdk-language.md'); + }); + + it('keeps repeated validation-error escalation generic', async () => { + const context = { + userId: 'user-1', + runId: 'run-1', + workflowService: {}, + credentialService: {}, + permissions: { createWorkflow: 'always_allow' }, + logger: { warn: vi.fn() }, + } as unknown as InstanceAiContext; + const validationResult = { + workflow: { name: 'Generated workflow', nodes: [], connections: {} }, + warnings: [{ code: 'UNKNOWN_CONFIG_KEY', message: 'Unknown config key "recipient"' }], + }; + const partitionedWarnings = { + errors: [{ code: 'UNKNOWN_CONFIG_KEY', message: 'Unknown config key "recipient"' }], + informational: [], + }; + vi.mocked(parseAndValidate) + .mockReturnValueOnce(validationResult) + .mockReturnValueOnce(validationResult); + vi.mocked(partitionWarnings) + .mockReturnValueOnce(partitionedWarnings) + .mockReturnValueOnce(partitionedWarnings); + + const tool = createBuildWorkflowTool(context); + + await executeTool<{ success: boolean; errors?: string[] }>(tool, { + code: 'workflow code', + workItemId: 'wi-1', + }); + const second = await executeTool<{ success: boolean; errors?: string[] }>(tool, { + code: 'workflow code', + workItemId: 'wi-1', + }); + const errorText = (second.errors ?? []).join('\n'); + expect(errorText).toContain('You already tried this'); + expect(errorText).not.toContain('workflow-sdk-language.md'); + expect(errorText).not.toContain('Code node'); + }); + + it('uses workflowBuildContext work item as the repeat-failure key', async () => { + const workflowBuildContext = { + threadId: 'thread-1', + runId: 'run-1', + taskId: 'task-1', + workItemId: 'wi-1', + }; + const context = { + userId: 'user-1', + runId: 'run-1', + workflowService: {}, + credentialService: {}, + workflowBuildContext, + permissions: { createWorkflow: 'always_allow' }, + logger: { warn: vi.fn() }, + } as unknown as InstanceAiContext; + + const throwJoinError = () => { + throw new Error("Failed to parse workflow code: Method 'join' is not an allowed SDK method."); + }; + vi.mocked(parseAndValidate) + .mockImplementationOnce(throwJoinError) + .mockImplementationOnce(throwJoinError) + .mockImplementationOnce(throwJoinError); + + const tool = createBuildWorkflowTool(context); + await executeTool<{ success: boolean; errors?: string[] }>(tool, { code: 'a.join()' }); + workflowBuildContext.workItemId = 'wi-2'; + const firstForSecondWorkItem = await executeTool<{ success: boolean; errors?: string[] }>( + tool, + { + code: 'a.join()', + }, + ); + const repeatForSecondWorkItem = await executeTool<{ success: boolean; errors?: string[] }>( + tool, + { + code: 'a.join()', + }, + ); + + expect((firstForSecondWorkItem.errors ?? []).join('\n')).not.toContain( + 'You already tried this', + ); + expect((repeatForSecondWorkItem.errors ?? []).join('\n')).toContain('You already tried this'); + }); + + it('does not share repeat-failure history between main and supporting workflows', async () => { + const context = { + userId: 'user-1', + runId: 'run-1', + workflowService: {}, + credentialService: {}, + workflowBuildContext: { + threadId: 'thread-1', + runId: 'run-1', + taskId: 'task-1', + workItemId: 'wi-main', + }, + permissions: { createWorkflow: 'always_allow' }, + logger: { warn: vi.fn() }, + } as unknown as InstanceAiContext; + + const throwJoinError = () => { + throw new Error("Failed to parse workflow code: Method 'join' is not an allowed SDK method."); + }; + vi.mocked(parseAndValidate) + .mockImplementationOnce(throwJoinError) + .mockImplementationOnce(throwJoinError) + .mockImplementationOnce(throwJoinError); + + const tool = createBuildWorkflowTool(context); + await executeTool<{ success: boolean; errors?: string[] }>(tool, { code: 'a.join()' }); + const firstSupportingAttempt = await executeTool<{ success: boolean; errors?: string[] }>( + tool, + { + code: 'a.join()', + isSupportingWorkflow: true, + name: 'Support workflow', + }, + ); + const repeatSupportingAttempt = await executeTool<{ success: boolean; errors?: string[] }>( + tool, + { + code: 'a.join()', + isSupportingWorkflow: true, + name: 'Support workflow', + }, + ); + + expect((firstSupportingAttempt.errors ?? []).join('\n')).not.toContain( + 'You already tried this', + ); + expect((repeatSupportingAttempt.errors ?? []).join('\n')).toContain('You already tried this'); + }); + + it('uses workflowBuildContext task id as the fallback repeat-failure key', async () => { + const workflowBuildContext = { + threadId: 'thread-1', + runId: 'run-1', + taskId: 'task-1', + }; + const context = { + userId: 'user-1', + runId: 'run-1', + workflowService: {}, + credentialService: {}, + workflowBuildContext, + permissions: { createWorkflow: 'always_allow' }, + logger: { warn: vi.fn() }, + } as unknown as InstanceAiContext; + + const throwJoinError = () => { + throw new Error("Failed to parse workflow code: Method 'join' is not an allowed SDK method."); + }; + vi.mocked(parseAndValidate) + .mockImplementationOnce(throwJoinError) + .mockImplementationOnce(throwJoinError) + .mockImplementationOnce(throwJoinError); + + const tool = createBuildWorkflowTool(context); + await executeTool<{ success: boolean; errors?: string[] }>(tool, { code: 'a.join()' }); + workflowBuildContext.taskId = 'task-2'; + const firstForSecondTask = await executeTool<{ success: boolean; errors?: string[] }>(tool, { + code: 'a.join()', + }); + const repeatForSecondTask = await executeTool<{ success: boolean; errors?: string[] }>(tool, { + code: 'a.join()', + }); + + expect((firstForSecondTask.errors ?? []).join('\n')).not.toContain('You already tried this'); + expect((repeatForSecondTask.errors ?? []).join('\n')).toContain('You already tried this'); + }); + + it('allows direct new workflow builds without a name parameter when code provides one', async () => { const context = { userId: 'user-1', runId: 'run-1', @@ -231,6 +400,7 @@ describe('createBuildWorkflowTool', () => { expect(reportBuildOutcome).toHaveBeenCalledWith( expect.objectContaining>({ workItemId: 'wi-1', + owner: { type: 'direct' }, workflowId: 'wf-1', submitted: true, }), @@ -348,10 +518,100 @@ describe('createBuildWorkflowTool', () => { const reportedOutcome = reportBuildOutcome.mock.calls[0]?.[0]; expect(reportedOutcome).toMatchObject({ workItemId: supportingWorkItemId, + owner: { type: 'direct' }, workflowId: 'wf-support', submitted: true, }); expect(reportedOutcome?.taskId).toEqual(expect.stringMatching(/^task-1:supporting-/)); + expect(reportedOutcome?.plannedTaskId).toBeUndefined(); + }); + + it('finalizes the planned task when the task deliverable is a supporting workflow', async () => { + const reportBuildOutcome = vi.fn< + (outcome: WorkflowBuildOutcome) => Promise<{ type: 'verify'; workflowId: string }> + >(async () => await Promise.resolve({ type: 'verify', workflowId: 'wf-support' })); + const markSucceeded = vi.fn< + ( + threadId: string, + taskId: string, + update: { result?: string; outcome?: WorkflowBuildOutcome }, + ) => Promise + >(async () => await Promise.resolve(null)); + const onBuildOutcome = vi.fn(); + const context = { + userId: 'user-1', + runId: 'run-1', + workflowService: { + createFromWorkflowJSON: vi.fn(async () => await Promise.resolve({ id: 'wf-support' })), + clearAiTemporary: vi.fn(async () => await Promise.resolve()), + }, + credentialService: {}, + nodeService: {}, + dataTableService: {}, + executionService: {}, + workflowBuildContext: { + threadId: 'thread-1', + runId: 'run-1', + taskId: 'task-1', + workItemId: 'wi-main', + isSupportingWorkflowTask: true, + plannedTaskService: { + markSucceeded, + }, + workflowTaskService: { + reportBuildOutcome, + }, + onBuildOutcome, + }, + permissions: { createWorkflow: 'always_allow' }, + logger: { warn: vi.fn() }, + } as unknown as InstanceAiContext; + + const tool = createBuildWorkflowTool(context); + const result = await executeTool(tool, { + code: 'workflow code', + isSupportingWorkflow: true, + }); + + expect(result).toMatchObject({ + success: true, + workflowId: 'wf-support', + workItemId: 'wi-main', + isSupportingWorkflow: true, + }); + expect(context.workflowService.clearAiTemporary).toHaveBeenCalledWith('wf-support'); + expect(onBuildOutcome).toHaveBeenCalledWith( + expect.objectContaining>({ + workItemId: 'wi-main', + taskId: 'task-1', + owner: { type: 'planned', taskId: 'task-1' }, + plannedTaskId: 'task-1', + workflowId: 'wf-support', + submitted: true, + }), + ); + expect(reportBuildOutcome).toHaveBeenCalledWith( + expect.objectContaining>({ + workItemId: 'wi-main', + taskId: 'task-1', + owner: { type: 'planned', taskId: 'task-1' }, + plannedTaskId: 'task-1', + workflowId: 'wf-support', + submitted: true, + }), + ); + expect(markSucceeded).toHaveBeenCalledWith('thread-1', 'task-1', expect.any(Object)); + const succeededUpdate = markSucceeded.mock.calls[0]?.[2]; + expect(succeededUpdate?.result).toBe( + 'Created supporting workflow "Generated workflow" (wf-support).', + ); + expect(succeededUpdate?.outcome).toMatchObject({ + workItemId: 'wi-main', + taskId: 'task-1', + owner: { type: 'planned', taskId: 'task-1' }, + plannedTaskId: 'task-1', + workflowId: 'wf-support', + }); }); it('reports a workflow-loop outcome when saving succeeds', async () => { @@ -416,6 +676,8 @@ describe('createBuildWorkflowTool', () => { workItemId: 'wi-1', runId: 'run-1', taskId: 'task-1', + owner: { type: 'planned', taskId: 'task-1' }, + plannedTaskId: 'task-1', workflowId: 'wf-1', submitted: true, verificationReadiness: { status: 'ready' }, @@ -425,7 +687,12 @@ describe('createBuildWorkflowTool', () => { expect(markSucceeded).toHaveBeenCalledWith('thread-1', 'task-1', expect.any(Object)); const succeededUpdate = markSucceeded.mock.calls[0]?.[2]; expect(succeededUpdate?.result).toBe('Created workflow "Generated workflow" (wf-1).'); - expect(succeededUpdate?.outcome).toMatchObject({ workItemId: 'wi-1', workflowId: 'wf-1' }); + expect(succeededUpdate?.outcome).toMatchObject({ + workItemId: 'wi-1', + owner: { type: 'planned', taskId: 'task-1' }, + plannedTaskId: 'task-1', + workflowId: 'wf-1', + }); }); it('keeps the build successful when main workflow promotion fails', async () => { @@ -471,4 +738,78 @@ describe('createBuildWorkflowTool', () => { 'Failed to clear AI-builder temporary marker on main workflow wf-1: temporary marker cleanup failed', ); }); + + it('records workflow code snapshot on success when callback is set', async () => { + const recordWorkflowCodeSnapshot = vi.fn(); + const context = { + userId: 'user-1', + runId: 'run-1', + workflowService: { + createFromWorkflowJSON: vi.fn(async () => await Promise.resolve({ id: 'wf-1' })), + clearAiTemporary: vi.fn(async () => await Promise.resolve()), + }, + credentialService: {}, + nodeService: {}, + dataTableService: {}, + executionService: {}, + permissions: { createWorkflow: 'always_allow' }, + logger: { warn: vi.fn() }, + recordWorkflowCodeSnapshot, + } as unknown as InstanceAiContext; + + const tool = createBuildWorkflowTool(context); + const result = await executeTool( + tool, + { + code: 'workflow code', + name: 'Snapshot Test Workflow', + }, + { toolCallId: 'tc-build-1' }, + ); + + expect(result).toMatchObject({ success: true, workflowId: 'wf-1' }); + expect(recordWorkflowCodeSnapshot).toHaveBeenCalledWith( + expect.objectContaining({ + code: 'workflow code', + source: 'full-code', + success: true, + toolCallId: 'tc-build-1', + capturedAt: expect.any(Number) as unknown, + }), + ); + }); + + it('records workflow code snapshot on parse failure when callback is set', async () => { + const recordWorkflowCodeSnapshot = vi.fn(); + const context = { + userId: 'user-1', + runId: 'run-1', + workflowService: {}, + credentialService: {}, + permissions: { createWorkflow: 'always_allow' }, + logger: { warn: vi.fn() }, + recordWorkflowCodeSnapshot, + } as unknown as InstanceAiContext; + + vi.mocked(parseAndValidate).mockImplementationOnce(() => { + throw new Error('Failed to parse workflow code'); + }); + + const tool = createBuildWorkflowTool(context); + const result = await executeTool<{ success: boolean; errors?: string[] }>(tool, { + code: 'broken workflow code', + name: 'Broken Workflow', + }); + + expect(result.success).toBe(false); + expect(recordWorkflowCodeSnapshot).toHaveBeenCalledWith( + expect.objectContaining({ + source: 'full-code', + success: false, + errors: expect.arrayContaining([ + expect.stringContaining('Failed to parse workflow code'), + ]) as unknown, + }), + ); + }); }); diff --git a/packages/@n8n/instance-ai/src/tools/workflows/__tests__/classify-node-destructiveness.service.test.ts b/packages/@n8n/instance-ai/src/tools/workflows/__tests__/classify-node-destructiveness.service.test.ts new file mode 100644 index 00000000000..8510dc29ae2 --- /dev/null +++ b/packages/@n8n/instance-ai/src/tools/workflows/__tests__/classify-node-destructiveness.service.test.ts @@ -0,0 +1,355 @@ +import type { WorkflowJSON } from '@n8n/workflow-sdk'; +import type { MockedFunction } from 'vitest'; + +vi.mock('../../../utils/eval-agents', async () => { + const actual: object = await vi.importActual('../../../utils/eval-agents'); + return { ...actual, createEvalAgent: vi.fn(), extractText: vi.fn() }; +}); + +import { createEvalAgent, extractText } from '../../../utils/eval-agents'; +import { classifyNodesForSimulation } from '../classify-node-destructiveness.service'; + +const mockCreateEvalAgent = createEvalAgent as MockedFunction; +const mockExtractText = extractText as MockedFunction; + +function setupAgentMock(responseText: string) { + const generate = vi.fn().mockResolvedValue({ messages: [] }); + mockCreateEvalAgent.mockReturnValue({ generate } as unknown as ReturnType< + typeof createEvalAgent + >); + mockExtractText.mockReturnValue(responseText); +} + +function setupAgentFailure() { + const generate = vi.fn().mockRejectedValue(new Error('boom')); + mockCreateEvalAgent.mockReturnValue({ generate } as unknown as ReturnType< + typeof createEvalAgent + >); +} + +type NodeSpec = { + name: string; + type: string; + parameters?: Record; + disabled?: boolean; +}; + +/** Build a workflow whose nodes form a single main-connection chain. */ +function chainWorkflow(nodes: NodeSpec[]): WorkflowJSON { + const connections: Record = {}; + for (let i = 0; i < nodes.length - 1; i++) { + connections[nodes[i].name] = { + main: [[{ node: nodes[i + 1].name, type: 'main', index: 0 }]], + }; + } + return { + name: 'test', + nodes: nodes.map((n, i) => ({ + id: `id-${i}`, + name: n.name, + type: n.type, + typeVersion: 1, + position: [i * 100, 0], + parameters: n.parameters ?? {}, + ...(n.disabled !== undefined ? { disabled: n.disabled } : {}), + })), + connections, + pinData: {}, + settings: {}, + } as unknown as WorkflowJSON; +} + +const trigger: NodeSpec = { name: 'Webhook', type: 'n8n-nodes-base.webhook' }; + +async function classify(nodes: NodeSpec[], mockedNodeNames?: string[]) { + return await classifyNodesForSimulation({ + workflow: chainWorkflow(nodes), + mockedNodeNames, + }); +} + +function verdictOf(verdicts: Awaited>, nodeName: string) { + const verdict = verdicts.find((v) => v.nodeName === nodeName); + expect(verdict).toBeDefined(); + return verdict!; +} + +describe('classifyNodesForSimulation', () => { + beforeEach(() => vi.clearAllMocks()); + + it('classifies transform nodes as execute without calling the LLM', async () => { + const verdicts = await classify([trigger, { name: 'Set', type: 'n8n-nodes-base.set' }]); + expect(verdictOf(verdicts, 'Set')).toMatchObject({ + verdict: 'execute', + confidence: 'high', + source: 'deterministic', + }); + expect(mockCreateEvalAgent).not.toHaveBeenCalled(); + }); + + it('classifies unambiguous write operations as simulate deterministically', async () => { + const verdicts = await classify([ + trigger, + { + name: 'Insert Row', + type: 'n8n-nodes-base.dataTable', + parameters: { operation: 'insert', dataTableId: 'dt1' }, + }, + ]); + expect(verdictOf(verdicts, 'Insert Row')).toMatchObject({ + verdict: 'simulate', + confidence: 'high', + source: 'deterministic', + }); + expect(mockCreateEvalAgent).not.toHaveBeenCalled(); + }); + + it('classifies unambiguous read operations as execute deterministically', async () => { + const verdicts = await classify([ + trigger, + { + name: 'Get Rows', + type: 'n8n-nodes-base.dataTable', + parameters: { operation: 'getAll' }, + }, + ]); + expect(verdictOf(verdicts, 'Get Rows')).toMatchObject({ + verdict: 'execute', + source: 'deterministic', + }); + }); + + it('forces simulate for nodes with mocked credentials, even read operations', async () => { + const verdicts = await classify( + [ + trigger, + { name: 'Get Rows', type: 'n8n-nodes-base.slack', parameters: { operation: 'get' } }, + ], + ['Get Rows'], + ); + expect(verdictOf(verdicts, 'Get Rows')).toMatchObject({ + verdict: 'simulate', + source: 'deterministic', + reason: 'Credentials are not configured for this node', + }); + }); + + it('excludes triggers, sticky notes, disabled nodes, and nodes outside the main flow', async () => { + const workflow = chainWorkflow([ + trigger, + { name: 'Set', type: 'n8n-nodes-base.set' }, + { name: 'Disabled', type: 'n8n-nodes-base.set', disabled: true }, + ]); + // Sticky note and an unconnected sub-node-style entry + workflow.nodes.push( + { + id: 'sticky', + name: 'Note', + type: 'n8n-nodes-base.stickyNote', + typeVersion: 1, + position: [0, 200], + parameters: {}, + } as unknown as WorkflowJSON['nodes'][number], + { + id: 'model', + name: 'Model', + type: '@n8n/n8n-nodes-langchain.lmChatOpenAi', + typeVersion: 1, + position: [0, 300], + parameters: {}, + } as unknown as WorkflowJSON['nodes'][number], + ); + const verdicts = await classifyNodesForSimulation({ workflow }); + expect(verdicts.map((v) => v.nodeName)).toEqual(['Set']); + }); + + it('classifies HTTP GET as execute deterministically', async () => { + const verdicts = await classify([ + trigger, + { + name: 'Fetch', + type: 'n8n-nodes-base.httpRequest', + parameters: { method: 'GET', url: 'https://api.example.com/items' }, + }, + ]); + expect(verdictOf(verdicts, 'Fetch')).toMatchObject({ + verdict: 'execute', + source: 'deterministic', + }); + expect(mockCreateEvalAgent).not.toHaveBeenCalled(); + }); + + it('sends non-GET HTTP requests to the LLM and respects its execute verdict', async () => { + setupAgentMock( + JSON.stringify({ + Search: { verdict: 'execute', reason: 'POST to a search endpoint', confidence: 'high' }, + }), + ); + const verdicts = await classify([ + trigger, + { + name: 'Search', + type: 'n8n-nodes-base.httpRequest', + parameters: { method: 'POST', url: 'https://api.example.com/search' }, + }, + ]); + expect(verdictOf(verdicts, 'Search')).toMatchObject({ + verdict: 'execute', + source: 'llm', + confidence: 'high', + }); + expect(mockCreateEvalAgent).toHaveBeenCalledTimes(1); + }); + + it('classifies IO-free Code nodes as execute deterministically', async () => { + const verdicts = await classify([ + trigger, + { + name: 'Transform', + type: 'n8n-nodes-base.code', + parameters: { jsCode: 'return items.map(i => ({ json: { n: i.json.n * 2 } }));' }, + }, + ]); + expect(verdictOf(verdicts, 'Transform')).toMatchObject({ + verdict: 'execute', + source: 'deterministic', + }); + expect(mockCreateEvalAgent).not.toHaveBeenCalled(); + }); + + it('falls back to simulate when the LLM call fails', async () => { + setupAgentFailure(); + const verdicts = await classify([ + trigger, + { + name: 'Custom', + type: 'n8n-nodes-community.someNode', + parameters: {}, + }, + ]); + expect(verdictOf(verdicts, 'Custom')).toMatchObject({ + verdict: 'simulate', + confidence: 'low', + source: 'fallback', + }); + }); + + it('falls back to simulate for nodes the LLM response omits', async () => { + setupAgentMock( + JSON.stringify({ + Known: { verdict: 'execute', reason: 'reads data', confidence: 'high' }, + }), + ); + const verdicts = await classify([ + trigger, + { name: 'Known', type: 'n8n-nodes-community.a', parameters: {} }, + { name: 'Omitted', type: 'n8n-nodes-community.b', parameters: {} }, + ]); + expect(verdictOf(verdicts, 'Known').verdict).toBe('execute'); + expect(verdictOf(verdicts, 'Omitted')).toMatchObject({ + verdict: 'simulate', + source: 'fallback', + }); + }); + + it('returns a plan with fallback verdicts even when the LLM path throws before the call', async () => { + // A throw outside the LLM call's own try/catch (here: JSON.stringify on + // circular parameters while building the prompt) must not abort the whole + // plan — the plan is the only source of verification pin data. + const circular: Record = { method: 'POST' }; + circular.self = circular; + const verdicts = await classify([ + trigger, + { name: 'Transform', type: 'n8n-nodes-base.set', parameters: {} }, + { name: 'Post', type: 'n8n-nodes-base.httpRequest', parameters: circular }, + ]); + expect(verdictOf(verdicts, 'Transform').verdict).toBe('execute'); + expect(verdictOf(verdicts, 'Post')).toMatchObject({ + verdict: 'simulate', + confidence: 'low', + source: 'fallback', + }); + }); + + it('falls back to simulate on malformed LLM output', async () => { + setupAgentMock('not json'); + const verdicts = await classify([ + trigger, + { name: 'Custom', type: 'n8n-nodes-community.someNode', parameters: {} }, + ]); + expect(verdictOf(verdicts, 'Custom')).toMatchObject({ + verdict: 'simulate', + source: 'fallback', + }); + }); + + it('returns an empty plan for a trigger-only workflow', async () => { + const verdicts = await classify([trigger]); + expect(verdicts).toEqual([]); + expect(mockCreateEvalAgent).not.toHaveBeenCalled(); + }); + + it('classifies mid-workflow form pages as simulate', async () => { + const verdicts = await classify([ + trigger, + { + name: 'Approval Form', + type: 'n8n-nodes-base.form', + parameters: { formFields: { values: [{ fieldLabel: 'Approved?' }] } }, + }, + ]); + expect(verdictOf(verdicts, 'Approval Form')).toMatchObject({ + verdict: 'simulate', + source: 'deterministic', + }); + expect(mockCreateEvalAgent).not.toHaveBeenCalled(); + }); + + it('executes short time-interval waits to preserve pass-through data', async () => { + const verdicts = await classify([ + trigger, + { + name: 'Brief Pause', + type: 'n8n-nodes-base.wait', + parameters: { resume: 'timeInterval', amount: 30, unit: 'seconds' }, + }, + ]); + expect(verdictOf(verdicts, 'Brief Pause')).toMatchObject({ + verdict: 'execute', + source: 'deterministic', + }); + }); + + it('simulates a default wait node (1 hour time interval)', async () => { + const verdicts = await classify([ + trigger, + { name: 'Wait', type: 'n8n-nodes-base.wait', parameters: {} }, + ]); + expect(verdictOf(verdicts, 'Wait')).toMatchObject({ + verdict: 'simulate', + source: 'deterministic', + }); + }); + + it('simulates waits that resume on webhook or form', async () => { + const verdicts = await classify([ + trigger, + { name: 'Wait Hook', type: 'n8n-nodes-base.wait', parameters: { resume: 'webhook' } }, + { name: 'Wait Form', type: 'n8n-nodes-base.wait', parameters: { resume: 'form' } }, + ]); + expect(verdictOf(verdicts, 'Wait Hook').verdict).toBe('simulate'); + expect(verdictOf(verdicts, 'Wait Form').verdict).toBe('simulate'); + expect(mockCreateEvalAgent).not.toHaveBeenCalled(); + }); + + it('classifies destructive-by-type nodes as simulate', async () => { + const verdicts = await classify([ + trigger, + { name: 'Send Email', type: 'n8n-nodes-base.emailSend', parameters: {} }, + ]); + expect(verdictOf(verdicts, 'Send Email')).toMatchObject({ + verdict: 'simulate', + source: 'deterministic', + }); + }); +}); 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 new file mode 100644 index 00000000000..155afb47240 --- /dev/null +++ b/packages/@n8n/instance-ai/src/tools/workflows/__tests__/generate-simulation-fixtures.service.test.ts @@ -0,0 +1,170 @@ +import type { WorkflowJSON } from '@n8n/workflow-sdk'; +import type { MockedFunction } from 'vitest'; + +vi.mock('../../../utils/eval-agents', async () => { + const actual: object = await vi.importActual('../../../utils/eval-agents'); + return { ...actual, createEvalAgent: vi.fn(), extractText: vi.fn() }; +}); + +import { createEvalAgent, extractText } from '../../../utils/eval-agents'; +import type { NodeSimulationVerdict } from '../../../workflow-loop/workflow-loop-state'; +import { generateSimulationFixtures } from '../generate-simulation-fixtures.service'; + +const mockCreateEvalAgent = createEvalAgent as MockedFunction; +const mockExtractText = extractText as MockedFunction; + +function setupAgentMock(responseText: string) { + const generate = vi.fn().mockResolvedValue({ messages: [] }); + mockCreateEvalAgent.mockReturnValue({ generate } as unknown as ReturnType< + typeof createEvalAgent + >); + mockExtractText.mockReturnValue(responseText); +} + +const wf = (nodes: Array<{ name: string; type: string }>): WorkflowJSON => + ({ + name: 'test', + nodes: nodes.map((n, i) => ({ + id: `id-${i}`, + name: n.name, + type: n.type, + typeVersion: 1, + position: [i * 100, 0], + parameters: {}, + })), + connections: {}, + pinData: {}, + settings: {}, + }) as unknown as WorkflowJSON; + +const simulateVerdict = (nodeName: string): NodeSimulationVerdict => ({ + nodeName, + verdict: 'simulate', + reason: 'Sends a message', + confidence: 'high', + source: 'deterministic', +}); + +const executeVerdict = (nodeName: string): NodeSimulationVerdict => ({ + nodeName, + verdict: 'execute', + reason: 'Reads data', + confidence: 'high', + source: 'deterministic', +}); + +describe('generateSimulationFixtures', () => { + beforeEach(() => vi.clearAllMocks()); + + it('returns {} when the plan has no simulate verdicts', async () => { + const result = await generateSimulationFixtures({ + workflow: wf([{ name: 'Get', type: 'n8n-nodes-base.slack' }]), + plan: [executeVerdict('Get')], + }); + expect(result).toEqual({}); + expect(mockCreateEvalAgent).not.toHaveBeenCalled(); + }); + + it('returns LLM fixtures for simulated nodes only', async () => { + setupAgentMock( + JSON.stringify({ + 'Send Slack': [{ json: { ok: true, ts: '1718000000.000100', channel: 'C123' } }], + }), + ); + const result = await generateSimulationFixtures({ + workflow: wf([ + { name: 'Send Slack', type: 'n8n-nodes-base.slack' }, + { name: 'Get Rows', type: 'n8n-nodes-base.dataTable' }, + ]), + plan: [simulateVerdict('Send Slack'), executeVerdict('Get Rows')], + }); + expect(Object.keys(result)).toEqual(['Send Slack']); + expect(result['Send Slack'][0]).toMatchObject({ ok: true }); + }); + + it('fills empty fixtures for nodes the LLM omitted', async () => { + setupAgentMock(JSON.stringify({ A: [{ json: { id: 1 } }] })); + const result = await generateSimulationFixtures({ + workflow: wf([ + { name: 'A', type: 'n8n-nodes-base.slack' }, + { name: 'B', type: 'n8n-nodes-base.gmail' }, + ]), + plan: [simulateVerdict('A'), simulateVerdict('B')], + }); + expect(result.A).toEqual([{ id: 1 }]); + expect(result.B).toEqual([{}]); + }); + + it('returns empty fixtures for every node on malformed LLM output', async () => { + setupAgentMock('not json'); + const result = await generateSimulationFixtures({ + workflow: wf([{ name: 'A', type: 'n8n-nodes-base.slack' }]), + plan: [simulateVerdict('A')], + }); + expect(result).toEqual({ A: [{}] }); + }); + + it('returns empty fixtures for every node when the LLM call throws', async () => { + const generate = vi.fn().mockRejectedValue(new Error('boom')); + mockCreateEvalAgent.mockReturnValue({ generate } as unknown as ReturnType< + typeof createEvalAgent + >); + const result = await generateSimulationFixtures({ + workflow: wf([{ name: 'A', type: 'n8n-nodes-base.slack' }]), + plan: [simulateVerdict('A')], + }); + expect(result).toEqual({ A: [{}] }); + }); + + it('strips markdown fences around the JSON output', async () => { + setupAgentMock('```json\n{"A":[{"json":{"ok":true}}]}\n```'); + const result = await generateSimulationFixtures({ + workflow: wf([{ name: 'A', type: 'n8n-nodes-base.slack' }]), + plan: [simulateVerdict('A')], + }); + expect(result.A).toEqual([{ ok: true }]); + }); + + it('includes upstream context in the prompt for user-action nodes', async () => { + const generate = vi.fn().mockResolvedValue({ messages: [] }); + mockCreateEvalAgent.mockReturnValue({ generate } as unknown as ReturnType< + typeof createEvalAgent + >); + mockExtractText.mockReturnValue(JSON.stringify({ Wait: [{ json: { email: 'a@b.c' } }] })); + + const workflow = wf([ + { name: 'Fetch User', type: 'n8n-nodes-base.httpRequest' }, + { name: 'Wait', type: 'n8n-nodes-base.wait' }, + ]); + (workflow.connections as Record)['Fetch User'] = { + main: [[{ node: 'Wait', type: 'main', index: 0 }]], + }; + + await generateSimulationFixtures({ + workflow, + plan: [ + { + nodeName: 'Wait', + verdict: 'simulate', + reason: 'Pauses the workflow', + confidence: 'high', + source: 'deterministic', + }, + ], + }); + + const promptText = (generate.mock.calls[0][0] as Array<{ content: Array<{ text: string }> }>)[0] + .content[0].text; + expect(promptText).toContain('Immediate upstream nodes'); + expect(promptText).toContain('"Fetch User" (n8n-nodes-base.httpRequest)'); + }); + + it('ignores plan entries whose node is missing from the workflow', async () => { + const result = await generateSimulationFixtures({ + workflow: wf([{ name: 'A', type: 'n8n-nodes-base.slack' }]), + plan: [simulateVerdict('Ghost')], + }); + expect(result).toEqual({}); + expect(mockCreateEvalAgent).not.toHaveBeenCalled(); + }); +}); diff --git a/packages/@n8n/instance-ai/src/tools/workflows/__tests__/resolve-credentials.test.ts b/packages/@n8n/instance-ai/src/tools/workflows/__tests__/resolve-credentials.test.ts index 1d256a9b0b9..4a66f564158 100644 --- a/packages/@n8n/instance-ai/src/tools/workflows/__tests__/resolve-credentials.test.ts +++ b/packages/@n8n/instance-ai/src/tools/workflows/__tests__/resolve-credentials.test.ts @@ -30,6 +30,7 @@ function createMockContext(existingWorkflow?: WorkflowJSON): InstanceAiContext { }, nodeService: {} as InstanceAiContext['nodeService'], dataTableService: {} as InstanceAiContext['dataTableService'], + logger: { info: vi.fn(), warn: vi.fn(), error: vi.fn(), debug: vi.fn() } as never, }; } @@ -78,9 +79,6 @@ describe('resolveCredentials', () => { expect(result.mockedCredentialTypes).toEqual(['slackApi']); expect(result.mockedCredentialsByNode).toEqual({ Slack: ['slackApi'] }); expect(json.nodes[0].credentials).toEqual({}); - expect(result.verificationPinData).toEqual({ - Slack: [{ _mockedCredential: 'slackApi' }], - }); }); it('mocks null credentials', async () => { @@ -143,8 +141,8 @@ describe('resolveCredentials', () => { }); }); - describe('credential mocking with sidecar verification data', () => { - it('mocks unresolved credentials and marks existing pinData as verification-ready', async () => { + describe('credential mocking', () => { + it('mocks unresolved credentials and preserves existing pinData', async () => { const json = makeWorkflow({ nodes: [ { @@ -172,12 +170,9 @@ describe('resolveCredentials', () => { expect(json.pinData).toEqual({ Slack: [{ ok: true, channel: 'C123', message: { text: 'Hello' } }], }); - // No sidecar pin data needed — existing workflow pinData suffices - expect(result.verificationPinData).toEqual({}); - expect(result.usesWorkflowPinDataForVerification).toBe(true); }); - it('produces sidecar verification pinData when no existing pinData', async () => { + it('mocks unresolved credentials without touching json.pinData', async () => { const json = makeWorkflow({ nodes: [ { @@ -199,10 +194,6 @@ describe('resolveCredentials', () => { expect(json.nodes[0].credentials).toEqual({}); // json.pinData must NOT be mutated expect(json.pinData).toBeUndefined(); - // Verification pin data in sidecar - expect(result.verificationPinData).toEqual({ - Gmail: [{ _mockedCredential: 'gmailOAuth2Api' }], - }); }); it('does not mock credentials that are already resolved (non-null value)', async () => { @@ -224,7 +215,6 @@ describe('resolveCredentials', () => { expect(result.mockedNodeNames).toEqual([]); expect(result.mockedCredentialTypes).toEqual([]); expect(result.mockedCredentialsByNode).toEqual({}); - expect(result.verificationPinData).toEqual({}); expect(json.nodes[0].credentials).toEqual({ slackApi: { id: 'real-id', name: 'Real Slack' }, }); @@ -262,11 +252,6 @@ describe('resolveCredentials', () => { }); // json.pinData must NOT be mutated expect(json.pinData).toBeUndefined(); - // Sidecar verification data for both nodes - expect(result.verificationPinData).toEqual({ - 'Slack 1': [{ _mockedCredential: 'slackApi' }], - 'Slack 2': [{ _mockedCredential: 'slackApi' }], - }); }); }); @@ -357,9 +342,6 @@ describe('resolveCredentials', () => { expect(result.mockedCredentialTypes).toEqual(['slackApi']); expect(result.mockedCredentialsByNode).toEqual({ Slack: ['slackApi'] }); expect(json.nodes[0].credentials).toEqual({}); - expect(result.verificationPinData).toEqual({ - Slack: [{ _mockedCredential: 'slackApi' }], - }); }); it('mocks a mock-* raw credential id that is absent from the snapshot', async () => { @@ -519,8 +501,6 @@ describe('resolveCredentials', () => { expect(json.pinData).toEqual({ Slack: [{ ok: true }], }); - expect(result.verificationPinData).toEqual({}); - expect(result.usesWorkflowPinDataForVerification).toBe(true); }); }); diff --git a/packages/@n8n/instance-ai/src/tools/workflows/__tests__/setup-workflow.service.test.ts b/packages/@n8n/instance-ai/src/tools/workflows/__tests__/setup-workflow.service.test.ts index 4a596ca4135..0c9a715733a 100644 --- a/packages/@n8n/instance-ai/src/tools/workflows/__tests__/setup-workflow.service.test.ts +++ b/packages/@n8n/instance-ai/src/tools/workflows/__tests__/setup-workflow.service.test.ts @@ -68,6 +68,7 @@ function createMockContext(overrides?: Partial): InstanceAiCo updateRows: vi.fn(), deleteRows: vi.fn(), }, + logger: { info: vi.fn(), warn: vi.fn(), error: vi.fn(), debug: vi.fn() } as never, ...overrides, }; } diff --git a/packages/@n8n/instance-ai/src/tools/workflows/__tests__/submit-workflow.tool.test.ts b/packages/@n8n/instance-ai/src/tools/workflows/__tests__/submit-workflow.tool.test.ts index 172802b250d..c055b6daa15 100644 --- a/packages/@n8n/instance-ai/src/tools/workflows/__tests__/submit-workflow.tool.test.ts +++ b/packages/@n8n/instance-ai/src/tools/workflows/__tests__/submit-workflow.tool.test.ts @@ -21,6 +21,14 @@ vi.mock('@n8n/workflow-sdk', () => ({ validateWorkflow: vi.fn(() => ({ errors: [], warnings: [] })), })); +// LLM-backed services must never hit the network from unit tests. +vi.mock('../classify-node-destructiveness.service', () => ({ + classifyNodesForSimulation: vi.fn(async () => await Promise.resolve([])), +})); +vi.mock('../generate-simulation-fixtures.service', () => ({ + generateSimulationFixtures: vi.fn(async () => await Promise.resolve({})), +})); + import { createSubmitWorkflowTool } from '../submit-workflow.tool'; const mockedValidateWorkflow = vi.mocked(validateWorkflow); @@ -254,7 +262,7 @@ describe('createSubmitWorkflowTool — successful submit metadata', () => { ); }); - it('returns and reports workflow pin-data verification and referenced workflow IDs', async () => { + it('returns and reports mocked credentials and referenced workflow IDs', async () => { const attempts: SubmitWorkflowAttempt[] = []; const workflowService = { createFromWorkflowJSON: vi.fn(async () => { @@ -286,7 +294,9 @@ describe('createSubmitWorkflowTool — successful submit metadata', () => { }, }, ], - connections: {}, + connections: { + Slack: { main: [[{ node: 'Call Sub', type: 'main', index: 0 }]] }, + }, pinData: { Slack: [{ ok: true }], }, @@ -310,14 +320,16 @@ describe('createSubmitWorkflowTool — successful submit metadata', () => { expect(output).toMatchObject({ success: true, workflowId: 'main-workflow-id', - usesWorkflowPinDataForVerification: true, + mockedNodeNames: ['Slack'], + mockedCredentialTypes: ['slackApi'], referencedWorkflowIds: ['sub-workflow-id'], }); + expect(output.verificationGuidance).toContain('Call verify-built-workflow next'); expect(attempts).toHaveLength(1); expect(attempts[0]).toMatchObject({ success: true, workflowId: 'main-workflow-id', - usesWorkflowPinDataForVerification: true, + mockedNodeNames: ['Slack'], referencedWorkflowIds: ['sub-workflow-id'], }); }); diff --git a/packages/@n8n/instance-ai/src/tools/workflows/__tests__/write-sandbox-file.tool.test.ts b/packages/@n8n/instance-ai/src/tools/workflows/__tests__/write-sandbox-file.tool.test.ts index e3ebd6a6c10..2b99b798be7 100644 --- a/packages/@n8n/instance-ai/src/tools/workflows/__tests__/write-sandbox-file.tool.test.ts +++ b/packages/@n8n/instance-ai/src/tools/workflows/__tests__/write-sandbox-file.tool.test.ts @@ -1,9 +1,9 @@ +import { getWorkspaceRoot } from '@n8n/agents/sandbox'; import type { MockedFunction } from 'vitest'; import { executeTool } from '../../../__tests__/tool-test-utils'; import type { SandboxWorkspace } from '../../../workspace/sandbox-fs'; import { writeFileViaSandbox } from '../../../workspace/sandbox-fs'; -import { getWorkspaceRoot } from '../../../workspace/sandbox-setup'; import { createWriteSandboxFileTool } from '../write-sandbox-file.tool'; // --------------------------------------------------------------------------- @@ -14,7 +14,7 @@ vi.mock('../../../workspace/sandbox-fs', () => ({ writeFileViaSandbox: vi.fn(), })); -vi.mock('../../../workspace/sandbox-setup', () => ({ +vi.mock('@n8n/agents/sandbox', () => ({ getWorkspaceRoot: vi.fn(), })); 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 1c3e2ffa3a6..e754f4f62eb 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 @@ -2,10 +2,10 @@ import { Tool } from '@n8n/agents'; import { instanceAiConfirmationSeveritySchema } from '@n8n/api-types'; import { hasPlaceholderDeep } from '@n8n/utils'; import { generateWorkflowCode } from '@n8n/workflow-sdk'; -import { UserError } from 'n8n-workflow'; import { nanoid } from 'nanoid'; import { z } from 'zod'; +import { planVerificationSimulation } from './plan-verification-simulation'; import { buildCredentialMap, resolveCredentials } from './resolve-credentials'; import { stripStaleCredentialsFromWorkflow } from './setup-workflow.service'; import { ensureWebhookIds } from './submit-workflow.tool'; @@ -16,6 +16,7 @@ import { } from './workflow-json-utils'; import type { InstanceAiContext } from '../../types'; import { parseAndValidate, partitionWarnings } from '../../workflow-builder'; +import { BuildFailureTracker } from '../../workflow-builder/build-failure-tracker'; import { extractWorkflowCode } from '../../workflow-builder/extract-code'; import { applyPatches } from '../../workflow-builder/patch-code'; import { createRemediation } from '../../workflow-loop/remediation'; @@ -41,6 +42,7 @@ const confirmationResumeSchema = z.object({ }); interface BuildCtx { + toolCallId?: string; resumeData?: z.infer; suspend?: (payload: z.infer) => Promise; } @@ -86,7 +88,7 @@ export const buildWorkflowInputSchema = z.object({ .optional() .describe( 'Set true when saving a supporting sub-workflow that will be referenced by the main workflow. ' + - 'Supporting workflows are saved and can be verified, but do not complete the planned build task.', + 'In a planned build task, this completes the task only when the task itself is marked isSupportingWorkflow; otherwise save the main workflow later.', ), }); @@ -132,12 +134,55 @@ function hasMockedCredentials( ); } +/** + * True when every mocked-credential node is covered by a `simulate` verdict in + * the node simulation plan — verification can run because those nodes will be + * pinned with generated fixtures instead of executing without credentials. + */ function hasCredentialVerificationData( - outcome: Pick, + outcome: Pick, ): boolean { + const mocked = outcome.mockedNodeNames ?? []; + if (mocked.length === 0) return false; + const simulated = new Set( + (outcome.nodeSimulationPlan ?? []) + .filter((verdict) => verdict.verdict === 'simulate') + .map((verdict) => verdict.nodeName), + ); + return mocked.every((name) => simulated.has(name)); +} + +function getBuildFailureTrackingKey({ + workItemId, + workflowId, + workflowName, + isAuxiliarySupportingWorkflow, + buildContext, + runId, +}: { + workItemId?: string; + workflowId?: string; + workflowName?: string; + isAuxiliarySupportingWorkflow: boolean; + buildContext?: InstanceAiContext['workflowBuildContext']; + runId?: string; +}): string { + if (workItemId) return workItemId; + + if (isAuxiliarySupportingWorkflow) { + return [ + 'supporting-workflow', + buildContext?.taskId ?? (runId ? `run:${runId}` : 'unknown-run'), + workflowId ?? workflowName ?? 'new', + ].join(':'); + } + return ( - Object.keys(outcome.verificationPinData ?? {}).length > 0 || - outcome.usesWorkflowPinDataForVerification === true + buildContext?.workItemId ?? + buildContext?.taskId ?? + workflowId ?? + workflowName ?? + `run:${runId ?? 'unknown'}` ); } @@ -149,8 +194,8 @@ function determineVerificationReadiness( | 'triggerNodes' | 'mockedCredentialTypes' | 'mockedCredentialsByNode' - | 'verificationPinData' - | 'usesWorkflowPinDataForVerification' + | 'mockedNodeNames' + | 'nodeSimulationPlan' | 'hasUnresolvedPlaceholders' >, ): WorkflowVerificationReadiness { @@ -245,14 +290,6 @@ function isApprovedBuildContext(context: InstanceAiContext): boolean { return Boolean(buildContext?.plannedTaskService ?? buildContext?.allowPostPlanWorkflowCreate); } -function isBuildViaPlanGuardEnabled(): boolean { - const raw = process.env.N8N_INSTANCE_AI_ENFORCE_BUILD_VIA_PLAN; - if (raw === undefined) return true; - return raw.toLowerCase() !== 'false' && raw !== '0'; -} - -const PLAN_GUARD_REJECTION_LIMIT = 3; - async function resolveWorkflowName( context: InstanceAiContext, workflowId: string, @@ -276,7 +313,7 @@ async function reportWorkflowBuildOutcome( try { await buildContext.onBuildOutcome?.(outcome); } catch (error) { - context.logger?.warn('Failed to store workflow build outcome on run context', { + context.logger.warn('Failed to store workflow build outcome on run context', { error: error instanceof Error ? error.message : String(error), }); } @@ -285,7 +322,7 @@ async function reportWorkflowBuildOutcome( try { await buildContext.workflowTaskService?.reportBuildOutcome(outcome); } catch (error) { - context.logger?.warn('Failed to report workflow build outcome to workflow loop', { + context.logger.warn('Failed to report workflow build outcome to workflow loop', { workItemId: outcome.workItemId, error: error instanceof Error ? error.message : String(error), }); @@ -303,7 +340,7 @@ async function reportWorkflowBuildOutcome( }, ); } catch (error) { - context.logger?.warn('Failed to mark planned workflow build task succeeded', { + context.logger.warn('Failed to mark planned workflow build task succeeded', { taskId: buildContext.taskId, error: error instanceof Error ? error.message : String(error), }); @@ -316,7 +353,7 @@ async function promoteMainWorkflow(context: InstanceAiContext, workflowId: strin try { await context.workflowService.clearAiTemporary(workflowId); } catch (error) { - context.logger?.warn( + context.logger.warn( `Failed to clear AI-builder temporary marker on main workflow ${workflowId}: ${ error instanceof Error ? error.message : String(error) }`, @@ -332,38 +369,11 @@ export function createBuildWorkflowTool(context: InstanceAiContext) { // invalidates the cache so patches don't silently overwrite the user's work. let lastCode: string | null = null; let lastCodeVersionId: string | null = null; - let planGuardRejectionCount = 0; - - const rejectPlanGuardCall = () => { - planGuardRejectionCount++; - context.logger?.warn('build-workflow called outside plan/replan context — rejecting', { - threadId: context.workflowBuildContext?.threadId, - runId: context.runId, - rejectionCount: planGuardRejectionCount, - }); - - if (planGuardRejectionCount >= PLAN_GUARD_REJECTION_LIMIT) { - context.logger?.warn('build-workflow plan-guard rejection limit reached — aborting run', { - threadId: context.workflowBuildContext?.threadId, - runId: context.runId, - rejectionCount: planGuardRejectionCount, - }); - throw new UserError( - 'Stopped: the agent looped on `build-workflow` rejections without correcting them. Try again or rephrase the request.', - ); - } - - return { - success: false, - errors: [ - 'New workflow builds must be planned first: call `plan` so the user can approve the build plan before saving.', - ], - }; - }; + const failureTracker = new BuildFailureTracker(); return new Tool('build-workflow') .description( - 'Build a workflow from TypeScript SDK code. Two modes:\n' + + 'Primary workflow-builder tool — save TypeScript SDK code or apply targeted patches. Two modes:\n' + '1. Full code: pass `code` to create/update a workflow from scratch.\n' + '2. Patch mode: pass `patches` (+ optional `workflowId`) to apply str_replace fixes. ' + 'Patches apply to last submitted code, or auto-fetch from saved workflow if workflowId given.', @@ -382,8 +392,6 @@ export function createBuildWorkflowTool(context: InstanceAiContext) { mockedNodeNames: z.array(z.string()).optional(), mockedCredentialTypes: z.array(z.string()).optional(), mockedCredentialsByNode: z.record(z.array(z.string())).optional(), - verificationPinData: z.record(z.array(z.record(z.unknown()))).optional(), - usesWorkflowPinDataForVerification: z.boolean().optional(), referencedWorkflowIds: z.array(z.string()).optional(), hasUnresolvedPlaceholders: z.boolean().optional(), denied: z.boolean().optional(), @@ -400,10 +408,6 @@ export function createBuildWorkflowTool(context: InstanceAiContext) { return { success: false, errors: ['Action blocked by admin'] }; } - if (!input.workflowId && !isApprovedBuildContext(context) && isBuildViaPlanGuardEnabled()) { - return rejectPlanGuardCall(); - } - if ( input.workflowId && !isApprovedBuildContext(context) && @@ -432,6 +436,24 @@ export function createBuildWorkflowTool(context: InstanceAiContext) { const { code, patches, workflowId, projectId, name, workItemId } = input; const isSupportingWorkflow = input.isSupportingWorkflow === true; + const buildContext = context.workflowBuildContext; + const isAuxiliarySupportingWorkflow = + isSupportingWorkflow && buildContext?.isSupportingWorkflowTask !== true; + const workItemKey = getBuildFailureTrackingKey({ + workItemId, + workflowId, + workflowName: name, + isAuxiliarySupportingWorkflow, + buildContext, + runId: context.runId, + }); + const withEscalation = ( + errors: string[], + options: { includeSdkLanguageGuidance?: boolean } = {}, + ): string[] => { + const escalation = failureTracker.record(workItemKey, errors, options); + return escalation ? [...errors, escalation] : errors; + }; let finalCode: string; if (patches) { @@ -498,6 +520,23 @@ export function createBuildWorkflowTool(context: InstanceAiContext) { // Remember for future patches lastCode = finalCode; + const codeSource = patches ? ('patch' as const) : ('full-code' as const); + const recordWorkflowCodeSnapshot = (result: { + success: boolean; + errors?: string[]; + }): void => { + context.recordWorkflowCodeSnapshot?.({ + code: finalCode, + source: codeSource, + patches: patches ?? undefined, + workflowId: workflowId ?? undefined, + toolCallId: ctx.toolCallId, + success: result.success, + errors: result.errors, + capturedAt: Date.now(), + }); + }; + // Parse TypeScript to WorkflowJSON with two-stage validation let result; try { @@ -505,38 +544,50 @@ export function createBuildWorkflowTool(context: InstanceAiContext) { nodeTypesProvider: context.nodeTypesProvider, }); } catch (error) { - return { + const failure = { success: false, - errors: [error instanceof Error ? error.message : 'Failed to parse workflow code'], + errors: withEscalation( + [error instanceof Error ? error.message : 'Failed to parse workflow code'], + { + includeSdkLanguageGuidance: true, + }, + ), }; + recordWorkflowCodeSnapshot(failure); + return failure; } // Partition validation results into blocking errors and informational warnings const { errors, informational } = partitionWarnings(result.warnings); if (errors.length > 0) { - return { + const failure = { success: false, - errors: errors.map( - (e) => `[${e.code}]${e.nodeName ? ` (${e.nodeName})` : ''}: ${e.message}`, + errors: withEscalation( + errors.map((e) => `[${e.code}]${e.nodeName ? ` (${e.nodeName})` : ''}: ${e.message}`), ), warnings: informational.length > 0 ? informational.map((w) => `[${w.code}]: ${w.message}`) : undefined, }; + recordWorkflowCodeSnapshot(failure); + return failure; } const json = result.workflow; + if (name) { json.name = name; } else if (!json.name && !workflowId) { - return { + const failure = { success: false, errors: [ 'Workflow name is required for new workflows. Provide a name parameter or set it in the SDK code.', ], }; + recordWorkflowCodeSnapshot(failure); + return failure; } // Resolve undefined/null credentials before saving. @@ -564,17 +615,30 @@ export function createBuildWorkflowTool(context: InstanceAiContext) { Boolean(t.nodeName) && Boolean(t.nodeType), ); const hasPlaceholders = (json.nodes ?? []).some((n) => hasPlaceholderDeep(n.parameters)); - const buildContext = context.workflowBuildContext; + const plannedTaskId = + buildContext?.plannedTaskService && !isAuxiliarySupportingWorkflow + ? buildContext.taskId + : undefined; + const owner = plannedTaskId + ? { type: 'planned' as const, taskId: plannedTaskId } + : { type: 'direct' as const }; const resolvedWorkItemId = workItemId ?? - (isSupportingWorkflow ? undefined : buildContext?.workItemId) ?? + (isAuxiliarySupportingWorkflow ? undefined : buildContext?.workItemId) ?? `wi_${nanoid(8)}`; - const resolvedTaskId = isSupportingWorkflow + const resolvedTaskId = isAuxiliarySupportingWorkflow ? `${buildContext?.taskId ?? (context.runId ? `build-${context.runId}` : 'build')}:supporting-${nanoid(6)}` : (buildContext?.taskId ?? (context.runId ? `build-${context.runId}` : `build-${nanoid(8)}`)); const createSuccessResponse = async (savedId: string) => { + const { nodeSimulationPlan, simulationFixtures } = await planVerificationSimulation({ + workflow: json, + mockedNodeNames: mockResult.mockedNodeNames, + workflowId: savedId, + logger: context.logger, + }); + const runId = buildContext?.runId ?? context.runId; const workflowName = json.name || 'workflow'; const summary = `${workflowId ? 'Updated' : 'Created'} ${isSupportingWorkflow ? 'supporting ' : ''}workflow "${workflowName}" (${savedId}).`; @@ -591,6 +655,8 @@ export function createBuildWorkflowTool(context: InstanceAiContext) { workItemId: resolvedWorkItemId, ...(runId ? { runId } : {}), taskId: resolvedTaskId, + owner, + plannedTaskId, workflowId: savedId, submitted: true, triggerType: 'manual_or_testable', @@ -604,12 +670,8 @@ export function createBuildWorkflowTool(context: InstanceAiContext) { mockedCredentialsByNode: hasMockedCredentialNodes ? mockResult.mockedCredentialsByNode : undefined, - verificationPinData: - hasMockedCredentialNodes && Object.keys(mockResult.verificationPinData).length > 0 - ? mockResult.verificationPinData - : undefined, - usesWorkflowPinDataForVerification: - mockResult.usesWorkflowPinDataForVerification || undefined, + nodeSimulationPlan, + simulationFixtures, supportingWorkflowIds: referencedWorkflowIds.length > 0 ? referencedWorkflowIds : undefined, hasUnresolvedPlaceholders: hasPlaceholders || undefined, @@ -619,11 +681,13 @@ export function createBuildWorkflowTool(context: InstanceAiContext) { await promoteMainWorkflow(context, savedId); await reportWorkflowBuildOutcome(context, outcome, { - storeOnRunContext: !isSupportingWorkflow, - markPlannedTaskSucceeded: !isSupportingWorkflow, + storeOnRunContext: !isAuxiliarySupportingWorkflow, + markPlannedTaskSucceeded: !isAuxiliarySupportingWorkflow, }); - return { + failureTracker.clear(workItemKey); + + const successResult = { success: true, workflowId: savedId, workflowName: json.name || undefined, @@ -639,12 +703,6 @@ export function createBuildWorkflowTool(context: InstanceAiContext) { mockedCredentialsByNode: hasMockedCredentialNodes ? mockResult.mockedCredentialsByNode : undefined, - verificationPinData: - hasMockedCredentialNodes && Object.keys(mockResult.verificationPinData).length > 0 - ? mockResult.verificationPinData - : undefined, - usesWorkflowPinDataForVerification: - mockResult.usesWorkflowPinDataForVerification || undefined, referencedWorkflowIds: referencedWorkflowIds.length > 0 ? referencedWorkflowIds : undefined, hasUnresolvedPlaceholders: hasPlaceholders || undefined, @@ -653,6 +711,8 @@ export function createBuildWorkflowTool(context: InstanceAiContext) { ? informational.map((w) => `[${w.code}]: ${w.message}`) : undefined, }; + recordWorkflowCodeSnapshot(successResult); + return successResult; }; if (workflowId) { 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 new file mode 100644 index 00000000000..1e68be2b22a --- /dev/null +++ b/packages/@n8n/instance-ai/src/tools/workflows/classify-node-destructiveness.service.ts @@ -0,0 +1,441 @@ +/** + * Node Destructiveness Classification + * + * Decides, per main-flow node, whether a verification execution may run the + * node for real (`execute`) or must mock its output via per-execution pin + * data (`simulate`) because the node would create, update, or delete data in + * an external system. + * + * Hybrid strategy (see `.claude/specs/instance-ai-simulated-verification.md`): + * 1. Deterministic floor — known-safe transform nodes, unambiguous read/write + * operation names, HTTP method semantics, IO-free Code nodes. + * 2. Batched LLM call for the ambiguous middle (non-GET HTTP Request, Code + * with IO, community/unknown node types). + * 3. Fail-destructive fallback — when classification is unavailable or + * low-signal, the node is simulated. Losing verification coverage is + * recoverable; running a destructive operation against user data is not. + */ + +import type { WorkflowJSON } from '@n8n/workflow-sdk'; +import type { IConnections } from 'n8n-workflow'; +import { z } from 'zod'; + +import { isTriggerNodeType } from './workflow-json-utils'; +import { HAIKU_MODEL } from '../../utils/eval-agents'; +import { generateValidatedJson } from '../../utils/generate-validated-json'; +import type { NodeSimulationVerdict } from '../../workflow-loop/workflow-loop-state'; + +type WorkflowNode = WorkflowJSON['nodes'][number]; + +export interface ClassifyNodesForSimulationInput { + workflow: WorkflowJSON; + /** Node names whose credentials were mocked — always simulated. */ + mockedNodeNames?: string[]; +} + +const STICKY_NOTE_TYPE = 'n8n-nodes-base.stickyNote'; + +/** Transform/control nodes with no external side effects. */ +const SAFE_NODE_TYPES = new Set([ + 'n8n-nodes-base.set', + 'n8n-nodes-base.if', + 'n8n-nodes-base.filter', + 'n8n-nodes-base.switch', + 'n8n-nodes-base.merge', + 'n8n-nodes-base.noOp', + 'n8n-nodes-base.splitOut', + 'n8n-nodes-base.splitInBatches', + 'n8n-nodes-base.aggregate', + 'n8n-nodes-base.summarize', + 'n8n-nodes-base.sort', + 'n8n-nodes-base.limit', + 'n8n-nodes-base.removeDuplicates', + 'n8n-nodes-base.itemLists', + 'n8n-nodes-base.renameKeys', + 'n8n-nodes-base.dateTime', + 'n8n-nodes-base.html', + 'n8n-nodes-base.markdown', + 'n8n-nodes-base.xml', + 'n8n-nodes-base.crypto', + 'n8n-nodes-base.compareDatasets', + 'n8n-nodes-base.extractFromFile', + 'n8n-nodes-base.convertToFile', + 'n8n-nodes-base.editImage', + 'n8n-nodes-base.stopAndError', + // Responds to the workflow's own caller — part of the trigger contract. + 'n8n-nodes-base.respondToWebhook', + // AI processing nodes: they call an LLM (read-only towards user systems). + // Write operations living as agent *tools* are a known gap — see spec. + '@n8n/n8n-nodes-langchain.agent', + '@n8n/n8n-nodes-langchain.chainLlm', + '@n8n/n8n-nodes-langchain.chainSummarization', + '@n8n/n8n-nodes-langchain.informationExtractor', + '@n8n/n8n-nodes-langchain.textClassifier', + '@n8n/n8n-nodes-langchain.sentimentAnalysis', +]); + +/** Node types that are destructive by their very type (no operation param needed). */ +const DESTRUCTIVE_NODE_TYPES = new Map([ + ['n8n-nodes-base.emailSend', 'Sends an email'], + ['n8n-nodes-base.executeCommand', 'Executes a shell command on the host'], + ['n8n-nodes-base.ssh', 'Runs commands on a remote machine'], + // Simulating the call skips the sub-workflow entirely, side effects included. + ['n8n-nodes-base.executeWorkflow', 'Executes another workflow which may have side effects'], +]); + +const CODE_NODE_TYPES = new Set([ + 'n8n-nodes-base.code', + 'n8n-nodes-base.function', + 'n8n-nodes-base.functionItem', +]); + +const FORM_NODE_TYPE = 'n8n-nodes-base.form'; +const WAIT_NODE_TYPE = 'n8n-nodes-base.wait'; + +/** + * A real wait this short is harmless during verification and — unlike a + * simulated one — preserves pass-through data for downstream expressions. + */ +const MAX_EXECUTABLE_WAIT_SECONDS = 60; + +const WAIT_UNIT_SECONDS: Record = { + seconds: 1, + minutes: 60, + hours: 3600, + days: 86_400, +}; + +const HTTP_REQUEST_NODE_TYPE = 'n8n-nodes-base.httpRequest'; + +/** Operation/mode values that unambiguously read. */ +const READ_OPERATIONS = new Set([ + 'get', + 'getall', + 'getmany', + 'search', + 'list', + 'read', + 'lookup', + 'fetch', + 'download', + 'retrieve', + 'select', + 'query', + 'load', +]); + +/** Operation/mode values that unambiguously write. */ +const WRITE_OPERATIONS = new Set([ + 'create', + 'update', + 'upsert', + 'delete', + 'deleterows', + 'insert', + 'send', + 'sendandwait', + 'post', + 'append', + 'appendorupdate', + 'write', + 'remove', + 'archive', + 'unarchive', + 'move', + 'add', + 'publish', + 'invite', + 'share', + 'complete', + 'cancel', + 'upload', + 'mark', + 'star', + 'assign', +]); + +/** Tokens in Code-node source that indicate network/filesystem/process access. */ +const CODE_IO_TOKENS = [ + 'fetch', + 'axios', + 'http', + 'request', + 'helpers.', + 'child_process', + 'execsync', + 'fs.', + 'net.', + 'dgram', + 'websocket', +]; + +function isRecord(value: unknown): value is Record { + return typeof value === 'object' && value !== null && !Array.isArray(value); +} + +function getStringParam(node: WorkflowNode, key: string): string | undefined { + const params = node.parameters; + if (!isRecord(params)) return undefined; + const value = params[key]; + return typeof value === 'string' && value.length > 0 ? value : undefined; +} + +/** + * Node names reachable over `main` connections (sources and destinations). + * Sub-nodes (ai_tool, ai_languageModel, …) and disconnected nodes never carry + * pin data, so the plan excludes them. + */ +function collectMainFlowNodeNames(workflow: WorkflowJSON): Set { + const connections = (workflow.connections ?? {}) as IConnections; + const names = new Set(); + for (const [sourceName, outputs] of Object.entries(connections)) { + const main = outputs.main; + if (!main) continue; + names.add(sourceName); + for (const port of main) { + for (const target of port ?? []) { + names.add(target.node); + } + } + } + return names; +} + +function deterministic( + nodeName: string, + verdict: 'simulate' | 'execute', + reason: string, +): NodeSimulationVerdict { + return { nodeName, verdict, reason, confidence: 'high', source: 'deterministic' }; +} + +function deterministicVerdict( + node: WorkflowNode & { name: string }, + mockedNodeNames: Set, +): NodeSimulationVerdict | 'ambiguous' { + if (mockedNodeNames.has(node.name)) { + return deterministic(node.name, 'simulate', 'Credentials are not configured for this node'); + } + + if (SAFE_NODE_TYPES.has(node.type)) { + return deterministic(node.name, 'execute', 'Transforms data without touching external systems'); + } + + const destructiveByType = DESTRUCTIVE_NODE_TYPES.get(node.type); + if (destructiveByType) { + return deterministic(node.name, 'simulate', destructiveByType); + } + + if (node.type === HTTP_REQUEST_NODE_TYPE) { + const method = (getStringParam(node, 'method') ?? 'GET').toUpperCase(); + if (['GET', 'HEAD', 'OPTIONS'].includes(method)) { + return deterministic( + node.name, + 'execute', + `HTTP ${method} request — read-only by HTTP semantics`, + ); + } + // POST/PUT/PATCH/DELETE can still be reads (e.g. POST /search) — let the + // LLM judge URL + body; the fallback is simulate. + return 'ambiguous'; + } + + // User-action nodes: nothing destructive about them, but executing one + // parks the run in `waiting` and everything downstream is never verified. + // Pinning them lets execution flow past (a pinned node never calls + // putExecutionToWait). + if (node.type === FORM_NODE_TYPE) { + return deterministic( + node.name, + 'simulate', + 'Displays a form page and waits for a user submission', + ); + } + + if (node.type === WAIT_NODE_TYPE) { + // Wait node defaults: resume='timeInterval', amount=1, unit='hours'. + const params = isRecord(node.parameters) ? node.parameters : {}; + const resume = typeof params.resume === 'string' ? params.resume : 'timeInterval'; + if (resume === 'timeInterval') { + const amount = typeof params.amount === 'number' ? params.amount : 1; + const unit = typeof params.unit === 'string' ? params.unit : 'hours'; + const seconds = amount * (WAIT_UNIT_SECONDS[unit] ?? 3600); + if (seconds <= MAX_EXECUTABLE_WAIT_SECONDS) { + return deterministic( + node.name, + 'execute', + `Short wait (${seconds}s) — runs for real to preserve pass-through data`, + ); + } + } + return deterministic( + node.name, + 'simulate', + resume === 'timeInterval' || resume === 'specificTime' + ? 'Pauses the workflow for longer than verification can wait' + : 'Pauses the workflow until a user or external system resumes it', + ); + } + + if (CODE_NODE_TYPES.has(node.type)) { + const source = ( + getStringParam(node, 'jsCode') ?? + getStringParam(node, 'pythonCode') ?? + getStringParam(node, 'functionCode') ?? + '' + ).toLowerCase(); + const hasIo = CODE_IO_TOKENS.some((token) => source.includes(token)); + if (!hasIo) { + return deterministic(node.name, 'execute', 'Code without network or filesystem access'); + } + return 'ambiguous'; + } + + const operation = (getStringParam(node, 'operation') ?? getStringParam(node, 'mode')) + ?.toLowerCase() + .replace(/[^a-z]/g, ''); + if (operation) { + if (WRITE_OPERATIONS.has(operation)) { + return deterministic( + node.name, + 'simulate', + `The "${operation}" operation modifies external data`, + ); + } + if (READ_OPERATIONS.has(operation)) { + return deterministic(node.name, 'execute', `The "${operation}" operation only reads data`); + } + } + + return 'ambiguous'; +} + +const FALLBACK_REASON = + 'Could not determine whether this node modifies external data — simulated for safety'; + +function fallbackVerdict(nodeName: string): NodeSimulationVerdict { + return { + nodeName, + verdict: 'simulate', + reason: FALLBACK_REASON, + confidence: 'low', + source: 'fallback', + }; +} + +const LlmVerdictSchema = z.record( + z.string(), + z.object({ + verdict: z.enum(['simulate', 'execute']), + reason: z.string(), + confidence: z.enum(['high', 'low']).optional(), + }), +); + +const SYSTEM_INSTRUCTIONS = `You classify n8n workflow nodes by whether executing them would CREATE, UPDATE, DELETE, or SEND data in an external system (destructive), or only READ/transform data (safe). + +Rules: +- "simulate" = destructive: the node writes, sends, deletes, uploads, or otherwise mutates state outside the workflow. Reads that consume or mutate state (marking items read, consuming queue messages, acknowledging events) count as destructive. +- "execute" = safe: the node only reads or transforms data. +- For HTTP requests, judge the URL, method, and body semantics (e.g. POST to a /search or /query endpoint is a read). +- For code, judge what the code actually does with its network/filesystem access. +- When uncertain, prefer "simulate" with confidence "low". Never guess "execute" when uncertain. +- "reason" must be one short user-facing sentence describing what the node would do (e.g. "Sends a message to a Slack channel"). + +Output: a single JSON object keyed by node name, each value {"verdict": "simulate"|"execute", "reason": string, "confidence": "high"|"low"}. Return only the JSON object — no prose, no markdown fences.`; + +function formatNodeBlock(node: WorkflowNode & { name: string }): string { + const params = isRecord(node.parameters) + ? JSON.stringify(node.parameters).slice(0, 800) + : '(none)'; + return [`Node name: ${node.name}`, `Node type: ${node.type}`, `Parameters: ${params}`].join('\n'); +} + +async function classifyAmbiguousNodes( + nodes: Array, +): Promise { + const userText = [ + 'Classify the following n8n workflow nodes.', + '', + nodes.map(formatNodeBlock).join('\n\n'), + '', + `Output a single JSON object with exactly these keys: ${nodes.map((n) => `"${n.name}"`).join(', ')}.`, + ].join('\n'); + + const result = await generateValidatedJson('verification-destructiveness-classifier', { + model: HAIKU_MODEL, + instructions: SYSTEM_INSTRUCTIONS, + userText, + schema: LlmVerdictSchema, + }); + const parsed = result.ok ? result.data : undefined; + + return nodes.map((node) => { + const entry = parsed?.[node.name]; + if (!entry) return fallbackVerdict(node.name); + return { + nodeName: node.name, + verdict: entry.verdict, + reason: entry.reason, + confidence: entry.confidence ?? 'low', + source: 'llm', + }; + }); +} + +function nodeHasName(node: WorkflowNode): node is WorkflowNode & { name: string } { + return typeof node.name === 'string' && node.name.length > 0; +} + +/** + * Classify every main-flow, non-trigger node of the workflow. Returns one + * verdict per node, ordered as the nodes appear in the workflow. Triggers and + * user-action nodes are out of scope (Mechanism A handles them); sub-nodes + * and disconnected nodes are excluded because pin data cannot apply to them. + */ +export async function classifyNodesForSimulation( + input: ClassifyNodesForSimulationInput, +): Promise { + const mainFlowNames = collectMainFlowNodeNames(input.workflow); + const mockedNodeNames = new Set(input.mockedNodeNames ?? []); + + const candidates = (input.workflow.nodes ?? []).filter( + (node): node is WorkflowNode & { name: string } => + nodeHasName(node) && + node.disabled !== true && + node.type !== STICKY_NOTE_TYPE && + !isTriggerNodeType(node.type) && + mainFlowNames.has(node.name), + ); + if (candidates.length === 0) return []; + + const verdictByName = new Map(); + const ambiguous: Array = []; + for (const node of candidates) { + const verdict = deterministicVerdict(node, mockedNodeNames); + if (verdict === 'ambiguous') { + ambiguous.push(node); + } else { + verdictByName.set(node.name, verdict); + } + } + + if (ambiguous.length > 0) { + // The LLM path must never abort the whole plan: with the marker channel + // 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)) { + verdictByName.set(verdict.nodeName, verdict); + } + } catch { + for (const node of ambiguous) { + verdictByName.set(node.name, fallbackVerdict(node.name)); + } + } + } + + return candidates + .map((node) => verdictByName.get(node.name)) + .filter((v): v is NodeSimulationVerdict => v !== undefined); +} 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 new file mode 100644 index 00000000000..15b51ed7714 --- /dev/null +++ b/packages/@n8n/instance-ai/src/tools/workflows/generate-simulation-fixtures.service.ts @@ -0,0 +1,167 @@ +/** + * Simulation Fixture Generation + * + * Generates realistic mock output (pin-data items) for nodes the + * destructiveness classifier marked `simulate`. One batched LLM call keeps + * the fixtures cross-node consistent. The fixtures live on the build outcome + * sidecar and become per-execution pin data during verification — they are + * never written to the workflow. + * + * Fallback posture: fixture generation is best-effort. On any failure every + * simulated node gets a single empty item — verification stays safe (the node + * still never executes), downstream data coverage degrades. + */ + +import type { WorkflowJSON } from '@n8n/workflow-sdk'; +import { getParentNodes, mapConnectionsByDestination, type IConnections } from 'n8n-workflow'; +import { z } from 'zod'; + +import { HAIKU_MODEL } from '../../utils/eval-agents'; +import { generateValidatedJson } from '../../utils/generate-validated-json'; +import type { NodeSimulationVerdict } from '../../workflow-loop/workflow-loop-state'; + +/** + * Fixture items per node name, stored UNWRAPPED (plain objects, not n8n's + * `{json: ...}` envelope) — the same shape `executionService.run` expects for + * pin data, so they flow to the verification run without conversion. Only the + * LLM prompt/response uses the `{json}` envelope; it is unwrapped here. + */ +export type SimulationFixtures = Record>>; + +export interface GenerateSimulationFixturesInput { + workflow: WorkflowJSON; + plan: NodeSimulationVerdict[]; +} + +const FixturesResponseSchema = z.record( + z.string(), + z.array(z.object({ json: z.record(z.unknown()) })).min(1), +); + +const SYSTEM_INSTRUCTIONS = `You generate realistic mock output for n8n workflow nodes whose real execution is being simulated (their operation would create, update, send, or delete data in an external system, or pause the workflow for user action). + +For each node, return the output items the node would naturally emit after a SUCCESSFUL run of its operation — matching the response shape of the underlying service (e.g. a Slack message post returns "ok", "ts" and "channel"; a row insert returns the row including its new "id"). Base the field values on the node's parameters so the data is plausible in context, and keep values consistent across nodes (same fictional users, ids, timestamps). + +Special node types: +- 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". +- Wait nodes: their real output is their INPUT passed through unchanged. Emit data matching what the listed upstream nodes would produce, so downstream expressions keep resolving. + +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. + +Return only the JSON object. No prose, no markdown fences.`; + +const USER_ACTION_NODE_TYPES = new Set(['n8n-nodes-base.form', 'n8n-nodes-base.wait']); + +function isRecord(value: unknown): value is Record { + return typeof value === 'object' && value !== null && !Array.isArray(value); +} + +function formatNodeBlock( + node: WorkflowJSON['nodes'][number] & { name: string }, + reason: string, + upstreamContext?: string, +): string { + const params = isRecord(node.parameters) + ? JSON.stringify(node.parameters).slice(0, 600) + : '(none)'; + return [ + `Node name: ${node.name}`, + `Node type: ${node.type}`, + `Simulated because: ${reason}`, + `Parameters: ${params}`, + ...(upstreamContext ? [upstreamContext] : []), + ].join('\n'); +} + +/** + * For user-action nodes (Form pages, Waits) the output rides on upstream + * data, so the prompt block includes the immediate upstream nodes' type and + * parameters — enough for the LLM to fabricate a plausible pass-through. + */ +function buildUpstreamContext( + workflow: WorkflowJSON, + nodeName: string, + connectionsByDestination: IConnections, +): string | undefined { + const parentNames = getParentNodes(connectionsByDestination, nodeName, 'main', 1); + if (parentNames.length === 0) return undefined; + const nodesByName = new Map( + (workflow.nodes ?? []) + .filter((n): n is WorkflowJSON['nodes'][number] & { name: string } => Boolean(n.name)) + .map((n) => [n.name, n] as const), + ); + const lines = parentNames + .map((name) => { + const parent = nodesByName.get(name); + if (!parent) return undefined; + const params = isRecord(parent.parameters) + ? JSON.stringify(parent.parameters).slice(0, 300) + : '(none)'; + return `- "${name}" (${parent.type}), parameters: ${params}`; + }) + .filter((line): line is string => line !== undefined); + if (lines.length === 0) return undefined; + return ['Immediate upstream nodes (this node passes their data through):', ...lines].join('\n'); +} + +function emptyFixtures(nodeNames: string[]): SimulationFixtures { + return Object.fromEntries(nodeNames.map((name) => [name, [{}]])); +} + +/** + * Generate one fixture per `simulate`-verdict node. Always returns an entry + * for every simulated node — LLM output is used when valid, a single empty + * item otherwise. + */ +export async function generateSimulationFixtures( + input: GenerateSimulationFixturesInput, +): Promise { + const reasonByName = new Map( + input.plan.filter((v) => v.verdict === 'simulate').map((v) => [v.nodeName, v.reason] as const), + ); + if (reasonByName.size === 0) return {}; + + const nodes = (input.workflow.nodes ?? []).filter( + (node): node is WorkflowJSON['nodes'][number] & { name: string } => + typeof node.name === 'string' && reasonByName.has(node.name), + ); + const nodeNames = nodes.map((n) => n.name); + if (nodeNames.length === 0) return {}; + + const connectionsByDestination = mapConnectionsByDestination( + (input.workflow.connections ?? {}) as IConnections, + ); + const userText = [ + 'Generate realistic mock output (pin-data items) for the following simulated n8n nodes.', + input.workflow.name ? `\nWorkflow: ${input.workflow.name}` : '', + '', + nodes + .map((n) => + formatNodeBlock( + n, + reasonByName.get(n.name) ?? '', + USER_ACTION_NODE_TYPES.has(n.type) + ? buildUpstreamContext(input.workflow, n.name, connectionsByDestination) + : undefined, + ), + ) + .join('\n\n'), + '', + `Output a single JSON object with exactly these keys: ${nodeNames.map((n) => `"${n}"`).join(', ')}.`, + 'Each value: an array with one item shaped like { "json": { ...fields } }.', + ].join('\n'); + + const result = await generateValidatedJson('verification-simulation-fixtures', { + model: HAIKU_MODEL, + instructions: SYSTEM_INSTRUCTIONS, + userText, + schema: FixturesResponseSchema, + }); + if (!result.ok) return emptyFixtures(nodeNames); + + const fixtures: SimulationFixtures = {}; + for (const name of nodeNames) { + fixtures[name] = result.data[name]?.map((item) => item.json) ?? [{}]; + } + return fixtures; +} diff --git a/packages/@n8n/instance-ai/src/tools/workflows/materialize-node-type.tool.ts b/packages/@n8n/instance-ai/src/tools/workflows/materialize-node-type.tool.ts index 9073129ded4..bea50c9514b 100644 --- a/packages/@n8n/instance-ai/src/tools/workflows/materialize-node-type.tool.ts +++ b/packages/@n8n/instance-ai/src/tools/workflows/materialize-node-type.tool.ts @@ -10,11 +10,11 @@ */ import { Tool } from '@n8n/agents'; +import { getWorkspaceRoot } from '@n8n/agents/sandbox'; import { z } from 'zod'; import type { InstanceAiContext } from '../../types'; import { runInSandbox, type SandboxWorkspace } from '../../workspace/sandbox-fs'; -import { getWorkspaceRoot } from '../../workspace/sandbox-setup'; const nodeRequestSchema = z.union([ z.string().describe('Simple node ID, e.g. "n8n-nodes-base.httpRequest"'), 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 new file mode 100644 index 00000000000..5eaec03e5f3 --- /dev/null +++ b/packages/@n8n/instance-ai/src/tools/workflows/plan-verification-simulation.ts @@ -0,0 +1,69 @@ +/** + * Verification Simulation Planning + * + * Single entry point for the execute-vs-simulate plan and its mock fixtures, + * shared by the build and submit tools so the planning policy cannot drift + * between the two submit paths. The policy: + * + * - Never blocks the submit — failures degrade, they do not throw. + * - An empty plan (no candidate nodes) is kept as `[]` so verify can tell + * "nothing to simulate" apart from "classification failed". Only the latter + * (plan `undefined`) runs unprotected and makes verify surface a warning. + * - Fixtures are only generated for non-empty plans; a fixture failure keeps + * the plan (verify pins fixture-less simulated nodes with an empty item). + */ + +import type { WorkflowJSON } from '@n8n/workflow-sdk'; + +import { classifyNodesForSimulation } from './classify-node-destructiveness.service'; +import { + generateSimulationFixtures, + type SimulationFixtures, +} from './generate-simulation-fixtures.service'; +import type { Logger } from '../../logger'; +import type { NodeSimulationVerdict } from '../../workflow-loop/workflow-loop-state'; + +export interface PlanVerificationSimulationInput { + workflow: WorkflowJSON; + /** Node names whose credentials were mocked — always simulated. */ + mockedNodeNames?: string[]; + /** Saved workflow id, for log context only. */ + workflowId: string; + logger?: Logger; +} + +export interface VerificationSimulationPlan { + nodeSimulationPlan?: NodeSimulationVerdict[]; + simulationFixtures?: SimulationFixtures; +} + +export async function planVerificationSimulation({ + workflow, + mockedNodeNames, + workflowId, + logger, +}: PlanVerificationSimulationInput): Promise { + let nodeSimulationPlan: NodeSimulationVerdict[] | undefined; + let simulationFixtures: SimulationFixtures | undefined; + try { + nodeSimulationPlan = await classifyNodesForSimulation({ workflow, mockedNodeNames }); + if (nodeSimulationPlan.length > 0) { + const fixtures = await generateSimulationFixtures({ workflow, plan: nodeSimulationPlan }); + simulationFixtures = Object.keys(fixtures).length > 0 ? fixtures : undefined; + logger?.debug('Classified workflow nodes for verification simulation', { + workflowId, + nodeCount: nodeSimulationPlan.length, + simulateCount: nodeSimulationPlan.filter((v) => v.verdict === 'simulate').length, + llmCount: nodeSimulationPlan.filter((v) => v.source === 'llm').length, + fallbackCount: nodeSimulationPlan.filter((v) => v.source === 'fallback').length, + }); + } + } catch (error) { + logger?.warn('Node simulation planning failed', { + workflowId, + planAvailable: nodeSimulationPlan !== undefined, + error: error instanceof Error ? error.message : String(error), + }); + } + return { nodeSimulationPlan, simulationFixtures }; +} diff --git a/packages/@n8n/instance-ai/src/tools/workflows/resolve-credentials.ts b/packages/@n8n/instance-ai/src/tools/workflows/resolve-credentials.ts index a33b1774165..1523819730e 100644 --- a/packages/@n8n/instance-ai/src/tools/workflows/resolve-credentials.ts +++ b/packages/@n8n/instance-ai/src/tools/workflows/resolve-credentials.ts @@ -2,7 +2,9 @@ * Credential Resolution * * Shared helper that resolves undefined/null credentials in WorkflowJSON. - * Produces sidecar verification pin data instead of mutating the workflow's pinData. + * Unresolvable credentials are removed ("mocked") and reported via the mock + * metadata fields; the node simulation plan (classify-node-destructiveness) + * picks mocked nodes up and pins them with generated fixtures at verify time. */ import type { WorkflowJSON } from '@n8n/workflow-sdk'; @@ -43,7 +45,7 @@ export async function buildCredentialMap( return map; } -/** Result of credential resolution — includes mock metadata and sidecar verification data. */ +/** Result of credential resolution — mock metadata for the simulation plan. */ export interface CredentialResolutionResult { /** Node names whose credentials were mocked. */ mockedNodeNames: string[]; @@ -51,10 +53,6 @@ export interface CredentialResolutionResult { mockedCredentialTypes: string[]; /** Map of node name → credential types that were mocked on that node. */ mockedCredentialsByNode: Record; - /** Pin data for verification only — NEVER written to workflow JSON. */ - verificationPinData: Record>>; - /** True when mocked credential nodes can be skipped by existing workflow-level pin data. */ - usesWorkflowPinDataForVerification: boolean; } /** @@ -64,10 +62,9 @@ export interface CredentialResolutionResult { * in `toJSON()`. Resolution strategy (in order): * 1. Restore from the existing workflow (preserve the user's chosen credential on updates) * 2. Preserve explicit valid raw credential ids - * 3. Mock: remove the credential key and produce sidecar verification pin data + * 3. Mock: remove the credential key and report the node in the mock metadata * - * Mocked credentials produce verification-only pin data that is returned separately - * and NEVER written into json.pinData. The saved workflow stays clean. + * Nothing is ever written into json.pinData — the saved workflow stays clean. */ export async function resolveCredentials( json: WorkflowJSON, @@ -78,8 +75,6 @@ export async function resolveCredentials( const mockedNodeNames: string[] = []; const mockedCredentialTypesSet = new Set(); const mockedCredentialsByNode: Record = {}; - const verificationPinData: Record>> = {}; - let usesWorkflowPinDataForVerification = false; // Build a map of existing credentials by node name (for updates) const existingCredsByNode = new Map>(); @@ -123,21 +118,11 @@ export async function resolveCredentials( nodeMocked = true; if (nodeName) { - // Track which credential types were mocked on this node + // Track which credential types were mocked on this node. The node + // simulation plan forces these nodes to `simulate`, so verification + // pins them with generated fixtures instead of executing them. mockedCredentialsByNode[nodeName] ??= []; mockedCredentialsByNode[nodeName].push(key); - - // Produce sidecar verification pin data (never saved to workflow). - // If the workflow already has real pinData for this node, skip — the - // existing pinData will suffice for execution skipping. - if (json.pinData && nodeName in json.pinData) { - usesWorkflowPinDataForVerification = true; - } else { - verificationPinData[nodeName] ??= []; - if (verificationPinData[nodeName].length === 0) { - verificationPinData[nodeName].push({ _mockedCredential: key }); - } - } } }; @@ -181,8 +166,6 @@ export async function resolveCredentials( mockedNodeNames, mockedCredentialTypes: [...mockedCredentialTypesSet], mockedCredentialsByNode, - verificationPinData, - usesWorkflowPinDataForVerification, }; } diff --git a/packages/@n8n/instance-ai/src/tools/workflows/setup-workflow.service.ts b/packages/@n8n/instance-ai/src/tools/workflows/setup-workflow.service.ts index 2be2a196a03..b367b86b643 100644 --- a/packages/@n8n/instance-ai/src/tools/workflows/setup-workflow.service.ts +++ b/packages/@n8n/instance-ai/src/tools/workflows/setup-workflow.service.ts @@ -72,7 +72,7 @@ export async function getValidCredentialTypes( } catch (error) { // Falling through to description-based detection is safe, but the dynamic // resolver isn't expected to throw — log so we can investigate if it does. - context.logger?.warn( + context.logger.warn( '[setup-workflow] getNodeCredentialTypes threw during credential validation', { nodeType: node.type, diff --git a/packages/@n8n/instance-ai/src/tools/workflows/submit-workflow.tool.ts b/packages/@n8n/instance-ai/src/tools/workflows/submit-workflow.tool.ts index 2e7a88b22cd..e9ce13da6ad 100644 --- a/packages/@n8n/instance-ai/src/tools/workflows/submit-workflow.tool.ts +++ b/packages/@n8n/instance-ai/src/tools/workflows/submit-workflow.tool.ts @@ -7,6 +7,7 @@ */ import { Tool } from '@n8n/agents'; +import { getWorkspaceRoot } from '@n8n/agents/sandbox'; import { hasPlaceholderDeep } from '@n8n/utils'; import type { WorkflowJSON } from '@n8n/workflow-sdk'; import { validateWorkflow } from '@n8n/workflow-sdk'; @@ -14,6 +15,8 @@ import type { WorkflowStructureIssue } from 'n8n-workflow'; import { createHash, randomUUID } from 'node:crypto'; import { z } from 'zod'; +import type { SimulationFixtures } from './generate-simulation-fixtures.service'; +import { planVerificationSimulation } from './plan-verification-simulation'; import { resolveCredentials, type CredentialMap } from './resolve-credentials'; import { stripStaleCredentialsFromWorkflow } from './setup-workflow.service'; import { getReferencedWorkflowIds, isTriggerNodeType } from './workflow-json-utils'; @@ -21,14 +24,16 @@ import type { InstanceAiContext } from '../../types'; import type { ValidationWarning } from '../../workflow-builder'; import { partitionWarnings } from '../../workflow-builder'; import { createRemediation } from '../../workflow-loop/remediation'; -import type { RemediationMetadata } from '../../workflow-loop/workflow-loop-state'; +import type { + NodeSimulationVerdict, + RemediationMetadata, +} from '../../workflow-loop/workflow-loop-state'; import { escapeSingleQuotes, readFileViaSandbox, runInSandbox, type SandboxWorkspace, } from '../../workspace/sandbox-fs'; -import { getWorkspaceRoot } from '../../workspace/sandbox-setup'; export interface SubmitWorkflowAttempt { filePath: string; @@ -49,14 +54,16 @@ export interface SubmitWorkflowAttempt { mockedCredentialTypes?: string[]; /** Map of node name → credential types that were mocked on that node. */ mockedCredentialsByNode?: Record; - /** Verification-only pin data — scoped to this build, never persisted to workflow. */ - verificationPinData?: Record>>; - /** True when mocked credential nodes can be skipped by existing workflow-level pin data. */ - usesWorkflowPinDataForVerification?: boolean; + /** Per-node execute-vs-simulate plan for verification. Sidecar — never persisted to workflow. */ + nodeSimulationPlan?: NodeSimulationVerdict[]; + /** Mock output for simulated nodes, keyed by node name. Sidecar — never persisted to workflow. */ + simulationFixtures?: SimulationFixtures; /** Sub-workflow IDs referenced by the submitted main workflow. */ referencedWorkflowIds?: string[]; /** Whether any node parameters contain unresolved placeholder values. */ hasUnresolvedPlaceholders?: boolean; + /** Builder-facing instruction for the next verification step. */ + verificationGuidance?: string; remediation?: RemediationMetadata; errors?: string[]; errorDetails?: SubmitWorkflowErrorDetail[]; @@ -307,16 +314,16 @@ export const submitWorkflowOutputSchema = z.object({ success: z.boolean(), workflowId: z.string().optional(), workflowName: z.string().optional(), - /** Node names whose credentials were mocked via pinned data. */ + verificationGuidance: z + .string() + .optional() + .describe('Builder-facing next step after a successful submit. Follow this before setup.'), + /** Node names whose credentials were mocked (simulated during verification). */ mockedNodeNames: z.array(z.string()).optional(), /** Credential types that were mocked (not resolved to real credentials). */ mockedCredentialTypes: z.array(z.string()).optional(), /** Map of node name → credential types that were mocked on that node. */ mockedCredentialsByNode: z.record(z.array(z.string())).optional(), - /** Verification-only pin data — scoped to this build, never persisted to workflow. */ - verificationPinData: z.record(z.array(z.record(z.unknown()))).optional(), - /** True when mocked credentials can be verified with saved workflow-level pin data. */ - usesWorkflowPinDataForVerification: z.boolean().optional(), /** Sub-workflow IDs referenced by the submitted main workflow. */ referencedWorkflowIds: z.array(z.string()).optional(), remediation: z @@ -348,6 +355,10 @@ export type SubmitWorkflowInput = z.infer; export type SubmitWorkflowOutput = z.infer; export type SubmitWorkflowErrorDetail = z.infer; +const POST_SUBMIT_VERIFICATION_GUIDANCE = + 'Call verify-built-workflow next with the work item ID from your briefing and this workflowId. ' + + 'It uses sidecar or saved pin data to fake unavailable services, so run it before any setup handoff.'; + export interface SubmitWorkflowToolOptions { root?: string; defaultFilePath?: string; @@ -608,7 +619,8 @@ export function createSubmitWorkflowTool( // newCredential() produces NewCredentialImpl which serializes to undefined in toJSON(). // For updates: restore from the existing workflow's resolved credentials. // For new nodes: look up credentials by name from the credential service. - // Unresolved credentials are mocked via pinned data when available. + // Unresolved credentials are mocked; the node simulation plan pins the + // affected nodes with generated fixtures during verification. const mockResult = await resolveCredentials(json, workflowId, context, credentialMap); // Strip credential entries that are no longer valid for the current @@ -671,7 +683,7 @@ export function createSubmitWorkflowTool( if (hasMockedCredentials) { informational.push({ code: 'CREDENTIALS_MOCKED', - message: `Mocked ${mockResult.mockedCredentialTypes.join(', ')} via pinned data on nodes: ${mockResult.mockedNodeNames.join(', ')}. Add real credentials before publishing.`, + message: `Mocked ${mockResult.mockedCredentialTypes.join(', ')} on nodes: ${mockResult.mockedNodeNames.join(', ')} — verification will simulate their output. Add real credentials before publishing.`, }); } @@ -686,10 +698,19 @@ export function createSubmitWorkflowTool( // Scan node parameters for unresolved placeholder values const hasPlaceholders = (json.nodes ?? []).some((n) => hasPlaceholderDeep(n.parameters)); + const { nodeSimulationPlan, simulationFixtures } = await planVerificationSimulation({ + workflow: json, + mockedNodeNames: mockResult.mockedNodeNames, + workflowId: savedId, + logger: context.logger, + }); + await reportAttempt({ success: true, workflowId: savedId, triggerNodes, + nodeSimulationPlan, + simulationFixtures, mockedNodeNames: hasMockedCredentials ? mockResult.mockedNodeNames : undefined, mockedCredentialTypes: hasMockedCredentials ? mockResult.mockedCredentialTypes @@ -697,12 +718,6 @@ export function createSubmitWorkflowTool( mockedCredentialsByNode: hasMockedCredentials ? mockResult.mockedCredentialsByNode : undefined, - verificationPinData: - hasMockedCredentials && Object.keys(mockResult.verificationPinData).length > 0 - ? mockResult.verificationPinData - : undefined, - usesWorkflowPinDataForVerification: - mockResult.usesWorkflowPinDataForVerification || undefined, referencedWorkflowIds: referencedWorkflowIds.length > 0 ? referencedWorkflowIds : undefined, hasUnresolvedPlaceholders: hasPlaceholders || undefined, @@ -711,6 +726,7 @@ export function createSubmitWorkflowTool( success: true, workflowId: savedId, workflowName: json.name || undefined, + verificationGuidance: POST_SUBMIT_VERIFICATION_GUIDANCE, mockedNodeNames: hasMockedCredentials ? mockResult.mockedNodeNames : undefined, mockedCredentialTypes: hasMockedCredentials ? mockResult.mockedCredentialTypes @@ -718,12 +734,6 @@ export function createSubmitWorkflowTool( mockedCredentialsByNode: hasMockedCredentials ? mockResult.mockedCredentialsByNode : undefined, - verificationPinData: - hasMockedCredentials && Object.keys(mockResult.verificationPinData).length > 0 - ? mockResult.verificationPinData - : undefined, - usesWorkflowPinDataForVerification: - mockResult.usesWorkflowPinDataForVerification || undefined, referencedWorkflowIds: referencedWorkflowIds.length > 0 ? referencedWorkflowIds : undefined, warnings: diff --git a/packages/@n8n/instance-ai/src/tools/workflows/write-sandbox-file.tool.ts b/packages/@n8n/instance-ai/src/tools/workflows/write-sandbox-file.tool.ts index 10694dfbafb..e50ea23f67a 100644 --- a/packages/@n8n/instance-ai/src/tools/workflows/write-sandbox-file.tool.ts +++ b/packages/@n8n/instance-ai/src/tools/workflows/write-sandbox-file.tool.ts @@ -7,11 +7,11 @@ */ import { Tool } from '@n8n/agents'; +import { getWorkspaceRoot } from '@n8n/agents/sandbox'; import path from 'node:path'; import { z } from 'zod'; import { writeFileViaSandbox, type SandboxWorkspace } from '../../workspace/sandbox-fs'; -import { getWorkspaceRoot } from '../../workspace/sandbox-setup'; export const writeSandboxFileInputSchema = z.object({ filePath: z diff --git a/packages/@n8n/instance-ai/src/tracing/__tests__/langsmith-tracing.test.ts b/packages/@n8n/instance-ai/src/tracing/__tests__/langsmith-tracing.test.ts index de8700a04dd..a7195918bae 100644 --- a/packages/@n8n/instance-ai/src/tracing/__tests__/langsmith-tracing.test.ts +++ b/packages/@n8n/instance-ai/src/tracing/__tests__/langsmith-tracing.test.ts @@ -615,6 +615,26 @@ describe('createInstanceAiTraceContext', () => { expect(serialized).toContain('[REDACTED]'); }); + it('redacts PII (email, credit-card, SSN) from telemetry strings', () => { + const span = { + attributes: { + 'ai.operationId': 'ai.streamText.doStream', + 'ai.response.text': 'reach me at jane.doe@example.com about card 4111 1111 1111 1111', + 'ai.prompt.messages': JSON.stringify([{ role: 'user', content: 'my ssn is 123-45-6789' }]), + }, + }; + + const redacted = redactLangSmithTelemetrySpan(span) as { + attributes: Record; + }; + const serialized = JSON.stringify(redacted.attributes); + + expect(serialized).not.toContain('jane.doe@example.com'); + expect(serialized).not.toContain('4111 1111 1111 1111'); + expect(serialized).not.toContain('123-45-6789'); + expect(serialized).toContain('[REDACTED]'); + }); + it('uses cache-only Anthropic input tokens for LangSmith prompt totals', () => { const span = { attributes: { diff --git a/packages/@n8n/instance-ai/src/tracing/trace-payloads.ts b/packages/@n8n/instance-ai/src/tracing/trace-payloads.ts index 11e3473a34f..82374ddadd0 100644 --- a/packages/@n8n/instance-ai/src/tracing/trace-payloads.ts +++ b/packages/@n8n/instance-ai/src/tracing/trace-payloads.ts @@ -1,5 +1,10 @@ -import type { AttributeValue, RuntimeSkillRegistry } from '@n8n/agents'; -import { scrubSecretsInText } from '@n8n/utils'; +import { + redactText, + SUPPORTED_PII_CATEGORIES, + type AttributeValue, + type RedactionOptions, + type RuntimeSkillRegistry, +} from '@n8n/agents'; import { createHash } from 'node:crypto'; import { @@ -22,6 +27,20 @@ const MAX_TRACE_OBJECT_KEYS = 30; const SENSITIVE_TELEMETRY_KEY_PATTERN = /(api[_-]?key|authorization|bearer|cookie|credentials?|password|secret|access[_-]?token|refresh[_-]?token|id[_-]?token|session[_-]?token|auth[_-]?token|(?:^|[._-])token$)/i; +/** + * Telemetry/tracing redaction policy. Deliberately stricter than the + * user-facing output policy `DEFAULT_OUTPUT_REDACTION_OPTIONS`. + */ +export const DEFAULT_TELEMETRY_REDACTION_OPTIONS: RedactionOptions = { + secrets: true, + detect: SUPPORTED_PII_CATEGORIES, +}; + +/** Redact secrets + all PII from a free-text telemetry value before it egresses. */ +function scrubTelemetryText(value: string): string { + return redactText(value, DEFAULT_TELEMETRY_REDACTION_OPTIONS).text; +} + const LANGSMITH_TRACE_NAME = 'langsmith.trace.name'; const LANGSMITH_SPAN_KIND = 'langsmith.span.kind'; const LANGSMITH_USAGE_METADATA = 'langsmith.usage_metadata'; @@ -133,7 +152,7 @@ function redactTelemetryJsonValue( } if (typeof value === 'string') { - return scrubSecretsInText(value); + return scrubTelemetryText(value); } if (typeof value === 'number' || typeof value === 'boolean' || value === null) { @@ -187,11 +206,11 @@ function redactTelemetryAttribute(key: string, value: unknown): unknown { const parsed: unknown = JSON.parse(trimmed); return JSON.stringify(redactTelemetryJsonValue(parsed, key, 0, maxDepth)); } catch { - return scrubSecretsInText(value); + return scrubTelemetryText(value); } } - return scrubSecretsInText(value); + return scrubTelemetryText(value); } function parseTelemetryJson(value: unknown): unknown { @@ -966,11 +985,7 @@ function classifyToolCategory(name: string): string { if (name === DOMAIN_TOOL_IDS.NODES || name === 'materialize-node-type') return 'node'; if (name === DOMAIN_TOOL_IDS.EXECUTIONS) return 'execution'; if (name.includes('research')) return 'research'; - if ( - name === ORCHESTRATION_TOOL_IDS.PLAN || - name.includes('plan') || - name === ORCHESTRATION_TOOL_IDS.CREATE_TASKS - ) { + if (name.includes('plan') || name === ORCHESTRATION_TOOL_IDS.CREATE_TASKS) { return 'planning'; } if (name.startsWith('workspace_')) return 'workspace'; diff --git a/packages/@n8n/instance-ai/src/types.ts b/packages/@n8n/instance-ai/src/types.ts index 399af45f6d1..db9de51e417 100644 --- a/packages/@n8n/instance-ai/src/types.ts +++ b/packages/@n8n/instance-ai/src/types.ts @@ -4,6 +4,7 @@ import type { BuiltMemory, BuiltTool, CheckpointStore, + RedactionOptions, RuntimeSkillSource, ModelConfig as NativeModelConfig, Telemetry, @@ -29,6 +30,7 @@ import type { // Service interfaces — dependency inversion so the package stays decoupled from n8n internals. // The backend module provides concrete implementations via InstanceAiAdapterService. +import type { WorkflowCodeSnapshotInput } from './debug/run-debug-buffer'; import type { DomainAccessTracker } from './domain-access/domain-access-tracker'; import type { InstanceAiEventBus } from './event-bus/event-bus.interface'; import type { Logger } from './logger'; @@ -40,6 +42,7 @@ import type { WorkflowBuildOutcome, WorkflowLoopAction, WorkflowLoopState, + WorkflowVerificationObligation, } from './workflow-loop/workflow-loop-state'; import type { BuilderTemplatesService } from './workspace/builder-templates-service'; @@ -76,6 +79,14 @@ export interface ExecutionResult { executionId: string; status: 'running' | 'success' | 'error' | 'waiting' | 'unknown'; data?: Record; + /** + * Every node that ran, including those whose last run produced zero output + * items (`data` omits those). Lets verification tell "ran and returned + * nothing" apart from "never reached". + */ + executedNodeNames?: string[]; + /** Name of the last node the execution processed, when available. */ + lastNodeExecuted?: string; error?: string; startedAt?: string; finishedAt?: string; @@ -247,6 +258,7 @@ export interface InstanceAiWorkflowService { query?: string; limit?: number; status?: WorkflowListStatus; + scope?: 'project' | 'instance'; }): Promise; get(workflowId: string): Promise; /** Get the workflow as the SDK's WorkflowJSON (full node data for generateWorkflowCode). */ @@ -335,6 +347,12 @@ export interface InstanceAiExecutionService { options?: { timeout?: number; pinData?: Record; + /** + * Nodes whose pin data simulates a destructive operation, keyed by node + * name. Persisted onto the saved execution (`resultData.simulation`) so + * the editor can label simulated outputs. + */ + simulation?: Record; /** When set, execute this specific trigger node instead of auto-detecting. */ triggerNodeName?: string; }, @@ -424,7 +442,7 @@ export interface ExploreResourcesResult { url?: string; description?: string; }>; - paginationToken?: unknown; + paginationToken?: string; /** The `@builderHint` from the node property whose method was queried, if any. * Surfaced alongside results so agents that skip the `type-definition` step * still receive selection guidance at the point of decision. */ @@ -717,6 +735,7 @@ export type LocalGatewayStatus = export interface InstanceAiContext { userId: string; + projectId?: string; workflowService: InstanceAiWorkflowService; executionService: InstanceAiExecutionService; credentialService: InstanceAiCredentialService; @@ -755,6 +774,8 @@ export interface InstanceAiContext { domainAccessTracker?: DomainAccessTracker; /** Current run ID — used for transient (allow_once) domain approvals. */ runId?: string; + /** Records workflow code snapshots for the run debug buffer (dev tooling). */ + recordWorkflowCodeSnapshot?: (snapshot: WorkflowCodeSnapshotInput) => void; /** * IDs of workflows the agent created during the **currently active plan * cycle**. Populated by build-workflow and submit-workflow on every @@ -771,8 +792,8 @@ export interface InstanceAiContext { * Used to register `parse-file` and supply data to the parser. */ currentUserAttachments?: InstanceAiAttachment[]; - /** Optional logger for diagnostics from domain tools. */ - logger?: Logger; + /** Logger for diagnostics from domain tools. */ + logger: Logger; /** Synchronous node-types provider used by host-side schema validation * (`validateWorkflow` from `@n8n/workflow-sdk`). Plumbed from the CLI * adapter; absent in pure-package contexts where no NodeTypes instance @@ -793,6 +814,8 @@ export interface InstanceAiContext { * exists and the builder may retry directly without creating a new plan. */ allowPostPlanWorkflowCreate?: boolean; + /** True when the active planned build task's final deliverable is a supporting workflow. */ + isSupportingWorkflowTask?: boolean; plannedTaskService?: PlannedTaskService; workflowTaskService?: WorkflowTaskService; onBuildOutcome?: (outcome: WorkflowBuildOutcome) => void | Promise; @@ -821,6 +844,12 @@ export interface PlannedTask { tools?: string[]; /** Existing workflow ID for build-workflow tasks that modify an existing workflow. */ workflowId?: string; + /** + * True when the build-workflow task's final deliverable is intentionally a + * supporting sub-workflow. Auxiliary supporting workflows created inside a + * larger main-workflow task should not set this. + */ + isSupportingWorkflow?: boolean; } export type PlannedTaskStatus = 'planned' | 'running' | 'succeeded' | 'failed' | 'cancelled'; @@ -851,11 +880,22 @@ export interface PlannedTaskGraph { tasks: PlannedTaskRecord[]; } +export interface PlannedWorkflowVerification { + task: PlannedTaskRecord; + obligation: WorkflowVerificationObligation; + outcome?: WorkflowBuildOutcome; +} + export type PlannedTaskSchedulerAction = | { type: 'none'; graph: PlannedTaskGraph | null } | { type: 'dispatch'; graph: PlannedTaskGraph; tasks: PlannedTaskRecord[] } | { type: 'orchestrate-build-workflow'; graph: PlannedTaskGraph; tasks: PlannedTaskRecord[] } | { type: 'orchestrate-checkpoint'; graph: PlannedTaskGraph; tasks: PlannedTaskRecord[] } + | { + type: 'orchestrate-workflow-verification'; + graph: PlannedTaskGraph; + verification: PlannedWorkflowVerification; + } | { type: 'replan'; graph: PlannedTaskGraph; failedTask: PlannedTaskRecord } | { type: 'synthesize'; graph: PlannedTaskGraph }; @@ -915,7 +955,10 @@ export interface PlannedTaskService { revertBuildWorkflowToPlanned(threadId: string, taskId: string): Promise; tick( threadId: string, - options?: { availableSlots?: number }, + options?: { + availableSlots?: number; + pendingWorkflowVerification?: PlannedWorkflowVerification; + }, ): Promise; clear(threadId: string): Promise; /** Transition an `awaiting_approval` graph → `active` after the user @@ -951,6 +994,7 @@ export interface McpServerConfig { command?: string; args?: string[]; env?: Record; + toolFilter?: { mode: 'allow' | 'exclude'; tools: string[] }; fetch?: typeof fetch; /** * Optional cache discriminator used by `McpClientManager` when a server's @@ -1180,12 +1224,15 @@ export interface OrchestrationContext { runId: string; messageGroupId?: string; userId: string; + projectId?: string; orchestratorAgentId: string; modelId: ModelConfig; checkpointStore?: CheckpointStore; subAgentMaxSteps: number; eventBus: InstanceAiEventBus; logger: Logger; + /** Output-redaction policy for sub-agent streams: omit for the safe default, or `false` to disable. */ + outputRedaction?: RedactionOptions | false; trackTelemetry?: (eventName: string, properties: Record) => void; domainTools: InstanceAiToolRegistry; abortSignal: AbortSignal; @@ -1264,25 +1311,6 @@ export interface OrchestrationContext { taskId: string, correction: string, ) => 'queued' | 'task-completed' | 'task-not-found'; - /** - * Resume info for a suspended sub-agent of this thread, looked up from the - * persisted checkpoint store by the deterministic sub-agent resourceId - * (`instance-ai-subagent:{threadId}:{agentKind}`). Used by the cascading - * suspend path: when the orchestrator's `plan` tool resumes, it calls - * this to find the planner sub-agent's `runId` + suspended `toolCallId` - * + the persistence the planner was running under, so the resume path - * can rebuild the sub-agent with the same persistence and call - * `plannerAgent.resume('stream', resumeData, { runId, toolCallId })` - * without stashing anything across its own suspend/resume cycle. - */ - findSubAgentResumeInfo?: (agentKind: string) => Promise< - | { - runId: string; - toolCallId: string; - persistence: { threadId: string; resourceId: string }; - } - | undefined - >; /** * Persist the current user message to thread memory immediately, so it * survives a restart that happens while the orchestrator is suspended on @@ -1327,6 +1355,4 @@ export interface CreateInstanceAgentOptions { * Intended for tests and fallback paths that need the full toolset visible immediately. */ disableDeferredTools?: boolean; - /** IANA time zone for the current user (e.g. "Europe/Helsinki"). Falls back to instance default. */ - timeZone?: string; } 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 new file mode 100644 index 00000000000..2ced1a5bb71 --- /dev/null +++ b/packages/@n8n/instance-ai/src/utils/__tests__/eval-agents.test.ts @@ -0,0 +1,112 @@ +/* eslint-disable import-x/order */ +import type { Mock } from 'vitest'; + +type MockAgentInstance = { + model: Mock; + instructions: Mock; + thinking: Mock; +}; + +const mockAgentInstances: MockAgentInstance[] = []; + +vi.mock('@n8n/agents', () => ({ + Agent: vi.fn().mockImplementation(function Agent(this: MockAgentInstance) { + this.model = vi.fn().mockReturnThis(); + this.instructions = vi.fn().mockReturnThis(); + this.thinking = vi.fn().mockReturnThis(); + mockAgentInstances.push(this); + }), + Tool: vi.fn(), +})); + +import { createEvalAgent, resolveEvalModelConfig } from '../eval-agents'; + +const ORIGINAL_ENV = { ...process.env }; +const MODEL_ENV_KEYS = [ + 'N8N_INSTANCE_AI_MODEL', + 'N8N_INSTANCE_AI_EVAL_MODEL', + 'N8N_INSTANCE_AI_MODEL_API_KEY', + 'N8N_AI_ANTHROPIC_KEY', + 'ANTHROPIC_API_KEY', + 'OPENAI_API_KEY', + 'GOOGLE_GENERATIVE_AI_API_KEY', + 'XAI_API_KEY', +]; + +function resetModelEnv(): void { + process.env = { ...ORIGINAL_ENV }; + for (const key of MODEL_ENV_KEYS) { + delete process.env[key]; + } +} + +describe('eval agent model config', () => { + beforeEach(() => { + resetModelEnv(); + mockAgentInstances.length = 0; + vi.clearAllMocks(); + }); + + afterAll(() => { + process.env = ORIGINAL_ENV; + }); + + it('keeps the legacy Anthropic key fallback for eval models', () => { + process.env.N8N_AI_ANTHROPIC_KEY = 'legacy-anthropic-key'; + + const config = resolveEvalModelConfig(); + + expect(config.modelId).toBe('anthropic/claude-sonnet-4-6'); + expect(config.apiKey).toBe('legacy-anthropic-key'); + }); + + it('prefers the generic eval model key over provider-specific keys', () => { + process.env.N8N_INSTANCE_AI_MODEL_API_KEY = 'generic-key'; + process.env.N8N_AI_ANTHROPIC_KEY = 'legacy-anthropic-key'; + process.env.ANTHROPIC_API_KEY = 'provider-key'; + + const config = resolveEvalModelConfig('anthropic/claude-sonnet-4-6'); + + expect(config.apiKey).toBe('generic-key'); + }); + + it('does not enable OpenAI reasoning when thinking is omitted', () => { + process.env.OPENAI_API_KEY = 'openai-key'; + + createEvalAgent('test-agent', { + model: 'openai/gpt-5.5', + instructions: 'Do the task.', + }); + + expect(mockAgentInstances[0]?.thinking).not.toHaveBeenCalled(); + }); + + it('enables OpenAI reasoning only when thinking is requested', () => { + process.env.OPENAI_API_KEY = 'openai-key'; + + createEvalAgent('test-agent', { + model: 'openai/gpt-5.5', + instructions: 'Do the task.', + thinking: 'adaptive', + }); + + expect(mockAgentInstances[0]?.thinking).toHaveBeenCalledWith('openai', { + reasoningEffort: 'high', + }); + }); + + it('keeps Anthropic budgeted thinking provider-specific', () => { + process.env.N8N_AI_ANTHROPIC_KEY = 'anthropic-key'; + + createEvalAgent('test-agent', { + model: 'anthropic/claude-sonnet-4-6', + instructions: 'Do the task.', + thinking: { budgetTokens: 2048 }, + }); + + expect(mockAgentInstances[0]?.thinking).toHaveBeenCalledWith('anthropic', { + mode: 'enabled', + budgetTokens: 2048, + }); + }); +}); 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 new file mode 100644 index 00000000000..94ba3a52aca --- /dev/null +++ b/packages/@n8n/instance-ai/src/utils/__tests__/generate-validated-json.test.ts @@ -0,0 +1,82 @@ +import type { MockedFunction } from 'vitest'; +import { z } from 'zod'; + +vi.mock('../eval-agents', async () => { + const actual: object = await vi.importActual('../eval-agents'); + return { ...actual, createEvalAgent: vi.fn(), extractText: vi.fn() }; +}); + +import { createEvalAgent, extractText } from '../eval-agents'; +import { generateValidatedJson } from '../generate-validated-json'; + +const mockCreateEvalAgent = createEvalAgent as MockedFunction; +const mockExtractText = extractText as MockedFunction; + +const schema = z.object({ ok: z.boolean() }); + +function setupAgentMock(responseText: string) { + const generate = vi.fn().mockResolvedValue({ messages: [] }); + mockCreateEvalAgent.mockReturnValue({ generate } as unknown as ReturnType< + typeof createEvalAgent + >); + mockExtractText.mockReturnValue(responseText); + return generate; +} + +async function generate(userText = 'do it') { + return await generateValidatedJson('test-agent', { + instructions: 'instructions', + userText, + schema, + }); +} + +describe('generateValidatedJson', () => { + beforeEach(() => vi.clearAllMocks()); + + it('returns validated data for a plain JSON response', async () => { + setupAgentMock('{"ok": true}'); + expect(await generate()).toEqual({ ok: true, data: { ok: true } }); + }); + + it('strips markdown fences around the JSON', async () => { + setupAgentMock('```json\n{"ok": false}\n```'); + expect(await generate()).toEqual({ ok: true, data: { ok: false } }); + }); + + it('sends the user text as a single user message', async () => { + const generateMock = setupAgentMock('{"ok": true}'); + await generate('classify this'); + expect(generateMock).toHaveBeenCalledWith([ + { role: 'user', content: [{ type: 'text', text: 'classify this' }] }, + ]); + }); + + it('reports invalid_json on unparseable output', async () => { + setupAgentMock('not json'); + expect(await generate()).toEqual({ ok: false, reason: 'invalid_json' }); + }); + + it('reports schema_mismatch with issues on shape errors', async () => { + setupAgentMock('{"ok": "yes"}'); + const result = await generate(); + expect(result).toMatchObject({ ok: false, reason: 'schema_mismatch' }); + expect(result.ok).toBe(false); + if (!result.ok) expect(result.issues?.length).toBeGreaterThan(0); + }); + + it('reports generation_failed when the LLM call throws', async () => { + const generateMock = vi.fn().mockRejectedValue(new Error('boom')); + mockCreateEvalAgent.mockReturnValue({ generate: generateMock } as unknown as ReturnType< + typeof createEvalAgent + >); + expect(await generate()).toEqual({ ok: false, reason: 'generation_failed' }); + }); + + 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' }); + }); +}); diff --git a/packages/@n8n/instance-ai/src/utils/eval-agents.ts b/packages/@n8n/instance-ai/src/utils/eval-agents.ts index deab97985ad..9eb8fed83cb 100644 --- a/packages/@n8n/instance-ai/src/utils/eval-agents.ts +++ b/packages/@n8n/instance-ai/src/utils/eval-agents.ts @@ -12,22 +12,79 @@ export const SONNET_MODEL = 'anthropic/claude-sonnet-4-6'; export const HAIKU_MODEL = 'anthropic/claude-haiku-4-5-20251001'; // --------------------------------------------------------------------------- -// API key resolution +// Model config resolution // --------------------------------------------------------------------------- -function getApiKey(): string { +const PROVIDER_API_KEY_ENV: Record = { + anthropic: 'ANTHROPIC_API_KEY', + google: 'GOOGLE_GENERATIVE_AI_API_KEY', + openai: 'OPENAI_API_KEY', + xai: 'XAI_API_KEY', +}; + +export interface EvalModelConfig { + modelId: string; + provider: string; + providerModelId: string; + apiKey: string; + url?: string; +} + +function getModelId(model?: string): string { + const modelId = + model ?? + process.env.N8N_INSTANCE_AI_EVAL_MODEL ?? + process.env.N8N_INSTANCE_AI_MODEL ?? + SONNET_MODEL; + return modelId; +} + +function getApiKey(modelId: string): string { + const [provider] = modelId.split('/'); + const providerKeyEnv = PROVIDER_API_KEY_ENV[provider]; + const providerKey = providerKeyEnv ? process.env[providerKeyEnv] : undefined; const key = process.env.N8N_INSTANCE_AI_MODEL_API_KEY ?? - process.env.N8N_AI_ANTHROPIC_KEY ?? - process.env.ANTHROPIC_API_KEY; + (provider === 'anthropic' ? process.env.N8N_AI_ANTHROPIC_KEY : undefined) ?? + providerKey; + if (!key) { throw new Error( - 'Missing API key. Set N8N_INSTANCE_AI_MODEL_API_KEY, N8N_AI_ANTHROPIC_KEY, or ANTHROPIC_API_KEY in your environment.', + `Missing API key for eval model "${modelId}". Set N8N_INSTANCE_AI_MODEL_API_KEY${ + provider === 'anthropic' + ? ' or N8N_AI_ANTHROPIC_KEY or ANTHROPIC_API_KEY' + : providerKeyEnv + ? ` or ${providerKeyEnv}` + : '' + } in your environment.`, ); } return key; } +function getModelUrl(): string | undefined { + const url = process.env.N8N_INSTANCE_AI_MODEL_URL?.trim(); + if (!url) return undefined; + return url; +} + +export function resolveEvalModelConfig(model?: string): EvalModelConfig { + const modelId = getModelId(model); + const [provider, ...rest] = modelId.split('/'); + const joinedProviderModelId = rest.join('/'); + let providerModelId = modelId; + if (joinedProviderModelId.length > 0) { + providerModelId = joinedProviderModelId; + } + return { + modelId, + provider, + providerModelId, + apiKey: getApiKey(modelId), + url: getModelUrl(), + }; +} + // --------------------------------------------------------------------------- // Agent factory // --------------------------------------------------------------------------- @@ -50,9 +107,11 @@ export function createEvalAgent( thinking?: 'adaptive' | 'off' | { budgetTokens: number }; }, ): Agent { + const { modelId, provider, apiKey, url } = resolveEvalModelConfig(options.model); const agent = new Agent(name).model({ - id: options.model ?? SONNET_MODEL, - apiKey: getApiKey(), + id: modelId, + apiKey, + url, }); if (options.cache) { @@ -62,9 +121,11 @@ export function createEvalAgent( } const thinking = options.thinking ?? 'off'; - if (thinking === 'adaptive') { + if (provider === 'openai' && thinking !== 'off') { + agent.thinking('openai', { reasoningEffort: 'high' }); + } else if (provider === 'anthropic' && thinking === 'adaptive') { agent.thinking('anthropic', { mode: 'adaptive' }); - } else if (typeof thinking === 'object') { + } else if (provider === 'anthropic' && typeof thinking === 'object') { agent.thinking('anthropic', { mode: 'enabled', budgetTokens: thinking.budgetTokens }); } diff --git a/packages/@n8n/instance-ai/src/utils/generate-validated-json.ts b/packages/@n8n/instance-ai/src/utils/generate-validated-json.ts new file mode 100644 index 00000000000..466069c41f5 --- /dev/null +++ b/packages/@n8n/instance-ai/src/utils/generate-validated-json.ts @@ -0,0 +1,66 @@ +/** + * One-shot "LLM returns a JSON object" helper for eval-agent calls: create the + * agent, send the user text, strip markdown fences, parse, validate against a + * zod schema. Never throws — callers own their fallback (and the schema-issue + * details when they want to log them). + * + * Lives outside `eval-agents.ts` so tests can mock this module while the + * helper's own tests mock `eval-agents`. + */ + +import type { z } from 'zod'; + +import { createEvalAgent, extractText } from './eval-agents'; + +export type ValidatedJsonResult = + | { ok: true; data: T } + | { + ok: false; + reason: 'generation_failed' | 'invalid_json' | 'schema_mismatch'; + issues?: z.ZodIssue[]; + }; + +export interface GenerateValidatedJsonOptions { + model?: string; + instructions: string; + userText: string; + schema: z.ZodType; +} + +function stripMarkdownFences(text: string): string { + const trimmed = text.trim(); + const fencedMatch = /^```(?:json)?\s*([\s\S]*?)\s*```$/i.exec(trimmed); + return fencedMatch ? fencedMatch[1].trim() : trimmed; +} + +export async function generateValidatedJson( + agentName: string, + options: GenerateValidatedJsonOptions, +): Promise> { + let text: string; + try { + const llm = createEvalAgent(agentName, { + model: options.model, + instructions: options.instructions, + }); + const result = await llm.generate([ + { role: 'user' as const, content: [{ type: 'text' as const, text: options.userText }] }, + ]); + text = extractText(result); + } catch { + return { ok: false, reason: 'generation_failed' }; + } + + let parsed: unknown; + try { + parsed = JSON.parse(stripMarkdownFences(text)); + } catch { + return { ok: false, reason: 'invalid_json' }; + } + + const validated = options.schema.safeParse(parsed); + if (!validated.success) { + return { ok: false, reason: 'schema_mismatch', issues: validated.error.issues }; + } + return { ok: true, data: validated.data }; +} diff --git a/packages/@n8n/instance-ai/src/workflow-builder/__tests__/build-failure-tracker.test.ts b/packages/@n8n/instance-ai/src/workflow-builder/__tests__/build-failure-tracker.test.ts new file mode 100644 index 00000000000..db57650c176 --- /dev/null +++ b/packages/@n8n/instance-ai/src/workflow-builder/__tests__/build-failure-tracker.test.ts @@ -0,0 +1,81 @@ +import { BuildFailureTracker, buildFailureSignature } from '../build-failure-tracker'; + +const joinError = [ + "Failed to parse workflow code: Method 'join' is not an allowed SDK method. Allowed methods: add, to.\n\n> 3 | wf.join(', ')\n | ^", +]; + +describe('buildFailureSignature', () => { + it('ignores code frames and line numbers so the same violation matches across attempts', () => { + const first = buildFailureSignature([ + "Failed to parse workflow code: Method 'join' is not an allowed SDK method.\n\n> 3 | a.join()", + ]); + const second = buildFailureSignature([ + "Failed to parse workflow code: Method 'join' is not an allowed SDK method.\n\n> 17 | b.join()", + ]); + expect(first).toBe(second); + }); + + it('distinguishes different violations', () => { + expect(buildFailureSignature(["Method 'join' is not an allowed SDK method"])).not.toBe( + buildFailureSignature(["Method 'map' is not an allowed SDK method"]), + ); + }); +}); + +describe('BuildFailureTracker', () => { + it('escalates only on a repeated failure for the same work item', () => { + const tracker = new BuildFailureTracker(); + expect( + tracker.record('wi_1', joinError, { + includeSdkLanguageGuidance: true, + }), + ).toBeUndefined(); + const escalation = tracker.record('wi_1', joinError, { + includeSdkLanguageGuidance: true, + }); + expect(escalation).toBeDefined(); + expect(escalation).toContain('You already tried this'); + expect(escalation).toContain('workflow-sdk-language.md'); + expect(escalation).toContain('Code node'); + }); + + it('keeps generic validation repeats free of SDK-specific repair advice', () => { + const tracker = new BuildFailureTracker(); + const validationError = ['[UNKNOWN_CONFIG_KEY] (Gmail): Unknown config key "recipient"']; + expect(tracker.record('wi_1', validationError)).toBeUndefined(); + const escalation = tracker.record('wi_1', validationError); + expect(escalation).toContain('You already tried this'); + expect(escalation).not.toContain('workflow-sdk-language.md'); + expect(escalation).not.toContain('Code node'); + }); + + it('does not loop: every repeat after the first keeps escalating', () => { + const tracker = new BuildFailureTracker(); + tracker.record('wi_1', joinError, { + includeSdkLanguageGuidance: true, + }); + expect( + tracker.record('wi_1', joinError, { + includeSdkLanguageGuidance: true, + }), + ).toBeDefined(); + expect( + tracker.record('wi_1', joinError, { + includeSdkLanguageGuidance: true, + }), + ).toBeDefined(); + }); + + it('tracks work items independently', () => { + const tracker = new BuildFailureTracker(); + tracker.record('wi_1', joinError); + expect(tracker.record('wi_2', joinError)).toBeUndefined(); + }); + + it('resets history after a successful save', () => { + const tracker = new BuildFailureTracker(); + tracker.record('wi_1', joinError); + tracker.clear('wi_1'); + expect(tracker.record('wi_1', joinError)).toBeUndefined(); + }); +}); diff --git a/packages/@n8n/instance-ai/src/workflow-builder/build-failure-tracker.ts b/packages/@n8n/instance-ai/src/workflow-builder/build-failure-tracker.ts new file mode 100644 index 00000000000..ec03febf6a3 --- /dev/null +++ b/packages/@n8n/instance-ai/src/workflow-builder/build-failure-tracker.ts @@ -0,0 +1,59 @@ +/** + * Detects when a build fails with the same signature twice for one work item, so + * the tool can escalate instead of letting the builder repeat an invalid strategy. + */ + +/** Stable signature for a set of build errors, ignoring code frames and numbers. */ +export function buildFailureSignature(errors: string[]): string { + return errors + .map((error) => + error.split('\n\n')[0].toLowerCase().replace(/\d+/g, '#').replace(/\s+/g, ' ').trim(), + ) + .sort() + .join(' | '); +} + +interface BuildFailureTrackerOptions { + includeSdkLanguageGuidance?: boolean; +} + +const GENERIC_ESCALATION = + 'You already tried this and it failed with the same error. Do not repeat the same approach. ' + + 'Use a different repair strategy for this work item.'; + +const SDK_LANGUAGE_GUIDANCE = + 'SDK builder code is a restricted subset of TypeScript (see ' + + 'knowledge-base/reference/workflow-sdk-language.md): only SDK builder methods are allowed, not ' + + 'native array/string methods or globals. Build strings with template literals or explicit lines, ' + + 'and move runtime joining, aggregation, or transforms into a Code node or an n8n expression.'; + +/** Tracks repeated build-failure signatures per work item within a tool instance. */ +export class BuildFailureTracker { + private readonly history = new Map>(); + + /** + * Records a failure and returns escalation guidance when the same signature + * has already been seen for this work item, otherwise undefined. + */ + record( + workItemKey: string, + errors: string[], + options: BuildFailureTrackerOptions = {}, + ): string | undefined { + const signature = buildFailureSignature(errors); + const seen = this.history.get(workItemKey) ?? new Set(); + const repeated = seen.has(signature); + seen.add(signature); + this.history.set(workItemKey, seen); + return repeated + ? [GENERIC_ESCALATION, options.includeSdkLanguageGuidance ? SDK_LANGUAGE_GUIDANCE : ''] + .filter(Boolean) + .join(' ') + : undefined; + } + + /** Clears history once the work item has been saved successfully. */ + clear(workItemKey: string): void { + this.history.delete(workItemKey); + } +} diff --git a/packages/@n8n/instance-ai/src/workflow-builder/index.ts b/packages/@n8n/instance-ai/src/workflow-builder/index.ts index 3cee489447f..02de2969d9a 100644 --- a/packages/@n8n/instance-ai/src/workflow-builder/index.ts +++ b/packages/@n8n/instance-ai/src/workflow-builder/index.ts @@ -6,6 +6,7 @@ export { } from './extract-code'; export { applyPatches } from './patch-code'; export { parseAndValidate, partitionWarnings } from './parse-validate'; +export { BuildFailureTracker, buildFailureSignature } from './build-failure-tracker'; export { EXPRESSION_REFERENCE, ADDITIONAL_FUNCTIONS, diff --git a/packages/@n8n/instance-ai/src/workflow-loop/__tests__/guidance.test.ts b/packages/@n8n/instance-ai/src/workflow-loop/__tests__/guidance.test.ts index 0e7996f6335..cc78dae6765 100644 --- a/packages/@n8n/instance-ai/src/workflow-loop/__tests__/guidance.test.ts +++ b/packages/@n8n/instance-ai/src/workflow-loop/__tests__/guidance.test.ts @@ -157,6 +157,8 @@ describe('formatWorkflowLoopGuidance', () => { workflowId: 'wf-789', }; const result = formatWorkflowLoopGuidance(action); + expect(result).toContain('workflows(action="get-json")'); + expect(result).toContain('Build/save success only means a workflow was saved'); expect(result).toContain('verify-built-workflow'); expect(result).toContain('executions(action="run")'); }); @@ -168,7 +170,10 @@ describe('formatWorkflowLoopGuidance', () => { }; const result = formatWorkflowLoopGuidance(action); expect(result).toContain('executions(action="debug")'); + expect(result).toContain('needs_patch'); + expect(result).toContain('needs_rebuild'); expect(result).toContain('report-verification-verdict'); + expect(result).toContain('workflowInspection'); }); }); diff --git a/packages/@n8n/instance-ai/src/workflow-loop/__tests__/verification-obligation.test.ts b/packages/@n8n/instance-ai/src/workflow-loop/__tests__/verification-obligation.test.ts new file mode 100644 index 00000000000..373a2662246 --- /dev/null +++ b/packages/@n8n/instance-ai/src/workflow-loop/__tests__/verification-obligation.test.ts @@ -0,0 +1,287 @@ +import { + deriveWorkflowVerificationObligation, + deriveWorkflowVerificationObligationFromOutcome, +} from '../verification-obligation'; +import type { + AttemptRecord, + WorkflowBuildOutcome, + WorkflowLoopState, +} from '../workflow-loop-state'; + +function makeState(overrides: Partial = {}): WorkflowLoopState { + return { + workItemId: 'wi-1', + threadId: 'thread-1', + runId: 'run-1', + workflowId: 'wf-1', + phase: 'verifying', + status: 'active', + source: 'create', + rebuildAttempts: 0, + ...overrides, + }; +} + +function makeAttempt(overrides: Partial = {}): AttemptRecord { + return { + workItemId: 'wi-1', + phase: 'building', + attempt: 1, + action: 'build', + result: 'success', + createdAt: '2026-01-01T00:00:00.000Z', + ...overrides, + }; +} + +function makeOutcome(overrides: Partial = {}): WorkflowBuildOutcome { + return { + workItemId: 'wi-1', + runId: 'run-1', + taskId: 'build-1', + workflowId: 'wf-1', + submitted: true, + triggerType: 'manual_or_testable', + needsUserInput: false, + verificationReadiness: { status: 'ready' }, + setupRequirement: { status: 'not_required' }, + summary: 'Submitted.', + ...overrides, + }; +} + +describe('deriveWorkflowVerificationObligation', () => { + it('marks ready build outcomes as ready to verify', () => { + const obligation = deriveWorkflowVerificationObligation('thread-1', { + state: makeState(), + attempts: [makeAttempt()], + lastBuildOutcome: makeOutcome(), + }); + + expect(obligation).toEqual( + expect.objectContaining({ + workItemId: 'wi-1', + workflowId: 'wf-1', + status: 'ready_to_verify', + policy: 'required', + updatedAt: '2026-01-01T00:00:00.000Z', + }), + ); + }); + + it('marks successful structured evidence as verified', () => { + const obligation = deriveWorkflowVerificationObligation('thread-1', { + state: makeState(), + attempts: [makeAttempt()], + lastBuildOutcome: makeOutcome({ + verificationReadiness: { status: 'already_verified' }, + verification: { + attempted: true, + success: true, + executionId: 'exec-1', + status: 'success', + }, + }), + }); + + expect(obligation.status).toBe('verified'); + expect(obligation.evidence?.executionId).toBe('exec-1'); + }); + + it('does not mark partial-coverage evidence as verified', () => { + const obligation = deriveWorkflowVerificationObligation('thread-1', { + state: makeState(), + attempts: [makeAttempt()], + lastBuildOutcome: makeOutcome({ + verification: { + attempted: true, + success: true, + executionId: 'exec-1', + status: 'success', + evidence: { nodesNotReached: ['Send Email'] }, + }, + }), + }); + + expect(obligation.status).toBe('ready_to_verify'); + }); + + it('treats not-verifiable outcomes as manual warning completions', () => { + const obligation = deriveWorkflowVerificationObligation('thread-1', { + state: makeState(), + attempts: [makeAttempt()], + lastBuildOutcome: makeOutcome({ + verificationReadiness: { + status: 'not_verifiable', + reason: 'non-mockable-trigger', + guidance: 'Ask the user to test manually.', + }, + }), + }); + + expect(obligation.status).toBe('not_verifiable'); + expect(obligation.policy).toBe('manual'); + expect(obligation.blockingReason).toBe('Ask the user to test manually.'); + }); + + it('preserves setup handoff status when the loop state is blocked for setup', () => { + const obligation = deriveWorkflowVerificationObligation('thread-1', { + state: makeState({ phase: 'blocked', status: 'blocked' }), + attempts: [makeAttempt({ result: 'blocked' })], + lastBuildOutcome: makeOutcome({ + needsUserInput: true, + blockingReason: 'Setup required.', + verificationReadiness: { + status: 'needs_setup', + reason: 'unresolved-placeholders', + guidance: 'Route through setup.', + }, + setupRequirement: { + status: 'required', + reason: 'unresolved-placeholders', + guidance: 'Route through setup.', + }, + }), + }); + + expect(obligation.status).toBe('needs_setup'); + expect(obligation.blockingReason).toBe('Route through setup.'); + }); + + it('treats failed verification evidence with required setup as needs setup', () => { + const obligation = deriveWorkflowVerificationObligation('thread-1', { + state: makeState(), + attempts: [makeAttempt()], + lastBuildOutcome: makeOutcome({ + setupRequirement: { + status: 'required', + reason: 'mocked-credentials', + guidance: 'Route through setup.', + }, + verification: { + attempted: true, + success: false, + executionId: 'exec-1', + status: 'error', + failureSignature: 'Missing credentials', + }, + }), + }); + + expect(obligation.status).toBe('needs_setup'); + expect(obligation.blockingReason).toBe('Route through setup.'); + }); + + it('marks missing submit as blocked', () => { + const obligation = deriveWorkflowVerificationObligation('thread-1', { + state: makeState({ workflowId: undefined }), + attempts: [makeAttempt({ result: 'failure' })], + lastBuildOutcome: makeOutcome({ + workflowId: undefined, + submitted: false, + verificationReadiness: { + status: 'not_verifiable', + reason: 'not-submitted', + guidance: 'Nothing to verify.', + }, + failureSignature: 'submit failed', + }), + }); + + expect(obligation.status).toBe('blocked'); + expect(obligation.blockingReason).toBe('submit failed'); + }); + + it('derives planned ownership from the workflow-loop state', () => { + const obligation = deriveWorkflowVerificationObligation('thread-1', { + state: makeState({ plannedTaskId: 'planned-1' }), + attempts: [makeAttempt()], + lastBuildOutcome: makeOutcome({ verificationReadiness: { status: 'ready' } }), + }); + + expect(obligation).toEqual( + expect.objectContaining({ + owner: { type: 'planned', taskId: 'planned-1' }, + source: 'planned', + plannedTaskId: 'planned-1', + }), + ); + }); +}); + +describe('deriveWorkflowVerificationObligationFromOutcome', () => { + it('derives the same obligation as a synthetic loop record', () => { + const obligation = deriveWorkflowVerificationObligationFromOutcome( + 'thread-1', + makeOutcome({ verificationReadiness: { status: 'ready' } }), + { source: 'planned', plannedTaskId: 'task-1' }, + ); + + expect(obligation).toEqual( + expect.objectContaining({ + workItemId: 'wi-1', + workflowId: 'wf-1', + owner: { type: 'planned', taskId: 'task-1' }, + source: 'planned', + plannedTaskId: 'task-1', + status: 'ready_to_verify', + policy: 'required', + }), + ); + }); + + it('marks already-verified outcomes as verified', () => { + const obligation = deriveWorkflowVerificationObligationFromOutcome( + 'thread-1', + makeOutcome({ + verificationReadiness: { status: 'already_verified' }, + verification: { attempted: true, success: true, executionId: 'exec-1', status: 'success' }, + }), + ); + + expect(obligation.status).toBe('verified'); + expect(obligation.evidence?.executionId).toBe('exec-1'); + }); + + it('does not mark already-verified outcomes as verified when evidence is partial', () => { + const obligation = deriveWorkflowVerificationObligationFromOutcome( + 'thread-1', + makeOutcome({ + verificationReadiness: { status: 'already_verified' }, + verification: { + attempted: true, + success: true, + executionId: 'exec-1', + status: 'success', + evidence: { nodesNotReached: ['Send Email'] }, + }, + }), + ); + + expect(obligation.status).toBe('ready_to_verify'); + }); + + it('marks setup-blocked failed evidence as needs setup from outcome-only records', () => { + const obligation = deriveWorkflowVerificationObligationFromOutcome( + 'thread-1', + makeOutcome({ + setupRequirement: { + status: 'required', + reason: 'mocked-credentials', + guidance: 'Route through setup.', + }, + verification: { + attempted: true, + success: false, + executionId: 'exec-1', + status: 'error', + failureSignature: 'Missing credentials', + }, + }), + { source: 'planned', plannedTaskId: 'task-1' }, + ); + + expect(obligation.status).toBe('needs_setup'); + expect(obligation.plannedTaskId).toBe('task-1'); + }); +}); diff --git a/packages/@n8n/instance-ai/src/workflow-loop/__tests__/workflow-loop-controller.test.ts b/packages/@n8n/instance-ai/src/workflow-loop/__tests__/workflow-loop-controller.test.ts index 456d70b9729..5631267bcb3 100644 --- a/packages/@n8n/instance-ai/src/workflow-loop/__tests__/workflow-loop-controller.test.ts +++ b/packages/@n8n/instance-ai/src/workflow-loop/__tests__/workflow-loop-controller.test.ts @@ -476,6 +476,7 @@ describe('handleVerificationVerdict', () => { verdict: 'needs_patch', failedNodeName: 'Gmail Send', diagnosis: 'Invalid recipient address', + workflowInspection: 'Saved graph is missing the recipient mapping.', patch: { parameters: { to: 'fix@example.com' } }, failureSignature: 'gmail:invalid_recipient', }); @@ -484,6 +485,7 @@ describe('handleVerificationVerdict', () => { expect(next.phase).toBe('repairing'); expect(next.rebuildAttempts).toBe(1); + expect(next.lastWorkflowInspection).toBe('Saved graph is missing the recipient mapping.'); expect(action.type).toBe('patch'); if (action.type === 'patch') { expect(action.workflowId).toBe('wf_123'); @@ -492,6 +494,7 @@ describe('handleVerificationVerdict', () => { expect(action.patch).toEqual({ parameters: { to: 'fix@example.com' } }); } expect(attempt.action).toBe('patch'); + expect(attempt.workflowInspection).toBe('Saved graph is missing the recipient mapping.'); }); it('produces patch action with fallback node name when failedNodeName is missing', () => { @@ -514,6 +517,7 @@ describe('handleVerificationVerdict', () => { const verdict = makeVerdict({ verdict: 'needs_rebuild', diagnosis: 'Multiple nodes misconfigured', + workflowInspection: 'Saved graph has no connection into the final response node.', failureSignature: 'multi:config_error', }); @@ -522,6 +526,11 @@ describe('handleVerificationVerdict', () => { expect(next.phase).toBe('repairing'); expect(next.rebuildAttempts).toBe(1); expect(action.type).toBe('rebuild'); + if (action.type === 'rebuild') { + expect(action.failureDetails).toContain( + 'Workflow inspection: Saved graph has no connection into the final response node.', + ); + } }); }); @@ -699,6 +708,34 @@ describe('retry policy', () => { }); }); + it('preserves the concrete verdict failure in the budget-exhausted blocked reason', () => { + const state = makeState({ + phase: 'verifying', + workflowId: 'wf_123', + successfulSubmitSeen: true, + postSubmitRemediationSubmitsUsed: 2, + }); + + const { action } = handleVerificationVerdict( + state, + [], + makeVerdict({ + verdict: 'needs_rebuild', + summary: 'HTTP Request node returned 401 Unauthorized', + diagnosis: 'The Authorization header is missing the bearer token', + failureSignature: 'http:401', + }), + ); + + expect(action.type).toBe('blocked'); + if (action.type !== 'blocked') throw new Error('expected blocked action'); + // The concrete failure must survive alongside the budget-exhaustion guidance. + expect(action.reason).toContain('HTTP Request node returned 401 Unauthorized'); + expect(action.reason).toContain('The Authorization header is missing the bearer token'); + expect(action.reason).toContain('Signature: http:401'); + expect(action.reason).toContain('repair budget is exhausted'); + }); + it('blocks non-editable remediation immediately and preserves workflow id', () => { const state = makeState({ phase: 'verifying', diff --git a/packages/@n8n/instance-ai/src/workflow-loop/__tests__/workflow-task-service.test.ts b/packages/@n8n/instance-ai/src/workflow-loop/__tests__/workflow-task-service.test.ts index 38454229365..c2aafe97ceb 100644 --- a/packages/@n8n/instance-ai/src/workflow-loop/__tests__/workflow-task-service.test.ts +++ b/packages/@n8n/instance-ai/src/workflow-loop/__tests__/workflow-task-service.test.ts @@ -93,6 +93,13 @@ describe('WorkflowTaskCoordinator', () => { workflowId: 'wf-1', }), ); + expect(await coordinator.getBuildOutcome('wi_1')).toEqual( + expect.objectContaining({ + workItemId: 'wi_1', + workflowId: 'wf-1', + mockedCredentialTypes: ['slackOAuth2Api'], + }), + ); }); it('ignores stale build outcomes without overwriting the current work item', async () => { diff --git a/packages/@n8n/instance-ai/src/workflow-loop/guidance.ts b/packages/@n8n/instance-ai/src/workflow-loop/guidance.ts index 5a035fb6d86..7e4488eb2c7 100644 --- a/packages/@n8n/instance-ai/src/workflow-loop/guidance.ts +++ b/packages/@n8n/instance-ai/src/workflow-loop/guidance.ts @@ -27,11 +27,13 @@ export function formatWorkflowLoopGuidance( } case 'verify': return ( - `VERIFY: Run workflow ${action.workflowId}. ` + + `VERIFY: Inspect the persisted workflow ${action.workflowId} with \`workflows(action="get-json")\` and compare it to the requested outcome. ` + + 'Build/save success only means a workflow was saved. ' + `If the build had mocked credentials, use \`verify-built-workflow\` with workItemId "${options.workItemId ?? 'unknown'}". ` + 'Otherwise use `executions(action="run")`. ' + 'If it fails, use `executions(action="debug")` to diagnose. ' + - `Then call \`report-verification-verdict\` with workItemId "${options.workItemId ?? 'unknown'}" and your findings.` + 'If the saved graph or run evidence is not good enough, report `needs_patch` or `needs_rebuild` and keep patching the same workflow. ' + + `Then call \`report-verification-verdict\` with workItemId "${options.workItemId ?? 'unknown'}", \`workflowInspection\`, and your findings.` ); case 'blocked': return `BUILD BLOCKED: ${action.reason}. Explain this to the user and ask how to proceed.`; diff --git a/packages/@n8n/instance-ai/src/workflow-loop/index.ts b/packages/@n8n/instance-ai/src/workflow-loop/index.ts index 2da88cbc88f..5613ee77373 100644 --- a/packages/@n8n/instance-ai/src/workflow-loop/index.ts +++ b/packages/@n8n/instance-ai/src/workflow-loop/index.ts @@ -4,16 +4,25 @@ export { workflowLoopSourceSchema, remediationCategorySchema, remediationMetadataSchema, + workflowBuildOwnerSchema, workflowLoopStateSchema, attemptActionSchema, attemptResultSchema, attemptRecordSchema, triggerTypeSchema, + workflowVerificationEvidenceSchema, workflowVerificationReadinessSchema, workflowSetupRequirementSchema, + workflowVerificationObligationStatusSchema, + workflowVerificationObligationPolicySchema, + workflowVerificationObligationSourceSchema, + workflowVerificationObligationSchema, workflowBuildOutcomeSchema, verificationVerdictSchema, verificationResultSchema, + resolveWorkflowBuildOwner, + plannedTaskIdFromWorkflowBuildOwner, + isPlannedWorkflowBuildOwner, } from './workflow-loop-state'; export type { @@ -22,6 +31,7 @@ export type { WorkflowLoopSource, RemediationCategory, RemediationMetadata, + WorkflowBuildOwner, WorkflowLoopState, AttemptAction, AttemptResult, @@ -30,6 +40,10 @@ export type { WorkflowVerificationEvidence, WorkflowVerificationReadiness, WorkflowSetupRequirement, + WorkflowVerificationObligationStatus, + WorkflowVerificationObligationPolicy, + WorkflowVerificationObligationSource, + WorkflowVerificationObligation, WorkflowBuildOutcome, VerificationVerdict, VerificationResult, @@ -45,6 +59,13 @@ export { export { formatWorkflowLoopGuidance } from './guidance'; export { WorkflowTaskCoordinator } from './workflow-task-service'; +export { + deriveWorkflowVerificationObligation, + deriveWorkflowVerificationObligationFromOutcome, + isWorkflowVerificationObligationUnsettled, + type DeriveWorkflowVerificationObligationOptions, + type WorkflowVerificationObligationRecord, +} from './verification-obligation'; export { MAX_POST_SUBMIT_REMEDIATION_SUBMITS, MAX_PRE_SAVE_SUBMIT_FAILURES, diff --git a/packages/@n8n/instance-ai/src/workflow-loop/runtime.ts b/packages/@n8n/instance-ai/src/workflow-loop/runtime.ts index 8258e00956b..46bf95e2ebc 100644 --- a/packages/@n8n/instance-ai/src/workflow-loop/runtime.ts +++ b/packages/@n8n/instance-ai/src/workflow-loop/runtime.ts @@ -16,6 +16,8 @@ function createInitialState(threadId: string, outcome: WorkflowBuildOutcome): Wo phase: 'building', status: 'active', source: outcome.workflowId ? 'modify' : 'create', + owner: outcome.owner, + plannedTaskId: outcome.plannedTaskId, rebuildAttempts: 0, preSaveSubmitFailures: 0, postSubmitRemediationSubmitsUsed: 0, @@ -56,7 +58,12 @@ export class WorkflowLoopRuntime { } = handleVerificationVerdict(existing.state, existing.attempts, verdict); if (action.type === 'ignored') return action; - await this.storage.saveWorkItem(threadId, newState, [...existing.attempts, attempt]); + await this.storage.saveWorkItem( + threadId, + newState, + [...existing.attempts, attempt], + existing.lastBuildOutcome, + ); return action; } } diff --git a/packages/@n8n/instance-ai/src/workflow-loop/verification-obligation.ts b/packages/@n8n/instance-ai/src/workflow-loop/verification-obligation.ts new file mode 100644 index 00000000000..55bd12b2aab --- /dev/null +++ b/packages/@n8n/instance-ai/src/workflow-loop/verification-obligation.ts @@ -0,0 +1,208 @@ +import type { + AttemptRecord, + WorkflowBuildOwner, + WorkflowBuildOutcome, + WorkflowLoopState, + WorkflowVerificationObligation, + WorkflowVerificationObligationPolicy, + WorkflowVerificationObligationSource, + WorkflowVerificationObligationStatus, +} from './workflow-loop-state'; +import { + plannedTaskIdFromWorkflowBuildOwner, + resolveWorkflowBuildOwner, +} from './workflow-loop-state'; + +export interface WorkflowVerificationObligationRecord { + state: WorkflowLoopState; + attempts: AttemptRecord[]; + lastBuildOutcome?: WorkflowBuildOutcome; +} + +export interface DeriveWorkflowVerificationObligationOptions { + source?: WorkflowVerificationObligationSource; + owner?: WorkflowBuildOwner; + plannedTaskId?: string; + updatedAt?: string; +} + +const UNSETTLED_OBLIGATION_STATUSES = new Set([ + 'pending_build', + 'ready_to_verify', + 'verifying', +]); + +function hasSuccessfulEvidence(outcome: WorkflowBuildOutcome): boolean { + const nodesNotReached = outcome.verification?.evidence?.nodesNotReached; + return ( + outcome.verification?.attempted === true && + outcome.verification.success && + !!outcome.verification.executionId && + (nodesNotReached === undefined || nodesNotReached.length === 0) + ); +} + +function hasPartialCoverageEvidence(outcome: WorkflowBuildOutcome): boolean { + return (outcome.verification?.evidence?.nodesNotReached?.length ?? 0) > 0; +} + +function hasFailedEvidence(outcome: WorkflowBuildOutcome): boolean { + return outcome.verification?.attempted === true && !outcome.verification.success; +} + +function isNeedsSetupRemediation(remediation: WorkflowBuildOutcome['remediation']): boolean { + return remediation?.category === 'needs_setup' && !remediation.shouldEdit; +} + +function hasSetupBlockingEvidence( + state: WorkflowLoopState, + outcome: WorkflowBuildOutcome, +): boolean { + if (outcome.verificationReadiness?.status === 'needs_setup') return true; + if (isNeedsSetupRemediation(outcome.remediation)) return true; + if (isNeedsSetupRemediation(state.lastRemediation)) return true; + + return outcome.setupRequirement?.status === 'required' && hasFailedEvidence(outcome); +} + +function deriveStatus( + state: WorkflowLoopState, + outcome: WorkflowBuildOutcome | undefined, +): WorkflowVerificationObligationStatus { + if (!outcome) return 'pending_build'; + + if (!outcome.submitted) return 'blocked'; + if (hasSuccessfulEvidence(outcome)) return 'verified'; + if (hasSetupBlockingEvidence(state, outcome)) return 'needs_setup'; + + switch (outcome.verificationReadiness?.status) { + case 'already_verified': + if (hasPartialCoverageEvidence(outcome)) return 'ready_to_verify'; + return 'verified'; + case 'needs_setup': + return 'needs_setup'; + case 'not_verifiable': + return 'not_verifiable'; + case 'ready': + if (state.status === 'blocked') return 'blocked'; + return 'ready_to_verify'; + default: + if (state.status === 'blocked') return 'blocked'; + return outcome.workflowId ? 'ready_to_verify' : 'blocked'; + } +} + +function derivePolicy( + status: WorkflowVerificationObligationStatus, + outcome: WorkflowBuildOutcome | undefined, +): WorkflowVerificationObligationPolicy { + if (status === 'not_verifiable') return 'manual'; + if (outcome?.verificationReadiness?.status === 'not_verifiable') return 'manual'; + return 'required'; +} + +function deriveBlockingReason( + state: WorkflowLoopState, + outcome: WorkflowBuildOutcome | undefined, +): string | undefined { + if (!outcome) return undefined; + if (!outcome.submitted) { + return ( + outcome.blockingReason ?? outcome.failureSignature ?? 'Builder did not submit a workflow.' + ); + } + if (outcome.verificationReadiness?.status === 'not_verifiable') { + return outcome.verificationReadiness.guidance; + } + if (outcome.verificationReadiness?.status === 'needs_setup') { + return outcome.verificationReadiness.guidance; + } + const outcomeRemediation = outcome.remediation; + if (outcomeRemediation?.category === 'needs_setup' && !outcomeRemediation.shouldEdit) { + return outcomeRemediation.guidance; + } + const lastRemediation = state.lastRemediation; + if (lastRemediation?.category === 'needs_setup' && !lastRemediation.shouldEdit) { + return lastRemediation.guidance; + } + if (outcome.setupRequirement?.status === 'required' && hasFailedEvidence(outcome)) { + return outcome.setupRequirement.guidance; + } + if (state.status === 'blocked') { + return state.lastRemediation?.guidance ?? outcome.blockingReason ?? outcome.failureSignature; + } + return undefined; +} + +function lastAttemptTimestamp(attempts: AttemptRecord[]): string | undefined { + return attempts.at(-1)?.createdAt; +} + +export function deriveWorkflowVerificationObligation( + threadId: string, + record: WorkflowVerificationObligationRecord, + options: DeriveWorkflowVerificationObligationOptions = {}, +): WorkflowVerificationObligation { + const outcome = record.lastBuildOutcome; + const status = deriveStatus(record.state, outcome); + const updatedAt = + options.updatedAt ?? lastAttemptTimestamp(record.attempts) ?? new Date().toISOString(); + const owner = resolveWorkflowBuildOwner(options, record.state, outcome); + const plannedTaskId = plannedTaskIdFromWorkflowBuildOwner(owner); + const source = options.source ?? owner.type; + + return { + workItemId: record.state.workItemId, + threadId, + runId: outcome?.runId ?? record.state.runId, + taskId: outcome?.taskId ?? record.state.lastTaskId, + owner, + plannedTaskId, + workflowId: outcome?.workflowId ?? record.state.workflowId, + source, + policy: derivePolicy(status, outcome), + status, + readiness: outcome?.verificationReadiness, + setupRequirement: outcome?.setupRequirement, + evidence: outcome?.verification, + blockingReason: deriveBlockingReason(record.state, outcome), + updatedAt, + }; +} + +export function isWorkflowVerificationObligationUnsettled( + obligation: WorkflowVerificationObligation, +): boolean { + return UNSETTLED_OBLIGATION_STATUSES.has(obligation.status); +} + +/** + * Derive an obligation from a build outcome alone, for callers that have a + * settled build outcome (e.g. a planned task's recorded outcome) but no live + * workflow-loop record to read. Backs the obligation with a minimal synthetic + * state so the same derivation rules apply. + */ +export function deriveWorkflowVerificationObligationFromOutcome( + threadId: string, + outcome: WorkflowBuildOutcome, + options: DeriveWorkflowVerificationObligationOptions = {}, +): WorkflowVerificationObligation { + const state: WorkflowLoopState = { + workItemId: outcome.workItemId, + threadId, + runId: outcome.runId, + workflowId: outcome.workflowId, + lastTaskId: outcome.taskId, + owner: outcome.owner, + plannedTaskId: outcome.plannedTaskId, + phase: 'verifying', + status: 'active', + source: 'create', + rebuildAttempts: 0, + }; + return deriveWorkflowVerificationObligation( + threadId, + { state, attempts: [], lastBuildOutcome: outcome }, + options, + ); +} diff --git a/packages/@n8n/instance-ai/src/workflow-loop/workflow-loop-controller.ts b/packages/@n8n/instance-ai/src/workflow-loop/workflow-loop-controller.ts index 4663c4e4c8d..d991373c16c 100644 --- a/packages/@n8n/instance-ai/src/workflow-loop/workflow-loop-controller.ts +++ b/packages/@n8n/instance-ai/src/workflow-loop/workflow-loop-controller.ts @@ -223,6 +223,7 @@ export function handleVerificationVerdict( const attempt = makeAttempt(normalizedState, 'verify', attempts); attempt.executionId = verdict.executionId; attempt.failureSignature = verdict.failureSignature; + attempt.workflowInspection = verdict.workflowInspection; attempt.diagnosis = verdict.diagnosis; const remediation = withRemainingSubmitFixes( verdict.remediation, @@ -239,6 +240,7 @@ export function handleVerificationVerdict( status: 'blocked', lastExecutionId: verdict.executionId, lastFailureSignature: verdict.failureSignature, + lastWorkflowInspection: verdict.workflowInspection, lastRemediation: remediation, }, action: { type: 'blocked', reason: remediation.guidance }, @@ -255,6 +257,7 @@ export function handleVerificationVerdict( phase: 'done', status: 'completed', lastExecutionId: verdict.executionId, + lastWorkflowInspection: verdict.workflowInspection, lastRemediation: remediation, }, action: { @@ -275,6 +278,7 @@ export function handleVerificationVerdict( ...normalizedState, phase: 'done', status: 'completed', + lastWorkflowInspection: verdict.workflowInspection, lastRemediation: remediation, }, action: { @@ -295,6 +299,7 @@ export function handleVerificationVerdict( ...normalizedState, phase: 'blocked', status: 'blocked', + lastWorkflowInspection: verdict.workflowInspection, lastRemediation: remediation, }, action: { type: 'blocked', reason: verdict.diagnosis ?? 'Needs user input' }, @@ -310,6 +315,7 @@ export function handleVerificationVerdict( phase: 'blocked', status: 'blocked', lastFailureSignature: verdict.failureSignature, + lastWorkflowInspection: verdict.workflowInspection, lastRemediation: remediation, }, action: { type: 'blocked', reason: verdict.summary }, @@ -335,6 +341,7 @@ export function handleVerificationVerdict( const failureDetails = [ verdict.diagnosis ?? '', + verdict.workflowInspection ? `Workflow inspection: ${verdict.workflowInspection}` : '', verdict.failedNodeName ? `Failed node: ${verdict.failedNodeName}` : '', verdict.failureSignature ? `Signature: ${verdict.failureSignature}` : '', ] @@ -377,6 +384,7 @@ function escalateToRepair( phase: 'blocked', status: 'blocked', lastFailureSignature: verdict.failureSignature, + lastWorkflowInspection: verdict.workflowInspection, lastRemediation: blockedRemediation, }, action: { @@ -398,17 +406,27 @@ function escalateToRepair( 'The workflow was saved, but the automatic repair budget is exhausted. Stop editing and explain the blocker to the user.', }); applyRemediationToAttempt(attempt, blockedRemediation); + // Lead the blocked reason with the concrete verification failure, then the + // budget-exhaustion guidance. The guidance alone ("repair budget exhausted, + // stop editing") tells the agent *what to do next* but buries *what went + // wrong* — the agent needs the latter to explain the real blocker to the + // user. Fall back to guidance only when the verdict carries no failure text. + const failureDetail = describeVerificationFailure(verdict); + const reason = failureDetail + ? `${failureDetail} ${blockedRemediation.guidance}` + : blockedRemediation.guidance; return { state: { ...state, phase: 'blocked', status: 'blocked', lastFailureSignature: verdict.failureSignature, + lastWorkflowInspection: verdict.workflowInspection, lastRemediation: blockedRemediation, }, action: { type: 'blocked', - reason: blockedRemediation.guidance, + reason, }, attempt, }; @@ -422,6 +440,7 @@ function escalateToRepair( rebuildAttempts: state.rebuildAttempts + 1, lastFailureSignature: verdict.failureSignature, lastExecutionId: verdict.executionId, + lastWorkflowInspection: verdict.workflowInspection, lastRemediation: remediation, }, action, @@ -458,6 +477,22 @@ function applyRemediationToAttempt( attempt.remediationGuidance = remediation.guidance; } +/** + * Compose a concise, human-readable description of *what* a verification verdict + * found, so blocked actions can surface the concrete failure rather than only + * generic remediation guidance. `summary` is always present; `diagnosis` and + * `failureSignature` are appended when they add information. + */ +function describeVerificationFailure(verdict: VerificationResult): string { + return [ + verdict.summary, + verdict.diagnosis && verdict.diagnosis !== verdict.summary ? verdict.diagnosis : '', + verdict.failureSignature ? `Signature: ${verdict.failureSignature}` : '', + ] + .filter(Boolean) + .join('. '); +} + /** * Check if we've already attempted a repair (patch or rebuild) for the same failure signature. * Returns true when a prior repair attempt exists with the same failureSignature, @@ -496,6 +531,7 @@ export function formatAttemptHistory(attempts: AttemptRecord[]): string { const lines = attempts.map((a) => { let line = `Attempt ${a.attempt} [${a.action}]: ${a.result}`; if (a.failureSignature) line += ` — ${a.failureSignature}`; + if (a.workflowInspection) line += ` | Inspection: ${a.workflowInspection}`; if (a.diagnosis) line += ` | ${a.diagnosis}`; if (a.fixApplied) line += ` | Fix: ${a.fixApplied}`; return line; 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 3f2ec32c2d1..cd027072348 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 @@ -28,6 +28,40 @@ export const remediationMetadataSchema = z.object({ export type RemediationCategory = z.infer; export type RemediationMetadata = z.infer; +// ── WorkflowBuildOwner ────────────────────────────────────────────────────── + +export const workflowBuildOwnerSchema = z.discriminatedUnion('type', [ + z.object({ type: z.literal('direct') }), + z.object({ type: z.literal('planned'), taskId: z.string() }), +]); + +export type WorkflowBuildOwner = z.infer; + +type WorkflowBuildOwnerSource = { + owner?: WorkflowBuildOwner; + plannedTaskId?: string; +}; + +export function resolveWorkflowBuildOwner( + ...sources: Array +): WorkflowBuildOwner { + for (const source of sources) { + if (source?.owner) return source.owner; + if (source?.plannedTaskId) return { type: 'planned', taskId: source.plannedTaskId }; + } + return { type: 'direct' }; +} + +export function plannedTaskIdFromWorkflowBuildOwner( + owner: WorkflowBuildOwner | undefined, +): string | undefined { + return owner?.type === 'planned' ? owner.taskId : undefined; +} + +export function isPlannedWorkflowBuildOwner(owner: WorkflowBuildOwner | undefined): boolean { + return owner?.type === 'planned'; +} + // ── WorkflowLoopState ─────────────────────────────────────────────────────── export const workflowLoopStateSchema = z.object({ @@ -38,9 +72,14 @@ export const workflowLoopStateSchema = z.object({ phase: workflowLoopPhaseSchema, status: workflowLoopStatusSchema, source: workflowLoopSourceSchema, + /** Canonical owner of this workflow build. Defaults to direct for legacy records. */ + owner: workflowBuildOwnerSchema.optional(), + /** Planned task that owns this workflow build, when the build came from an approved plan. */ + plannedTaskId: z.string().optional(), lastTaskId: z.string().optional(), lastExecutionId: z.string().optional(), lastFailureSignature: z.string().optional(), + lastWorkflowInspection: z.string().optional(), rebuildAttempts: z.number().int().min(0), /** Credential types that were mocked during build (persisted across phases). */ mockedCredentialTypes: z.array(z.string()).optional(), @@ -50,6 +89,18 @@ export const workflowLoopStateSchema = z.object({ preSaveSubmitFailures: z.number().int().min(0).optional(), postSubmitRemediationSubmitsUsed: z.number().int().min(0).optional(), lastRemediation: remediationMetadataSchema.optional(), + /** + * Set once the service has routed this work item to post-verification setup. + * Guards the deterministic setup follow-up so it fires at most once per build. + */ + setupRoutedAt: z.string().optional(), + /** + * Short-lived service claim while a setup follow-up run is being started. + * Prevents concurrent scheduler re-entries from opening duplicate setup runs. + */ + setupRoutingClaimId: z.string().optional(), + setupRoutingClaimedAt: z.string().optional(), + setupRoutingClaimExpiresAt: z.string().optional(), }); export type WorkflowLoopPhase = z.infer; @@ -71,6 +122,7 @@ export const attemptRecordSchema = z.object({ workflowId: z.string().optional(), executionId: z.string().optional(), failureSignature: z.string().optional(), + workflowInspection: z.string().optional(), diagnosis: z.string().optional(), fixApplied: z.string().optional(), remediationCategory: remediationCategorySchema.optional(), @@ -101,6 +153,12 @@ export const workflowVerificationEvidenceSchema = z.object({ evidence: z .object({ nodesExecuted: z.array(z.string()).optional(), + /** + * Plan nodes the execution never reached (e.g. a lookup returned zero + * items and stopped the chain). Non-empty means partial coverage — + * checkpoints must not treat the run as full end-to-end evidence. + */ + nodesNotReached: z.array(z.string()).optional(), producedOutputRows: z.number().optional(), errorNodeName: z.string().optional(), errorMessage: z.string().optional(), @@ -155,10 +213,31 @@ export const triggerNodeDescriptorSchema = z.object({ export type TriggerNodeDescriptor = z.infer; +/** + * Per-node execute-vs-simulate verdict for verification runs. Nodes with + * verdict `simulate` are mocked via per-execution pin data so verification + * never performs their real (potentially destructive) operation. + * See `.claude/specs/instance-ai-simulated-verification.md`. + */ +export const nodeSimulationVerdictSchema = z.object({ + nodeName: z.string(), + verdict: z.enum(['simulate', 'execute']), + /** Human-readable rationale — doubles as user-facing labeling copy. */ + reason: z.string(), + confidence: z.enum(['high', 'low']), + source: z.enum(['deterministic', 'llm', 'fallback']), +}); + +export type NodeSimulationVerdict = z.infer; + export const workflowBuildOutcomeSchema = z.object({ workItemId: z.string(), runId: z.string().optional(), taskId: z.string(), + /** Canonical owner of this workflow build. Defaults to direct for legacy outcomes. */ + owner: workflowBuildOwnerSchema.optional(), + /** Planned task that owns this build outcome, when the build came from an approved plan. */ + plannedTaskId: z.string().optional(), workflowId: z.string().optional(), submitted: z.boolean(), triggerType: triggerTypeSchema, @@ -171,16 +250,33 @@ export const workflowBuildOutcomeSchema = z.object({ needsUserInput: z.boolean(), blockingReason: z.string().optional(), failureSignature: z.string().optional(), - /** Node names whose credentials were mocked via pinned data. */ + /** Node names whose credentials were mocked (simulated during verification). */ mockedNodeNames: z.array(z.string()).optional(), /** Credential types that were mocked (not resolved to real credentials). */ mockedCredentialTypes: z.array(z.string()).optional(), /** Map of node name → credential types that were mocked on that node. */ mockedCredentialsByNode: z.record(z.array(z.string())).optional(), - /** Verification-only pin data — scoped to this build, never persisted to workflow. */ + /** + * @deprecated Legacy `{_mockedCredential}` marker channel. No longer + * written — `nodeSimulationPlan` + `simulationFixtures` replaced it. Kept + * in the schema so build outcomes stored before the change still parse and + * verify (verify-built-workflow merges it under the new pin data). + */ verificationPinData: z.record(z.array(z.record(z.unknown()))).optional(), - /** True when mocked credentials can be verified with saved workflow-level pin data. */ + /** @deprecated See `verificationPinData`. No longer written. */ usesWorkflowPinDataForVerification: z.boolean().optional(), + /** + * Per-node execute-vs-simulate plan for verification. Sidecar — scoped to + * this build, never persisted to the workflow. + */ + nodeSimulationPlan: z.array(nodeSimulationVerdictSchema).optional(), + /** + * LLM-generated mock output for `simulate`-verdict nodes, keyed by node + * name. Items are plain objects (no `{json}` envelope) — the shape + * `executionService.run` expects for pin data. Becomes per-execution pin + * data during verification. Sidecar — never persisted to the workflow. + */ + simulationFixtures: z.record(z.array(z.record(z.unknown()))).optional(), /** Draft sub-workflows created by the builder that must publish before the main workflow. */ supportingWorkflowIds: z.array(z.string()).optional(), /** Whether any node parameters contain unresolved placeholder values. */ @@ -205,6 +301,55 @@ export const workflowBuildOutcomeSchema = z.object({ export type TriggerType = z.infer; export type WorkflowBuildOutcome = z.infer; +// ── WorkflowVerificationObligation ───────────────────────────────────────── + +export const workflowVerificationObligationStatusSchema = z.enum([ + 'pending_build', + 'ready_to_verify', + 'verifying', + 'verified', + 'needs_setup', + 'not_verifiable', + 'blocked', +]); + +export const workflowVerificationObligationPolicySchema = z.enum([ + 'required', + 'best_effort', + 'manual', +]); + +export const workflowVerificationObligationSourceSchema = z.enum(['direct', 'planned']); + +export const workflowVerificationObligationSchema = z.object({ + workItemId: z.string(), + threadId: z.string(), + runId: z.string().optional(), + taskId: z.string().optional(), + owner: workflowBuildOwnerSchema.optional(), + plannedTaskId: z.string().optional(), + workflowId: z.string().optional(), + source: workflowVerificationObligationSourceSchema, + policy: workflowVerificationObligationPolicySchema, + status: workflowVerificationObligationStatusSchema, + readiness: workflowVerificationReadinessSchema.optional(), + setupRequirement: workflowSetupRequirementSchema.optional(), + evidence: workflowVerificationEvidenceSchema.optional(), + blockingReason: z.string().optional(), + updatedAt: z.string(), +}); + +export type WorkflowVerificationObligationStatus = z.infer< + typeof workflowVerificationObligationStatusSchema +>; +export type WorkflowVerificationObligationPolicy = z.infer< + typeof workflowVerificationObligationPolicySchema +>; +export type WorkflowVerificationObligationSource = z.infer< + typeof workflowVerificationObligationSourceSchema +>; +export type WorkflowVerificationObligation = z.infer; + // ── VerificationResult ────────────────────────────────────────────────────── export const verificationVerdictSchema = z.enum([ @@ -222,6 +367,7 @@ export const verificationResultSchema = z.object({ workflowId: z.string(), executionId: z.string().optional(), verdict: verificationVerdictSchema, + workflowInspection: z.string().optional(), failureSignature: z.string().optional(), failedNodeName: z.string().optional(), diagnosis: z.string().optional(), diff --git a/packages/@n8n/instance-ai/src/workspace/__tests__/builder-templates-service.test.ts b/packages/@n8n/instance-ai/src/workspace/__tests__/builder-templates-service.test.ts index 2a29b5c4afa..5ea7f6f92f2 100644 --- a/packages/@n8n/instance-ai/src/workspace/__tests__/builder-templates-service.test.ts +++ b/packages/@n8n/instance-ai/src/workspace/__tests__/builder-templates-service.test.ts @@ -117,6 +117,7 @@ function makeOptions( fetchTimeoutMs: 1_000, // Keep retry tests fast; production default is much higher. retryBackoffBaseMs: 1, + logger: { info: vi.fn(), warn: vi.fn(), error: vi.fn(), debug: vi.fn() } as never, ...overrides, }; } @@ -598,6 +599,7 @@ describe('BuilderTemplatesService', () => { describe('builderTemplatesOptionsFromEnv', () => { const ORIGINAL_ENV = { ...process.env }; + const envLogger = { info: vi.fn(), warn: vi.fn(), error: vi.fn(), debug: vi.fn() } as never; afterEach(() => { process.env = { ...ORIGINAL_ENV }; @@ -612,7 +614,7 @@ describe('builderTemplatesOptionsFromEnv', () => { it('parses a valid refresh hours value', () => { clearEnv(); process.env.N8N_INSTANCE_AI_TEMPLATES_REFRESH_HOURS = '6'; - const opts = builderTemplatesOptionsFromEnv(); + const opts = builderTemplatesOptionsFromEnv({ logger: envLogger }); expect(opts.refreshIntervalMs).toBe(6 * 60 * 60 * 1000); }); @@ -631,17 +633,17 @@ describe('builderTemplatesOptionsFromEnv', () => { it('omits refreshIntervalMs when refresh hours is zero or negative', () => { clearEnv(); process.env.N8N_INSTANCE_AI_TEMPLATES_REFRESH_HOURS = '0'; - expect(builderTemplatesOptionsFromEnv().refreshIntervalMs).toBeUndefined(); + expect(builderTemplatesOptionsFromEnv({ logger: envLogger }).refreshIntervalMs).toBeUndefined(); process.env.N8N_INSTANCE_AI_TEMPLATES_REFRESH_HOURS = '-4'; - expect(builderTemplatesOptionsFromEnv().refreshIntervalMs).toBeUndefined(); + expect(builderTemplatesOptionsFromEnv({ logger: envLogger }).refreshIntervalMs).toBeUndefined(); }); it('honours the disabled flag and base URL', () => { clearEnv(); process.env.N8N_INSTANCE_AI_TEMPLATES_DISABLED = 'true'; process.env.N8N_INSTANCE_AI_TEMPLATES_URL = 'https://example.com/v2'; - const opts = builderTemplatesOptionsFromEnv(); + const opts = builderTemplatesOptionsFromEnv({ logger: envLogger }); expect(opts.disabled).toBe(true); expect(opts.cdnBaseUrl).toBe('https://example.com/v2'); }); diff --git a/packages/@n8n/instance-ai/src/workspace/__tests__/create-workspace.test.ts b/packages/@n8n/instance-ai/src/workspace/__tests__/create-workspace.test.ts index 62b8a0e3141..27f4291cb84 100644 --- a/packages/@n8n/instance-ai/src/workspace/__tests__/create-workspace.test.ts +++ b/packages/@n8n/instance-ai/src/workspace/__tests__/create-workspace.test.ts @@ -1,135 +1,101 @@ import { Workspace } from '@n8n/agents'; +import type * as SharedSandboxMod from '@n8n/agents/sandbox'; +import type { SandboxFilesystem, SandboxInstance } from '@n8n/agents/sandbox'; -import { type SandboxConfig, createSandbox, createWorkspace } from '../create-workspace'; -import { DaytonaFilesystem } from '../daytona-filesystem'; -import { DaytonaSandbox } from '../daytona-sandbox'; -import { N8nSandboxFilesystem } from '../n8n-sandbox-filesystem'; -import { N8nSandboxServiceSandbox } from '../n8n-sandbox-sandbox'; +const { + mockCreateSharedSandbox, + mockCreateFilesystem, + mockSnapshotManagerConstructor, + mockSnapshotName, + mockEnsureImage, +} = vi.hoisted(() => ({ + mockCreateSharedSandbox: vi.fn(), + mockCreateFilesystem: vi.fn(), + mockSnapshotManagerConstructor: vi.fn(), + mockSnapshotName: vi.fn(), + mockEnsureImage: vi.fn(), +})); -function getPrivateOptions(value: unknown): Record { - if (!value || typeof value !== 'object') return {}; - const options = (value as Record).options; - return options && typeof options === 'object' ? (options as Record) : {}; -} +vi.mock('@n8n/agents/sandbox', async (importOriginal) => ({ + ...(await importOriginal()), + createSandbox: mockCreateSharedSandbox, + createFilesystem: mockCreateFilesystem, +})); + +vi.mock('../snapshot-manager', () => ({ + SnapshotManager: class { + constructor(baseImage: string | undefined, logger: unknown, n8nVersion: string | undefined) { + mockSnapshotManagerConstructor(baseImage, logger, n8nVersion); + } + + snapshotName = mockSnapshotName; + ensureImage = mockEnsureImage; + }, +})); + +import { + type SandboxConfig, + type InstanceAiCreateSandboxOptions, + createSandbox, + createWorkspace, +} from '../create-workspace'; + +type DaytonaSandboxConfig = Extract; + +const sandbox = { + id: 'sandbox-1', + name: 'Sandbox', + provider: 'daytona', + status: 'running', +} satisfies SandboxInstance; + +const filesystem = { + id: 'filesystem-1', + name: 'Filesystem', + provider: 'daytona', + status: 'ready', + readFile: vi.fn(), + writeFile: vi.fn(), + appendFile: vi.fn(), + deleteFile: vi.fn(), + copyFile: vi.fn(), + moveFile: vi.fn(), + mkdir: vi.fn(), + rmdir: vi.fn(), + readdir: vi.fn(), + exists: vi.fn(), + stat: vi.fn(), +} satisfies SandboxFilesystem; + +const logger = { + info: vi.fn(), + warn: vi.fn(), + error: vi.fn(), + debug: vi.fn(), +}; + +const errorReporter = { + error: vi.fn(), +}; describe('createSandbox', () => { - it('should return undefined when sandbox is disabled', async () => { + beforeEach(() => { + vi.clearAllMocks(); + mockCreateSharedSandbox.mockResolvedValue(sandbox); + mockSnapshotName.mockReturnValue('n8n/instance-ai:1.2.3'); + mockEnsureImage.mockResolvedValue({ dockerfile: 'FROM node:20' }); + }); + + it('returns undefined when sandbox is disabled', async () => { const config: SandboxConfig = { enabled: false, provider: 'n8n-sandbox' }; const result = await createSandbox(config); expect(result).toBeUndefined(); + expect(mockCreateSharedSandbox).not.toHaveBeenCalled(); }); - it('should return a DaytonaSandbox for "daytona" provider', async () => { - const config: SandboxConfig = { - enabled: true, - provider: 'daytona', - id: 'instance-ai-thread-thread-1', - name: 'instance-ai-thread-thread-1', - daytonaApiUrl: 'https://api.daytona.io', - daytonaApiKey: 'test-key', - image: 'node:20', - timeout: 60_000, - createTimeoutSeconds: 900, - }; - - const result = await createSandbox(config); - - expect(result).toBeInstanceOf(DaytonaSandbox); - expect(getPrivateOptions(result)).toEqual( - expect.objectContaining({ - id: 'instance-ai-thread-thread-1', - name: 'instance-ai-thread-thread-1', - apiKey: 'test-key', - apiUrl: 'https://api.daytona.io', - image: 'node:20', - language: 'typescript', - timeout: 60_000, - createTimeoutSeconds: 900, - ephemeral: true, - }), - ); - }); - - it('should preserve Daytona labels and default create timeout', async () => { - const config: SandboxConfig = { - enabled: true, - provider: 'daytona', - daytonaApiKey: 'test-key', - labels: { - 'n8n-builder': 'instance-ai-thread-thread-1', - thread_id: 'thread-1', - run_id: 'run-1', - }, - }; - - const result = await createSandbox(config); - - expect(result).toBeInstanceOf(DaytonaSandbox); - expect(getPrivateOptions(result)).toEqual( - expect.objectContaining({ - createTimeoutSeconds: 300, - ephemeral: true, - labels: { - 'n8n-builder': 'instance-ai-thread-thread-1', - thread_id: 'thread-1', - run_id: 'run-1', - }, - }), - ); - }); - - it('should pass getAuthToken through to DaytonaSandbox in proxy mode (lazy resolution)', async () => { - const getAuthToken = vi.fn().mockResolvedValue('jwt-token-123'); - const config: SandboxConfig = { - enabled: true, - provider: 'daytona', - daytonaApiUrl: 'https://proxy.example.com', - getAuthToken, - timeout: 60_000, - }; - - const result = await createSandbox(config); - - expect(getAuthToken).not.toHaveBeenCalled(); - expect(result).toBeInstanceOf(DaytonaSandbox); - expect(getPrivateOptions(result)).toEqual( - expect.objectContaining({ - apiKey: undefined, - getAuthToken, - apiUrl: 'https://proxy.example.com', - }), - ); - }); - - it('should use default timeout of 300_000 for "daytona" provider when not specified', async () => { - const config: SandboxConfig = { - enabled: true, - provider: 'daytona', - daytonaApiKey: 'test-key', - }; - - const result = await createSandbox(config); - - expect(result).toBeInstanceOf(DaytonaSandbox); - expect(getPrivateOptions(result).timeout).toBe(300_000); - }); - - it('should not include image in DaytonaSandbox config when not specified', async () => { - const config: SandboxConfig = { - enabled: true, - provider: 'daytona', - daytonaApiKey: 'test-key', - }; - - const result = await createSandbox(config); - - expect(result).toBeInstanceOf(DaytonaSandbox); - expect(getPrivateOptions(result)).not.toHaveProperty('image'); - }); - - it('should return an N8nSandboxServiceSandbox for "n8n-sandbox" provider', async () => { + it('delegates n8n-sandbox config to the shared factory without snapshot fallback', async () => { const config: SandboxConfig = { enabled: true, provider: 'n8n-sandbox', @@ -138,44 +104,196 @@ describe('createSandbox', () => { timeout: 45_000, }; - const result = await createSandbox(config); + await expect(createSandbox(config, { logger, errorReporter })).resolves.toBe(sandbox); - expect(result).toBeInstanceOf(N8nSandboxServiceSandbox); - expect(getPrivateOptions(result)).toEqual({ - serviceUrl: 'https://sandbox.example.com', - apiKey: 'sandbox-key', - timeout: 45_000, + expect(mockSnapshotManagerConstructor).not.toHaveBeenCalled(); + expect(mockCreateSharedSandbox).toHaveBeenCalledWith(config, { logger, errorReporter }); + }); + + it('delegates Daytona config when snapshot fallback is not requested', async () => { + const config: SandboxConfig = { + enabled: true, + provider: 'daytona', + daytonaApiUrl: 'https://api.daytona.io', + daytonaApiKey: 'test-key', + image: 'node:20', + timeout: 60_000, + }; + + await expect(createSandbox(config)).resolves.toBe(sandbox); + + expect(mockSnapshotManagerConstructor).not.toHaveBeenCalled(); + const sharedConfig = mockCreateSharedSandbox.mock.calls[0][0] as DaytonaSandboxConfig; + expect(sharedConfig.id).toMatch(/^daytona-sandbox-/); + expect(sharedConfig).toEqual({ + ...config, + id: sharedConfig.id, + labels: { + 'n8n-instance-ai-sandbox-id': sharedConfig.id, + }, }); + expect(mockCreateSharedSandbox).toHaveBeenCalledWith(sharedConfig, { + logger: undefined, + errorReporter: undefined, + }); + }); + + it('prepares image in direct Daytona snapshot fallback mode without a versioned snapshot', async () => { + const config: SandboxConfig = { + enabled: true, + provider: 'daytona', + daytonaApiUrl: 'https://api.daytona.io', + daytonaApiKey: 'test-key', + image: 'node:20', + n8nVersion: '1.2.3', + }; + const options: InstanceAiCreateSandboxOptions = { + logger, + errorReporter, + useSnapshotFallback: true, + }; + + await expect(createSandbox(config, options)).resolves.toBe(sandbox); + + expect(mockSnapshotManagerConstructor).toHaveBeenCalledWith('node:20', logger, '1.2.3'); + expect(mockSnapshotName).not.toHaveBeenCalled(); + expect(mockEnsureImage).toHaveBeenCalledWith(); + const sharedConfig = mockCreateSharedSandbox.mock.calls[0][0] as DaytonaSandboxConfig; + expect(mockCreateSharedSandbox).toHaveBeenCalledWith( + { + enabled: true, + provider: 'daytona', + id: sharedConfig.id, + daytonaApiUrl: 'https://api.daytona.io', + daytonaApiKey: 'test-key', + image: { dockerfile: 'FROM node:20' }, + labels: { + 'n8n-instance-ai-sandbox-id': sharedConfig.id, + }, + }, + { logger, errorReporter }, + ); + }); + + it('uses a no-op logger for snapshot fallback when no logger is provided', async () => { + const config: SandboxConfig = { + enabled: true, + provider: 'daytona', + daytonaApiKey: 'test-key', + n8nVersion: '1.2.3', + }; + + await createSandbox(config, { useSnapshotFallback: true }); + + expect(mockSnapshotManagerConstructor).toHaveBeenCalledWith( + undefined, + expect.anything(), + '1.2.3', + ); + }); + + it('does not pass a Daytona image descriptor back into SnapshotManager as a base image', async () => { + const image = { dockerfile: 'FROM node:20' } as NonNullable; + const config: SandboxConfig = { + enabled: true, + provider: 'daytona', + daytonaApiKey: 'test-key', + image, + n8nVersion: '1.2.3', + }; + + await createSandbox(config, { logger, useSnapshotFallback: true }); + + expect(mockSnapshotManagerConstructor).toHaveBeenCalledWith(undefined, logger, '1.2.3'); + }); + + it('prepares snapshot and image in Daytona proxy snapshot fallback mode', async () => { + const getAuthToken = vi.fn().mockResolvedValue('jwt-token'); + const config: SandboxConfig = { + enabled: true, + provider: 'daytona', + daytonaApiUrl: 'https://proxy.example.com', + getAuthToken, + image: 'node:20', + n8nVersion: '1.2.3', + }; + + await expect( + createSandbox(config, { + logger, + errorReporter, + useSnapshotFallback: true, + }), + ).resolves.toBe(sandbox); + + expect(mockSnapshotName).toHaveBeenCalledWith(); + expect(mockEnsureImage).toHaveBeenCalledWith(); + const sharedConfig = mockCreateSharedSandbox.mock.calls[0][0] as DaytonaSandboxConfig; + expect(mockCreateSharedSandbox).toHaveBeenCalledWith( + { + enabled: true, + provider: 'daytona', + id: sharedConfig.id, + daytonaApiUrl: 'https://proxy.example.com', + getAuthToken, + image: { dockerfile: 'FROM node:20' }, + labels: { + 'n8n-instance-ai-sandbox-id': sharedConfig.id, + }, + snapshot: 'n8n/instance-ai:1.2.3', + }, + { logger, errorReporter }, + ); + }); + + it('preserves explicit Daytona id and labels when delegating', async () => { + const config: SandboxConfig = { + enabled: true, + provider: 'daytona', + id: 'sandbox-id', + daytonaApiKey: 'test-key', + labels: { + team: 'instance-ai', + }, + }; + + await createSandbox(config); + + expect(mockCreateSharedSandbox).toHaveBeenCalledWith( + { + ...config, + labels: { + team: 'instance-ai', + 'n8n-instance-ai-sandbox-id': 'sandbox-id', + }, + }, + { + logger: undefined, + errorReporter: undefined, + }, + ); }); }); describe('createWorkspace', () => { - it('should return undefined when sandbox is undefined', () => { + beforeEach(() => { + vi.clearAllMocks(); + mockCreateFilesystem.mockReturnValue(filesystem); + }); + + it('returns undefined when sandbox is undefined', () => { const result = createWorkspace(undefined); expect(result).toBeUndefined(); + expect(mockCreateFilesystem).not.toHaveBeenCalled(); }); - it('should wrap DaytonaSandbox with DaytonaFilesystem', () => { - const sandbox = new DaytonaSandbox({ apiKey: 'key' }); - + it('wraps a shared sandbox with its shared filesystem', () => { const result = createWorkspace(sandbox); expect(result).toBeInstanceOf(Workspace); expect(result?.sandbox).toBe(sandbox); - expect(result?.filesystem).toBeInstanceOf(DaytonaFilesystem); - }); - - it('should wrap N8nSandboxServiceSandbox with N8nSandboxFilesystem', () => { - const sandbox = new N8nSandboxServiceSandbox({ - apiKey: 'key', - serviceUrl: 'https://sandbox.example.com', - }); - - const result = createWorkspace(sandbox); - - expect(result).toBeInstanceOf(Workspace); - expect(result?.sandbox).toBe(sandbox); - expect(result?.filesystem).toBeInstanceOf(N8nSandboxFilesystem); + expect(result?.filesystem).toBe(filesystem); + expect(mockCreateFilesystem).toHaveBeenCalledWith(sandbox); }); }); 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 b4d797c157e..2613c3af0b6 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 @@ -7,6 +7,8 @@ import { stringifyWorkspaceJson } from '../workspace-file-content'; 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; @@ -62,6 +64,7 @@ describe('loadPrebakedWorkspaceBundle', () => { ); const result = await loadPrebakedWorkspaceBundle({ + logger: mockLogger, workspace, manifestPath, expectedHash: bundle.contentHash, @@ -85,6 +88,7 @@ describe('loadPrebakedWorkspaceBundle', () => { ); const result = await loadPrebakedWorkspaceBundle({ + logger: mockLogger, workspace, manifestPath, expectedHash: bundle.contentHash, @@ -113,6 +117,7 @@ describe('loadPrebakedWorkspaceBundle', () => { ); const result = await loadPrebakedWorkspaceBundle({ + logger: mockLogger, workspace, manifestPath, expectedHash: bundle.contentHash, @@ -148,6 +153,7 @@ describe('materializeWorkspaceBundle', () => { const { workspace, writes } = createSandboxWorkspace(new Map()); const result = await materializeWorkspaceBundle({ + logger: mockLogger, workspace, resourceLabel: 'Test bundle file', loadPrebaked: async () => await Promise.resolve(undefined), @@ -176,6 +182,7 @@ describe('materializeWorkspaceBundle', () => { }; await materializeWorkspaceBundle({ + logger: mockLogger, workspace, resourceLabel: 'Test bundle file', loadPrebaked: async () => await Promise.resolve(undefined), @@ -196,10 +203,12 @@ describe('materializeWorkspaceBundle', () => { ); const result = await materializeWorkspaceBundle({ + logger: mockLogger, workspace, resourceLabel: 'Test bundle file', loadPrebaked: async () => await loadPrebakedWorkspaceBundle({ + logger: mockLogger, workspace, manifestPath, expectedHash: bundle.contentHash, 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 4bdccc5330e..b61eb6a4f65 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 @@ -6,13 +6,13 @@ import type { InstanceAiContext, SearchableNodeDescription } from '../../types'; import type { BuilderTemplatesBundle } from '../builder-templates-service'; import type { SandboxWorkspace } from '../sandbox-fs'; import type { setupSandboxWorkspace as setupSandboxWorkspaceFunction } from '../sandbox-setup'; -import { formatNodeCatalogLine, getPromptWorkspaceRoot, getWorkspaceRoot } from '../sandbox-setup'; +import { formatNodeCatalogLine } from '../sandbox-setup'; type SetupSandboxWorkspace = typeof setupSandboxWorkspaceFunction; type LinkWorkspaceSdkIfEnabled = ( workspace: SandboxWorkspace, root: string, - logger?: { error: Mock; info: Mock }, + logger: { error: Mock; info: Mock; warn: Mock; debug: Mock }, ) => Promise; type RunInSandboxMock = Mock< ( @@ -25,6 +25,7 @@ function createSetupContext( templatesBundle: BuilderTemplatesBundle | null = null, ): InstanceAiContext { return { + logger: { info: vi.fn(), warn: vi.fn(), error: vi.fn(), debug: vi.fn() }, nodeService: { listSearchable: vi.fn().mockResolvedValue([]), }, @@ -56,7 +57,11 @@ function createFilesystemWorkspace( vi.fn<(...args: [string, { recursive?: boolean }?]) => Promise>(async () => {}), }, sandbox: { - executeCommand: vi.fn(), + executeCommand: vi.fn().mockResolvedValue({ + exitCode: 0, + stdout: '/home/daytona\n', + stderr: '', + }), }, }; } @@ -64,15 +69,21 @@ function createFilesystemWorkspace( function createLocalWorkspace( writeFile: Mock<(...args: [string, string | Buffer, { recursive?: boolean }?]) => Promise>, mkdir?: Mock<(...args: [string, { recursive?: boolean }?]) => Promise>, + readFile: Mock<(...args: [string]) => Promise> = vi.fn( + async () => await Promise.reject(new Error('ENOENT')), + ), ): SandboxWorkspace { return { filesystem: { provider: 'local', basePath: '/sandbox', + readFile, writeFile, mkdir: mkdir ?? - vi.fn<(...args: [string, { recursive?: boolean }?]) => Promise>(async () => {}), + vi.fn<(...args: [string, { recursive?: boolean }?]) => Promise>( + async () => await Promise.resolve(), + ), }, }; } @@ -175,7 +186,6 @@ describe('PACKAGE_JSON', () => { expect(packageJson.dependencies.tsx).toBeDefined(); }); }); - describe('setupSandboxWorkspace', () => { afterEach(() => { vi.doUnmock('../sandbox-fs'); @@ -199,7 +209,7 @@ describe('setupSandboxWorkspace', () => { ); const writeFile = vi.fn< (...args: [string, string | Buffer, { recursive?: boolean }?]) => Promise - >(async () => {}); + >(async () => await Promise.resolve()); await setupSandboxWorkspace(createFilesystemWorkspace(writeFile), createSetupContext()); @@ -270,14 +280,20 @@ describe('setupSandboxWorkspace', () => { ); const writeFile = vi.fn< (...args: [string, string | Buffer, { recursive?: boolean }?]) => Promise - >(async () => {}); + >(async () => await Promise.resolve()); + const readFile = vi.fn(async (path: string) => { + if (path === '/sandbox/.sandbox-initialized') { + return await Promise.resolve('2024-01-01T00:00:00.000Z'); + } + return await Promise.reject(new Error(`ENOENT: ${path}`)); + }); const bundle: BuilderTemplatesBundle = { archive: makeBuilderTemplatesTarGz([{ name: 'example-workflow.ts', content: 'export {}' }]), version: 'test-sha', }; const initialized = await setupSandboxWorkspace( - createLocalWorkspace(writeFile), + createLocalWorkspace(writeFile, undefined, readFile), createSetupContext(bundle), ); @@ -327,7 +343,13 @@ describe('setupSandboxWorkspace', () => { ...args: [SandboxWorkspace, string, string?] ) => Promise<{ exitCode: number; stdout: string; stderr: string }> >(); - runInSandbox.mockResolvedValue({ exitCode: 0, stdout: '', stderr: '' }); + runInSandbox.mockImplementation(async (_workspace, command) => { + await Promise.resolve(); + if (command.startsWith('cat ')) { + return { exitCode: 1, stdout: '', stderr: '' }; + } + return { exitCode: 0, stdout: '/home/daytona\n', stderr: '' }; + }); const readFileViaSandbox: ReadFileViaSandboxMock = vi.fn<(...args: [SandboxWorkspace, string]) => Promise>(); readFileViaSandbox.mockResolvedValue(null); @@ -488,13 +510,21 @@ describe('setupSandboxWorkspace', () => { provider: 'daytona', writeFile, }, + sandbox: { + executeCommand: vi.fn().mockResolvedValue({ + exitCode: 0, + stdout: '', + stderr: '', + }), + }, } as unknown as SandboxWorkspace; + const logger = { error: vi.fn(), info: vi.fn(), warn: vi.fn(), debug: vi.fn() }; try { - await expect(linkWorkspaceSdkIfEnabled(workspace, '/workspace')).rejects.toThrow( + await expect(linkWorkspaceSdkIfEnabled(workspace, '/workspace', logger)).rejects.toThrow( 'workspace SDK could not be packed', ); - await linkWorkspaceSdkIfEnabled(workspace, '/workspace'); + await linkWorkspaceSdkIfEnabled(workspace, '/workspace', logger); } finally { if (originalLinkSdk === undefined) { delete process.env.N8N_INSTANCE_AI_SANDBOX_LINK_SDK; @@ -509,37 +539,6 @@ describe('setupSandboxWorkspace', () => { }); }); }); - -describe('getWorkspaceRoot', () => { - it('uses the resolved filesystem base path for lazy workspaces', async () => { - let initialized = false; - const executeCommand = vi.fn(); - const init = vi.fn<(...args: []) => Promise>(async () => { - await Promise.resolve(); - initialized = true; - }); - const workspace = { - filesystem: { - provider: 'lazy', - get basePath() { - return initialized ? '/sandbox' : undefined; - }, - init, - writeFile: vi.fn(), - mkdir: vi.fn(), - }, - sandbox: { - executeCommand, - }, - } as unknown as SandboxWorkspace; - - await expect(getWorkspaceRoot(workspace)).resolves.toBe('/sandbox'); - - expect(init).toHaveBeenCalledTimes(1); - expect(executeCommand).not.toHaveBeenCalled(); - }); -}); - describe('formatNodeCatalogLine', () => { it('should format a basic node with a string version', () => { const node: SearchableNodeDescription = { @@ -662,10 +661,3 @@ describe('formatNodeCatalogLine', () => { expect(result).toBe('n8n-nodes-base.code | Code | Run custom JavaScript code | v2'); }); }); - -describe('getPromptWorkspaceRoot', () => { - it('returns the provider-specific workspace root used in agent prompts', () => { - expect(getPromptWorkspaceRoot('daytona')).toBe('/home/daytona/workspace'); - expect(getPromptWorkspaceRoot('n8n-sandbox')).toBe('/home/user/workspace'); - }); -}); diff --git a/packages/@n8n/instance-ai/src/workspace/__tests__/snapshot-image-context.test.ts b/packages/@n8n/instance-ai/src/workspace/__tests__/snapshot-image-context.test.ts index a0b038a178a..3415ddb19c6 100644 --- a/packages/@n8n/instance-ai/src/workspace/__tests__/snapshot-image-context.test.ts +++ b/packages/@n8n/instance-ai/src/workspace/__tests__/snapshot-image-context.test.ts @@ -53,6 +53,22 @@ describe('snapshot-image-context', () => { ); }); + it('removes stale files when reusing a cache-keyed staging directory', async () => { + const cacheKey = 'cccccccccccc-dddddddddddd'; + const filesWithExtra = new Map([ + [`${WORKSPACE_ROOT}/package.json`, '{"name":"a"}'], + [`${WORKSPACE_ROOT}/skills/removed/SKILL.md`, '# Removed'], + ]); + const filesWithoutExtra = new Map([[`${WORKSPACE_ROOT}/package.json`, '{"name":"b"}']]); + + const first = await stageWorkspaceFilesForImage(filesWithExtra, WORKSPACE_ROOT, cacheKey); + const second = await stageWorkspaceFilesForImage(filesWithoutExtra, WORKSPACE_ROOT, cacheKey); + tempDirs.push(first.stagingDir); + + expect(second.stagingDir).toBe(first.stagingDir); + await expect(access(join(first.stagingDir, 'skills/removed/SKILL.md'))).rejects.toThrow(); + }); + it('disposeSnapshotImageContext removes the staging directory', async () => { const files = new Map([[`${WORKSPACE_ROOT}/build.mjs`, 'export {};']]); const { stagingDir } = await stageWorkspaceFilesForImage(files, WORKSPACE_ROOT); diff --git a/packages/@n8n/instance-ai/src/workspace/__tests__/snapshot-manager.test.ts b/packages/@n8n/instance-ai/src/workspace/__tests__/snapshot-manager.test.ts index 4ea555af8c2..c37bb58e227 100644 --- a/packages/@n8n/instance-ai/src/workspace/__tests__/snapshot-manager.test.ts +++ b/packages/@n8n/instance-ai/src/workspace/__tests__/snapshot-manager.test.ts @@ -1,9 +1,10 @@ /* eslint-disable import-x/order */ +import type * as SharedSandboxMod from '@n8n/agents/sandbox'; import type { Mock } from 'vitest'; // The Daytona SDK is consumed in source via `loadDaytona()` (which `require()`s // @daytonaio/sdk — a path the test runner can't resolve in this monorepo), so we -// mock the first-party `lazy-daytona` module. The mock classes live in vi.hoisted +// mock the shared sandbox module. The mock classes live in vi.hoisted // so they are shared between the mock factory and the test (`instanceof` checks in // source must see the same DaytonaError the test constructs). const { DaytonaError, DaytonaNotFoundError, Image } = vi.hoisted(() => { @@ -44,7 +45,8 @@ const { DaytonaError, DaytonaNotFoundError, Image } = vi.hoisted(() => { return { DaytonaError, DaytonaNotFoundError, Image }; }); -vi.mock('../lazy-daytona', () => ({ +vi.mock('@n8n/agents/sandbox', async (importOriginal) => ({ + ...(await importOriginal()), loadDaytona: () => ({ DaytonaError, DaytonaNotFoundError, Image }), })); @@ -69,7 +71,7 @@ import { join } from 'node:path'; import type { Logger } from '../../logger'; import { SnapshotManager } from '../snapshot-manager'; -const SNAPSHOT_NAME_PATTERN = /^n8n\/instance-ai:1\.123\.0-[a-f0-9]{12}-[a-f0-9]{12}$/; +const SNAPSHOT_NAME = 'n8n/instance-ai:1.123.0'; const SKILLS_HASH_A = 'aaaaaaaaaaaa'; const SKILLS_HASH_B = 'bbbbbbbbbbbb'; @@ -139,13 +141,6 @@ function makeFakeDaytona(): FakeDaytona { }; } -async function knowledgeBaseHash(): Promise { - const { buildKnowledgeBaseWorkspaceBundle } = await import( - '../../knowledge-base/materialize-knowledge-base' - ); - return buildKnowledgeBaseWorkspaceBundle({ root: '/home/daytona/workspace' }).contentHash; -} - describe('SnapshotManager.ensureImage', () => { it('stages workspace files and builds a small COPY-based Daytona image descriptor', async () => { const manager = new SnapshotManager(undefined, NOOP_LOGGER, '1.123.0'); @@ -162,6 +157,7 @@ describe('SnapshotManager.ensureImage', () => { const stagingDir = image.contextList[0]?.sourcePath; expect(stagingDir).toBeDefined(); + expect(stagingDir).toContain('n8n-snapshot-context-1.123.0'); await expect( readFile(join(stagingDir, 'skills/data-table-manager/SKILL.md'), 'utf-8'), ).resolves.toContain('data-table'); @@ -188,37 +184,43 @@ describe('SnapshotManager.ensureImage', () => { ).resolves.toBeDefined(); }); - it('changes the snapshot suffix when the runtime skills hash changes', async () => { + it('uses a content-hash cache key when no n8n version is configured', async () => { + const manager = new SnapshotManager(undefined, NOOP_LOGGER, undefined); + + const image = await manager.ensureImage(); + const stagingDir = image.contextList[0]?.sourcePath; + + expect(stagingDir).toBeDefined(); + expect(stagingDir).not.toContain('n8n-snapshot-context-temp-'); + expect(stagingDir).toMatch(/n8n-snapshot-context-.+-/); + }); + + it('uses the same snapshot name regardless of runtime skills hash', async () => { const daytonaA = makeFakeDaytona(); const daytonaB = makeFakeDaytona(); - daytonaA.snapshot.create.mockResolvedValue({ name: 'ignored-a' }); - daytonaB.snapshot.create.mockResolvedValue({ name: 'ignored-b' }); + daytonaA.snapshot.create.mockResolvedValue({ name: SNAPSHOT_NAME }); + daytonaB.snapshot.create.mockResolvedValue({ name: SNAPSHOT_NAME }); const managerA = new SnapshotManager( undefined, NOOP_LOGGER, '1.123.0', - undefined, createRuntimeSkillSource(SKILLS_HASH_A), ); const managerB = new SnapshotManager( undefined, NOOP_LOGGER, '1.123.0', - undefined, createRuntimeSkillSource(SKILLS_HASH_B), ); const snapshotA = await managerA.createSnapshot(daytonaA as never); const snapshotB = await managerB.createSnapshot(daytonaB as never); - expect(snapshotA).toMatch(SNAPSHOT_NAME_PATTERN); - expect(snapshotB).toMatch(SNAPSHOT_NAME_PATTERN); - expect(snapshotA).toBe(`n8n/instance-ai:1.123.0-${SKILLS_HASH_A}-${await knowledgeBaseHash()}`); - expect(snapshotB).toBe(`n8n/instance-ai:1.123.0-${SKILLS_HASH_B}-${await knowledgeBaseHash()}`); - expect(snapshotA).not.toBe(snapshotB); + expect(snapshotA).toBe(SNAPSHOT_NAME); + expect(snapshotB).toBe(SNAPSHOT_NAME); }); - it('keeps the snapshot suffix stable when the base image changes', async () => { + it('keeps the snapshot name stable when the base image changes', async () => { const daytonaA = makeFakeDaytona(); const daytonaB = makeFakeDaytona(); daytonaA.snapshot.create.mockResolvedValue({ name: 'ignored-a' }); @@ -227,22 +229,20 @@ describe('SnapshotManager.ensureImage', () => { 'daytonaio/sandbox:0.5.0', NOOP_LOGGER, '1.123.0', - undefined, createRuntimeSkillSource(SKILLS_HASH_A), ); const managerB = new SnapshotManager( 'node:24', NOOP_LOGGER, '1.123.0', - undefined, createRuntimeSkillSource(SKILLS_HASH_A), ); const snapshotA = await managerA.createSnapshot(daytonaA as never); const snapshotB = await managerB.createSnapshot(daytonaB as never); - expect(snapshotA).toBe(`n8n/instance-ai:1.123.0-${SKILLS_HASH_A}-${await knowledgeBaseHash()}`); - expect(snapshotB).toBe(snapshotA); + expect(snapshotA).toBe(SNAPSHOT_NAME); + expect(snapshotB).toBe(SNAPSHOT_NAME); expect(daytonaA.snapshot.create.mock.calls[0][0].image.dockerfile).toContain( 'FROM daytonaio/sandbox:0.5.0', ); @@ -258,10 +258,10 @@ describe('SnapshotManager.createSnapshot', () => { const result = await manager.createSnapshot(daytona as never); - expect(result).toMatch(SNAPSHOT_NAME_PATTERN); + expect(result).toBe(SNAPSHOT_NAME); expect(daytona.snapshot.create).toHaveBeenCalledTimes(1); const callArgs = daytona.snapshot.create.mock.calls[0][0]; - expect(callArgs.name).toMatch(SNAPSHOT_NAME_PATTERN); + expect(callArgs.name).toBe(SNAPSHOT_NAME); expect(callArgs.image).toBeDefined(); }); @@ -272,7 +272,7 @@ describe('SnapshotManager.createSnapshot', () => { const result = await manager.createSnapshot(daytona as never); - expect(result).toMatch(SNAPSHOT_NAME_PATTERN); + expect(result).toBe(SNAPSHOT_NAME); }); it('treats messages mentioning "already exists" as success', async () => { @@ -284,7 +284,7 @@ describe('SnapshotManager.createSnapshot', () => { const result = await manager.createSnapshot(daytona as never); - expect(result).toMatch(SNAPSHOT_NAME_PATTERN); + expect(result).toBe(SNAPSHOT_NAME); }); it('throws on transient errors', async () => { @@ -312,135 +312,21 @@ describe('SnapshotManager.createSnapshot', () => { await manager.createSnapshot(daytona as never, { timeout: 1800, onLogs }); const [snapshotParams, options] = daytona.snapshot.create.mock.calls[0]; - expect(snapshotParams.name).toMatch(SNAPSHOT_NAME_PATTERN); + expect(snapshotParams.name).toBe(SNAPSHOT_NAME); expect(options).toMatchObject({ timeout: 1800, onLogs }); }); }); -describe('SnapshotManager.ensureSnapshot', () => { - describe('when no version is provided', () => { - it('returns null without calling daytona', async () => { - const manager = new SnapshotManager(undefined, NOOP_LOGGER, undefined); - const daytona = makeFakeDaytona(); +describe('SnapshotManager.snapshotName', () => { + it('returns null when no version is configured', () => { + const manager = new SnapshotManager(undefined, NOOP_LOGGER, undefined); - const result = await manager.ensureSnapshot(daytona as never, 'direct'); - - expect(result).toBeNull(); - expect(daytona.snapshot.get).not.toHaveBeenCalled(); - expect(daytona.snapshot.create).not.toHaveBeenCalled(); - }); - - it('returns null in proxy mode without calling daytona', async () => { - const manager = new SnapshotManager(undefined, NOOP_LOGGER, undefined); - const daytona = makeFakeDaytona(); - - const result = await manager.ensureSnapshot(daytona as never, 'proxy'); - - expect(result).toBeNull(); - expect(daytona.snapshot.get).not.toHaveBeenCalled(); - }); + expect(manager.snapshotName()).toBeNull(); }); - describe('proxy mode', () => { - it('returns the snapshot name without calling daytona', async () => { - const manager = new SnapshotManager(undefined, NOOP_LOGGER, '1.123.0'); - const daytona = makeFakeDaytona(); + it('returns the versioned snapshot name', () => { + const manager = new SnapshotManager(undefined, NOOP_LOGGER, '1.123.0'); - const result = await manager.ensureSnapshot(daytona as never, 'proxy'); - - expect(result).toMatch(SNAPSHOT_NAME_PATTERN); - expect(daytona.snapshot.get).not.toHaveBeenCalled(); - expect(daytona.snapshot.create).not.toHaveBeenCalled(); - }); - }); - - describe('direct mode', () => { - it('optimistically creates and returns the snapshot name', async () => { - const manager = new SnapshotManager(undefined, NOOP_LOGGER, '1.123.0'); - const daytona = makeFakeDaytona(); - daytona.snapshot.create.mockResolvedValue({ name: 'n8n/instance-ai:1.123.0' }); - - const result = await manager.ensureSnapshot(daytona as never, 'direct'); - - expect(result).toMatch(SNAPSHOT_NAME_PATTERN); - expect(daytona.snapshot.create).toHaveBeenCalledTimes(1); - expect(daytona.snapshot.get).not.toHaveBeenCalled(); - }); - - it('treats 409 conflict as success', async () => { - const manager = new SnapshotManager(undefined, NOOP_LOGGER, '1.123.0'); - const daytona = makeFakeDaytona(); - daytona.snapshot.create.mockRejectedValue(new DaytonaError('already exists', 409)); - - const result = await manager.ensureSnapshot(daytona as never, 'direct'); - - expect(result).toMatch(SNAPSHOT_NAME_PATTERN); - }); - - it('returns null and clears memoization on transient errors', async () => { - const manager = new SnapshotManager(undefined, NOOP_LOGGER, '1.123.0'); - const daytona = makeFakeDaytona(); - daytona.snapshot.create - .mockRejectedValueOnce(new DaytonaError('upstream 500', 500)) - .mockResolvedValueOnce({ name: 'n8n/instance-ai:1.123.0' }); - - const first = await manager.ensureSnapshot(daytona as never, 'direct'); - const second = await manager.ensureSnapshot(daytona as never, 'direct'); - - expect(first).toBeNull(); - expect(second).toMatch(SNAPSHOT_NAME_PATTERN); - expect(daytona.snapshot.create).toHaveBeenCalledTimes(2); - }); - - it('memoizes a successful create — does not call create twice', async () => { - const manager = new SnapshotManager(undefined, NOOP_LOGGER, '1.123.0'); - const daytona = makeFakeDaytona(); - daytona.snapshot.create.mockResolvedValue({ name: 'n8n/instance-ai:1.123.0' }); - - await manager.ensureSnapshot(daytona as never, 'direct'); - const second = await manager.ensureSnapshot(daytona as never, 'direct'); - - expect(second).toMatch(SNAPSHOT_NAME_PATTERN); - expect(daytona.snapshot.create).toHaveBeenCalledTimes(1); - }); - - it('reports transient failures via the error reporter', async () => { - const errorReporter = { error: vi.fn() }; - const manager = new SnapshotManager(undefined, NOOP_LOGGER, '1.123.0', errorReporter); - const daytona = makeFakeDaytona(); - const error = new DaytonaError('upstream 500', 500); - daytona.snapshot.create.mockRejectedValue(error); - - await manager.ensureSnapshot(daytona as never, 'direct'); - - expect(errorReporter.error).toHaveBeenCalledWith( - error, - expect.objectContaining({ - tags: expect.objectContaining({ component: 'snapshot-manager' }) as unknown, - }), - ); - }); - - it('does not report when create succeeds', async () => { - const errorReporter = { error: vi.fn() }; - const manager = new SnapshotManager(undefined, NOOP_LOGGER, '1.123.0', errorReporter); - const daytona = makeFakeDaytona(); - daytona.snapshot.create.mockResolvedValue({ name: 'n8n/instance-ai:1.123.0' }); - - await manager.ensureSnapshot(daytona as never, 'direct'); - - expect(errorReporter.error).not.toHaveBeenCalled(); - }); - - it('does not report 409/already-exists as an error', async () => { - const errorReporter = { error: vi.fn() }; - const manager = new SnapshotManager(undefined, NOOP_LOGGER, '1.123.0', errorReporter); - const daytona = makeFakeDaytona(); - daytona.snapshot.create.mockRejectedValue(new DaytonaError('already exists', 409)); - - await manager.ensureSnapshot(daytona as never, 'direct'); - - expect(errorReporter.error).not.toHaveBeenCalled(); - }); + expect(manager.snapshotName()).toBe(SNAPSHOT_NAME); }); }); diff --git a/packages/@n8n/instance-ai/src/workspace/__tests__/workspace-files.test.ts b/packages/@n8n/instance-ai/src/workspace/__tests__/workspace-files.test.ts index b8d49a42aa7..51bcebf2c4d 100644 --- a/packages/@n8n/instance-ai/src/workspace/__tests__/workspace-files.test.ts +++ b/packages/@n8n/instance-ai/src/workspace/__tests__/workspace-files.test.ts @@ -94,4 +94,29 @@ describe('workspace-files', () => { expect(writes.get('/tmp/b.txt')).toBe('beta'); expect(writes.get('/tmp/c.txt')).toBe('gamma'); }); + + it('logs successful command fallback at warn level', async () => { + const { target } = createWorkspaceTarget(new Map()); + const writeError = new Error('filesystem unavailable'); + target.filesystem = { + writeFile: vi.fn(async () => await Promise.reject(writeError)), + }; + const logger = { + info: vi.fn(), + warn: vi.fn(), + error: vi.fn(), + debug: vi.fn(), + }; + + await writeWorkspaceFile(target, '/tmp/a.txt', 'alpha', { + logger, + resourceLabel: 'Knowledge base file', + }); + + expect(logger.warn).toHaveBeenCalledWith( + 'Knowledge base file filesystem write failed; used command fallback', + expect.objectContaining({ path: '/tmp/a.txt' }), + ); + expect(logger.debug).not.toHaveBeenCalled(); + }); }); diff --git a/packages/@n8n/instance-ai/src/workspace/builder-templates-service.ts b/packages/@n8n/instance-ai/src/workspace/builder-templates-service.ts index 24bc42eeb83..fecd7785bee 100644 --- a/packages/@n8n/instance-ai/src/workspace/builder-templates-service.ts +++ b/packages/@n8n/instance-ai/src/workspace/builder-templates-service.ts @@ -93,8 +93,8 @@ export interface BuilderTemplatesServiceOptions { failureRetryIntervalMs?: number; /** When true, the service short-circuits to an empty bundle and never fetches. */ disabled?: boolean; - /** Optional structured logger. */ - logger?: Logger; + /** Structured logger. */ + logger: Logger; } export interface BuilderTemplatesBundle { @@ -133,14 +133,14 @@ export class BuilderTemplatesService { private readonly retryBackoffBaseMs: number; private readonly failureRetryIntervalMs: number; private readonly disabled: boolean; - private readonly logger?: Logger; + private readonly logger: Logger; private state: CacheState | null = null; private hydratePromise: Promise | null = null; private backgroundRefresh: Promise | null = null; private lastHydrateFailureAt: number | null = null; - constructor(opts: BuilderTemplatesServiceOptions = {}) { + constructor(opts: BuilderTemplatesServiceOptions) { this.cdnBase = (opts.cdnBaseUrl ?? DEFAULT_CDN_BASE_URL).replace(/\/+$/, ''); this.sdkVersion = opts.sdkVersion ?? WORKFLOW_SDK_VERSION; this.versionPrefix = sdkVersionToPrefix(this.sdkVersion); @@ -240,7 +240,7 @@ export class BuilderTemplatesService { const expectedSha = await this.readSha256FromDisk(); if (expectedSha && expectedSha !== actualSha) { - this.logger?.warn('[builder-templates] disk cache sha256 mismatch, dropping cache', { + this.logger.warn('[builder-templates] disk cache sha256 mismatch, dropping cache', { expected: expectedSha, actual: actualSha, }); @@ -253,7 +253,7 @@ export class BuilderTemplatesService { // CDN folder this archive came from, so its etag is unsafe to echo // back in If-None-Match. Drop the cache and let the next refresh // repopulate from scratch. - this.logger?.debug( + this.logger.debug( '[builder-templates] disk cache missing channel.txt, treating as legacy and refetching', ); return null; @@ -268,7 +268,7 @@ export class BuilderTemplatesService { }; } catch (error) { if ((error as NodeJS.ErrnoException).code !== 'ENOENT') { - this.logger?.warn('[builder-templates] failed to load disk cache', { + this.logger.warn('[builder-templates] failed to load disk cache', { error: error instanceof Error ? error.message : String(error), }); } @@ -312,10 +312,9 @@ export class BuilderTemplatesService { let channel: Channel = 'exact'; if (outcome.kind === 'not-found') { - this.logger?.warn( - '[builder-templates] no archive at /v/, falling back to /latest/', - { sdkVersion: this.sdkVersion }, - ); + this.logger.warn('[builder-templates] no archive at /v/, falling back to /latest/', { + sdkVersion: this.sdkVersion, + }); outcome = await this.fetchBundleWithRetries('latest', maxAttempts); channel = 'latest'; } @@ -335,7 +334,7 @@ export class BuilderTemplatesService { channel, }; } catch (error) { - this.logger?.warn('[builder-templates] refresh failed', { + this.logger.warn('[builder-templates] refresh failed', { error: error instanceof Error ? error.message : String(error), }); } @@ -390,7 +389,7 @@ export class BuilderTemplatesService { }); } catch (error) { // Network / abort errors — assume transient. - this.logger?.warn('[builder-templates] archive fetch threw', { + this.logger.warn('[builder-templates] archive fetch threw', { error: error instanceof Error ? error.message : String(error), url: archiveUrl, }); @@ -410,7 +409,7 @@ export class BuilderTemplatesService { } if (!response.ok) { - this.logger?.warn('[builder-templates] archive fetch returned non-OK', { + this.logger.warn('[builder-templates] archive fetch returned non-OK', { status: response.status, url: archiveUrl, }); @@ -422,7 +421,7 @@ export class BuilderTemplatesService { const expectedSha = await this.fetchSha256Sidecar(channel); if (expectedSha && expectedSha !== actualSha) { - this.logger?.warn('[builder-templates] sha256 mismatch on downloaded archive, rejecting', { + this.logger.warn('[builder-templates] sha256 mismatch on downloaded archive, rejecting', { expected: expectedSha, actual: actualSha, url: archiveUrl, @@ -450,14 +449,14 @@ export class BuilderTemplatesService { signal: AbortSignal.timeout(this.fetchTimeoutMs), }); if (response.status === 404) { - this.logger?.warn( + this.logger.warn( '[builder-templates] sha256 sidecar missing — proceeding without integrity check', { url: sha256Url }, ); return null; } if (!response.ok) { - this.logger?.warn( + this.logger.warn( '[builder-templates] sha256 sidecar fetch returned non-OK — proceeding without integrity check', { status: response.status, url: sha256Url }, ); @@ -465,7 +464,7 @@ export class BuilderTemplatesService { } return parseSha256(await response.text()); } catch (error) { - this.logger?.warn( + this.logger.warn( '[builder-templates] sha256 sidecar fetch threw — proceeding without integrity check', { error: error instanceof Error ? error.message : String(error), @@ -589,7 +588,7 @@ async function touchArchiveFile(target: string): Promise { */ export function builderTemplatesOptionsFromEnv({ logger, -}: { logger?: Logger } = {}): BuilderTemplatesServiceOptions { +}: { logger: Logger }): BuilderTemplatesServiceOptions { const url = process.env.N8N_INSTANCE_AI_TEMPLATES_URL; const hoursRaw = process.env.N8N_INSTANCE_AI_TEMPLATES_REFRESH_HOURS; const disabled = process.env.N8N_INSTANCE_AI_TEMPLATES_DISABLED; @@ -597,17 +596,18 @@ export function builderTemplatesOptionsFromEnv({ const refreshIntervalMs = parseRefreshHoursMs(hoursRaw, logger); return { + logger, ...(url ? { cdnBaseUrl: url } : {}), ...(refreshIntervalMs !== null ? { refreshIntervalMs } : {}), disabled: disabled === '1' || disabled?.toLowerCase() === 'true', }; } -function parseRefreshHoursMs(raw: string | undefined, logger?: Logger): number | null { +function parseRefreshHoursMs(raw: string | undefined, logger: Logger): number | null { if (raw === undefined || raw === '') return null; const hours = Number(raw); if (!Number.isFinite(hours) || hours <= 0) { - logger?.warn( + logger.warn( '[builder-templates] ignoring invalid N8N_INSTANCE_AI_TEMPLATES_REFRESH_HOURS, using default', { value: raw }, ); diff --git a/packages/@n8n/instance-ai/src/workspace/create-workspace.ts b/packages/@n8n/instance-ai/src/workspace/create-workspace.ts index 786e5aaaea1..d40801c58ec 100644 --- a/packages/@n8n/instance-ai/src/workspace/create-workspace.ts +++ b/packages/@n8n/instance-ai/src/workspace/create-workspace.ts @@ -1,66 +1,36 @@ -import { Workspace, type WorkspaceFilesystem } from '@n8n/agents'; +import { Workspace } from '@n8n/agents'; +import { + createFilesystem, + createSandbox as createSharedSandbox, + type CreateSandboxOptions, + type DaytonaSandboxConfig, + type DisabledSandboxConfig, + type N8nSandboxConfig, + type SandboxConfig as SharedSandboxConfig, + type SandboxInstance, + type SandboxProvider, +} from '@n8n/agents/sandbox'; +import { randomUUID } from 'node:crypto'; -import type { ErrorReporter, Logger } from '../logger'; -import { DaytonaFilesystem } from './daytona-filesystem'; -import { DaytonaSandbox } from './daytona-sandbox'; -import { loadDaytona } from './lazy-daytona'; -import { N8nSandboxFilesystem } from './n8n-sandbox-filesystem'; -import { N8nSandboxServiceSandbox } from './n8n-sandbox-sandbox'; +import type { Logger } from '../logger'; import { SnapshotManager } from './snapshot-manager'; -export type SandboxProvider = 'daytona' | 'n8n-sandbox'; - -interface SandboxConfigBase { - provider: SandboxProvider; - timeout?: number; -} - -interface DisabledSandboxConfig extends SandboxConfigBase { - enabled: false; -} - -interface DaytonaSandboxConfig extends SandboxConfigBase { - enabled: true; - provider: 'daytona'; - id?: string; - name?: string; - labels?: Record; - daytonaApiUrl?: string; - daytonaApiKey?: string; - image?: string; - /** Running n8n version, used to resolve a versioned prebuilt snapshot (`n8n-instance-ai-`). */ +export type InstanceAiDaytonaSandboxConfig = DaytonaSandboxConfig & { + /** Running n8n version, used to resolve a versioned prebuilt snapshot. */ n8nVersion?: string; - /** Prefix prepended to the Daytona sandbox name; also surfaced as a `name_prefix` label. */ + /** Prefix prepended to the Daytona sandbox name and surfaced as a label. */ namePrefix?: string; - /** - * Seconds to wait for `daytona.create()` (image build + container boot). - * Cold image builds can exceed the SDK default; bump this in environments - * where the image has not been pre-warmed. Defaults to 300 in the factory - * to preserve existing behavior when unset. - */ - createTimeoutSeconds?: number; - /** When provided, called before each Daytona interaction to get a fresh auth token (e.g. a short-lived JWT for proxy mode). */ - getAuthToken?: () => Promise; - /** Optional override (ms) for the JWT refresh skew window. Only used in proxy mode. */ - refreshSkewMs?: number; - /** Optional logger forwarded to the auth manager for refresh-event logging. */ - logger?: Logger; -} +}; -interface N8nSandboxConfig extends SandboxConfigBase { - enabled: true; - provider: 'n8n-sandbox'; - serviceUrl: string; - apiKey?: string; -} +export type InstanceAiSandboxConfig = + | DisabledSandboxConfig + | InstanceAiDaytonaSandboxConfig + | N8nSandboxConfig; -export type SandboxConfig = DisabledSandboxConfig | DaytonaSandboxConfig | N8nSandboxConfig; +export type SandboxConfig = InstanceAiSandboxConfig; +export { type SandboxInstance, type SandboxProvider }; -export type SandboxInstance = DaytonaSandbox | N8nSandboxServiceSandbox; - -export interface CreateSandboxOptions { - logger?: Logger; - errorReporter?: ErrorReporter; +export interface InstanceAiCreateSandboxOptions extends CreateSandboxOptions { useSnapshotFallback?: boolean; } @@ -70,6 +40,33 @@ const NOOP_LOGGER: Logger = { error: () => {}, debug: () => {}, }; +const INSTANCE_AI_SANDBOX_ID_LABEL = 'n8n-instance-ai-sandbox-id'; + +function createSandboxId(): string { + return `daytona-sandbox-${randomUUID()}`; +} + +function toSharedDaytonaSandboxConfig( + config: InstanceAiDaytonaSandboxConfig, +): DaytonaSandboxConfig { + const id = config.id ?? createSandboxId(); + const sharedConfig = { + ...config, + id, + labels: { + ...config.labels, + [INSTANCE_AI_SANDBOX_ID_LABEL]: id, + }, + }; + delete sharedConfig.n8nVersion; + delete sharedConfig.namePrefix; + return sharedConfig; +} + +function toSharedSandboxConfig(config: InstanceAiSandboxConfig): SharedSandboxConfig { + if (!config.enabled || config.provider !== 'daytona') return config; + return toSharedDaytonaSandboxConfig(config); +} /** * Create a sandbox instance based on config. @@ -79,66 +76,40 @@ const NOOP_LOGGER: Logger = { * - 'n8n-sandbox': n8n sandbox service-backed container. */ export async function createSandbox( - config: SandboxConfig, - options: CreateSandboxOptions = {}, + config: InstanceAiSandboxConfig, + options: InstanceAiCreateSandboxOptions = {}, ): Promise { if (!config.enabled) return undefined; - if (config.provider === 'daytona') { - const mode = config.getAuthToken ? 'proxy' : 'direct'; - const logger = options.logger ?? config.logger; - const snapshotManager = options.useSnapshotFallback - ? new SnapshotManager( - config.image, - logger ?? NOOP_LOGGER, - config.n8nVersion, - options.errorReporter, - ) - : undefined; - const snapshot = - snapshotManager && mode === 'direct' - ? await snapshotManager.ensureSnapshot( - new (loadDaytona().Daytona)({ - apiKey: config.daytonaApiKey, - apiUrl: config.daytonaApiUrl, - }), - mode, - ) - : await snapshotManager?.ensureSnapshot(undefined, mode); - const image = snapshotManager ? await snapshotManager.ensureImage() : config.image; - - // Pass the auth source through to the sandbox so it owns the JWT lifecycle: - // proxy mode mints fresh tokens on demand via `getAuthToken`; direct mode uses the static key. - return new DaytonaSandbox({ - id: config.id, - name: config.name, - apiKey: config.getAuthToken ? undefined : config.daytonaApiKey, - getAuthToken: config.getAuthToken, - refreshSkewMs: config.refreshSkewMs, - logger, - apiUrl: config.daytonaApiUrl, - labels: config.labels, - ...(image ? { image } : {}), - ...(snapshot ? { snapshot } : {}), - ephemeral: true, - language: 'typescript', - timeout: config.timeout ?? 300_000, - createTimeoutSeconds: config.createTimeoutSeconds ?? 300, + if (config.provider !== 'daytona' || options.useSnapshotFallback !== true) { + return await createSharedSandbox(toSharedSandboxConfig(config), { + logger: options.logger, errorReporter: options.errorReporter, - createStrategyMode: mode, }); } - if (config.provider === 'n8n-sandbox') { - return new N8nSandboxServiceSandbox({ - apiKey: config.apiKey, - serviceUrl: config.serviceUrl, - timeout: config.timeout ?? 300_000, - }); - } + const logger = options.logger ?? config.logger ?? NOOP_LOGGER; + const snapshotManager = new SnapshotManager( + typeof config.image === 'string' ? config.image : undefined, + logger, + config.n8nVersion, + ); - const exhaustiveProvider: never = config; - throw new Error(`Unsupported sandbox provider: ${JSON.stringify(exhaustiveProvider)}`); + const isProxyMode = config.getAuthToken !== undefined; + const snapshot = isProxyMode ? (snapshotManager.snapshotName() ?? undefined) : undefined; + const image = await snapshotManager.ensureImage(); + + return await createSharedSandbox( + { + ...toSharedDaytonaSandboxConfig(config), + image, + ...(snapshot ? { snapshot } : {}), + }, + { + logger: options.logger, + errorReporter: options.errorReporter, + }, + ); } /** @@ -147,12 +118,10 @@ export async function createSandbox( export function createWorkspace(sandbox: SandboxInstance | undefined): Workspace | undefined { if (!sandbox) return undefined; - const createWorkspaceWithFilesystem = (filesystem: WorkspaceFilesystem) => - new Workspace({ sandbox, filesystem }); + const filesystem = createFilesystem(sandbox); - if (sandbox instanceof N8nSandboxServiceSandbox) { - return createWorkspaceWithFilesystem(new N8nSandboxFilesystem(sandbox)); - } - - return createWorkspaceWithFilesystem(new DaytonaFilesystem(sandbox)); + return new Workspace({ + sandbox, + filesystem, + }); } diff --git a/packages/@n8n/instance-ai/src/workspace/daytona-filesystem.ts b/packages/@n8n/instance-ai/src/workspace/daytona-filesystem.ts deleted file mode 100644 index c3042f71e09..00000000000 --- a/packages/@n8n/instance-ai/src/workspace/daytona-filesystem.ts +++ /dev/null @@ -1,174 +0,0 @@ -/** - * Daytona Filesystem Adapter - * - * Implements a native agents filesystem backed by the Daytona SDK's FileSystem API. - * This gives Daytona workspaces all built-in workspace tools: - * read_file, write_file, edit_file, list_files, grep, ast_edit, etc. - * - * Without this adapter, Daytona workspaces only get sandbox tools (execute_command). - */ - -import type { - FileContent, - FileStat, - FileEntry, - ReadOptions, - WriteOptions, - ListOptions, - RemoveOptions, - CopyOptions, - ProviderStatus, -} from '@n8n/agents'; -import { BaseFilesystem } from '@n8n/agents'; - -import type { DaytonaSandbox } from './daytona-sandbox'; - -/** - * A native agents filesystem implementation that delegates to the Daytona SDK's - * sandbox.instance.fs API for all file operations. - */ -export class DaytonaFilesystem extends BaseFilesystem { - readonly id: string; - readonly name = 'DaytonaFilesystem'; - readonly provider = 'daytona'; - status: ProviderStatus = 'pending'; - - constructor(private readonly sandbox: DaytonaSandbox) { - super(); - this.id = `daytona-fs-${sandbox.id}`; - } - - private get fs() { - return this.sandbox.instance.fs; - } - - private async prepare(): Promise { - // `ensureAuthFresh()` triggers a proactive JWT refresh + sandbox refetch if the - // cached client is near expiry, so `this.fs` (bound to the underlying Sandbox) - // points at a client with valid auth. - await this.ensureReady(); - await this.sandbox.ensureAuthFresh(); - } - - async readFile(path: string, options?: ReadOptions): Promise { - await this.prepare(); - const buffer = await this.fs.downloadFile(path); - if (options?.encoding) { - return buffer.toString(options.encoding); - } - return buffer; - } - - async writeFile(path: string, content: FileContent, options?: WriteOptions): Promise { - await this.prepare(); - if (options?.recursive) { - const dir = path.substring(0, path.lastIndexOf('/')); - if (dir) { - await this.fs.createFolder(dir, '755'); - } - } - const buffer = - typeof content === 'string' ? Buffer.from(content, 'utf-8') : Buffer.from(content); - await this.fs.uploadFile(buffer, path); - } - - async appendFile(path: string, content: FileContent): Promise { - await this.prepare(); - let existing: Buffer; - try { - existing = await this.fs.downloadFile(path); - } catch { - existing = Buffer.alloc(0); - } - const append = - typeof content === 'string' ? Buffer.from(content, 'utf-8') : Buffer.from(content); - await this.fs.uploadFile(Buffer.concat([existing, append]), path); - } - - async deleteFile(path: string, options?: RemoveOptions): Promise { - await this.prepare(); - await this.fs.deleteFile(path, options?.recursive); - } - - async copyFile(src: string, dest: string, _options?: CopyOptions): Promise { - await this.prepare(); - const content = await this.fs.downloadFile(src); - await this.fs.uploadFile(content, dest); - } - - async moveFile(src: string, dest: string, _options?: CopyOptions): Promise { - await this.prepare(); - await this.fs.moveFiles(src, dest); - } - - async mkdir(path: string, options?: { recursive?: boolean }): Promise { - await this.prepare(); - if (options?.recursive) { - // createFolder with mode '755' creates intermediate dirs - await this.fs.createFolder(path, '755'); - } else { - await this.fs.createFolder(path, '755'); - } - } - - async rmdir(path: string, options?: RemoveOptions): Promise { - await this.prepare(); - await this.fs.deleteFile(path, options?.recursive ?? false); - } - - async readdir(path: string, _options?: ListOptions): Promise { - await this.prepare(); - const files = await this.fs.listFiles(path); - return files.map((f) => ({ - name: f.name ?? '', - type: f.isDir ? ('directory' as const) : ('file' as const), - size: f.size, - })); - } - - async exists(path: string): Promise { - await this.prepare(); - try { - await this.fs.getFileDetails(path); - return true; - } catch { - return false; - } - } - - async stat(path: string): Promise { - await this.prepare(); - let info; - try { - info = await this.fs.getFileDetails(path); - } catch (error: unknown) { - if (isDaytona404(error)) { - throw new DaytonaFileNotFoundError(path); - } - throw error; - } - return { - name: info.name ?? path.split('/').pop() ?? '', - path, - type: info.isDir ? 'directory' : 'file', - size: info.size ?? 0, - createdAt: new Date(info.modTime ?? 0), - modifiedAt: new Date(info.modTime ?? 0), - }; - } -} - -class DaytonaFileNotFoundError extends Error { - constructor(path: string) { - super(`File not found: ${path}`); - this.name = 'DaytonaFileNotFoundError'; - } -} - -function isDaytona404(error: unknown): boolean { - return ( - error instanceof Error && - 'statusCode' in error && - (error as { statusCode: unknown }).statusCode === 404 - ); -} 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 953c431f61d..cb283947a47 100644 --- a/packages/@n8n/instance-ai/src/workspace/prebaked-workspace-bundle.ts +++ b/packages/@n8n/instance-ai/src/workspace/prebaked-workspace-bundle.ts @@ -14,7 +14,7 @@ export interface LoadPrebakedWorkspaceBundleOptions { hashField: string; schemaVersion: number; resourceLabel: string; - logger?: Logger; + logger: Logger; invalidManifestLogMessage: string; staleManifestLogMessage: string; staleManifestLogKeys: { @@ -41,14 +41,14 @@ export async function loadPrebakedWorkspaceBundle !check.exists)?.path; if (missingPath) { - options.logger?.debug('Ignoring incomplete prebaked workspace bundle', { + options.logger.debug('Ignoring incomplete prebaked workspace bundle', { manifestPath: options.manifestPath, missingPath, }); return undefined; } - options.logger?.debug(options.successLogMessage, options.successLogContext(bundle)); + options.logger.debug(options.successLogMessage, options.successLogContext(bundle)); return bundle; } @@ -90,7 +90,7 @@ export interface MaterializeWorkspaceBundleOptions< > { workspace: WorkspaceFileTarget; resourceLabel: string; - logger?: Logger; + logger: Logger; loadPrebaked: () => Promise; buildBundle: () => Promise | TBundle; materializedLogMessage: string; @@ -121,6 +121,6 @@ export async function materializeWorkspaceBundle< }); } - options.logger?.debug(options.materializedLogMessage, options.materializedLogContext(bundle)); + options.logger.debug(options.materializedLogMessage, options.materializedLogContext(bundle)); return bundle; } diff --git a/packages/@n8n/instance-ai/src/workspace/sandbox-fs.ts b/packages/@n8n/instance-ai/src/workspace/sandbox-fs.ts index 2c0e3dd5872..27472f0ecaa 100644 --- a/packages/@n8n/instance-ai/src/workspace/sandbox-fs.ts +++ b/packages/@n8n/instance-ai/src/workspace/sandbox-fs.ts @@ -8,41 +8,25 @@ * command fallback keeps setup compatible with command-only providers. */ -interface SandboxCommandResult { - exitCode: number; - stdout: string; - stderr: string; -} +import { + runInSandbox as runInSharedSandbox, + type SandboxCommandTarget, + type SandboxWorkspace as SharedSandboxWorkspace, +} from '@n8n/agents/sandbox'; -interface SandboxCommandTarget { - sandbox?: { - provider?: string; - executeCommand?: ( - command: string, - args?: string[], - options?: { cwd?: string }, - ) => Promise; - processes?: { - spawn: ( - command: string, - options?: { cwd?: string }, - ) => Promise<{ wait: () => Promise }>; - }; - }; -} - -export interface SandboxWorkspace extends SandboxCommandTarget { +export interface SandboxWorkspace extends SharedSandboxWorkspace { filesystem?: { provider?: string; basePath?: string; init?: () => Promise; + readFile?: (path: string, options?: { encoding?: BufferEncoding }) => Promise; writeFile: ( path: string, content: string | Buffer, options?: { recursive?: boolean }, ) => Promise; mkdir: (path: string, options?: { recursive?: boolean }) => Promise; - }; + } & NonNullable; } import { getTemplateTelemetrySession } from './template-telemetry'; @@ -62,20 +46,7 @@ export async function runInSandbox( command: string, cwd?: string, ): Promise<{ exitCode: number; stdout: string; stderr: string }> { - const sandbox = workspace.sandbox; - if (!sandbox) throw new Error('Workspace has no sandbox'); - - let result: { exitCode: number; stdout: string; stderr: string }; - if (sandbox.executeCommand) { - const r = await sandbox.executeCommand(command, [], { cwd }); - result = { exitCode: r.exitCode, stdout: r.stdout, stderr: r.stderr }; - } else if (sandbox.processes) { - const handle = await sandbox.processes.spawn(command, { cwd }); - const r = await handle.wait(); - result = { exitCode: r.exitCode, stdout: r.stdout, stderr: r.stderr }; - } else { - throw new Error('Sandbox has neither executeCommand nor processes available'); - } + const result = await runInSharedSandbox(workspace, command, cwd); const session = getTemplateTelemetrySession(workspace); if (session) { diff --git a/packages/@n8n/instance-ai/src/workspace/sandbox-setup.ts b/packages/@n8n/instance-ai/src/workspace/sandbox-setup.ts index 5275628bc1b..27b3223765f 100644 --- a/packages/@n8n/instance-ai/src/workspace/sandbox-setup.ts +++ b/packages/@n8n/instance-ai/src/workspace/sandbox-setup.ts @@ -29,11 +29,11 @@ * *.ts # SDK workflow examples */ +import { getWorkspaceRoot } from '@n8n/agents/sandbox'; import { createRequire } from 'node:module'; import type { Logger } from '../logger'; import type { InstanceAiContext, SearchableNodeDescription } from '../types'; -import type { SandboxProvider } from './create-workspace'; import { isLinkWorkspaceSdkEnabled, packWorkspaceSdk, @@ -49,12 +49,6 @@ import { import { materializeKnowledgeBaseIntoWorkspace } from '../knowledge-base/materialize-knowledge-base'; const hostRequire = createRequire(__filename); -const NOOP_LOGGER: Logger = { - info: () => {}, - warn: () => {}, - error: () => {}, - debug: () => {}, -}; type SandboxWorkspaceSetupStep = | 'resolve-workspace-root' @@ -88,30 +82,6 @@ async function setupStep(step: SandboxWorkspaceSetupStep, action: () => Promi } } -export const WORKSPACE_DIR = 'workspace'; - -/** Default home directory inside the Daytona sandbox container. */ -export const DAYTONA_HOME = '/home/daytona'; - -/** Absolute workspace root inside the Daytona sandbox container. */ -export const DAYTONA_WORKSPACE_ROOT = `${DAYTONA_HOME}/${WORKSPACE_DIR}`; - -/** Default home directory inside the n8n sandbox service container. */ -export const N8N_SANDBOX_HOME = '/home/user'; - -/** Absolute workspace root inside the n8n sandbox service container. */ -export const N8N_SANDBOX_WORKSPACE_ROOT = `${N8N_SANDBOX_HOME}/${WORKSPACE_DIR}`; - -/** Resolve the `` path shown in agent system prompts for a sandbox provider. */ -export function getPromptWorkspaceRoot(provider: SandboxProvider): string { - switch (provider) { - case 'daytona': - return DAYTONA_WORKSPACE_ROOT; - case 'n8n-sandbox': - return N8N_SANDBOX_WORKSPACE_ROOT; - } -} - /** * Resolve a dependency's installed version from the host's node_modules. * Falls back to `'*'` if the package is unresolvable (should only happen in @@ -236,11 +206,11 @@ let sdkTarballPromise: Promise | null = null; export async function linkWorkspaceSdkIfEnabled( workspace: SandboxWorkspace, root: string, - logger?: Logger, + logger: Logger, ): Promise { if (!isLinkWorkspaceSdkEnabled()) return; - sdkTarballPromise ??= packWorkspaceSdk(logger ?? NOOP_LOGGER).catch((error: unknown) => { + sdkTarballPromise ??= packWorkspaceSdk(logger).catch((error: unknown) => { sdkTarballPromise = null; throw error; }); @@ -265,14 +235,14 @@ export async function linkWorkspaceSdkIfEnabled( root, ); if (install.exitCode !== 0) { - logger?.error('Failed to link workspace SDK into sandbox', { + logger.error('Failed to link workspace SDK into sandbox', { exitCode: install.exitCode, stderr: install.stderr, }); throw new Error(`Failed to install workspace SDK tarball: ${install.stderr}`); } - logger?.info('Linked workspace SDK into sandbox', { + logger.info('Linked workspace SDK into sandbox', { version: packed.version, sdkPath: packed.sdkPath, }); @@ -424,28 +394,21 @@ async function writeWorkspaceFile( } } -/** - * Resolve the absolute workspace root by querying $HOME from the sandbox. - * Caches per workspace instance (WeakMap) so parallel sandboxes don't collide. - */ -const workspaceRootCache = new WeakMap(); - -function getLocalFilesystemRoot(workspace: SandboxWorkspace): string | null { +async function readWorkspaceFile( + workspace: SandboxWorkspace, + path: string, +): Promise { const filesystem = workspace.filesystem; - if (!filesystem) return null; + if (filesystem?.readFile) { + try { + const content = await filesystem.readFile(path, { encoding: 'utf-8' }); + return typeof content === 'string' ? content : content.toString('utf-8'); + } catch { + if (!workspace.sandbox) return null; + } + } - const provider = filesystem.provider; - if (provider !== 'local' && provider !== 'lazy') return null; - - const basePath = Reflect.get(filesystem, 'basePath'); - return typeof basePath === 'string' && basePath.length > 0 ? basePath : null; -} - -async function initializeLazyFilesystem(workspace: SandboxWorkspace): Promise { - const filesystem = workspace.filesystem; - if (filesystem?.provider !== 'lazy') return; - - await filesystem.init?.(); + return await readFileViaSandbox(workspace, path); } async function materializeKnowledgeBaseStep( @@ -464,30 +427,6 @@ async function materializeKnowledgeBaseStep( }); } -export async function getWorkspaceRoot(workspace: SandboxWorkspace): Promise { - const cached = workspaceRootCache.get(workspace); - if (cached) return cached; - - const localRoot = getLocalFilesystemRoot(workspace); - if (localRoot) { - workspaceRootCache.set(workspace, localRoot); - return localRoot; - } - - await initializeLazyFilesystem(workspace); - const initializedLocalRoot = getLocalFilesystemRoot(workspace); - if (initializedLocalRoot) { - workspaceRootCache.set(workspace, initializedLocalRoot); - return initializedLocalRoot; - } - - const result = await runInSandbox(workspace, 'echo $HOME'); - const home = result.stdout.trim() || DAYTONA_HOME; - const root = `${home}/${WORKSPACE_DIR}`; - workspaceRootCache.set(workspace, root); - return root; -} - /** * Initialize the sandbox workspace for the workflow builder agent. * Idempotent — skips if already initialized (checks marker file). @@ -509,7 +448,7 @@ export async function setupSandboxWorkspace( // Check marker file for idempotency const marker = await setupStep( 'read-initialization-marker', - async () => await readFileViaSandbox(workspace, markerFile), + async () => await readWorkspaceFile(workspace, markerFile), ); if (marker !== null) { await materializeKnowledgeBaseStep(workspace, root, context); diff --git a/packages/@n8n/instance-ai/src/workspace/snapshot-image-context.ts b/packages/@n8n/instance-ai/src/workspace/snapshot-image-context.ts index cd8a3b2647e..bc589eef5cd 100644 --- a/packages/@n8n/instance-ai/src/workspace/snapshot-image-context.ts +++ b/packages/@n8n/instance-ai/src/workspace/snapshot-image-context.ts @@ -35,6 +35,7 @@ export async function stageWorkspaceFilesForImage( if (cacheKey) { stagingDir = join(tmpdir(), `${SNAPSHOT_CONTEXT_PREFIX}${cacheKey}`); + await rm(stagingDir, { recursive: true, force: true }); await mkdir(stagingDir, { recursive: true }); } else { stagingDir = await mkdtemp(join(tmpdir(), `${SNAPSHOT_CONTEXT_PREFIX}temp-`)); diff --git a/packages/@n8n/instance-ai/src/workspace/snapshot-manager.ts b/packages/@n8n/instance-ai/src/workspace/snapshot-manager.ts index 8159fcbe5c7..20a7cf78426 100644 --- a/packages/@n8n/instance-ai/src/workspace/snapshot-manager.ts +++ b/packages/@n8n/instance-ai/src/workspace/snapshot-manager.ts @@ -1,18 +1,12 @@ /** * Prepares and caches a Daytona Image descriptor with config files, * node_modules, and runtime skills pre-installed, and resolves a versioned - * named snapshot (`n8n/instance-ai:--`) for sandbox - * creation. + * named snapshot (`n8n/instance-ai:`) for sandbox creation. * - * Two strategies for `ensureSnapshot`: - * - 'direct' mode (self-hosted): optimistic create via `snapshot.create`. - * Treats a 409 / "already exists" response as success. Any other failure - * is reported (when an `errorReporter` is wired) and the manager falls - * back to declarative image so the next request retries the create. - * - 'proxy' mode (cloud): trusts CI to have published the snapshot for - * this version and returns the name without an upstream call. The - * sandbox-create request validates existence; missing-snapshot failures - * surface there with a discriminable Daytona error. + * `snapshotName` derives the versioned snapshot name for the running n8n + * version. CI is the producer of snapshots + * (see `scripts/build-snapshot.cjs`); the sandbox-create request validates + * existence and falls back to the declarative image when missing. * * The node-types catalog is NOT baked into the image (too large for API body limit). * It's written to each sandbox after creation via the filesystem API. @@ -20,24 +14,22 @@ import type { Daytona, DaytonaError as TDaytonaError, Image } from '@daytonaio/sdk'; import type { RuntimeSkillSource } from '@n8n/agents'; +import { DAYTONA_WORKSPACE_ROOT, loadDaytona } from '@n8n/agents/sandbox'; -import { loadDaytona } from './lazy-daytona'; import { buildKnowledgeBaseWorkspaceBundle, type KnowledgeBaseWorkspaceBundle, } from '../knowledge-base/materialize-knowledge-base'; -import type { ErrorReporter, Logger } from '../logger'; +import type { Logger } from '../logger'; import { BuilderTemplatesService, builderTemplatesOptionsFromEnv, } from './builder-templates-service'; -import { DAYTONA_WORKSPACE_ROOT, PACKAGE_JSON, TSCONFIG_JSON, BUILD_MJS } from './sandbox-setup'; +import { PACKAGE_JSON, TSCONFIG_JSON, BUILD_MJS } from './sandbox-setup'; import { disposeSnapshotImageContext, stageWorkspaceFilesForImage } from './snapshot-image-context'; import { buildRuntimeSkillWorkspaceBundle } from '../skills/materialize-runtime-skills'; import { loadInstanceAiRuntimeSkillSource } from '../skills/runtime-skills'; -export type SnapshotMode = 'direct' | 'proxy'; - export interface CreateSnapshotOptions { timeout?: number; onLogs?: (chunk: string) => void; @@ -45,9 +37,6 @@ export interface CreateSnapshotOptions { const DAYTONA_WORKSPACE_BAKE_ROOT = '/tmp/n8n-workspace-bake'; const SNAPSHOT_WORKSPACE_LAYOUT_DIRS = ['src', 'chunks', 'node-types'] as const; -const EMPTY_RUNTIME_SKILLS_HASH = '000000000000'; -const EMPTY_KNOWLEDGE_BASE_HASH = '000000000000'; - function isAlreadyExistsError(error: unknown): error is TDaytonaError { const { DaytonaError } = loadDaytona(); if (!(error instanceof DaytonaError)) return false; @@ -58,10 +47,6 @@ function isAlreadyExistsError(error: unknown): error is TDaytonaError { export class SnapshotManager { private cachedImage: Promise | null = null; - private snapshotPromise: Promise | null = null; - - private snapshotSuffixPromise: Promise | null = null; - private runtimeSkillBundlePromise: ReturnType | null = null; @@ -73,7 +58,6 @@ export class SnapshotManager { private readonly baseImage: string | undefined, private readonly logger: Logger, private readonly n8nVersion: string | undefined, - private readonly errorReporter?: ErrorReporter, private readonly runtimeSkillSource?: RuntimeSkillSource, private readonly templatesService?: BuilderTemplatesService, ) {} @@ -88,7 +72,8 @@ export class SnapshotManager { const base = this.baseImage ?? 'daytonaio/sandbox:0.5.0'; const runtimeSkillBundle = await this.runtimeSkillBundle(); const knowledgeBaseBundle = await this.knowledgeBaseBundle(); - const cacheKey = await this.snapshotSuffix(); + const cacheKey = + this.n8nVersion ?? `${runtimeSkillBundle?.skillsHash}-${knowledgeBaseBundle.contentHash}`; const workspaceFiles = new Map([ ...(runtimeSkillBundle?.files ?? []), @@ -134,12 +119,14 @@ export class SnapshotManager { * version are idempotent. Throws on transient or unexpected errors so * callers can decide whether to retry, fall back, or fail loudly. * - * Single source of truth for snapshot creation across: - * - Runtime direct mode (lazy create on first builder invocation) - * - CI release pipeline (`scripts/build-snapshot.cjs`) + * Single source of truth for snapshot creation in the CI release pipeline + * (`scripts/build-snapshot.cjs`). Runtime never calls this. */ async createSnapshot(daytona: Daytona, options?: CreateSnapshotOptions): Promise { - const name = await this.snapshotName(); + const name = this.snapshotName(); + if (!name) { + throw new Error('SnapshotManager: n8nVersion is required to derive a snapshot name'); + } try { await daytona.snapshot.create({ name, image: await this.ensureImage() }, options); @@ -155,54 +142,13 @@ export class SnapshotManager { } /** - * Resolve the named snapshot for the running n8n version, returning the - * snapshot name if it can be used, or null if the caller should fall back - * to the declarative image. - * - * - 'proxy': returns the name without an upstream call. CI is the only - * producer of cloud snapshots; trusting the name keeps the proxy - * surface minimal (no `snapshot.get` allow-list needed). Existence is - * validated implicitly by the subsequent `daytona.create({ snapshot })`. - * - 'direct': lazy-creates the snapshot via `createSnapshot`, memoized - * per process. On transient failure, clears the memo so the next - * request retries, and reports the error. + * Derive the versioned snapshot name for the running n8n version, or null + * when no version is configured. Existence is validated implicitly by the + * subsequent `daytona.create({ snapshot })`. */ - async ensureSnapshot(daytona: Daytona | undefined, mode: SnapshotMode): Promise { + snapshotName(): string | null { if (!this.n8nVersion) return null; - const name = await this.snapshotName(); - - if (mode === 'proxy') return name; - if (!daytona) { - throw new Error('SnapshotManager: Daytona client is required to create a snapshot'); - } - - this.snapshotPromise ??= this.createSnapshot(daytona).catch((error) => { - this.errorReporter?.error(error, { - tags: { component: 'snapshot-manager', operation: 'create-snapshot' }, - extra: { snapshotName: name }, - }); - this.logger.warn('Failed to create versioned snapshot; using declarative image', { - name, - error: error instanceof Error ? error.message : String(error), - }); - return null; - }); - - const result = await this.snapshotPromise; - if (result === null) this.snapshotPromise = null; - return result; - } - - private async snapshotSuffix(): Promise { - this.snapshotSuffixPromise ??= (async () => { - const runtimeSkillBundle = await this.runtimeSkillBundle(); - const knowledgeBaseBundle = await this.knowledgeBaseBundle(); - const skillsHash = runtimeSkillBundle?.skillsHash ?? EMPTY_RUNTIME_SKILLS_HASH; - const knowledgeBaseHash = knowledgeBaseBundle.contentHash ?? EMPTY_KNOWLEDGE_BASE_HASH; - return `${skillsHash}-${knowledgeBaseHash}`; - })(); - - return await this.snapshotSuffixPromise; + return `n8n/instance-ai:${this.n8nVersion}`; } private async runtimeSkillBundle(): ReturnType { @@ -226,26 +172,17 @@ export class SnapshotManager { new BuilderTemplatesService(builderTemplatesOptionsFromEnv({ logger: this.logger })); const templatesBundle = await templatesService.getBundle(); - return buildKnowledgeBaseWorkspaceBundle({ + return await buildKnowledgeBaseWorkspaceBundle({ root: DAYTONA_WORKSPACE_ROOT, templatesArchive: templatesBundle.archive, logger: this.logger, }); } - private async snapshotName(): Promise { - if (!this.n8nVersion) { - throw new Error('SnapshotManager: n8nVersion is required to derive a snapshot name'); - } - return `n8n/instance-ai:${this.n8nVersion}-${await this.snapshotSuffix()}`; - } - /** Invalidate cached image (e.g., when base image changes). */ invalidate(): void { const stagingDir = this.stagingDir; this.cachedImage = null; - this.snapshotPromise = null; - this.snapshotSuffixPromise = null; this.runtimeSkillBundlePromise = null; this.knowledgeBaseBundlePromise = null; this.stagingDir = null; diff --git a/packages/@n8n/instance-ai/src/workspace/workspace-files.ts b/packages/@n8n/instance-ai/src/workspace/workspace-files.ts index b764b453216..c303c13403d 100644 --- a/packages/@n8n/instance-ai/src/workspace/workspace-files.ts +++ b/packages/@n8n/instance-ai/src/workspace/workspace-files.ts @@ -15,7 +15,7 @@ export interface WorkspaceFileTarget { } export interface WorkspaceFileOptions { - logger?: Logger; + logger: Logger; /** Used in log and error messages, e.g. "Knowledge base file". */ resourceLabel?: string; } @@ -42,7 +42,7 @@ export async function readWorkspaceFile( try { return decodeWorkspaceFileContent(await filesystem.readFile(filePath, { encoding: 'utf-8' })); } catch (error) { - options?.logger?.debug(`${resourceLabel(options)} filesystem read missed`, { + options?.logger.debug(`${resourceLabel(options)} filesystem read missed`, { path: filePath, error: formatErrorForLog(error), }); @@ -55,7 +55,7 @@ export async function readWorkspaceFile( try { return await readFileViaSandbox(workspace, filePath); } catch (error) { - options?.logger?.debug(`${resourceLabel(options)} command read missed`, { + options?.logger.debug(`${resourceLabel(options)} command read missed`, { path: filePath, error: formatErrorForLog(error), }); @@ -82,7 +82,7 @@ export async function writeWorkspaceFile( } catch (error) { try { await writeFileViaSandbox(workspace, filePath, content); - options?.logger?.warn(`${label} filesystem write failed; used command fallback`, { + options?.logger.warn(`${label} filesystem write failed; used command fallback`, { path: filePath, error: formatErrorForLog(error), }); diff --git a/packages/@n8n/instance-ai/tsconfig.build.json b/packages/@n8n/instance-ai/tsconfig.build.json index 3849fc785bd..d73a01a4308 100644 --- a/packages/@n8n/instance-ai/tsconfig.build.json +++ b/packages/@n8n/instance-ai/tsconfig.build.json @@ -3,8 +3,7 @@ "compilerOptions": { "composite": true, "rootDir": "src", - "outDir": "dist", - "tsBuildInfoFile": "dist/build.tsbuildinfo" + "outDir": "dist" }, "include": ["src/**/*.ts"], "exclude": ["src/**/__tests__/**", "src/**/test-utils/**", "**/*.test.ts"] diff --git a/packages/@n8n/instance-ai/tsconfig.json b/packages/@n8n/instance-ai/tsconfig.json index 1d6699a5e8e..04180dd9ab8 100644 --- a/packages/@n8n/instance-ai/tsconfig.json +++ b/packages/@n8n/instance-ai/tsconfig.json @@ -11,7 +11,6 @@ "paths": { "@/*": ["./src/*"] }, - "tsBuildInfoFile": "dist/typecheck.tsbuildinfo", "types": ["node", "vitest/globals"] }, "include": ["src/**/*.ts"] diff --git a/packages/@n8n/instance-ai/vite.config.ts b/packages/@n8n/instance-ai/vite.config.ts index 4705bcdb412..13f0eb8c2f3 100644 --- a/packages/@n8n/instance-ai/vite.config.ts +++ b/packages/@n8n/instance-ai/vite.config.ts @@ -23,6 +23,7 @@ const INDEX_LAZY_REQUIRE_TEST_SPECS = new Set([ './utils/agent-tree', './workspace/builder-templates-service', './workspace/create-workspace', + '@n8n/agents/sandbox', './workspace/lazy-runtime-workspace', './workspace/sandbox-setup', './workspace/snapshot-manager', diff --git a/packages/@n8n/json-schema-to-zod/package.json b/packages/@n8n/json-schema-to-zod/package.json index 5ab946a0339..dbd6995793a 100644 --- a/packages/@n8n/json-schema-to-zod/package.json +++ b/packages/@n8n/json-schema-to-zod/package.json @@ -1,6 +1,6 @@ { "name": "@n8n/json-schema-to-zod", - "version": "1.9.0", + "version": "1.10.0", "description": "Converts JSON schema objects into Zod schemas", "types": "./dist/types/index.d.ts", "main": "./dist/cjs/index.js", @@ -60,7 +60,7 @@ "type": "git", "url": "https://github.com/n8n-io/n8n" }, - "peerDependencies": { + "dependencies": { "zod": "^3.25.76" }, "devDependencies": { diff --git a/packages/@n8n/local-gateway/package.json b/packages/@n8n/local-gateway/package.json index 289ee86e64e..e132d9b9d1c 100644 --- a/packages/@n8n/local-gateway/package.json +++ b/packages/@n8n/local-gateway/package.json @@ -24,6 +24,7 @@ }, "dependencies": { "@n8n/computer-use": "workspace:*", + "electron": "^41.3.0", "electron-store": "^8.2.0" }, "devDependencies": { @@ -34,9 +35,9 @@ "@types/node": "catalog:", "@vitest/coverage-v8": "catalog:", "concurrently": "^8.2.0", - "electron": "^41.3.0", "electron-builder": "^26.9.0", "rimraf": "catalog:", "vitest": "catalog:" - } + }, + "license": "LicenseRef-n8n-sustainable-use" } diff --git a/packages/@n8n/local-gateway/tsconfig.json b/packages/@n8n/local-gateway/tsconfig.json index ddb6a5b3555..6bf5ef2f952 100644 --- a/packages/@n8n/local-gateway/tsconfig.json +++ b/packages/@n8n/local-gateway/tsconfig.json @@ -5,8 +5,7 @@ "types": ["node", "vitest/globals"], "lib": ["es2021", "dom"], "moduleResolution": "nodenext", - "module": "nodenext", - "tsBuildInfoFile": "dist/typecheck.tsbuildinfo" + "module": "nodenext" }, "include": ["src/**/*.ts"] } diff --git a/packages/@n8n/mcp-apps/README.md b/packages/@n8n/mcp-apps/README.md index c7744168461..b382ae34778 100644 --- a/packages/@n8n/mcp-apps/README.md +++ b/packages/@n8n/mcp-apps/README.md @@ -18,9 +18,11 @@ helpers used by `packages/cli` to register them as MCP resources and tools. the host context the MCP client provides at runtime. Today the package ships a single app, `workflow-preview`, which is rendered -after the `create_workflow_from_code` MCP tool returns and gives the user a -button to open the freshly created workflow in n8n. New apps can be added -alongside it (see [Adding a new app](#adding-a-new-app)). +after the `create_workflow_from_code` MCP tool returns. It loads the sanitized +workflow graph through the existing `get_workflow_details` MCP tool, renders the +existing n8n demo canvas in an iframe, and keeps a button to open the freshly +created workflow in n8n. New apps can be added alongside it (see +[Adding a new app](#adding-a-new-app)). ## Package layout @@ -33,7 +35,15 @@ src/ main.ts # mounts App with i18n index.html # entry HTML (built into dist/apps/.html) tokens.scss # design tokens / global styles - url.ts # defense-in-depth URL validation + types.ts # workflow preview data types + type-guards.ts # workflow preview data guards + composables/ + use-workflow-preview.ts # workflow preview state and host tool handling + utils/ + url.ts # defense-in-depth URL validation + components/ # reusable MCP app Vue components + workflow-preview/ # workflow-preview-specific reusable components + composables/ # reusable MCP host/runtime composables i18n/ # vue-i18n setup + host locale resolution locales/ # flat-key locale files (en.json, …) server/ # consumed by packages/cli @@ -42,6 +52,7 @@ src/ register-mcp-app-tool.ts resource-loader.ts # lazy reads built HTML from dist/apps index.ts # public entry: @n8n/mcp-apps/server + utils/ # framework-agnostic client helpers ``` `apps-manifest.ts` is the canonical registry of MCP apps. Both the Vite @@ -63,14 +74,25 @@ Each app: through `onhostcontextchanged` and reflects it on the document. - Reads the originating tool's `structuredContent` via `ontoolresult` to populate its own state. +- Calls `app.callServerTool(...)` when it needs fresh n8n data from the MCP + server. The workflow preview uses this to call `get_workflow_details` with + the created workflow ID. - Calls `app.openLink({ url })` to ask the host to navigate — never opens links itself. URL handling is locked down by `isAllowedWorkflowUrl` in -`src/apps/workflow-preview/url.ts`: only `http(s)://` URLs with a non-empty +`src/apps/workflow-preview/utils/url.ts`: only `http(s)://` URLs with a non-empty host are accepted, both when reading the tool result and right before calling `openLink`. This is defense in depth on top of the host's own validation. +The workflow preview iframe uses a server-provided `previewUrl` when available. +Otherwise it uses the existing n8n preview service because instance routes are +commonly blocked or unreachable from MCP hosts. The resource metadata declares +broad `frameDomains` for `http` and `https` so hosts that enforce MCP Apps CSP +can load instance-specific or configured preview URLs. The framed n8n server's +own frame policy still applies, so the app falls back to the open-workflow +button when the preview cannot load. + ## Internationalization Locale files live under `src/locales/` and use flat, namespaced keys diff --git a/packages/@n8n/mcp-apps/package.json b/packages/@n8n/mcp-apps/package.json index faeace3537b..329029f6a0c 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.2.0", + "version": "0.4.0", "description": "MCP Apps UI resources and server helpers for n8n", "main": "dist/server/index.js", "types": "dist/server/index.d.ts", @@ -36,10 +36,15 @@ "format": "biome format --write src", "format:check": "biome ci src" }, - "devDependencies": { + "dependencies": { "@modelcontextprotocol/ext-apps": "catalog:", - "@modelcontextprotocol/sdk": "catalog:", "@n8n/design-system": "workspace:*", + "@n8n/utils": "workspace:*", + "vue": "catalog:frontend", + "vue-i18n": "catalog:frontend" + }, + "devDependencies": { + "@modelcontextprotocol/sdk": "catalog:", "@n8n/eslint-config": "workspace:*", "@n8n/typescript-config": "workspace:*", "@n8n/vitest-config": "workspace:*", @@ -54,11 +59,10 @@ "vite-plugin-singlefile": "catalog:", "vite-svg-loader": "catalog:frontend", "vitest": "catalog:", - "vue": "catalog:frontend", - "vue-i18n": "catalog:frontend", "vue-tsc": "catalog:frontend" }, "peerDependencies": { "@modelcontextprotocol/sdk": "catalog:" - } + }, + "license": "LicenseRef-n8n-sustainable-use" } diff --git a/packages/@n8n/mcp-apps/src/apps/workflow-preview/App.vue b/packages/@n8n/mcp-apps/src/apps/workflow-preview/App.vue index bbb84bfb6fa..a1a7b6a5b3b 100644 --- a/packages/@n8n/mcp-apps/src/apps/workflow-preview/App.vue +++ b/packages/@n8n/mcp-apps/src/apps/workflow-preview/App.vue @@ -1,140 +1,132 @@ diff --git a/packages/@n8n/mcp-apps/src/components/mcp-fallback-card.vue b/packages/@n8n/mcp-apps/src/components/mcp-fallback-card.vue new file mode 100644 index 00000000000..74f0a2cc903 --- /dev/null +++ b/packages/@n8n/mcp-apps/src/components/mcp-fallback-card.vue @@ -0,0 +1,60 @@ + + + + + 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 new file mode 100644 index 00000000000..958c4f41cf3 --- /dev/null +++ b/packages/@n8n/mcp-apps/src/components/open-in-n8n-button.vue @@ -0,0 +1,32 @@ + + + diff --git a/packages/@n8n/mcp-apps/src/components/workflow-preview/workflow-preview-card.vue b/packages/@n8n/mcp-apps/src/components/workflow-preview/workflow-preview-card.vue new file mode 100644 index 00000000000..9081c3d4db7 --- /dev/null +++ b/packages/@n8n/mcp-apps/src/components/workflow-preview/workflow-preview-card.vue @@ -0,0 +1,228 @@ + + + - {{ props.metadata }} + + {{ props.metadata }} + @@ -107,7 +109,6 @@ function handleClick(e: MouseEvent) { } .metadata { - color: var(--color--text--tint-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; diff --git a/packages/frontend/editor-ui/src/features/ai/instanceAi/components/ConnectionRow.vue b/packages/frontend/editor-ui/src/features/ai/instanceAi/components/ConnectionRow.vue index 676fe40cfae..b0096b95448 100644 --- a/packages/frontend/editor-ui/src/features/ai/instanceAi/components/ConnectionRow.vue +++ b/packages/frontend/editor-ui/src/features/ai/instanceAi/components/ConnectionRow.vue @@ -90,6 +90,7 @@ function handleSelect(action: RowAction) { align-items: center; gap: var(--spacing--xs); padding: var(--spacing--2xs) 0; + margin-left: var(--spacing--2xs); } .iconWrap { diff --git a/packages/frontend/editor-ui/src/features/ai/instanceAi/components/ConnectionsCard.vue b/packages/frontend/editor-ui/src/features/ai/instanceAi/components/ConnectionsCard.vue index d08c5aafe56..52efcc6afb4 100644 --- a/packages/frontend/editor-ui/src/features/ai/instanceAi/components/ConnectionsCard.vue +++ b/packages/frontend/editor-ui/src/features/ai/instanceAi/components/ConnectionsCard.vue @@ -1,6 +1,6 @@ + @@ -400,7 +391,17 @@ const resizable = computed(() => { .composer { display: flex; flex-direction: column; - gap: var(--spacing--xs); + > * + * { + margin-top: var(--spacing--xs); + } +} + +.inputWrapper { + z-index: 1; +} + +.suggestions { + margin-top: var(--spacing--lg); } .attachments { diff --git a/packages/frontend/editor-ui/src/features/ai/instanceAi/components/InstanceAiLlmStepDetail.vue b/packages/frontend/editor-ui/src/features/ai/instanceAi/components/InstanceAiLlmStepDetail.vue new file mode 100644 index 00000000000..6c898544fad --- /dev/null +++ b/packages/frontend/editor-ui/src/features/ai/instanceAi/components/InstanceAiLlmStepDetail.vue @@ -0,0 +1,393 @@ + + + + + diff --git a/packages/frontend/editor-ui/src/features/ai/instanceAi/components/InstanceAiLlmStepsModal.vue b/packages/frontend/editor-ui/src/features/ai/instanceAi/components/InstanceAiLlmStepsModal.vue new file mode 100644 index 00000000000..1c1b12d583b --- /dev/null +++ b/packages/frontend/editor-ui/src/features/ai/instanceAi/components/InstanceAiLlmStepsModal.vue @@ -0,0 +1,490 @@ + + + + + diff --git a/packages/frontend/editor-ui/src/features/ai/instanceAi/components/InstanceAiMarkdown.vue b/packages/frontend/editor-ui/src/features/ai/instanceAi/components/InstanceAiMarkdown.vue index 2bcc570d327..35b78386422 100644 --- a/packages/frontend/editor-ui/src/features/ai/instanceAi/components/InstanceAiMarkdown.vue +++ b/packages/frontend/editor-ui/src/features/ai/instanceAi/components/InstanceAiMarkdown.vue @@ -1,10 +1,19 @@ diff --git a/packages/frontend/editor-ui/src/features/ai/instanceAi/components/InstanceAiPromptSuggestions.vue b/packages/frontend/editor-ui/src/features/ai/instanceAi/components/InstanceAiPromptSuggestions.vue index 17d01888fe1..fc60e43fada 100644 --- a/packages/frontend/editor-ui/src/features/ai/instanceAi/components/InstanceAiPromptSuggestions.vue +++ b/packages/frontend/editor-ui/src/features/ai/instanceAi/components/InstanceAiPromptSuggestions.vue @@ -14,7 +14,7 @@ const props = defineProps<{ disabled: boolean; }>(); -interface SubmitSuggestionPayload { +interface InsertSuggestionPayload { promptKey: BaseTextKey; suggestionId: string; suggestionKind: 'prompt' | 'quick_example'; @@ -24,7 +24,7 @@ interface SubmitSuggestionPayload { const emit = defineEmits<{ 'preview-change': [promptKey: BaseTextKey | null]; 'quick-examples-opened': [payload: { suggestionId: string; position: number }]; - 'submit-suggestion': [payload: SubmitSuggestionPayload]; + 'insert-suggestion': [payload: InsertSuggestionPayload]; }>(); const i18n = useI18n(); @@ -70,13 +70,13 @@ function getQuickExamplePosition(exampleId: string) { return index >= 0 ? index + 1 : 0; } -function submitSuggestion(payload: SubmitSuggestionPayload) { +function insertSuggestion(payload: InsertSuggestionPayload) { if (props.disabled) { return; } closeQuickExamples(); - emit('submit-suggestion', payload); + emit('insert-suggestion', payload); } function handleDocumentKeydown(event: KeyboardEvent) { @@ -142,7 +142,7 @@ function handleSuggestionClick(suggestion: InstanceAiEmptyStateSuggestion) { clearHoverTimer(); if (isPromptSuggestion(suggestion)) { - submitSuggestion({ + insertSuggestion({ promptKey: suggestion.promptKey, suggestionId: suggestion.id, suggestionKind: 'prompt', @@ -251,7 +251,7 @@ function handleQuickExampleLeave() { :data-test-id="`instance-ai-quick-example-${example.id}`" :disabled="props.disabled" @click=" - submitSuggestion({ + insertSuggestion({ promptKey: example.promptKey, suggestionId: example.id, suggestionKind: 'quick_example', diff --git a/packages/frontend/editor-ui/src/features/ai/instanceAi/components/InstanceAiRunWorkflowCodeSection.vue b/packages/frontend/editor-ui/src/features/ai/instanceAi/components/InstanceAiRunWorkflowCodeSection.vue new file mode 100644 index 00000000000..62c4a455def --- /dev/null +++ b/packages/frontend/editor-ui/src/features/ai/instanceAi/components/InstanceAiRunWorkflowCodeSection.vue @@ -0,0 +1,136 @@ + + + + + diff --git a/packages/frontend/editor-ui/src/features/ai/instanceAi/components/InstanceAiStatusBar.vue b/packages/frontend/editor-ui/src/features/ai/instanceAi/components/InstanceAiStatusBar.vue index 5b3d6532e22..d17432f587f 100644 --- a/packages/frontend/editor-ui/src/features/ai/instanceAi/components/InstanceAiStatusBar.vue +++ b/packages/frontend/editor-ui/src/features/ai/instanceAi/components/InstanceAiStatusBar.vue @@ -5,6 +5,7 @@ import { N8nIcon } from '@n8n/design-system'; import type { InstanceAiMessage } from '@n8n/api-types'; import { useThread } from '../instanceAi.store'; import { useToolLabel } from '../toolLabels'; +import { collectActiveBuilderAgents, isActiveBuilderAgent } from '../builderAgents'; const thread = useThread(); const i18n = useI18n(); @@ -18,7 +19,16 @@ const ROLE_LABELS: Record = { }; function deriveActivity(messages: InstanceAiMessage[]): { label: string; detail?: string } | null { - const lastMsg = [...messages].reverse().find((m) => m.role === 'assistant' && m.isStreaming); + // Match the still-streaming orchestrator message, or — once it has handed off + // to a background builder — the message that owns the active builder, so the + // label keeps tracking work after `isStreaming` flips false. + const lastMsg = [...messages] + .reverse() + .find( + (m) => + m.role === 'assistant' && + (m.isStreaming || (m.agentTree?.children.some(isActiveBuilderAgent) ?? false)), + ); if (!lastMsg?.agentTree) return { label: i18n.baseText('instanceAi.statusBar.thinking') }; const tree = lastMsg.agentTree; @@ -52,7 +62,11 @@ const activity = computed(() => { return deriveActivity(thread.messages); }); -const isVisible = computed(() => thread.isStreaming); +// Stay visible while the orchestrator streams, and also while a builder runs in +// the background after the orchestrator run has ended (isStreaming === false). +const isVisible = computed( + () => thread.isStreaming || collectActiveBuilderAgents(thread.messages).length > 0, +); const formattedElapsed = computed(() => { const s = elapsed.value; @@ -93,30 +107,28 @@ onUnmounted(() => { diff --git a/packages/frontend/editor-ui/src/features/ai/instanceAi/components/InstanceAiViewHeader.vue b/packages/frontend/editor-ui/src/features/ai/instanceAi/components/InstanceAiViewHeader.vue index a245cf88990..fd25a6e8fab 100644 --- a/packages/frontend/editor-ui/src/features/ai/instanceAi/components/InstanceAiViewHeader.vue +++ b/packages/frontend/editor-ui/src/features/ai/instanceAi/components/InstanceAiViewHeader.vue @@ -45,6 +45,7 @@ const isReadOnlyEnvironment = computed(() => sourceControlStore.preferences.bran :credits-remaining="store.creditsRemaining" :credits-quota="store.creditsQuota" :is-low-credits="store.isLowCredits" + button-size="small" @upgrade-click="goToUpgrade('instance-ai', 'upgrade-instance-ai')" /> diff --git a/packages/frontend/editor-ui/src/features/ai/instanceAi/components/InstanceAiWorkflowPreview.vue b/packages/frontend/editor-ui/src/features/ai/instanceAi/components/InstanceAiWorkflowPreview.vue index 8d68c0428cf..a7ad6417cc7 100644 --- a/packages/frontend/editor-ui/src/features/ai/instanceAi/components/InstanceAiWorkflowPreview.vue +++ b/packages/frontend/editor-ui/src/features/ai/instanceAi/components/InstanceAiWorkflowPreview.vue @@ -1,12 +1,19 @@ diff --git a/packages/frontend/editor-ui/src/features/ai/instanceAi/components/ToolResultMedia.vue b/packages/frontend/editor-ui/src/features/ai/instanceAi/components/ToolResultImage.vue similarity index 100% rename from packages/frontend/editor-ui/src/features/ai/instanceAi/components/ToolResultMedia.vue rename to packages/frontend/editor-ui/src/features/ai/instanceAi/components/ToolResultImage.vue diff --git a/packages/frontend/editor-ui/src/features/ai/instanceAi/components/ToolResultRenderer.vue b/packages/frontend/editor-ui/src/features/ai/instanceAi/components/ToolResultRenderer.vue index ad028627710..4db4f39de3a 100644 --- a/packages/frontend/editor-ui/src/features/ai/instanceAi/components/ToolResultRenderer.vue +++ b/packages/frontend/editor-ui/src/features/ai/instanceAi/components/ToolResultRenderer.vue @@ -4,7 +4,8 @@ import type { McpToolCallResult } from '@n8n/api-types'; import ToolResultJson from './ToolResultJson.vue'; import ToolResultTable from './ToolResultTable.vue'; import ToolResultCode from './ToolResultCode.vue'; -import ToolResultMedia from './ToolResultMedia.vue'; +import ToolResultImage from './ToolResultImage.vue'; +import ToolResultFile from './ToolResultFile.vue'; import ToolResultText from './ToolResultText.vue'; const props = defineProps<{ @@ -52,6 +53,21 @@ function normalizeContentItem(item: unknown): McpContentItem | null { if (item.type === 'text' && typeof item.text === 'string') { return { type: 'text', text: item.text }; } + if ( + item.type === 'file-data' && + typeof item.mediaType === 'string' && + typeof item.data === 'string' && + !item.mediaType.startsWith('image/') + ) { + return { + type: 'resource', + resource: { + uri: '', + blob: item.data as string, + mimeType: item.mediaType, + }, + }; + } return normalizeImageContentItem(item); } @@ -149,7 +165,12 @@ const tableRows = computed(() => extractTableRows(props.result));