{"_id":"@diagrid/n8n","_rev":"3-1ca23cc14926ae20d54ee0bc4e103d86","name":"@diagrid/n8n","dist-tags":{"latest":"0.2.0"},"versions":{"0.1.0":{"name":"@diagrid/n8n","version":"0.1.0","keywords":["dapr","workflow","durable","n8n","automation","diagrid"],"author":{"name":"Diagrid Inc."},"license":"BUSL-1.1","_id":"@diagrid/n8n@0.1.0","maintainers":[{"name":"casperwmn","email":"whopsec@protonmail.com"}],"homepage":"https://github.com/diagridio/typescript-ai#readme","bugs":{"url":"https://github.com/diagridio/typescript-ai/issues"},"dist":{"shasum":"601b3a432c92b59a26a1324b8f47953cb50abe13","tarball":"https://registry.npmjs.org/@diagrid/n8n/-/n8n-0.1.0.tgz","fileCount":17,"integrity":"sha512-9s2s+SVNgAvYFJ0b+Iz1jrH9v+qaGG4qJZFFvFWggswhRNsagtotKy0ftJ1cWXc2zAgyKT1hS/Dc3Hm2yoqbMg==","signatures":[{"sig":"MEUCIQCsIGBsOuZIOGpVBCoGUesWMpokgZ/8NPkkugyc0r3akwIgQnVKLjpj66SEAbbRy4cooy6ndFxSkBZZsdNKIgdhHbw=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":755675},"main":"./dist/index.cjs","type":"module","_from":"file:packages/n8n/diagrid-n8n-0.1.0.tgz","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=22.13.0"},"exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"require":{"types":"./dist/index.d.cts","default":"./dist/index.cjs"}},"./register":{"import":{"types":"./dist/preload.d.ts","default":"./dist/preload.js"},"require":{"types":"./dist/preload.d.cts","default":"./dist/preload.cjs"}},"./package.json":"./package.json"},"scripts":{"build":"tsup","clean":"node -e \"require('node:fs').rmSync('dist',{recursive:true,force:true})\""},"_npmUser":{"name":"casperwmn","email":"whopsec@protonmail.com"},"_resolved":"/Users/caspernielsen/workspace/typescript-ai/packages/n8n/diagrid-n8n-0.1.0.tgz","_integrity":"sha512-9s2s+SVNgAvYFJ0b+Iz1jrH9v+qaGG4qJZFFvFWggswhRNsagtotKy0ftJ1cWXc2zAgyKT1hS/Dc3Hm2yoqbMg==","repository":{"url":"git+https://github.com/diagridio/typescript-ai.git","type":"git","directory":"packages/n8n"},"_npmVersion":"11.6.2","description":"Durable execution of n8n workflow node runs on Dapr Workflows","directories":{},"sideEffects":["./dist/preload.js","./dist/preload.cjs"],"_nodeVersion":"24.11.1","dependencies":{"@dapr/dapr":"3.18.0","@diagrid/agent-core":"0.1.0"},"publishConfig":{"access":"public","provenance":true},"_hasShrinkwrap":false,"devDependencies":{"zod":"4.4.3","tsup":"8.5.1","typescript":"6.0.3"},"peerDependencies":{"zod":"^4.0.0","@n8n/db":"*","@n8n/di":"*","n8n-core":"*","n8n-workflow":"*","n8n-nodes-base":"*"},"//devDependencies":["n8n-core/n8n-workflow/n8n-nodes-base/@n8n/db/@n8n/di are real peer","dependencies (see peerDependencies above) but are deliberately NOT listed","here as file: devDependencies pointing at the sibling n8n checkout: n8n's","own packages depend on ~20 further n8n-internal packages via workspace:*","(@n8n/backend-common, @n8n/config, n8n-workflow, ...), which only resolves","inside n8n's OWN pnpm workspace. Pointing a file: dependency at them from","this workspace makes pnpm try (and fail) to resolve those same specifiers","here, breaking `pnpm install` for the whole repo, not just this package.","See scripts/link-n8n-dev-deps.sh (in this package) and README.md's","'Developing against a local n8n checkout' section for how this","package's node_modules gets real","n8n type/runtime resolution instead: direct symlinks into","packages/n8n/node_modules, bypassing pnpm's own dependency graph for","exactly these five packages, the same way a real n8n install's own","node_modules is what actually satisfies these peers at runtime.","","A real, PUBLISHED-npm-version devDependency (not a file: link) for","n8n-core/n8n-workflow/@n8n/db/@n8n/di specifically — the four peers this","package actually has a static `import` for, so typecheck (not runtime)","would work in a from-scratch checkout with no sibling n8n repo at all","(CI included) — was investigated and reverted, not just skipped. It","resolved and installed, but hit two real, separate problems: (1) their","own transitive dependencies (n8n-core's isolated-vm/ssh2/cpu-features,","Sentry's native profiler) trip pnpm's allowBuilds gate — workable, by","setting those `false` (declined, not silently ignored) rather than","expanding the workspace's real native-build-script surface just for","types; but then (2) pnpm resolves n8n-workflow into two STRUCTURALLY","DIFFERENT peer-hashed instances (n8n-core's own copy vs @n8n/db's own","copy) when these packages are installed as independent top-level","devDependencies outside n8n's own cohesive workspace — TypeScript then","sees e.g. `INode` from one instance as a different nominal type than","`INode` from the other, producing real 'not assignable' errors across","this package's own files that have nothing to do with an actual bug.","That is a structural consequence of installing n8n's own","tightly-interdependent packages outside n8n's own workspace, not","something a version pin or a pnpm override can safely paper over without","significant, fragile upkeep.","","What actually resolves this for CI (and for anyone without a sibling","checkout) is scripts/ci-n8n-types.sh: a pinned, disposable n8n checkout","(n8n-ci-ref.txt), scoped-installed and scoped-built to just the closure","these four peers need, then symlinked in exactly like","link-n8n-dev-deps.sh does for a live one — never copied; a copy would","carry n8n-core's own internal symlink to n8n-workflow along with it and,","if dereferenced, reproduce the exact dual-instance problem above by a","different route. See README.md's 'CI has no sibling checkout of its","own' section for the full account, including why this is not a","substitute for a live checkout (it's read-only and pinned, not meant to","be developed against)."],"peerDependenciesMeta":{"@n8n/db":{"optional":true},"@n8n/di":{"optional":true},"n8n-core":{"optional":true},"n8n-workflow":{"optional":true},"n8n-nodes-base":{"optional":true}},"//peerDependenciesMeta":["`optional: true` here is a pnpm-install-time workaround, not a real","statement that this package works without these five peers — it does","not. Without it, pnpm's autoInstallPeers tries to satisfy the bare `*`","peer range by fetching the REAL published n8n-nodes-base from npm (a","different, unrelated version from this workspace's own local n8n","checkout), which pulls in xlsx via a non-standard URL and trips this","repo's own blockExoticSubdeps supply-chain policy. `optional: true`","stops that auto-install attempt; the real, correct versions still come","from the sibling n8n checkout via scripts/link-n8n-dev-deps.sh."],"_npmOperationalInternal":{"tmp":"tmp/n8n_0.1.0_1789076331104_0.42336876624176134","host":"s3://npm-registry-packages-npm-production"}},"0.1.1":{"name":"@diagrid/n8n","version":"0.1.1","keywords":["dapr","workflow","durable","n8n","automation","diagrid"],"author":{"name":"Diagrid Inc."},"license":"BUSL-1.1","_id":"@diagrid/n8n@0.1.1","maintainers":[{"name":"casperwmn","email":"whopsec@protonmail.com"}],"homepage":"https://github.com/diagridio/typescript-ai#readme","bugs":{"url":"https://github.com/diagridio/typescript-ai/issues"},"dist":{"shasum":"4947fd558abd6b901d22fb67cc75b305b51eef62","tarball":"https://registry.npmjs.org/@diagrid/n8n/-/n8n-0.1.1.tgz","fileCount":17,"integrity":"sha512-nJDX6g0OQdKOe33kQ/piKrZdM0ssqYu/OeK/v4LV/zy8ER2yTCIiN8fi0gA8NPNwpGfF4hTCCoSV+3m7iBgbmA==","signatures":[{"sig":"MEQCIAQq3ct2Xt9jbu+DixHYnunvnILIA86h/55FRU4QLn9CAiAiA0oDJ+7lt6sJZU3W5E00lmEHVZAN1/llGQksZ/I97Q==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEYCIQCrZD2Ji+/8eRzGgRDu7uDC0YfjB4qp1NajacLrrkpLfQIhAOVX2G8LQatwfydwv+9uFKepTIWNM0GKGGq3X6jbGzw7","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@diagrid%2fn8n@0.1.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":755675},"main":"./dist/index.cjs","type":"module","_from":"file:dist-packs/diagrid-n8n-0.1.1.tgz","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=22.13.0"},"exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"require":{"types":"./dist/index.d.cts","default":"./dist/index.cjs"}},"./register":{"import":{"types":"./dist/preload.d.ts","default":"./dist/preload.js"},"require":{"types":"./dist/preload.d.cts","default":"./dist/preload.cjs"}},"./package.json":"./package.json"},"scripts":{"build":"tsup","clean":"node -e \"require('node:fs').rmSync('dist',{recursive:true,force:true})\""},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:c6475b80-8743-4864-ac89-8bc4f8642937"}},"_resolved":"/home/runner/work/typescript-ai/typescript-ai/dist-packs/diagrid-n8n-0.1.1.tgz","_integrity":"sha512-nJDX6g0OQdKOe33kQ/piKrZdM0ssqYu/OeK/v4LV/zy8ER2yTCIiN8fi0gA8NPNwpGfF4hTCCoSV+3m7iBgbmA==","repository":{"url":"git+https://github.com/diagridio/typescript-ai.git","type":"git","directory":"packages/n8n"},"_npmVersion":"11.19.0","description":"Durable execution of n8n workflow node runs on Dapr Workflows","directories":{},"sideEffects":["./dist/preload.js","./dist/preload.cjs"],"_nodeVersion":"24.20.0","dependencies":{"@dapr/dapr":"3.18.0","@diagrid/agent-core":"0.1.1"},"publishConfig":{"access":"public","provenance":true},"_hasShrinkwrap":false,"devDependencies":{"zod":"4.4.3","tsup":"8.5.1","typescript":"6.0.3"},"peerDependencies":{"zod":"^4.0.0","@n8n/db":"*","@n8n/di":"*","n8n-core":"*","n8n-workflow":"*","n8n-nodes-base":"*"},"//devDependencies":["n8n-core/n8n-workflow/n8n-nodes-base/@n8n/db/@n8n/di are real peer","dependencies (see peerDependencies above) but are deliberately NOT listed","here as file: devDependencies pointing at the sibling n8n checkout: n8n's","own packages depend on ~20 further n8n-internal packages via workspace:*","(@n8n/backend-common, @n8n/config, n8n-workflow, ...), which only resolves","inside n8n's OWN pnpm workspace. Pointing a file: dependency at them from","this workspace makes pnpm try (and fail) to resolve those same specifiers","here, breaking `pnpm install` for the whole repo, not just this package.","See scripts/link-n8n-dev-deps.sh (in this package) and README.md's","'Developing against a local n8n checkout' section for how this","package's node_modules gets real","n8n type/runtime resolution instead: direct symlinks into","packages/n8n/node_modules, bypassing pnpm's own dependency graph for","exactly these five packages, the same way a real n8n install's own","node_modules is what actually satisfies these peers at runtime.","","A real, PUBLISHED-npm-version devDependency (not a file: link) for","n8n-core/n8n-workflow/@n8n/db/@n8n/di specifically — the four peers this","package actually has a static `import` for, so typecheck (not runtime)","would work in a from-scratch checkout with no sibling n8n repo at all","(CI included) — was investigated and reverted, not just skipped. It","resolved and installed, but hit two real, separate problems: (1) their","own transitive dependencies (n8n-core's isolated-vm/ssh2/cpu-features,","Sentry's native profiler) trip pnpm's allowBuilds gate — workable, by","setting those `false` (declined, not silently ignored) rather than","expanding the workspace's real native-build-script surface just for","types; but then (2) pnpm resolves n8n-workflow into two STRUCTURALLY","DIFFERENT peer-hashed instances (n8n-core's own copy vs @n8n/db's own","copy) when these packages are installed as independent top-level","devDependencies outside n8n's own cohesive workspace — TypeScript then","sees e.g. `INode` from one instance as a different nominal type than","`INode` from the other, producing real 'not assignable' errors across","this package's own files that have nothing to do with an actual bug.","That is a structural consequence of installing n8n's own","tightly-interdependent packages outside n8n's own workspace, not","something a version pin or a pnpm override can safely paper over without","significant, fragile upkeep.","","What actually resolves this for CI (and for anyone without a sibling","checkout) is scripts/ci-n8n-types.sh: a pinned, disposable n8n checkout","(n8n-ci-ref.txt), scoped-installed and scoped-built to just the closure","these four peers need, then symlinked in exactly like","link-n8n-dev-deps.sh does for a live one — never copied; a copy would","carry n8n-core's own internal symlink to n8n-workflow along with it and,","if dereferenced, reproduce the exact dual-instance problem above by a","different route. See README.md's 'CI has no sibling checkout of its","own' section for the full account, including why this is not a","substitute for a live checkout (it's read-only and pinned, not meant to","be developed against)."],"peerDependenciesMeta":{"@n8n/db":{"optional":true},"@n8n/di":{"optional":true},"n8n-core":{"optional":true},"n8n-workflow":{"optional":true},"n8n-nodes-base":{"optional":true}},"//peerDependenciesMeta":["`optional: true` here is a pnpm-install-time workaround, not a real","statement that this package works without these five peers — it does","not. Without it, pnpm's autoInstallPeers tries to satisfy the bare `*`","peer range by fetching the REAL published n8n-nodes-base from npm (a","different, unrelated version from this workspace's own local n8n","checkout), which pulls in xlsx via a non-standard URL and trips this","repo's own blockExoticSubdeps supply-chain policy. `optional: true`","stops that auto-install attempt; the real, correct versions still come","from the sibling n8n checkout via scripts/link-n8n-dev-deps.sh."],"_npmOperationalInternal":{"tmp":"tmp/n8n_0.1.1_1789669448236_0.23972981547052097","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"_id":"@diagrid/n8n@0.2.0","bugs":{"url":"https://github.com/diagridio/typescript-ai/issues"},"dist":{"shasum":"2dbcd858c9cb9649a0f86ab476698b8f46005afd","tarball":"https://registry.npmjs.org/@diagrid/n8n/-/n8n-0.2.0.tgz","fileCount":17,"integrity":"sha512-oL9t9URcTlF4c5a/unwFCrnWfrvBetsXwenWEHyr6+lvHTNcpcuNXUhravlpqI1OqpN6CY6Cv0cu3KaQqp3t9A==","signatures":[{"sig":"MEUCIHVHV+RurBs16NWgQY1WK71HVgPBo5LbMdCUi3CYXMfhAiEAwXYUs9+p1qgoL+uouURRTmyduUkdQx/ghPTVv5eqmn4=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIGfeNBnKgVc96apy3jbAQ6y0O547zksELLv2PTu9cdSSAiEAjj2PDFphq4iDcXA/O9yxwTH20MdkIAEGx+aDG8NSwS4="}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@diagrid%2fn8n@0.2.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":755675},"main":"./dist/index.cjs","name":"@diagrid/n8n","type":"module","_from":"file:dist-packs/diagrid-n8n-0.2.0.tgz","types":"./dist/index.d.ts","author":{"name":"Diagrid Inc."},"module":"./dist/index.js","engines":{"node":">=22.13.0"},"exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"require":{"types":"./dist/index.d.cts","default":"./dist/index.cjs"}},"./register":{"import":{"types":"./dist/preload.d.ts","default":"./dist/preload.js"},"require":{"types":"./dist/preload.d.cts","default":"./dist/preload.cjs"}},"./package.json":"./package.json"},"license":"BUSL-1.1","scripts":{"build":"tsup","clean":"node -e \"require('node:fs').rmSync('dist',{recursive:true,force:true})\""},"version":"0.2.0","_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:c6475b80-8743-4864-ac89-8bc4f8642937"}},"homepage":"https://github.com/diagridio/typescript-ai#readme","keywords":["dapr","workflow","durable","n8n","automation","diagrid"],"_resolved":"/home/runner/work/typescript-ai/typescript-ai/dist-packs/diagrid-n8n-0.2.0.tgz","_integrity":"sha512-oL9t9URcTlF4c5a/unwFCrnWfrvBetsXwenWEHyr6+lvHTNcpcuNXUhravlpqI1OqpN6CY6Cv0cu3KaQqp3t9A==","repository":{"url":"git+https://github.com/diagridio/typescript-ai.git","type":"git","directory":"packages/n8n"},"_npmVersion":"11.19.0","description":"Durable execution of n8n workflow node runs on Dapr Workflows","directories":{},"maintainers":[{"name":"casperwmn","email":"whopsec@protonmail.com"}],"sideEffects":["./dist/preload.js","./dist/preload.cjs"],"_nodeVersion":"24.20.0","dependencies":{"@dapr/dapr":"3.18.0","@diagrid/agent-core":"0.2.0"},"publishConfig":{"access":"public","provenance":true},"_hasShrinkwrap":false,"devDependencies":{"zod":"4.4.3","tsup":"8.5.1","typescript":"6.0.3"},"peerDependencies":{"zod":"^4.0.0","@n8n/db":"*","@n8n/di":"*","n8n-core":"*","n8n-workflow":"*","n8n-nodes-base":"*"},"//devDependencies":["n8n-core/n8n-workflow/n8n-nodes-base/@n8n/db/@n8n/di are real peer","dependencies (see peerDependencies above) but are deliberately NOT listed","here as file: devDependencies pointing at the sibling n8n checkout: n8n's","own packages depend on ~20 further n8n-internal packages via workspace:*","(@n8n/backend-common, @n8n/config, n8n-workflow, ...), which only resolves","inside n8n's OWN pnpm workspace. Pointing a file: dependency at them from","this workspace makes pnpm try (and fail) to resolve those same specifiers","here, breaking `pnpm install` for the whole repo, not just this package.","See scripts/link-n8n-dev-deps.sh (in this package) and README.md's","'Developing against a local n8n checkout' section for how this","package's node_modules gets real","n8n type/runtime resolution instead: direct symlinks into","packages/n8n/node_modules, bypassing pnpm's own dependency graph for","exactly these five packages, the same way a real n8n install's own","node_modules is what actually satisfies these peers at runtime.","","A real, PUBLISHED-npm-version devDependency (not a file: link) for","n8n-core/n8n-workflow/@n8n/db/@n8n/di specifically — the four peers this","package actually has a static `import` for, so typecheck (not runtime)","would work in a from-scratch checkout with no sibling n8n repo at all","(CI included) — was investigated and reverted, not just skipped. It","resolved and installed, but hit two real, separate problems: (1) their","own transitive dependencies (n8n-core's isolated-vm/ssh2/cpu-features,","Sentry's native profiler) trip pnpm's allowBuilds gate — workable, by","setting those `false` (declined, not silently ignored) rather than","expanding the workspace's real native-build-script surface just for","types; but then (2) pnpm resolves n8n-workflow into two STRUCTURALLY","DIFFERENT peer-hashed instances (n8n-core's own copy vs @n8n/db's own","copy) when these packages are installed as independent top-level","devDependencies outside n8n's own cohesive workspace — TypeScript then","sees e.g. `INode` from one instance as a different nominal type than","`INode` from the other, producing real 'not assignable' errors across","this package's own files that have nothing to do with an actual bug.","That is a structural consequence of installing n8n's own","tightly-interdependent packages outside n8n's own workspace, not","something a version pin or a pnpm override can safely paper over without","significant, fragile upkeep.","","What actually resolves this for CI (and for anyone without a sibling","checkout) is scripts/ci-n8n-types.sh: a pinned, disposable n8n checkout","(n8n-ci-ref.txt), scoped-installed and scoped-built to just the closure","these four peers need, then symlinked in exactly like","link-n8n-dev-deps.sh does for a live one — never copied; a copy would","carry n8n-core's own internal symlink to n8n-workflow along with it and,","if dereferenced, reproduce the exact dual-instance problem above by a","different route. See README.md's 'CI has no sibling checkout of its","own' section for the full account, including why this is not a","substitute for a live checkout (it's read-only and pinned, not meant to","be developed against)."],"peerDependenciesMeta":{"@n8n/db":{"optional":true},"@n8n/di":{"optional":true},"n8n-core":{"optional":true},"n8n-workflow":{"optional":true},"n8n-nodes-base":{"optional":true}},"//peerDependenciesMeta":["`optional: true` here is a pnpm-install-time workaround, not a real","statement that this package works without these five peers — it does","not. Without it, pnpm's autoInstallPeers tries to satisfy the bare `*`","peer range by fetching the REAL published n8n-nodes-base from npm (a","different, unrelated version from this workspace's own local n8n","checkout), which pulls in xlsx via a non-standard URL and trips this","repo's own blockExoticSubdeps supply-chain policy. `optional: true`","stops that auto-install attempt; the real, correct versions still come","from the sibling n8n checkout via scripts/link-n8n-dev-deps.sh."],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/n8n_0.2.0_1789684454034_0.35918991289445046"}}},"time":{"created":"2026-09-10T21:38:50.976Z","modified":"2026-09-17T22:34:14.479Z","0.1.0":"2026-09-10T21:38:51.273Z","0.1.1":"2026-09-17T18:24:08.362Z","0.2.0":"2026-09-17T22:34:14.133Z"},"bugs":{"url":"https://github.com/diagridio/typescript-ai/issues"},"author":{"name":"Diagrid Inc."},"license":"BUSL-1.1","homepage":"https://github.com/diagridio/typescript-ai#readme","keywords":["dapr","workflow","durable","n8n","automation","diagrid"],"repository":{"url":"git+https://github.com/diagridio/typescript-ai.git","type":"git","directory":"packages/n8n"},"description":"Durable execution of n8n workflow node runs on Dapr Workflows","maintainers":[{"name":"casperwmn","email":"whopsec@protonmail.com"}],"readme":"# @diagrid/n8n\n\nDurable execution of [n8n](https://n8n.io) workflow node runs on\n[Dapr Workflows](https://docs.dapr.io/developing-applications/building-blocks/workflow/).\n\nAttaches to a stock n8n process at load time\n(`NODE_OPTIONS=\"--require @diagrid/n8n/register\" n8n start`) — no upstream n8n\nchanges, no fork. Each n8n node run becomes a durable Dapr activity, guarded by\nan idempotency ledger, so a multi-node workflow survives a process crash and\nresumes from its last completed node, with no duplicate side effects.\n\n## Why not `SupportedFrameworks` / `BaseAgentMapper`\n\nEvery other package in this repo (`packages/mastra`, and every adapter planned\nalongside it) wraps an **LLM agent framework** — `SupportedFrameworks` in\n`@diagrid/agent-core` and `BaseAgentMapper` both model that specifically. An n8n\nworkflow is a general-purpose automation graph, not an agent in that sense, so\nthis package deliberately does **not** add an `N8N` entry to\n`SupportedFrameworks` and does not implement `BaseAgentMapper` —\n`tests/guards/cross-framework-imports.test.ts` covers this package under its\nown, separate assertions rather than the adapter ones for exactly this reason.\n\n`BaseWorkflowRunner` (`packages/core/src/workflow/runner.ts`) can't be\nsubclassed either way — its constructor requires a `SupportedFramework` value\nfrom that same closed union. `runtime.ts` borrows its _patterns_ directly\ninstead of inheriting them: lazy, idempotent construction (a memoized\nconstruction promise, not a static import — `@dapr/dapr` is dynamically\n`import()`-ed, exactly like `dapr.ts`/`status.ts` do in core, and for the same\nreason: a static import would make a bare `require()` of this package eagerly\nload ~136 `@dapr/dapr` modules and ~65 from `@grpc/grpc-js` before any n8n code\never runs — this package is `--require`d into every boot, so that cost is even\nmore directly paid here than for an adapter that's merely `import`ed once), a\n`shutdown()` that attempts every cleanup step independently and collects\nfailures into an `AggregateError` rather than letting one throw strand the\nrest, and the same opt-in `registerShutdownHandlers()` SIGINT/SIGTERM pattern.\n\n**Real, plainly-stated consequence:** since this package doesn't go through\n`BaseWorkflowRunner`, it needs `@dapr/dapr` as its own **direct** runtime\ndependency — unlike every other adapter here, whose only runtime dependency is\n`@diagrid/agent-core`. `runtime.ts` is the only file in this package that\nimports `@dapr/dapr` as a _value_; every other file only needs\n`WorkflowContext`/`WorkflowActivityContext` as **types**, reused from\n`@diagrid/agent-core`'s own type-only re-export (`workflow/dapr.ts`), which\nkeeps the divergence as narrow as it can be while still being real.\n\nReused from `@diagrid/agent-core` rather than duplicated:\n\n- `workflow/status.ts`'s `WorkflowRuntimeStatus`/`workflowStatusName` — a\n  numeric enum declared locally in core (not re-exported from `@dapr/dapr`, for\n  the same static-import reason above). Comparing a `runtimeStatus` to a string\n  literal is silently always false; this removes that whole risk class.\n- `state/store.ts`'s `DaprStateStore` — backs the idempotency ledger\n  (`ledger.ts`) instead of raw `DaprClient` usage. Its default component name,\n  `kvstore`, is adopted as-is: it's the real, live Catalyst-managed component\n  name, so an n8n deployment on Catalyst needs no extra configuration. Override\n  with `DIAGRID_N8N_STATE_STORE`.\n- `workflow/dapr.ts`'s type-only re-exports (`WorkflowContext`,\n  `WorkflowActivityContext`, `WorkflowRuntime`, `DaprWorkflowClient`, …) — used\n  everywhere except `runtime.ts`.\n\n## `@dapr/dapr` version: 3.18.0, the workspace-pinned published version\n\nVerified against the real, installed 3.18.0 — not assumed, and not the local,\nunreleased SDK checkout the original standalone package was first built\nagainst. Every part of the API surface this package depends on matches:\n`registerWorkflowWithName`/`registerActivityWithName`, `WorkflowContext`'s\n`callActivity`/`whenAll`/`whenAny`/`createTimer`/`waitForExternalEvent`/\n`callChildWorkflow`, `DaprWorkflowClient`'s\n`scheduleNewWorkflow`/`waitForWorkflowCompletion`/`getWorkflowState`/\n`raiseEvent`, and `WorkflowRuntimeStatus`'s exact numeric values (confirmed\nidentical to what `@diagrid/agent-core`'s own `status.ts` declares — RUNNING 0,\nCOMPLETED 1, CONTINUED_AS_NEW 2, FAILED 3, TERMINATED 5, PENDING 6, SUSPENDED 7) — including the exact same deterministic child-workflow instance-id\nderivation formula (`` `${parentInstanceId}:${seq.toString(16).padStart(4,'0')}` ``,\nconfirmed directly in `runtime-orchestration-context.js`'s\n`callSubOrchestrator`) the sub-workflow crash-recovery proof depends on.\n\nTwo known upstream findings from the original package's own Phase 0, each\nre-checked against 3.18.0's real source rather than re-asserted:\n\n- **The hardcoded-concurrency-ceiling silent work-item drop is fixed.**\n  `task-hub-grpc-worker.js` still caps in-flight work at 10\n  (`_maxConcurrentWorkItems`), but a work item beyond that ceiling now queues\n  (up to `_maxQueueSize = 100`, logged at `debug`) instead of being silently\n  dropped — it's only dropped, with a `warn` log, once that 100-item queue\n  itself is full.\n- **The unbounded `scheduleNewWorkflow` gRPC call is still present.**\n  `client.js`'s `scheduleNewOrchestration` calls\n  `promisify(this._stub.startInstance...)` with no deadline or call options —\n  confirmed by reading the file directly; there is no timeout anywhere in the\n  call chain. `run-durably.ts`'s own `SCHEDULE_TIMEOUT_MS`/`withTimeout` guard\n  is therefore still necessary and is kept unchanged.\n\n## Install\n\n```bash\npnpm add @diagrid/n8n\n```\n\n`n8n-core`, `n8n-workflow`, `n8n-nodes-base`, `@n8n/db`, and `@n8n/di` are\n**peer** dependencies (marked `optional: true` in `peerDependenciesMeta` — see\nthe `//peerDependenciesMeta` note in `package.json` for exactly why that's a\npnpm-install-time workaround, not a claim this package works without them): a\nreal n8n install already provides all five at the versions it was built\nagainst; this package must never bundle or pin its own copies.\n\n## Usage\n\n```bash\nNODE_OPTIONS=\"--require @diagrid/n8n/register\" n8n start\n```\n\nThat's the entire integration surface — no code changes to any workflow, no\nn8n configuration. Point the process at a reachable Dapr sidecar the normal\nway (`DAPR_HOST`/`DAPR_GRPC_PORT`, or Catalyst's `DAPR_GRPC_ENDPOINT`/\n`DAPR_API_TOKEN`), and every subsequent manual workflow execution runs as a\ndurable Dapr orchestration instead of an in-memory one.\n\n### Developing against a local n8n checkout\n\nTwo sibling checkouts (this repo and an n8n checkout) have no `node_modules`\npath from one to the other, so local development needs two extra steps `pnpm\nadd` alone doesn't cover:\n\n```bash\n# Symlink n8n's own packages into this package's node_modules — see the\n# script's own doc comment for why this can't be a plain `file:` dependency.\nN8N_CHECKOUT=/path/to/n8n packages/n8n/scripts/link-n8n-dev-deps.sh\n\n# --require by absolute path, since the bare `@diagrid/n8n/register` specifier\n# has no node_modules entry to resolve through in this shape:\nNODE_OPTIONS=\"--require /absolute/path/to/packages/n8n/dist/preload.cjs\" \\\n  node /path/to/n8n/packages/cli/bin/n8n start\n```\n\n**The absolute path must point at `dist/preload.cjs`, not `dist/preload.js`.**\nThis package declares `\"type\": \"module\"` (unlike the original standalone\npackage it was ported from, which had no dual build), so `dist/preload.js` is\nthe real ESM output. `--require`ing it _by absolute path_ bypasses this\npackage's own `exports` map — the thing that would otherwise route a real\n`--require \"@diagrid/n8n/register\"` to the correct build for a CJS caller — so\nNode's newer synchronous `require(esm)` support loads it as genuine ESM\ninstead, which cascades into the real, more serious defect described next.\nConfirmed by reproducing it directly: not a bug in this package's real-world\n`--require` usage — n8n's own entry point (`bin/n8n`) is plain CJS throughout,\nso the only path a genuine install ever takes is `require()` through the\n`exports` map's `\"require\"` condition, landing correctly on `dist/preload.cjs`\nevery time. It only bites a sibling-checkout absolute-path `--require`, which\nis why this section calls it out explicitly.\n\n### CI has no sibling checkout of its own — it builds a pinned, disposable one\n\nA from-scratch clone with nothing else done fails both `pnpm typecheck` and\n`pnpm build` with `Cannot find module 'n8n-core'` and similar, for every file\nthat imports one of this package's five optional peers — there is no\n`link-n8n-dev-deps.sh` step above for CI to run, and no sibling n8n checkout\nsitting next to the runner's copy of this repo. `scripts/ci-n8n-types.sh` is\nwhat every CI workflow that runs `pnpm build` runs first instead: it\nshallow-fetches the single n8n commit pinned in `n8n-ci-ref.txt`, builds only\nthe backend-internal closure `n8n-core`/`n8n-workflow`/`@n8n/db`/`@n8n/di`\nactually need (computed from turbo itself, not this monorepo's full ~1000\npackages — no `nodes-base`, no frontend, no `cli`), and symlinks — never\ncopies; see the script's own doc comment for why a copy reintroduces the\nexact dual-instance problem below — the result into this package's\n`node_modules`, the same shape `link-n8n-dev-deps.sh` produces for a live\ncheckout. It's idempotent and safe to run by hand too.\n\nThis is deliberately not a replacement for a live checkout: it's pinned and\ndisposable, good for exactly the typecheck/build/unit-test slice of CI, not\nfor iterating against an n8n change or running the real end-to-end\ncrash-recovery suite (`tests/e2e/n8n-crash-recovery*.integration.test.ts`),\nwhich still needs `N8N_CHECKOUT` pointing at a real, live, runnable install —\nsee \"Developing against a local n8n checkout\" above.\n\nTwo real alternative fixes were investigated before landing on this one, and\nboth were reverted, not just skipped (see `package.json`'s own\n`//devDependencies` note for the full account): an ambient shorthand module\ndeclaration (`declare module 'n8n-workflow';`, falling back to `any`)\nconflicted with the real types whenever both were present in the same\ncompilation (`TS2709: Cannot use namespace '...' as a type`); real, pinned npm\ndevDependencies for the four statically-imported peers resolved but then hit\npnpm installing n8n-core's and `@n8n/db`'s own copies of `n8n-workflow` as two\nstructurally distinct, non-interchangeable peer-hashed instances (n8n's\npackages are built to be installed inside n8n's own cohesive workspace, not\nas independent top-level devDependencies elsewhere) — real\n`INode`/`ITaskData`/etc. \"not assignable\" errors with no actual bug behind\nthem.\n\n### A real one, not just a dev-path quirk: `import`-ing this package's ESM build never works\n\nUnlike the `.cjs`-vs-`.js` mix-up above, this one isn't specific to a\nsibling-checkout `--require` — it reproduces from the _documented_, correctly\n`exports`-map-routed path too: a genuine `import { register } from\n'@diagrid/n8n'` from someone else's ESM code, or `node --input-type=module -e\n\"await import('@diagrid/n8n')\"`, both fail the same way. `index.ts` re-exports\n`register.ts`, which does `import { WorkflowExecute } from 'n8n-core';` as a\nreal value — under `dist/index.js` (the ESM build), that resolves `n8n-core`\nthrough _its own_ `exports[\"import\"]` condition into n8n-workflow's ESM\n`dist/esm/*` output, whose own relative imports (e.g. `from\n'./logger-proxy'`) have no file extension — invalid under Node's ESM resolver\n(unlike its CJS one), so it throws `ERR_MODULE_NOT_FOUND`. This is a real\ndefect in n8n's own published ESM build, not something this package can fix.\n`tests/guards/cross-framework-imports.test.ts`'s n8n-specific \"imports\ncleanly\" check therefore runs against `dist/index.cjs` rather than the default\nESM entry every other package's equivalent check uses — see that test's own\ncomment. **Practical consequence:** anything that needs to consume this\npackage programmatically (not just `--require`) should do so via `require()`\nor a bundler targeting CJS, not a native ESM `import`, until n8n's own\npublished ESM output fixes its extensionless relative imports.\n\n## Module layout\n\n| File                                     | Role                                                                                                       |\n| ---------------------------------------- | ---------------------------------------------------------------------------------------------------------- |\n| `preload.ts`                             | What `--require @diagrid/n8n/register` actually loads: patches n8n, starts the runtime eagerly             |\n| `register.ts`                            | The actual monkeypatch — `WorkflowExecute.prototype.processRunExecutionData`                               |\n| `runtime.ts`                             | Owns the Dapr `WorkflowRuntime`/`DaprWorkflowClient` lifecycle — see \"Why not `SupportedFrameworks`\" above |\n| `run-durably.ts`                         | Schedules one Dapr orchestration per n8n execution and waits for it, replacing the patched method          |\n| `orchestrator.ts` / `orchestrator-v2.ts` | The deterministic replay loop — see \"Versioning discipline\" below for why there are two                    |\n| `activity.ts`                            | The one generic activity every node type dispatches through — the only place real side effects happen      |\n| `execute-node.ts`                        | Builds the narrowest possible n8n execution context to call a node's real `execute()`                      |\n| `ledger.ts`                              | Idempotency ledger for activity results, backed by `@diagrid/agent-core`'s `DaprStateStore`                |\n| `sub-workflow.ts`                        | Resolves and dispatches an Execute Workflow node as a real Dapr child workflow                             |\n| `execution-status-sync.ts`               | Writes the orchestration's final outcome into n8n's own execution record, as a dispatched activity         |\n| `execution-progress.ts`                  | Syncs each node's outcome into n8n's execution record incrementally, as it happens                         |\n| `round-log.ts`                           | orchestrator-v2's one real behavioral addition — see \"Versioning discipline\"                               |\n| `task-data.ts`                           | Maps a finished node's result to n8n's own per-node `ITaskData` shape                                      |\n| `schemas.ts`                             | Zod schemas for everything crossing the workflow boundary — see \"Zod at boundaries\" below                  |\n| `types.ts` / `constants.ts`              | Shared types and versioned Dapr workflow/activity names                                                    |\n| `version.ts`                             | Version marker                                                                                             |\n\n## Versioning discipline\n\nEvery orchestrator/activity name is registered explicitly under a versioned\nname (`constants.ts`), never left to default inference — the design this\npackage inherited already recommended it, and this port is the first time it\nwas actually built _and proven_, not just asserted.\n\n`orchestrator-v2.ts` is a deliberate, near-total duplicate of `orchestrator.ts`\n(v1), forked at the point both versions share. Duplicating the whole file,\nrather than sharing the body through a parameterized helper, is intentional:\nit's the most literal way to guarantee v1's registered function is genuinely\nbyte-for-byte unmodified, which is the entire point of the proof — the Dapr JS\nSDK resolves which registered generator function handles a given orchestration\nby looking up the name persisted in that instance's own `ExecutionStarted`\nhistory event, on **every single replay**, against whichever process is\ncurrently connected. `runtime.ts` registers **both** names unconditionally, in\nthe same running process — the way a real rolling deploy, or an in-place\nupgrade of a single-worker deployment, actually looks. `run-durably.ts`\nschedules every new top-level execution against v2; v1 stays registered purely\nto keep draining whatever already committed to it. The one real (not\ncosmetic) difference in v2 is `round-log.ts`: a new activity dispatched at the\nstart of every dispatch round, which changes the yield sequence — exactly what\nmakes replaying a v1 instance under v2's code a genuine mismatch, and\nregistering both names side by side the actual fix.\n\n## Idempotency and at-least-once activities\n\nDapr guarantees each activity runs **at least once**. `activity.ts` is the\nonly place a real n8n node's `execute()` runs, and it's guarded by\n`ledger.ts`: a redelivery of the exact same attempt (same instance, node, run\nindex, and attempt number) reads back the already-recorded result instead of\ncalling `execute()` again. A genuinely new attempt — after a real failure and\nits durable backoff wait — gets a new attempt number and does run for real.\n\nThis is the mechanism the crash-recovery proof depends on: a process killed\nwhile an activity is genuinely in flight leaves no ledger entry (the activity\nnever returned), so a redelivery to the next connected process runs the node's\nreal side effect exactly once. A process killed _after_ an activity returned\nbut crashed before Dapr durably recorded that completion would, in principle,\nredeliver into a real second execution of that one node's side effect — the\nsame narrow, structural at-least-once window every Dapr Workflow-backed system\nhas. This package narrows it to per-node granularity; it does not close it.\n\n## Zod at boundaries\n\nReal, previously-missing rigor closed in this port, not just noted as a gap:\n`schemas.ts` gives every activity input/output, the top-level\n`OrchestrationInput` (the first thing replayed from an instance's own history\non every single replay), and every ledger read a real Zod schema, parsed\nrather than trusted via a bare cast. Deliberately proportionate, not\nexhaustive: n8n's own `INode`/`IConnections`/`INodeExecutionData` are large,\nevolving types owned by n8n, not this package — `nodeShapeSchema`/\n`nodeExecutionDataSchema` validate the handful of fields this package actually\nreads, with `.passthrough()` for the rest, rather than re-deriving n8n's whole\ntype system and drifting from it on every n8n upgrade.\n\n## Scope — real, honest gaps, not silent omissions\n\n`grep -rn 'TODO(n8n-integration)' src` lists every one of these with its exact\nlocation. Every gap below was already true of the original standalone package\nthis was ported from; none is new:\n\n- **Credentials are unimplemented.** Only credential-free node types are\n  wired up (`Set`, `NoOp`, `If`, `Merge`, `Wait`) — enough to prove branching,\n  retry, and durable waits without needing credential resolution, which is\n  real, separate work (`execute-node.ts`).\n- **n8n's real webhook HTTP endpoint doesn't call `raiseEvent` yet.**\n  External-event Wait-node resume is proven only via a direct\n  `DaprWorkflowClient.raiseEvent` call, not through n8n's own webhook routing\n  (`packages/cli`'s `waiting-webhooks.ts`/`live-webhooks.ts`) — untouched by\n  this package (`constants.ts`).\n- **Sub-workflow children have no execution-list row of their own** — they run\n  as real, durable Dapr child workflows, but don't appear as a separate entry\n  in n8n's UI (`types.ts`).\n- **The sub-workflow node has no retry loop** of its own — a failed resolve or\n  a failed child is recorded as that node's error on the first attempt, not\n  retried by the orchestrator's backoff logic (`orchestrator.ts`).\n- **Only \"select workflow by id\" is supported** for the Execute Workflow node,\n  with a literal id only — no expressions, no parameter/JSON, local-file, or\n  URL source modes (`sub-workflow.ts`).\n- **The incremental execution-list sync's concurrency guard is\n  single-process-only.** A queue-mode/multi-worker n8n deployment remains\n  untested — nothing reachable through `@n8n/db` offers a real\n  compare-and-swap on the column being written (`execution-progress.ts`).\n- **Cancellation is not implemented.** The real `processRunExecutionData`\n  returns a `PCancelable<IRun>`; this returns a plain `Promise`, so the\n  editor's \"stop execution\" button does not work yet (`run-durably.ts`,\n  `register.ts`).\n- **This package has never been published** — nothing currently stamps\n  `version.ts` alongside `package.json`'s own version the way\n  `.github/workflows/npm-release.yaml` does for `core`/`mastra` (`version.ts`).\n- **`pnpm typecheck` / `pnpm build` need real n8n types, which need either a\n  linked sibling checkout or CI's own pinned, disposable one.** Neither is\n  optional — this package cannot be meaningfully type-checked, built, or (as\n  the whole rest of this README documents) run without real n8n types from\n  somewhere. See \"CI has no sibling checkout of its own\" above for what\n  actually provides them and the two rejected alternatives that came before\n  it.\n\n## License\n\n[Business Source License 1.1](../../LICENSE.md) — © 2026–Present Diagrid Inc.\n","readmeFilename":"README.md"}