nodal-agents 0.1.3 → 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +81 -81
- package/cli.js +64 -10
- package/migrations/0000_flashy_clea.sql +528 -528
- package/migrations/0001_exotic_shooting_star.sql +2 -2
- package/migrations/0002_gray_devos.sql +38 -38
- package/migrations/0004_married_deadpool.sql +2 -2
- package/migrations/0006_credentials_table.sql +24 -24
- package/migrations/0007_free_speed.sql +16 -16
- package/migrations/0008_curious_thor_girl.sql +16 -16
- package/migrations/0009_agent_memory_token_budget.sql +1 -0
- package/migrations/0010_agent_workspace_root.sql +1 -0
- package/migrations/0011_agent_jobs_failed_delegations_count.sql +1 -0
- package/migrations/0012_agent_jobs_last_failed_delegation_slug.sql +2 -0
- package/migrations/0013_cascade_agent_fks.sql +39 -0
- package/migrations/0014_mcp_server_credentials.sql +24 -0
- package/migrations/0015_agent_mcp_servers_unique.sql +14 -0
- package/migrations/0016_drop_connector_entity_slug_unique.sql +10 -0
- package/migrations/0017_drop_mcp_server_entity_slug_unique.sql +9 -0
- package/migrations/meta/0009_snapshot.json +4712 -0
- package/migrations/meta/0010_snapshot.json +4718 -0
- package/migrations/meta/_journal.json +63 -0
- package/package.json +1 -1
- package/runner.js +23434 -9204
- package/web/.next/BUILD_ID +1 -1
- package/web/.next/app-path-routes-manifest.json +2 -1
- package/web/.next/build-manifest.json +6 -6
- package/web/.next/prerender-manifest.json +3 -3
- package/web/.next/react-loadable-manifest.json +2 -2
- package/web/.next/required-server-files.json +4 -5
- package/web/.next/routes-manifest.json +6 -0
- package/web/.next/server/app/(dashboard)/agents/[id]/edit/page.js +2 -2
- package/web/.next/server/app/(dashboard)/agents/[id]/edit/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/agents/[id]/edit/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/agents/[id]/telegram/page.js +2 -2
- package/web/.next/server/app/(dashboard)/agents/[id]/telegram/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/agents/[id]/telegram/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/agents/page.js +2 -2
- package/web/.next/server/app/(dashboard)/agents/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/agents/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/approvals/page.js +2 -2
- package/web/.next/server/app/(dashboard)/approvals/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/approvals/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/automations/page.js +2 -2
- package/web/.next/server/app/(dashboard)/automations/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/automations/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/billing/page.js +2 -2
- package/web/.next/server/app/(dashboard)/billing/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/billing/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/connectors/page.js +2 -2
- package/web/.next/server/app/(dashboard)/connectors/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/connectors/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/credentials/page.js +2 -2
- package/web/.next/server/app/(dashboard)/credentials/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/credentials/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/jobs/[id]/page.js +2 -2
- package/web/.next/server/app/(dashboard)/jobs/[id]/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/jobs/[id]/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/jobs/page.js +2 -2
- package/web/.next/server/app/(dashboard)/jobs/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/jobs/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/logs/page.js +2 -2
- package/web/.next/server/app/(dashboard)/logs/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/logs/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/mcp/page.js +2 -0
- package/web/.next/server/app/(dashboard)/mcp/page.js.nft.json +1 -0
- package/web/.next/server/app/(dashboard)/mcp/page_client-reference-manifest.js +1 -0
- package/web/.next/server/app/(dashboard)/memories/page.js +2 -2
- package/web/.next/server/app/(dashboard)/memories/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/memories/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/settings/page.js +2 -2
- package/web/.next/server/app/(dashboard)/settings/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/settings/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/skills/[id]/edit/page.js +2 -2
- package/web/.next/server/app/(dashboard)/skills/[id]/edit/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/skills/[id]/edit/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/skills/page.js +2 -2
- package/web/.next/server/app/(dashboard)/skills/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/skills/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/stats/page.js +2 -2
- package/web/.next/server/app/(dashboard)/stats/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/stats/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/_global-error/page.js +3 -3
- package/web/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/_global-error.html +1 -1
- package/web/.next/server/app/_global-error.rsc +3 -3
- package/web/.next/server/app/_global-error.segments/_full.segment.rsc +3 -3
- package/web/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/web/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
- package/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/web/.next/server/app/_global-error.segments/_index.segment.rsc +3 -3
- package/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/web/.next/server/app/_not-found/page.js +2 -2
- package/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/_not-found.html +1 -1
- package/web/.next/server/app/_not-found.rsc +4 -4
- package/web/.next/server/app/_not-found.segments/_full.segment.rsc +4 -4
- package/web/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/web/.next/server/app/_not-found.segments/_index.segment.rsc +4 -4
- package/web/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +2 -2
- package/web/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/web/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
- package/web/.next/server/app/api/auth/[...all]/route.js +1 -1
- package/web/.next/server/app/api/auth/[...all]/route.js.nft.json +1 -1
- package/web/.next/server/app/api/auth/[...all]/route_client-reference-manifest.js +1 -1
- package/web/.next/server/app/api/health/route.js +1 -1
- package/web/.next/server/app/api/health/route_client-reference-manifest.js +1 -1
- package/web/.next/server/app/api/oauth/[provider]/callback/route.js +1 -1
- package/web/.next/server/app/api/oauth/[provider]/callback/route.js.nft.json +1 -1
- package/web/.next/server/app/api/oauth/[provider]/callback/route_client-reference-manifest.js +1 -1
- package/web/.next/server/app/api/oauth/[provider]/start/route.js +1 -1
- package/web/.next/server/app/api/oauth/[provider]/start/route.js.nft.json +1 -1
- package/web/.next/server/app/api/oauth/[provider]/start/route_client-reference-manifest.js +1 -1
- package/web/.next/server/app/auth/callback/route.js +1 -1
- package/web/.next/server/app/auth/callback/route_client-reference-manifest.js +1 -1
- package/web/.next/server/app/index.html +1 -1
- package/web/.next/server/app/index.rsc +4 -4
- package/web/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
- package/web/.next/server/app/index.segments/_full.segment.rsc +4 -4
- package/web/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/web/.next/server/app/index.segments/_index.segment.rsc +4 -4
- package/web/.next/server/app/index.segments/_tree.segment.rsc +2 -2
- package/web/.next/server/app/login/page.js +2 -2
- package/web/.next/server/app/login/page.js.nft.json +1 -1
- package/web/.next/server/app/login/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/onboarding/page.js +2 -2
- package/web/.next/server/app/onboarding/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/onboarding.html +1 -1
- package/web/.next/server/app/onboarding.rsc +4 -4
- package/web/.next/server/app/onboarding.segments/_full.segment.rsc +4 -4
- package/web/.next/server/app/onboarding.segments/_head.segment.rsc +1 -1
- package/web/.next/server/app/onboarding.segments/_index.segment.rsc +4 -4
- package/web/.next/server/app/onboarding.segments/_tree.segment.rsc +2 -2
- package/web/.next/server/app/onboarding.segments/onboarding/__PAGE__.segment.rsc +1 -1
- package/web/.next/server/app/onboarding.segments/onboarding.segment.rsc +1 -1
- package/web/.next/server/app/page.js +2 -2
- package/web/.next/server/app/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app-paths-manifest.json +2 -1
- package/web/.next/server/chunks/134.js +1 -0
- package/web/.next/server/chunks/{699.js → 145.js} +1 -1
- package/web/.next/server/chunks/159.js +4 -4
- package/web/.next/server/chunks/184.js +2 -0
- package/web/.next/server/chunks/352.js +16 -0
- package/web/.next/server/chunks/437.js +62 -0
- package/web/.next/server/chunks/574.js +1 -1
- package/web/.next/server/chunks/631.js +12 -0
- package/web/.next/server/chunks/676.js +1 -0
- package/web/.next/server/chunks/807.js +1 -1
- package/web/.next/server/chunks/{606.js → 826.js} +31 -31
- package/web/.next/server/middleware-build-manifest.js +1 -1
- package/web/.next/server/middleware-react-loadable-manifest.js +1 -1
- package/web/.next/server/middleware.js +1 -1
- package/web/.next/server/pages/404.html +1 -1
- package/web/.next/server/pages/500.html +1 -1
- package/web/.next/server/server-reference-manifest.js +1 -1
- package/web/.next/server/server-reference-manifest.json +1 -1
- package/web/.next/static/2lmxaWvI1cL9_1Ob3gIFq/_buildManifest.js +1 -0
- package/web/.next/static/chunks/1045-82c87c31d5a8f54b.js +1 -0
- package/web/.next/static/chunks/2186-88c3d89f10bc57c3.js +1 -0
- package/web/.next/static/chunks/3363-613d9ccc7fe8a233.js +1 -0
- package/web/.next/static/chunks/3426-ddba5bb6b1e3f0ee.js +1 -0
- package/web/.next/static/chunks/4678-5cbc08f56a4fb74d.js +1 -0
- package/web/.next/static/chunks/7203.f516c74ab9532e2b.js +1 -0
- package/web/.next/static/chunks/{724-1d09b7ea367babbe.js → 8724-68ad0e948ea9a1cd.js} +1 -1
- package/web/.next/static/chunks/9174.9225c199db752381.js +1 -0
- package/web/.next/static/chunks/9504-9ba984747b116953.js +1 -0
- package/web/.next/static/chunks/a7a8b010-8a97df7bbea35b50.js +1 -0
- package/web/.next/static/chunks/app/(dashboard)/agents/[id]/edit/page-2c38c08bef6182ce.js +1 -0
- package/web/.next/static/chunks/app/(dashboard)/agents/[id]/telegram/page-9ddc8c77a1ec33df.js +1 -0
- package/web/.next/static/chunks/app/(dashboard)/agents/page-567400cb256c565d.js +1 -0
- package/web/.next/static/chunks/app/(dashboard)/approvals/page-38f4fe347d505bff.js +1 -0
- package/web/.next/static/chunks/app/(dashboard)/automations/page-d8c09fb42eeeca4d.js +1 -0
- package/web/.next/static/chunks/app/(dashboard)/billing/page-736acdd0781484e6.js +1 -0
- package/web/.next/static/chunks/app/(dashboard)/connectors/page-63889db4bf76fe10.js +1 -0
- package/web/.next/static/chunks/app/(dashboard)/credentials/page-4867266b3111cdf6.js +1 -0
- package/web/.next/static/chunks/app/(dashboard)/jobs/[id]/page-285ef9a609cc1190.js +1 -0
- package/web/.next/static/chunks/app/(dashboard)/jobs/page-8b0b38b7651507ba.js +1 -0
- package/web/.next/static/chunks/app/(dashboard)/layout-5bf62b7b4daa56d5.js +2 -0
- package/web/.next/static/chunks/app/(dashboard)/logs/page-8e809e843e8a6f76.js +1 -0
- package/web/.next/static/chunks/app/(dashboard)/mcp/page-77dd7810003d6437.js +1 -0
- package/web/.next/static/chunks/app/(dashboard)/memories/page-f4541a2f37851596.js +1 -0
- package/web/.next/static/chunks/app/(dashboard)/settings/page-95e9ff0349e579ef.js +1 -0
- package/web/.next/static/chunks/app/(dashboard)/skills/[id]/edit/page-a1a65f3cc8a9df31.js +1 -0
- package/web/.next/static/chunks/app/(dashboard)/skills/page-747e409f9f34cc3c.js +1 -0
- package/web/.next/static/chunks/app/(dashboard)/stats/page-9162acbb9015dd27.js +1 -0
- package/web/.next/static/chunks/app/_global-error/page-9162acbb9015dd27.js +1 -0
- package/web/.next/static/chunks/app/_not-found/page-9162acbb9015dd27.js +1 -0
- package/web/.next/static/chunks/app/api/auth/[...all]/route-9162acbb9015dd27.js +1 -0
- package/web/.next/static/chunks/app/api/health/route-9162acbb9015dd27.js +1 -0
- package/web/.next/static/chunks/app/api/oauth/[provider]/callback/route-9162acbb9015dd27.js +1 -0
- package/web/.next/static/chunks/app/api/oauth/[provider]/start/route-9162acbb9015dd27.js +1 -0
- package/web/.next/static/chunks/app/auth/callback/route-9162acbb9015dd27.js +1 -0
- package/web/.next/static/chunks/app/error-055d3c6a12b2b05a.js +1 -0
- package/web/.next/static/chunks/app/layout-c01e1c13a9f4e701.js +1 -0
- package/web/.next/static/chunks/app/login/page-a47d35197589a25b.js +1 -0
- package/web/.next/static/chunks/app/not-found-736acdd0781484e6.js +1 -0
- package/web/.next/static/chunks/app/onboarding/page-9162acbb9015dd27.js +1 -0
- package/web/.next/static/chunks/app/page-9162acbb9015dd27.js +1 -0
- package/web/.next/static/chunks/e5009a55-c08124f2223b51cc.js +1 -0
- package/web/.next/static/chunks/framework-dfbc3562811a52e8.js +1 -0
- package/web/.next/static/chunks/main-200183420347a1ea.js +5 -0
- package/web/.next/static/chunks/main-app-d81ba9a45427346e.js +1 -0
- package/web/.next/static/chunks/next/dist/client/components/builtin/app-error-9162acbb9015dd27.js +1 -0
- package/web/.next/static/chunks/next/dist/client/components/builtin/forbidden-9162acbb9015dd27.js +1 -0
- package/web/.next/static/chunks/next/dist/client/components/builtin/global-error-146c676c80b91e46.js +1 -0
- package/web/.next/static/chunks/next/dist/client/components/builtin/unauthorized-9162acbb9015dd27.js +1 -0
- package/web/.next/static/chunks/webpack-821bd0359b891822.js +1 -0
- package/web/.next/static/css/221ca0dcaf2fa31f.css +1 -0
- package/web/server.js +1 -1
- package/web/.next/server/chunks/376.js +0 -1
- package/web/.next/server/chunks/515.js +0 -2
- package/web/.next/server/chunks/605.js +0 -12
- package/web/.next/server/chunks/754.js +0 -62
- package/web/.next/server/chunks/856.js +0 -1
- package/web/.next/server/chunks/869.js +0 -1
- package/web/.next/static/53i9dRz-56tR45PA4C4YY/_buildManifest.js +0 -1
- package/web/.next/static/chunks/174.f5bd28884efa0000.js +0 -1
- package/web/.next/static/chunks/203.02a2bd001ebbe608.js +0 -1
- package/web/.next/static/chunks/231-fbb2baea2de90085.js +0 -1
- package/web/.next/static/chunks/363-483f33abe1809381.js +0 -1
- package/web/.next/static/chunks/45-b78e94bb1c396542.js +0 -1
- package/web/.next/static/chunks/504-baed39064a242351.js +0 -1
- package/web/.next/static/chunks/511-487710d0fe16fbe3.js +0 -1
- package/web/.next/static/chunks/678-46261e73dea11bc7.js +0 -1
- package/web/.next/static/chunks/a7a8b010-64b9ea0922a3e9c1.js +0 -1
- package/web/.next/static/chunks/app/(dashboard)/agents/[id]/edit/page-1cbc88f6ea30c04e.js +0 -1
- package/web/.next/static/chunks/app/(dashboard)/agents/[id]/telegram/page-c3393e2e0665b0a7.js +0 -1
- package/web/.next/static/chunks/app/(dashboard)/agents/page-fe6937dec50415e9.js +0 -1
- package/web/.next/static/chunks/app/(dashboard)/approvals/page-9509351c92665fc1.js +0 -1
- package/web/.next/static/chunks/app/(dashboard)/automations/page-d06b5eb3ec1ada30.js +0 -1
- package/web/.next/static/chunks/app/(dashboard)/billing/page-88165ec8f0c4df6b.js +0 -1
- package/web/.next/static/chunks/app/(dashboard)/connectors/page-9189af92fc7cddd4.js +0 -1
- package/web/.next/static/chunks/app/(dashboard)/credentials/page-9ad4cfdfb3fda068.js +0 -1
- package/web/.next/static/chunks/app/(dashboard)/jobs/[id]/page-fdaeff5be0544e4c.js +0 -1
- package/web/.next/static/chunks/app/(dashboard)/jobs/page-c1ddb55d4de1ae7d.js +0 -1
- package/web/.next/static/chunks/app/(dashboard)/layout-7ad84dfaa376ab9f.js +0 -2
- package/web/.next/static/chunks/app/(dashboard)/logs/page-a6006d9cc2590a0a.js +0 -1
- package/web/.next/static/chunks/app/(dashboard)/memories/page-8466e02527ae909b.js +0 -1
- package/web/.next/static/chunks/app/(dashboard)/settings/page-d7dd2b7586e23ec9.js +0 -1
- package/web/.next/static/chunks/app/(dashboard)/skills/[id]/edit/page-7c1e1566a93b3a65.js +0 -1
- package/web/.next/static/chunks/app/(dashboard)/skills/page-30cbb1e29d7e5147.js +0 -1
- package/web/.next/static/chunks/app/(dashboard)/stats/page-ddf08b608a2840c5.js +0 -1
- package/web/.next/static/chunks/app/_global-error/page-ddf08b608a2840c5.js +0 -1
- package/web/.next/static/chunks/app/_not-found/page-ddf08b608a2840c5.js +0 -1
- package/web/.next/static/chunks/app/api/auth/[...all]/route-ddf08b608a2840c5.js +0 -1
- package/web/.next/static/chunks/app/api/health/route-ddf08b608a2840c5.js +0 -1
- package/web/.next/static/chunks/app/api/oauth/[provider]/callback/route-ddf08b608a2840c5.js +0 -1
- package/web/.next/static/chunks/app/api/oauth/[provider]/start/route-ddf08b608a2840c5.js +0 -1
- package/web/.next/static/chunks/app/auth/callback/route-ddf08b608a2840c5.js +0 -1
- package/web/.next/static/chunks/app/error-41d8134c91e8652d.js +0 -1
- package/web/.next/static/chunks/app/layout-fb836a3464648614.js +0 -1
- package/web/.next/static/chunks/app/login/page-176e4c02453c9ce9.js +0 -1
- package/web/.next/static/chunks/app/not-found-88165ec8f0c4df6b.js +0 -1
- package/web/.next/static/chunks/app/onboarding/page-ddf08b608a2840c5.js +0 -1
- package/web/.next/static/chunks/app/page-ddf08b608a2840c5.js +0 -1
- package/web/.next/static/chunks/e5009a55-3b270d90dfdebefa.js +0 -1
- package/web/.next/static/chunks/framework-a208e71e7c780968.js +0 -1
- package/web/.next/static/chunks/main-949172f5a58d52c4.js +0 -5
- package/web/.next/static/chunks/main-app-ad34d1b1511b9a1c.js +0 -1
- package/web/.next/static/chunks/next/dist/client/components/builtin/app-error-ddf08b608a2840c5.js +0 -1
- package/web/.next/static/chunks/next/dist/client/components/builtin/forbidden-ddf08b608a2840c5.js +0 -1
- package/web/.next/static/chunks/next/dist/client/components/builtin/global-error-c836ffb6bc7442ca.js +0 -1
- package/web/.next/static/chunks/next/dist/client/components/builtin/unauthorized-ddf08b608a2840c5.js +0 -1
- package/web/.next/static/chunks/webpack-ea6870dc3308aa05.js +0 -1
- package/web/.next/static/css/bd2cf2f17af36e40.css +0 -1
- /package/web/.next/static/{53i9dRz-56tR45PA4C4YY → 2lmxaWvI1cL9_1Ob3gIFq}/_ssgManifest.js +0 -0
package/README.md
CHANGED
|
@@ -1,81 +1,81 @@
|
|
|
1
|
-
# Nodal-Agents
|
|
2
|
-
|
|
3
|
-
Local-first AI agent platform. Self-host on Mac, PC, Linux, VPS, or NAS in 3 commands.
|
|
4
|
-
|
|
5
|
-
## Install in 30 seconds (Docker)
|
|
6
|
-
|
|
7
|
-
Works on any host with Docker — Mac, PC, Linux, VPS, Synology / Unraid / TrueNAS NAS, Raspberry Pi.
|
|
8
|
-
|
|
9
|
-
```bash
|
|
10
|
-
curl -O https://raw.githubusercontent.com/Kwintspiracy/nodal-agents/main/docker-compose.yml
|
|
11
|
-
docker compose up -d
|
|
12
|
-
```
|
|
13
|
-
|
|
14
|
-
Open <http://localhost:3000> — Nodal-Agents is running. Configure your LLM provider from **Settings → LLM keys** in the dashboard.
|
|
15
|
-
|
|
16
|
-
Data (config, postgres, logs) lives in the `nodal-data` Docker volume. To wipe everything: `docker compose down -v`.
|
|
17
|
-
|
|
18
|
-
The image is published to `ghcr.io/kwintspiracy/nodal-agents:latest` (multi-arch: amd64 + arm64). To pin a version, replace `latest` with a release tag (e.g. `v0.1.0`).
|
|
19
|
-
|
|
20
|
-
### Build the image locally
|
|
21
|
-
|
|
22
|
-
If you'd rather build from source instead of pulling the published image:
|
|
23
|
-
|
|
24
|
-
```bash
|
|
25
|
-
git clone https://github.com/Kwintspiracy/nodal-agents.git
|
|
26
|
-
cd nodal-agents
|
|
27
|
-
docker compose build
|
|
28
|
-
docker compose up -d
|
|
29
|
-
```
|
|
30
|
-
|
|
31
|
-
(Comment the `image:` line and uncomment `build: .` in `docker-compose.yml`.)
|
|
32
|
-
|
|
33
|
-
## Developer setup (monorepo)
|
|
34
|
-
|
|
35
|
-
```bash
|
|
36
|
-
pnpm install
|
|
37
|
-
pnpm typecheck
|
|
38
|
-
pnpm lint
|
|
39
|
-
pnpm test
|
|
40
|
-
pnpm --filter nodal-agents dev # CLI in tsx watch mode
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
## Monorepo structure
|
|
44
|
-
|
|
45
|
-
- `apps/web` — Next.js dashboard (UI)
|
|
46
|
-
- `apps/runner` — Agent runtime (HTTP API, job execution, cron ticker)
|
|
47
|
-
- `apps/cli` — `nodal-agents` install + ops command
|
|
48
|
-
- `packages/db` — Drizzle schema + migrations + client (only place that imports postgres)
|
|
49
|
-
- `packages/shared` — Zod types and constants shared across web + runner
|
|
50
|
-
- `packages/llm` — Vercel AI SDK wrapper, multi-provider abstraction
|
|
51
|
-
- `packages/tools` — Tool registration + execution + approval gates
|
|
52
|
-
- `packages/memory` — Agent memory CRUD + embeddings
|
|
53
|
-
- `packages/orchestration` — Router + Planner patterns (delegation, task board)
|
|
54
|
-
- `packages/runner-adapters` — Connectors: notion, drive, gmail, sheets, etc.
|
|
55
|
-
- `packages/delivery` — Telegram, email, future Slack/Discord
|
|
56
|
-
- `packages/auth` — Pluggable auth provider (local-trust default, better-auth opt-in, bearer-token for LAN)
|
|
57
|
-
|
|
58
|
-
## Architecture rules (enforced by `dependency-cruiser`)
|
|
59
|
-
|
|
60
|
-
- `apps/*` may import `packages/*`, never the reverse
|
|
61
|
-
- `apps/web` and `apps/runner` cannot import each other (DB or HTTP only)
|
|
62
|
-
- Only `packages/db` may import postgres clients (`pg`, `postgres`, `drizzle-orm`)
|
|
63
|
-
- `packages/runner-adapters/*` may only import from `packages/tools` and `packages/shared`
|
|
64
|
-
- No circular dependencies
|
|
65
|
-
|
|
66
|
-
Run `pnpm deps:check` locally before pushing.
|
|
67
|
-
|
|
68
|
-
## Stack
|
|
69
|
-
|
|
70
|
-
- **Runtime:** Node 22+, TypeScript strict
|
|
71
|
-
- **Monorepo:** pnpm workspaces + Turborepo
|
|
72
|
-
- **DB:** embedded-postgres (local + Docker), Drizzle ORM, pgvector
|
|
73
|
-
- **Validation:** Zod
|
|
74
|
-
- **HTTP server:** Hono (runner)
|
|
75
|
-
- **LLM:** Vercel AI SDK
|
|
76
|
-
- **Auth:** local-trust (single-user loopback) / local-auth (better-auth, multi-user LAN) / bearer-token
|
|
77
|
-
- **Tests:** Vitest (unit), Playwright (e2e), dependency-cruiser (architecture)
|
|
78
|
-
|
|
79
|
-
## License
|
|
80
|
-
|
|
81
|
-
TBD.
|
|
1
|
+
# Nodal-Agents
|
|
2
|
+
|
|
3
|
+
Local-first AI agent platform. Self-host on Mac, PC, Linux, VPS, or NAS in 3 commands.
|
|
4
|
+
|
|
5
|
+
## Install in 30 seconds (Docker)
|
|
6
|
+
|
|
7
|
+
Works on any host with Docker — Mac, PC, Linux, VPS, Synology / Unraid / TrueNAS NAS, Raspberry Pi.
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
curl -O https://raw.githubusercontent.com/Kwintspiracy/nodal-agents/main/docker-compose.yml
|
|
11
|
+
docker compose up -d
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
Open <http://localhost:3000> — Nodal-Agents is running. Configure your LLM provider from **Settings → LLM keys** in the dashboard.
|
|
15
|
+
|
|
16
|
+
Data (config, postgres, logs) lives in the `nodal-data` Docker volume. To wipe everything: `docker compose down -v`.
|
|
17
|
+
|
|
18
|
+
The image is published to `ghcr.io/kwintspiracy/nodal-agents:latest` (multi-arch: amd64 + arm64). To pin a version, replace `latest` with a release tag (e.g. `v0.1.0`).
|
|
19
|
+
|
|
20
|
+
### Build the image locally
|
|
21
|
+
|
|
22
|
+
If you'd rather build from source instead of pulling the published image:
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
git clone https://github.com/Kwintspiracy/nodal-agents.git
|
|
26
|
+
cd nodal-agents
|
|
27
|
+
docker compose build
|
|
28
|
+
docker compose up -d
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
(Comment the `image:` line and uncomment `build: .` in `docker-compose.yml`.)
|
|
32
|
+
|
|
33
|
+
## Developer setup (monorepo)
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
pnpm install
|
|
37
|
+
pnpm typecheck
|
|
38
|
+
pnpm lint
|
|
39
|
+
pnpm test
|
|
40
|
+
pnpm --filter nodal-agents dev # CLI in tsx watch mode
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Monorepo structure
|
|
44
|
+
|
|
45
|
+
- `apps/web` — Next.js dashboard (UI)
|
|
46
|
+
- `apps/runner` — Agent runtime (HTTP API, job execution, cron ticker)
|
|
47
|
+
- `apps/cli` — `nodal-agents` install + ops command
|
|
48
|
+
- `packages/db` — Drizzle schema + migrations + client (only place that imports postgres)
|
|
49
|
+
- `packages/shared` — Zod types and constants shared across web + runner
|
|
50
|
+
- `packages/llm` — Vercel AI SDK wrapper, multi-provider abstraction
|
|
51
|
+
- `packages/tools` — Tool registration + execution + approval gates
|
|
52
|
+
- `packages/memory` — Agent memory CRUD + embeddings
|
|
53
|
+
- `packages/orchestration` — Router + Planner patterns (delegation, task board)
|
|
54
|
+
- `packages/runner-adapters` — Connectors: notion, drive, gmail, sheets, etc.
|
|
55
|
+
- `packages/delivery` — Telegram, email, future Slack/Discord
|
|
56
|
+
- `packages/auth` — Pluggable auth provider (local-trust default, better-auth opt-in, bearer-token for LAN)
|
|
57
|
+
|
|
58
|
+
## Architecture rules (enforced by `dependency-cruiser`)
|
|
59
|
+
|
|
60
|
+
- `apps/*` may import `packages/*`, never the reverse
|
|
61
|
+
- `apps/web` and `apps/runner` cannot import each other (DB or HTTP only)
|
|
62
|
+
- Only `packages/db` may import postgres clients (`pg`, `postgres`, `drizzle-orm`)
|
|
63
|
+
- `packages/runner-adapters/*` may only import from `packages/tools` and `packages/shared`
|
|
64
|
+
- No circular dependencies
|
|
65
|
+
|
|
66
|
+
Run `pnpm deps:check` locally before pushing.
|
|
67
|
+
|
|
68
|
+
## Stack
|
|
69
|
+
|
|
70
|
+
- **Runtime:** Node 22+, TypeScript strict
|
|
71
|
+
- **Monorepo:** pnpm workspaces + Turborepo
|
|
72
|
+
- **DB:** embedded-postgres (local + Docker), Drizzle ORM, pgvector
|
|
73
|
+
- **Validation:** Zod
|
|
74
|
+
- **HTTP server:** Hono (runner)
|
|
75
|
+
- **LLM:** Vercel AI SDK
|
|
76
|
+
- **Auth:** local-trust (single-user loopback) / local-auth (better-auth, multi-user LAN) / bearer-token
|
|
77
|
+
- **Tests:** Vitest (unit), Playwright (e2e), dependency-cruiser (architecture)
|
|
78
|
+
|
|
79
|
+
## License
|
|
80
|
+
|
|
81
|
+
TBD.
|
package/cli.js
CHANGED
|
@@ -12323,6 +12323,16 @@ var init_agents = __esm({
|
|
|
12323
12323
|
avatarUrl: text("avatar_url"),
|
|
12324
12324
|
systemAgent: boolean("system_agent").default(false),
|
|
12325
12325
|
maxTokensPerJob: integer("max_tokens_per_job").default(0).notNull(),
|
|
12326
|
+
// Cap on characters of agent_memory injected into the system prompt per job
|
|
12327
|
+
// (Memory Sprint 2). Pure char budget — token estimation done at call site
|
|
12328
|
+
// (length/4). 1500 chars ≈ ~375 tokens, similar to Hermes' 2200+1375 split.
|
|
12329
|
+
memoryTokenBudget: integer("memory_token_budget").default(1500).notNull(),
|
|
12330
|
+
// Absolute filesystem path the agent's file_* tools are scoped to. NULL =
|
|
12331
|
+
// file tools fail loud (`workspace_not_configured`). Per-agent so each
|
|
12332
|
+
// agent in an entity can have its own scope (e.g. one agent on Obsidian
|
|
12333
|
+
// vault, another on a code repo). Resolution at tool-call time runs
|
|
12334
|
+
// through realpath + boundary check (see file-ops/workspace.ts).
|
|
12335
|
+
workspaceRootPath: text("workspace_root_path"),
|
|
12326
12336
|
createdAt: timestamp("created_at", { withTimezone: true }).defaultNow(),
|
|
12327
12337
|
updatedAt: timestamp("updated_at", { withTimezone: true }).defaultNow()
|
|
12328
12338
|
},
|
|
@@ -12387,7 +12397,7 @@ var init_jobs = __esm({
|
|
|
12387
12397
|
{
|
|
12388
12398
|
id: uuid("id").primaryKey().defaultRandom(),
|
|
12389
12399
|
entityId: uuid("entity_id").references(() => entities.id, { onDelete: "cascade" }),
|
|
12390
|
-
agentId: uuid("agent_id").references(() => agents.id),
|
|
12400
|
+
agentId: uuid("agent_id").references(() => agents.id, { onDelete: "cascade" }),
|
|
12391
12401
|
status: text("status").default("pending"),
|
|
12392
12402
|
channel: text("channel").notNull(),
|
|
12393
12403
|
task: text("task").notNull(),
|
|
@@ -12407,6 +12417,21 @@ var init_jobs = __esm({
|
|
|
12407
12417
|
inputTokens: integer("input_tokens").default(0),
|
|
12408
12418
|
outputTokens: integer("output_tokens").default(0),
|
|
12409
12419
|
delegationDepth: integer("delegation_depth").default(0),
|
|
12420
|
+
/**
|
|
12421
|
+
* The slug of the last delegated child that failed on this parent job.
|
|
12422
|
+
* Set by `resumeDelegated` when a child returns `{status:'failed'}`, cleared
|
|
12423
|
+
* when any subsequent delegation succeeds. The runner uses this to block
|
|
12424
|
+
* NAIVE retries (parent re-emitting `assign_<sameSlug>` immediately after a
|
|
12425
|
+
* failure) while still allowing FALLBACK strategies (parent emitting
|
|
12426
|
+
* `assign_<differentSlug>` after a failure, e.g. note-taker as a fallback
|
|
12427
|
+
* after summarizer timeout).
|
|
12428
|
+
*
|
|
12429
|
+
* Replaces the earlier `failed_delegations_count` global counter from
|
|
12430
|
+
* commit `b76d449`, which was too coarse — it blocked ALL further
|
|
12431
|
+
* delegations after one failure, including legitimate fallbacks to a
|
|
12432
|
+
* different specialist (live regression: job `7767a3c1`, 2026-05-19).
|
|
12433
|
+
*/
|
|
12434
|
+
lastFailedDelegationSlug: text("last_failed_delegation_slug"),
|
|
12410
12435
|
pendingDelegation: jsonb("pending_delegation"),
|
|
12411
12436
|
completedAt: timestamp("completed_at", { withTimezone: true }),
|
|
12412
12437
|
createdAt: timestamp("created_at", { withTimezone: true }).defaultNow(),
|
|
@@ -12458,8 +12483,12 @@ var init_tasks = __esm({
|
|
|
12458
12483
|
priority: text("priority").notNull().default("medium"),
|
|
12459
12484
|
jobId: uuid("job_id").references(() => agentJobs.id, { onDelete: "set null" }),
|
|
12460
12485
|
result: text("result"),
|
|
12461
|
-
createdByAgentId: uuid("created_by_agent_id").references(() => agents.id
|
|
12462
|
-
|
|
12486
|
+
createdByAgentId: uuid("created_by_agent_id").references(() => agents.id, {
|
|
12487
|
+
onDelete: "cascade"
|
|
12488
|
+
}),
|
|
12489
|
+
assignedAgentId: uuid("assigned_agent_id").references(() => agents.id, {
|
|
12490
|
+
onDelete: "cascade"
|
|
12491
|
+
}),
|
|
12463
12492
|
inputTokens: integer("input_tokens").default(0),
|
|
12464
12493
|
outputTokens: integer("output_tokens").default(0),
|
|
12465
12494
|
costUsd: numeric("cost_usd", { precision: 10, scale: 6 }).default("0"),
|
|
@@ -12562,8 +12591,10 @@ var init_connectors = __esm({
|
|
|
12562
12591
|
check(
|
|
12563
12592
|
"connectors_auth_type_check",
|
|
12564
12593
|
sql`${table.authType} IN ('api_key','oauth2','bearer','basic','none')`
|
|
12565
|
-
)
|
|
12566
|
-
|
|
12594
|
+
)
|
|
12595
|
+
// Multi-instance brique (migration 0016): the (entity_id, slug) UNIQUE
|
|
12596
|
+
// constraint was dropped to allow multiple instances of the same connector
|
|
12597
|
+
// type per entity (e.g. several Gmail accounts).
|
|
12567
12598
|
]
|
|
12568
12599
|
);
|
|
12569
12600
|
}
|
|
@@ -12617,7 +12648,7 @@ var init_approvals = __esm({
|
|
|
12617
12648
|
id: uuid("id").primaryKey().defaultRandom(),
|
|
12618
12649
|
entityId: uuid("entity_id").references(() => entities.id, { onDelete: "cascade" }),
|
|
12619
12650
|
jobId: uuid("job_id").notNull().references(() => agentJobs.id, { onDelete: "cascade" }),
|
|
12620
|
-
agentId: uuid("agent_id").references(() => agents.id),
|
|
12651
|
+
agentId: uuid("agent_id").references(() => agents.id, { onDelete: "cascade" }),
|
|
12621
12652
|
toolName: text("tool_name").notNull(),
|
|
12622
12653
|
toolInput: jsonb("tool_input").notNull(),
|
|
12623
12654
|
status: text("status").default("pending"),
|
|
@@ -12689,7 +12720,7 @@ var init_memory2 = __esm({
|
|
|
12689
12720
|
{
|
|
12690
12721
|
id: uuid("id").primaryKey().defaultRandom(),
|
|
12691
12722
|
entityId: uuid("entity_id").references(() => entities.id, { onDelete: "cascade" }),
|
|
12692
|
-
agentId: uuid("agent_id").references(() => agents.id),
|
|
12723
|
+
agentId: uuid("agent_id").references(() => agents.id, { onDelete: "cascade" }),
|
|
12693
12724
|
fact: text("fact").notNull(),
|
|
12694
12725
|
category: text("category").default("context"),
|
|
12695
12726
|
importance: integer("importance").default(3),
|
|
@@ -12892,7 +12923,7 @@ var init_runs = __esm({
|
|
|
12892
12923
|
{
|
|
12893
12924
|
id: uuid("id").primaryKey().defaultRandom(),
|
|
12894
12925
|
entityId: uuid("entity_id").references(() => entities.id, { onDelete: "cascade" }),
|
|
12895
|
-
agentId: uuid("agent_id").references(() => agents.id),
|
|
12926
|
+
agentId: uuid("agent_id").references(() => agents.id, { onDelete: "cascade" }),
|
|
12896
12927
|
task: text("task").notNull(),
|
|
12897
12928
|
result: text("result"),
|
|
12898
12929
|
success: boolean("success").default(true),
|
|
@@ -12939,12 +12970,32 @@ var init_mcp = __esm({
|
|
|
12939
12970
|
command: text("command"),
|
|
12940
12971
|
args: text("args").array().default(sql`'{}'::text[]`),
|
|
12941
12972
|
envVars: jsonb("env_vars").default(sql`'{}'::jsonb`),
|
|
12973
|
+
// Encrypted (enc:v1: blob) credential for HTTP MCP servers — same pattern
|
|
12974
|
+
// as connectors.api_key. NULL for servers that need no auth.
|
|
12975
|
+
apiKey: text("api_key"),
|
|
12976
|
+
// Plaintext last 4 chars of the key for masked UI display only.
|
|
12977
|
+
apiKeyLast4: text("api_key_last4"),
|
|
12978
|
+
// How the API key is injected into the HTTP request: 'header' (a request
|
|
12979
|
+
// header named by auth_param_name) or 'query' (a URL query param). NULL =
|
|
12980
|
+
// no auth.
|
|
12981
|
+
authScheme: text("auth_scheme"),
|
|
12982
|
+
// The literal header name or query param name (e.g. 'x-api-key', 'api_key').
|
|
12983
|
+
authParamName: text("auth_param_name"),
|
|
12942
12984
|
active: boolean("active").default(true),
|
|
12943
12985
|
availableTools: jsonb("available_tools"),
|
|
12944
12986
|
createdAt: timestamp("created_at", { withTimezone: true }).defaultNow(),
|
|
12945
12987
|
updatedAt: timestamp("updated_at", { withTimezone: true }).defaultNow()
|
|
12946
12988
|
},
|
|
12947
|
-
(table) => [
|
|
12989
|
+
(table) => [
|
|
12990
|
+
check("mcp_servers_transport_check", sql`${table.transport} IN ('http','stdio')`),
|
|
12991
|
+
check(
|
|
12992
|
+
"mcp_servers_auth_scheme_check",
|
|
12993
|
+
sql`${table.authScheme} IN ('header','query') OR ${table.authScheme} IS NULL`
|
|
12994
|
+
)
|
|
12995
|
+
// Multi-instance brique (migration 0017): the (entity_id, slug) UNIQUE
|
|
12996
|
+
// index was dropped to allow multiple instances of the same MCP server
|
|
12997
|
+
// type per entity (e.g. two Cogni Cortex accounts).
|
|
12998
|
+
]
|
|
12948
12999
|
);
|
|
12949
13000
|
agentMcpServers = pgTable(
|
|
12950
13001
|
"agent_mcp_servers",
|
|
@@ -12959,7 +13010,10 @@ var init_mcp = __esm({
|
|
|
12959
13010
|
},
|
|
12960
13011
|
(table) => [
|
|
12961
13012
|
index("idx_agent_mcp_servers_agent").on(table.agentId),
|
|
12962
|
-
index("idx_agent_mcp_servers_entity").on(table.entityId)
|
|
13013
|
+
index("idx_agent_mcp_servers_entity").on(table.entityId),
|
|
13014
|
+
// Backs the assign/unassign UPSERT (onConflictDoUpdate) — one assignment
|
|
13015
|
+
// row per (agent, server).
|
|
13016
|
+
uniqueIndex("agent_mcp_servers_agent_server_unique").on(table.agentId, table.mcpServerId)
|
|
12963
13017
|
]
|
|
12964
13018
|
);
|
|
12965
13019
|
mcpConnections = pgTable(
|