nodal-agents 0.4.4 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +46 -21
- package/cli.js +88 -99
- package/migrations/0035_community_agent_skills.sql +13 -0
- package/migrations/0036_agent_jobs_effective_input_tokens.sql +18 -0
- package/migrations/0037_agent_jobs_total_cost_usd.sql +11 -0
- package/migrations/0038_agent_jobs_served_provider.sql +7 -0
- package/migrations/0039_agent_skills_learning_loop.sql +20 -0
- package/migrations/0040_entities_last_curator_run.sql +7 -0
- package/migrations/0041_reflection_enabled.sql +1 -0
- package/migrations/0042_drop_agent_runs.sql +1 -0
- package/migrations/0043_skill_assignment.sql +2 -0
- package/migrations/meta/_journal.json +307 -244
- package/package.json +4 -1
- package/runner.js +11967 -2097
- package/web/.next/BUILD_ID +1 -1
- package/web/.next/app-path-routes-manifest.json +2 -1
- package/web/.next/build-manifest.json +2 -2
- package/web/.next/prerender-manifest.json +3 -3
- package/web/.next/routes-manifest.json +6 -0
- package/web/.next/server/app/(dashboard)/agents/[id]/edit/page.js +3 -3
- 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)/chat/page.js +2 -2
- package/web/.next/server/app/(dashboard)/chat/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/chat/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)/learned-skills/page.js +2 -0
- package/web/.next/server/app/(dashboard)/learned-skills/page.js.nft.json +1 -0
- package/web/.next/server/app/(dashboard)/learned-skills/page_client-reference-manifest.js +1 -0
- package/web/.next/server/app/(dashboard)/llm-providers/page.js +2 -2
- package/web/.next/server/app/(dashboard)/llm-providers/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/llm-providers/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 -2
- package/web/.next/server/app/(dashboard)/mcp/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/mcp/page_client-reference-manifest.js +1 -1
- 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)/page.js +4 -4
- package/web/.next/server/app/(dashboard)/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/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/new/page.js +2 -2
- package/web/.next/server/app/(dashboard)/skills/new/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/skills/new/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/_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 +2 -2
- package/web/.next/server/app/_global-error.segments/_full.segment.rsc +2 -2
- 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 +2 -2
- 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 +3 -3
- package/web/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
- package/web/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/web/.next/server/app/_not-found.segments/_index.segment.rsc +3 -3
- 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/health/route.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]/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/auth/callback/route.js +1 -1
- package/web/.next/server/app/login/page.js +2 -2
- 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 +3 -3
- package/web/.next/server/app/onboarding.segments/_full.segment.rsc +3 -3
- package/web/.next/server/app/onboarding.segments/_head.segment.rsc +1 -1
- package/web/.next/server/app/onboarding.segments/_index.segment.rsc +3 -3
- 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-paths-manifest.json +2 -1
- package/web/.next/server/chunks/1567.js +16 -0
- package/web/.next/server/chunks/3279.js +1 -0
- package/web/.next/server/chunks/3636.js +1 -0
- package/web/.next/server/chunks/3966.js +1 -0
- package/web/.next/server/chunks/4108.js +1 -0
- package/web/.next/server/chunks/4574.js +1 -1
- package/web/.next/server/chunks/511.js +1 -0
- package/web/.next/server/chunks/7741.js +16 -16
- package/web/.next/server/chunks/{7826.js → 8732.js} +27 -27
- package/web/.next/server/chunks/8978.js +1 -0
- package/web/.next/server/chunks/9798.js +1 -0
- package/web/.next/server/middleware-build-manifest.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/PbmIekL33DORo2X47l_Ar/_buildManifest.js +1 -0
- package/web/.next/static/chunks/3178-bde220b789f10130.js +1 -0
- package/web/.next/static/chunks/4454-882460b60106f0d5.js +1 -0
- package/web/.next/static/chunks/6078-abdc3955397924b3.js +1 -0
- package/web/.next/static/chunks/{9098-2bfef80a73c706b3.js → 6347-6d9d5ab25cbd59b9.js} +1 -1
- package/web/.next/static/chunks/6413-c2d4ac3709048f19.js +1 -0
- package/web/.next/static/chunks/{8666-90a1f5d99b79411e.js → 6908-e8114db85dca4371.js} +1 -1
- package/web/.next/static/chunks/7164-a5cae6a1833041a7.js +1 -0
- package/web/.next/static/chunks/app/(dashboard)/agents/[id]/edit/page-651673d70c193f79.js +2 -0
- package/web/.next/static/chunks/app/(dashboard)/agents/[id]/telegram/page-1471b733a0d6dd17.js +1 -0
- package/web/.next/static/chunks/app/(dashboard)/agents/page-2a30943e74c78967.js +1 -0
- package/web/.next/static/chunks/app/(dashboard)/approvals/page-6d8c74fd86d2d3c3.js +1 -0
- package/web/.next/static/chunks/app/(dashboard)/automations/page-3b724d8f6e8c957f.js +1 -0
- package/web/.next/static/chunks/app/(dashboard)/chat/page-b98de38c17f2cd96.js +1 -0
- package/web/.next/static/chunks/app/(dashboard)/connectors/page-6591a8753b6a19c1.js +1 -0
- package/web/.next/static/chunks/app/(dashboard)/credentials/page-19061f4a8bf1978f.js +1 -0
- package/web/.next/static/chunks/app/(dashboard)/jobs/[id]/page-7e9af908ef12f252.js +1 -0
- package/web/.next/static/chunks/app/(dashboard)/jobs/page-9b09d95cc1a8053c.js +1 -0
- package/web/.next/static/chunks/app/(dashboard)/layout-509579b7d75ffd9d.js +1 -0
- package/web/.next/static/chunks/app/(dashboard)/learned-skills/page-447ba18bc6af3c57.js +1 -0
- package/web/.next/static/chunks/app/(dashboard)/llm-providers/page-c0c5aa806b9b47d4.js +1 -0
- package/web/.next/static/chunks/app/(dashboard)/logs/page-21d587049e8a6ccb.js +1 -0
- package/web/.next/static/chunks/app/(dashboard)/mcp/page-f9337250ed07249e.js +1 -0
- package/web/.next/static/chunks/app/(dashboard)/memories/page-b935752c6cb36a04.js +1 -0
- package/web/.next/static/chunks/app/(dashboard)/{page-29cfae3bf701076e.js → page-2a69294b49293833.js} +1 -1
- package/web/.next/static/chunks/app/(dashboard)/settings/page-5862a4767233ec26.js +1 -0
- package/web/.next/static/chunks/app/(dashboard)/skills/[id]/edit/page-85c75cc88ee1d6a8.js +1 -0
- package/web/.next/static/chunks/app/(dashboard)/skills/new/page-9b0777fccb89a00b.js +1 -0
- package/web/.next/static/chunks/app/(dashboard)/skills/page-e25db7f660751dfd.js +1 -0
- package/web/.next/static/css/46db738e95b440c0.css +3 -0
- package/web/.next/server/chunks/3233.js +0 -1
- package/web/.next/server/chunks/3889.js +0 -1
- package/web/.next/server/chunks/4808.js +0 -1
- package/web/.next/server/chunks/5329.js +0 -1
- package/web/.next/server/chunks/593.js +0 -1
- package/web/.next/server/chunks/6128.js +0 -1
- package/web/.next/server/chunks/7231.js +0 -1
- package/web/.next/server/chunks/7466.js +0 -16
- package/web/.next/static/PV5qpGylrVW3jZ7zKHuhE/_buildManifest.js +0 -1
- package/web/.next/static/chunks/8396-f3502b9af3172006.js +0 -1
- package/web/.next/static/chunks/9123-67530ba510c58003.js +0 -1
- package/web/.next/static/chunks/9167-12a4a42d1a7d7db5.js +0 -1
- package/web/.next/static/chunks/9582-fbf7c8d9b2a39101.js +0 -1
- package/web/.next/static/chunks/app/(dashboard)/agents/[id]/edit/page-a2c267f563cd1a70.js +0 -2
- package/web/.next/static/chunks/app/(dashboard)/agents/[id]/telegram/page-2d7cae43f5e6952a.js +0 -1
- package/web/.next/static/chunks/app/(dashboard)/agents/page-bed833ebdd3646fb.js +0 -1
- package/web/.next/static/chunks/app/(dashboard)/approvals/page-4b27762472802ce0.js +0 -1
- package/web/.next/static/chunks/app/(dashboard)/automations/page-9e5d2ce807ce1c37.js +0 -1
- package/web/.next/static/chunks/app/(dashboard)/chat/page-8f81d7e3abb475a6.js +0 -1
- package/web/.next/static/chunks/app/(dashboard)/connectors/page-39b1d9560235d574.js +0 -1
- package/web/.next/static/chunks/app/(dashboard)/credentials/page-f1e797e327ecdf7c.js +0 -1
- package/web/.next/static/chunks/app/(dashboard)/jobs/[id]/page-112bb22a9ec43be0.js +0 -1
- package/web/.next/static/chunks/app/(dashboard)/jobs/page-44351170ed5f9180.js +0 -1
- package/web/.next/static/chunks/app/(dashboard)/layout-53e69de869cba0d0.js +0 -1
- package/web/.next/static/chunks/app/(dashboard)/llm-providers/page-8f6ce47ba228e38b.js +0 -1
- package/web/.next/static/chunks/app/(dashboard)/logs/page-b814deb9854b0cb5.js +0 -1
- package/web/.next/static/chunks/app/(dashboard)/mcp/page-cdf057e468c6e92e.js +0 -1
- package/web/.next/static/chunks/app/(dashboard)/memories/page-e706ab4aa681fa99.js +0 -1
- package/web/.next/static/chunks/app/(dashboard)/settings/page-312ae27ae71ea6d1.js +0 -1
- package/web/.next/static/chunks/app/(dashboard)/skills/[id]/edit/page-89a8a30db5eb96e1.js +0 -1
- package/web/.next/static/chunks/app/(dashboard)/skills/new/page-46a424b203591560.js +0 -1
- package/web/.next/static/chunks/app/(dashboard)/skills/page-edad7bbd3230fb7a.js +0 -1
- package/web/.next/static/css/78ead23854ab041e.css +0 -3
- /package/web/.next/static/{PV5qpGylrVW3jZ7zKHuhE → PbmIekL33DORo2X47l_Ar}/_ssgManifest.js +0 -0
package/README.md
CHANGED
|
@@ -23,11 +23,13 @@ with **any LLM** — frontier or local, paid or free.
|
|
|
23
23
|
| | |
|
|
24
24
|
| --- | --- |
|
|
25
25
|
| 🏠 **Local-first** | Single binary, embedded Postgres, zero cloud dependency. Your conversations, memory, and credentials stay on your machine. |
|
|
26
|
-
| 🔌 **Any model, per agent** | Anthropic, OpenAI, Google, Groq, Mistral, OpenRouter, or any local model (LM Studio, Ollama). Setup is just an API key per provider — **each agent picks its own model**, so you can run Claude for the orchestrator and **DeepSeek V4** for the workers. The quirks of OSS frontier models (DeepSeek's non-spec tool args, Kimi/Qwen/GLM XML tool formats, and round-tripping a reasoning model's chain-of-thought across tool calls so MiniMax M3 / DeepSeek / Gemini 3 don't degrade mid-task) are handled automatically. |
|
|
26
|
+
| 🔌 **Any model, per agent** | Anthropic, OpenAI, Google, Groq, Mistral, OpenRouter, **native DeepSeek** (`api.deepseek.com`) and **native MiniMax** (`api.minimax.io`), or any local model (LM Studio, Ollama). Setup is just an API key per provider — **each agent picks its own model**, so you can run Claude for the orchestrator and **DeepSeek V4** for the workers. The quirks of OSS frontier models (DeepSeek's non-spec tool args, Kimi/Qwen/GLM XML tool formats, and round-tripping a reasoning model's chain-of-thought across tool calls so MiniMax M3 / DeepSeek / Gemini 3 don't degrade mid-task) are handled automatically. |
|
|
27
27
|
| 🛟 **Provider failover** | Give an agent a backup key chain — if its provider 5xx's, times out, or hits quota mid-job, the runner fails over to the next one and keeps going (and fails loud only when the whole chain is down). |
|
|
28
28
|
| 🧠 **Memory that compounds** | Persistent facts (entity-scoped, auto-injected into every job) and chat-thread continuity (your agent remembers what it said 30 seconds ago — and what it said yesterday). |
|
|
29
|
-
| 🤝 **Orchestrators that finish** |
|
|
30
|
-
|
|
|
29
|
+
| 🤝 **Orchestrators that finish** | Every orchestrator picks the delegation style per request — route to one specialist and resume on its result, or fan out independent work to many sub-agents in parallel and compile their results — then wraps up the answer. |
|
|
30
|
+
| 🌱 **Self-improving agents** | Opt-in learning loop: after a substantial job, an agent reflects on the transcript and writes itself a reusable skill; a weekly curator consolidates and prunes them. Every learned skill is reviewable, assignable, and revocable from the dashboard (off by default, per workspace). |
|
|
31
|
+
| 📥 **Install any community skill** | Point it at any open `SKILL.md` — a GitHub repo, a skills.sh slug, or a ClawHub package — and it fetches, unpacks, and installs it as a first-class skill. Pure HTTPS fetch with SSRF allow-listing and zip-slip guards; bundled scripts are flagged, never executed. |
|
|
32
|
+
| 🛡️ **Agents that don't lie, loop, or die** | Generic runtime guards: a per-job **real-dollar cost cap** (from the provider's actual billed cost) and a no-progress detector kill runaway loops; a no-false-success guard refuses to report "done" when an action actually failed; an atomic job claim prevents the same job running twice; and every failed or blocked job hands you a short, specific reason — never a silent stop. Turn/chain/delegation caps bound everything. |
|
|
31
33
|
| 🔧 **Multi-instance connectors** | Gmail perso *and* Gmail boulot on the same install. OAuth *and* API-key supported. Active list + Marketplace UI in the dashboard. |
|
|
32
34
|
| 🗂️ **Workspaces** | Multiple isolated workspaces on one install (personal vs work) — each with its own agents, skills, connectors, jobs and memory. Switch from the sidebar. |
|
|
33
35
|
| 🤖 **Self-extending (ROOT agent)** | Designate an orchestrator as ROOT and let it create skills/agents and assign them on your behalf — gated by per-grant toggles and an autonomy level (propose-confirm → fully-autonomous). |
|
|
@@ -84,7 +86,7 @@ When a newer version is available, `nodal-agents up` also prints a one-line
|
|
|
84
86
|
notice:
|
|
85
87
|
|
|
86
88
|
```
|
|
87
|
-
ℹ v0.
|
|
89
|
+
ℹ v0.5.1 available — run `nodal-agents update`
|
|
88
90
|
```
|
|
89
91
|
|
|
90
92
|
### Build from source
|
|
@@ -144,7 +146,8 @@ Delegations create child jobs that resume the parent on completion.
|
|
|
144
146
|
| `/connectors` | Active connector instances + Marketplace (multi-instance, OAuth or API-key). |
|
|
145
147
|
| `/mcp` | Active MCP servers + Marketplace — HTTP & stdio, a growing catalogue, plus add/edit your own custom servers. |
|
|
146
148
|
| `/memories` | Persistent facts per entity — search, edit, archive. |
|
|
147
|
-
| `/skills` | Assigned / Custom / Built-in Library tabs — reusable instructions appended to an agent's prompt; create your own
|
|
149
|
+
| `/skills` | Assigned / Custom / Built-in Library tabs — reusable instructions appended to an agent's prompt; create your own, customise built-ins, or install any community `SKILL.md` from GitHub / skills.sh / ClawHub. |
|
|
150
|
+
| `/learned-skills` | Skills the agents wrote themselves (learning loop) — review, assign, archive, restore; toggle reflection + auto-assign per workspace. |
|
|
148
151
|
| `/logs` | Tool-call audit — input/output JSON per call, filterable by tool name. |
|
|
149
152
|
| `/approvals` | Human-in-the-loop gates for risky tools (and the ROOT agent's meta-tools under propose-confirm). |
|
|
150
153
|
| `/automations` | Cron-scheduled agent triggers. |
|
|
@@ -212,7 +215,7 @@ pnpm deps:check # runs locally and in CI before every release
|
|
|
212
215
|
|
|
213
216
|
## Status
|
|
214
217
|
|
|
215
|
-
**Current release:** `0.
|
|
218
|
+
**Current release:** `0.5.0` on npm `latest`. Used daily by the
|
|
216
219
|
maintainer, stable enough for personal production. Pre-1.0 — breaking
|
|
217
220
|
changes are still possible between minors.
|
|
218
221
|
|
|
@@ -220,26 +223,45 @@ changes are still possible between minors.
|
|
|
220
223
|
|
|
221
224
|
- Multi-LLM, **per-agent model selection** — provider setup is just an API key
|
|
222
225
|
(one per provider); each agent chooses its own model on top. Frontier and
|
|
223
|
-
local providers,
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
226
|
+
local providers, plus **native DeepSeek** (`api.deepseek.com`) and **native
|
|
227
|
+
MiniMax** (`api.minimax.io`) endpoints alongside OpenRouter — pick the route
|
|
228
|
+
per key. **DeepSeek V4** non-spec tool-call args are normalized automatically
|
|
229
|
+
and **reasoning models like MiniMax M3** have their hidden chain-of-thought
|
|
230
|
+
round-tripped across tool calls so they keep reasoning on multi-turn tasks,
|
|
231
|
+
plus native tool-call parsing for Kimi K2 / Qwen3-Coder / GLM
|
|
227
232
|
- **Provider failover** — an opt-in ordered key chain per agent; on a 5xx /
|
|
228
233
|
timeout / quota mid-job the runner fails over to the next key, and fails loud
|
|
229
234
|
(`all_providers_failed`) only when the whole chain is exhausted
|
|
230
|
-
- **Reliability guards (generic, model-agnostic)** — per-job
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
235
|
+
- **Reliability guards (generic, model-agnostic)** — a per-job **real-dollar
|
|
236
|
+
cost cap** (read from the provider's actually-billed cost, `cost_budget_exceeded`)
|
|
237
|
+
+ token budget + no-progress / no-delivery detectors (kill runaway loops), an
|
|
238
|
+
**atomic job claim** so the same job never executes twice, a no-false-success
|
|
239
|
+
guard that refuses to complete a job as "success" when a tool action failed and
|
|
240
|
+
was never resolved (fail loud, never fake it), a **recoverable** path for a
|
|
241
|
+
mis-named tool call (a bounded "did you mean…" nudge, not an instant kill), and
|
|
242
|
+
context compaction that evicts stale tool output before the context window overflows
|
|
243
|
+
- **Never a silent stop** — every failed *or blocked* job hands the user a short,
|
|
244
|
+
specific reason (in the agent's own words when it blocks), propagated up through
|
|
245
|
+
delegation; a blocked job is honestly `failed`, never a fake "completed"
|
|
246
|
+
- **Diagnosable failures** — every failed job persists its full transcript, the
|
|
247
|
+
real upstream provider error (not an opaque "provider returned error"), and the
|
|
248
|
+
actual upstream that served each turn, so you can see exactly what the agent did
|
|
249
|
+
and why it stopped
|
|
250
|
+
- **Self-improving agents (opt-in learning loop)** — after a substantial job, an
|
|
251
|
+
agent reflects on its transcript and writes itself a reusable skill (sandboxed
|
|
252
|
+
provenance); a weekly curator consolidates and prunes them. Review, assign,
|
|
253
|
+
archive or revoke every learned skill from `/learned-skills` (off by default,
|
|
254
|
+
per workspace; auto-assign or require approval)
|
|
255
|
+
- **Install any community skill** — fetch any open `SKILL.md` from a GitHub repo,
|
|
256
|
+
a skills.sh slug, or a ClawHub package and install it as a first-class skill
|
|
257
|
+
(pure HTTPS, SSRF allow-list, zip-slip guard; bundled scripts flagged, never run)
|
|
238
258
|
- Persistent memory (sanitation, dedup, importance ranking, auto-injection,
|
|
239
259
|
feedback loop)
|
|
240
260
|
- Session-thread continuity on chat channels (Telegram today)
|
|
241
|
-
-
|
|
242
|
-
|
|
261
|
+
- **Unified orchestrator** — every orchestrator gets both delegation styles and
|
|
262
|
+
picks per request: route to one specialist and resume on its result (router),
|
|
263
|
+
or fan out independent tasks to a parallel task board that compiles + delivers
|
|
264
|
+
the combined result (planner). One commits to a single style per job
|
|
243
265
|
- Multi-instance connectors with OAuth (Gmail, Drive, Sheets, Docs, Notion,
|
|
244
266
|
Airtable) and API-key (Notion, Airtable, Apify, Firecrawl, Tavily)
|
|
245
267
|
- MCP catalog — Streamable HTTP *and* stdio (local subprocess) servers, API-key auth; a growing catalogue (Stripe, n8n, Supabase, Airtable, Notion…) with a "test pending" badge on entries not yet verified live, plus add *and edit* your own custom HTTP/stdio servers from the dashboard
|
|
@@ -254,8 +276,11 @@ changes are still possible between minors.
|
|
|
254
276
|
rather than completing a job without ever replying
|
|
255
277
|
- Approval gates for risky tools (execute-the-approved-action on resume) — on a chat channel, the agent sends a heads-up before the job pauses so the user knows an approval is waiting
|
|
256
278
|
- Cron scheduling — trigger any automation out-of-band ("Run now") + opt-in Telegram confirmation when a scheduled job succeeds
|
|
279
|
+
- Duplicate any automation in one click; opt-in retention to purge old terminal jobs
|
|
257
280
|
- `nodal-agents update` — one-command upgrade + boot version notice
|
|
258
|
-
- Encryption at rest for LLM keys + MCP keys
|
|
281
|
+
- Encryption at rest for LLM keys + MCP keys; in LAN / multi-user modes the
|
|
282
|
+
runner requires a shared `WORKER_SECRET` on every mutating route (no
|
|
283
|
+
unauthenticated job/LLM spend from other devices on the network)
|
|
259
284
|
- Embedded Postgres distribution via npm (no external DB to install)
|
|
260
285
|
|
|
261
286
|
### On the roadmap (genuine, not vaporware)
|
package/cli.js
CHANGED
|
@@ -11260,7 +11260,7 @@ var init_types2 = __esm({
|
|
|
11260
11260
|
|
|
11261
11261
|
// ../../packages/shared/src/enums.ts
|
|
11262
11262
|
import { z as z2 } from "zod";
|
|
11263
|
-
var JOB_CHANNELS, JobChannelSchema, JOB_STATUSES, JobStatusSchema, TASK_STATUSES, TaskStatusSchema, TASK_PRIORITIES, TaskPrioritySchema, AGENT_ROLES, AgentRoleSchema, ORCHESTRATOR_MODES, OrchestratorModeSchema, CONNECTOR_AUTH_TYPES, ConnectorAuthTypeSchema, APPROVAL_STATUSES, ApprovalStatusSchema, APPROVAL_RULE_ACTIONS, ApprovalRuleActionSchema, MEMORY_CATEGORIES, MemoryCategorySchema, MEMORY_SOURCES, MemorySourceSchema, MEMORY_LAYERS, MemoryLayerSchema, SCHEDULE_TYPES, ScheduleTypeSchema, SCHEDULE_LAST_STATUSES, ScheduleLastStatusSchema,
|
|
11263
|
+
var JOB_CHANNELS, JobChannelSchema, JOB_STATUSES, JobStatusSchema, TASK_STATUSES, TaskStatusSchema, TASK_PRIORITIES, TaskPrioritySchema, AGENT_ROLES, AgentRoleSchema, ORCHESTRATOR_MODES, OrchestratorModeSchema, CONNECTOR_AUTH_TYPES, ConnectorAuthTypeSchema, APPROVAL_STATUSES, ApprovalStatusSchema, APPROVAL_RULE_ACTIONS, ApprovalRuleActionSchema, MEMORY_CATEGORIES, MemoryCategorySchema, MEMORY_SOURCES, MemorySourceSchema, MEMORY_LAYERS, MemoryLayerSchema, SCHEDULE_TYPES, ScheduleTypeSchema, SCHEDULE_LAST_STATUSES, ScheduleLastStatusSchema, ENTITY_MEMBER_ROLES, EntityMemberRoleSchema, ENTITY_INDUSTRIES, EntityIndustrySchema, OPERATION_RISK_LEVELS, OperationRiskLevelSchema, PLUGIN_TYPES, PluginTypeSchema, PLUGIN_HOOKS, PluginHookSchema, MCP_TRANSPORTS, McpTransportSchema;
|
|
11264
11264
|
var init_enums = __esm({
|
|
11265
11265
|
"../../packages/shared/src/enums.ts"() {
|
|
11266
11266
|
"use strict";
|
|
@@ -11310,8 +11310,6 @@ var init_enums = __esm({
|
|
|
11310
11310
|
ScheduleTypeSchema = z2.enum(SCHEDULE_TYPES);
|
|
11311
11311
|
SCHEDULE_LAST_STATUSES = ["success", "failed", "no_action"];
|
|
11312
11312
|
ScheduleLastStatusSchema = z2.enum(SCHEDULE_LAST_STATUSES);
|
|
11313
|
-
RUN_KEY_SOURCES = ["entity", "operator"];
|
|
11314
|
-
RunKeySourceSchema = z2.enum(RUN_KEY_SOURCES);
|
|
11315
11313
|
ENTITY_MEMBER_ROLES = ["owner", "admin", "member", "viewer"];
|
|
11316
11314
|
EntityMemberRoleSchema = z2.enum(ENTITY_MEMBER_ROLES);
|
|
11317
11315
|
ENTITY_INDUSTRIES = [
|
|
@@ -11342,7 +11340,7 @@ var init_enums = __esm({
|
|
|
11342
11340
|
|
|
11343
11341
|
// ../../packages/shared/src/ids.ts
|
|
11344
11342
|
import { z as z3 } from "zod";
|
|
11345
|
-
var EntityIdSchema, UserIdSchema, AgentIdSchema, JobIdSchema, TaskIdSchema, ConnectorIdSchema, SkillIdSchema, ToolCallIdSchema, ApprovalRequestIdSchema, ApprovalRuleIdSchema, MemoryIdSchema, WebhookTriggerIdSchema, ScheduleIdSchema, McpServerIdSchema, PluginIdSchema, LlmKeyIdSchema
|
|
11343
|
+
var EntityIdSchema, UserIdSchema, AgentIdSchema, JobIdSchema, TaskIdSchema, ConnectorIdSchema, SkillIdSchema, ToolCallIdSchema, ApprovalRequestIdSchema, ApprovalRuleIdSchema, MemoryIdSchema, WebhookTriggerIdSchema, ScheduleIdSchema, McpServerIdSchema, PluginIdSchema, LlmKeyIdSchema;
|
|
11346
11344
|
var init_ids = __esm({
|
|
11347
11345
|
"../../packages/shared/src/ids.ts"() {
|
|
11348
11346
|
"use strict";
|
|
@@ -11362,7 +11360,6 @@ var init_ids = __esm({
|
|
|
11362
11360
|
McpServerIdSchema = z3.string().guid().brand();
|
|
11363
11361
|
PluginIdSchema = z3.string().guid().brand();
|
|
11364
11362
|
LlmKeyIdSchema = z3.string().guid().brand();
|
|
11365
|
-
AgentRunIdSchema = z3.string().guid().brand();
|
|
11366
11363
|
}
|
|
11367
11364
|
});
|
|
11368
11365
|
|
|
@@ -11994,44 +11991,6 @@ var init_llm_key = __esm({
|
|
|
11994
11991
|
}
|
|
11995
11992
|
});
|
|
11996
11993
|
|
|
11997
|
-
// ../../packages/shared/src/entities/agent-run.ts
|
|
11998
|
-
import { z as z18 } from "zod";
|
|
11999
|
-
var AgentRunSchema, AgentRunInsertSchema;
|
|
12000
|
-
var init_agent_run = __esm({
|
|
12001
|
-
"../../packages/shared/src/entities/agent-run.ts"() {
|
|
12002
|
-
"use strict";
|
|
12003
|
-
init_enums();
|
|
12004
|
-
AgentRunSchema = z18.object({
|
|
12005
|
-
id: z18.string().guid(),
|
|
12006
|
-
entity_id: z18.string().guid().nullable(),
|
|
12007
|
-
agent_id: z18.string().guid().nullable(),
|
|
12008
|
-
task: z18.string().min(1),
|
|
12009
|
-
result: z18.string().nullable(),
|
|
12010
|
-
success: z18.boolean(),
|
|
12011
|
-
tools_used: z18.array(z18.string()),
|
|
12012
|
-
tokens_used: z18.number().int().min(0).nullable(),
|
|
12013
|
-
input_tokens: z18.number().int().min(0).nullable(),
|
|
12014
|
-
output_tokens: z18.number().int().min(0).nullable(),
|
|
12015
|
-
duration_ms: z18.number().int().min(0).nullable(),
|
|
12016
|
-
key_source: RunKeySourceSchema.nullable(),
|
|
12017
|
-
created_at: z18.string().datetime()
|
|
12018
|
-
}).strict();
|
|
12019
|
-
AgentRunInsertSchema = AgentRunSchema.omit({
|
|
12020
|
-
id: true,
|
|
12021
|
-
created_at: true
|
|
12022
|
-
}).extend({
|
|
12023
|
-
success: z18.boolean().default(true),
|
|
12024
|
-
tools_used: z18.array(z18.string()).default([]),
|
|
12025
|
-
result: z18.string().nullable().optional(),
|
|
12026
|
-
tokens_used: z18.number().int().min(0).nullable().optional(),
|
|
12027
|
-
input_tokens: z18.number().int().min(0).nullable().optional(),
|
|
12028
|
-
output_tokens: z18.number().int().min(0).nullable().optional(),
|
|
12029
|
-
duration_ms: z18.number().int().min(0).nullable().optional(),
|
|
12030
|
-
key_source: RunKeySourceSchema.nullable().optional()
|
|
12031
|
-
});
|
|
12032
|
-
}
|
|
12033
|
-
});
|
|
12034
|
-
|
|
12035
11994
|
// ../../packages/shared/src/types/operation.ts
|
|
12036
11995
|
var init_operation = __esm({
|
|
12037
11996
|
"../../packages/shared/src/types/operation.ts"() {
|
|
@@ -12160,19 +12119,20 @@ var init_providers = __esm({
|
|
|
12160
12119
|
});
|
|
12161
12120
|
|
|
12162
12121
|
// ../../packages/shared/src/root-agent.ts
|
|
12163
|
-
import { z as
|
|
12122
|
+
import { z as z18 } from "zod";
|
|
12164
12123
|
var AutonomyLevelSchema, RootGrantsSchema;
|
|
12165
12124
|
var init_root_agent = __esm({
|
|
12166
12125
|
"../../packages/shared/src/root-agent.ts"() {
|
|
12167
12126
|
"use strict";
|
|
12168
|
-
AutonomyLevelSchema =
|
|
12169
|
-
RootGrantsSchema =
|
|
12170
|
-
createAgent:
|
|
12171
|
-
|
|
12172
|
-
|
|
12173
|
-
|
|
12174
|
-
|
|
12175
|
-
|
|
12127
|
+
AutonomyLevelSchema = z18.enum(["propose_confirm", "destructive_gate", "fully_autonomous"]);
|
|
12128
|
+
RootGrantsSchema = z18.object({
|
|
12129
|
+
createAgent: z18.boolean(),
|
|
12130
|
+
attachAgent: z18.boolean(),
|
|
12131
|
+
createSkill: z18.boolean(),
|
|
12132
|
+
updateSkill: z18.boolean(),
|
|
12133
|
+
assignSkill: z18.boolean(),
|
|
12134
|
+
createMcp: z18.boolean(),
|
|
12135
|
+
createConnector: z18.boolean(),
|
|
12176
12136
|
autonomy: AutonomyLevelSchema
|
|
12177
12137
|
});
|
|
12178
12138
|
}
|
|
@@ -12212,7 +12172,6 @@ var init_src2 = __esm({
|
|
|
12212
12172
|
init_skill();
|
|
12213
12173
|
init_schedule();
|
|
12214
12174
|
init_llm_key();
|
|
12215
|
-
init_agent_run();
|
|
12216
12175
|
init_operation();
|
|
12217
12176
|
init_providers();
|
|
12218
12177
|
init_root_agent();
|
|
@@ -12320,7 +12279,12 @@ var init_entities = __esm({
|
|
|
12320
12279
|
// Default is an empty object — the runtime falls back to DEFAULT_ROOT_GRANTS.
|
|
12321
12280
|
rootGrants: jsonb("root_grants").notNull().default(sql`'{}'::jsonb`),
|
|
12322
12281
|
createdAt: timestamp("created_at", { withTimezone: true }).defaultNow(),
|
|
12323
|
-
updatedAt: timestamp("updated_at", { withTimezone: true }).defaultNow()
|
|
12282
|
+
updatedAt: timestamp("updated_at", { withTimezone: true }).defaultNow(),
|
|
12283
|
+
lastCuratorRunAt: timestamp("last_curator_run_at", { withTimezone: true }),
|
|
12284
|
+
reflectionEnabled: boolean("reflection_enabled").notNull().default(false),
|
|
12285
|
+
// Controls whether agent-authored skills are auto-assigned to the authoring
|
|
12286
|
+
// agent ('auto') or queued for the entity owner to approve ('approval').
|
|
12287
|
+
skillAssignmentMode: text("skill_assignment_mode").notNull().default("approval").$type()
|
|
12324
12288
|
},
|
|
12325
12289
|
(table) => [
|
|
12326
12290
|
uniqueIndex("entities_mcp_token_idx").on(table.mcpToken),
|
|
@@ -12519,6 +12483,37 @@ var init_jobs = __esm({
|
|
|
12519
12483
|
totalDurationMs: integer("total_duration_ms").default(0),
|
|
12520
12484
|
inputTokens: integer("input_tokens").default(0),
|
|
12521
12485
|
outputTokens: integer("output_tokens").default(0),
|
|
12486
|
+
/**
|
|
12487
|
+
* Cumulative EFFECTIVE (non-cached) input tokens = Σ(inputTokens −
|
|
12488
|
+
* cachedInputTokens) per turn. The token budget (Guard 1a) measures this,
|
|
12489
|
+
* not raw input, so a job that re-sends a prompt-cached history (cheap, the
|
|
12490
|
+
* bulk read from cache) is not penalised as if every re-send were fresh.
|
|
12491
|
+
* Persisted alongside input_tokens so the budget stays cumulative across
|
|
12492
|
+
* self-chain resumes.
|
|
12493
|
+
*/
|
|
12494
|
+
effectiveInputTokens: integer("effective_input_tokens").default(0),
|
|
12495
|
+
/**
|
|
12496
|
+
* Cumulative real dollar cost billed to the provider across all turns of
|
|
12497
|
+
* this job (sum of per-call costs reported by the provider). Populated only
|
|
12498
|
+
* when the provider reports per-call cost (OpenRouter with
|
|
12499
|
+
* `usage:{include:true}`); undefined/null for providers that don't report it
|
|
12500
|
+
* (Anthropic, Ollama, etc.). Used by the cost-budget guard (Guard 1e) and
|
|
12501
|
+
* for cost observability in the dashboard.
|
|
12502
|
+
*
|
|
12503
|
+
* Stored as a real/float because sub-cent values are common (e.g. $0.00056).
|
|
12504
|
+
* Cumulative across self-chain / approval / delegation resumes, exactly like
|
|
12505
|
+
* effectiveInputTokens.
|
|
12506
|
+
*/
|
|
12507
|
+
totalCostUsd: real("total_cost_usd").default(0),
|
|
12508
|
+
/**
|
|
12509
|
+
* The upstream provider that actually served the last LLM call for this job
|
|
12510
|
+
* (e.g. 'DeepSeek' when an OpenRouter job was routed to the DeepSeek
|
|
12511
|
+
* upstream via provider-order preference). Populated from
|
|
12512
|
+
* `providerMetadata.openrouter.provider` on each LLM call; only the last
|
|
12513
|
+
* non-empty value is stored. NULL for providers that don't report upstream
|
|
12514
|
+
* identity (Anthropic, Ollama, etc.) or when the field was absent.
|
|
12515
|
+
*/
|
|
12516
|
+
servedProvider: text("served_provider"),
|
|
12522
12517
|
delegationDepth: integer("delegation_depth").default(0),
|
|
12523
12518
|
/**
|
|
12524
12519
|
* The slug of the last delegated child that failed on this parent job.
|
|
@@ -12924,12 +12919,38 @@ var init_skills = __esm({
|
|
|
12924
12919
|
requiredConfig: jsonb("required_config").default(sql`'[]'::jsonb`),
|
|
12925
12920
|
operations: jsonb("operations").default(sql`'[]'::jsonb`),
|
|
12926
12921
|
requiredBuiltins: text("required_builtins").array().notNull().default(sql`'{}'::text[]`),
|
|
12922
|
+
// ─── Community-installed skills (open Agent Skills / SKILL.md format) ───
|
|
12923
|
+
// is_community = true for skills installed at runtime from an external
|
|
12924
|
+
// source (vs system catalog or user-authored custom skills). source is the
|
|
12925
|
+
// install origin (GitHub URL / skills.sh path). installed_scripts records
|
|
12926
|
+
// the bundled scripts detected at install (.py/.sh/etc.) — surfaced to the
|
|
12927
|
+
// user as a warning, since the runtime does NOT execute skill scripts.
|
|
12928
|
+
isCommunity: boolean("is_community").notNull().default(false),
|
|
12929
|
+
source: text("source"),
|
|
12930
|
+
installedScripts: jsonb("installed_scripts").$type(),
|
|
12931
|
+
// ─── Learning-loop columns (Phase A) ─────────────────────────────────────
|
|
12932
|
+
// createdBy: provenance — 'user' (default) | 'system' | 'agent'
|
|
12933
|
+
// state: lifecycle — 'active' (default) | 'stale' | 'archived'
|
|
12934
|
+
// lastUsedAt: fire-and-forget timestamp bumped each job, NULL = never used
|
|
12935
|
+
// patchCount: agent-authored patches applied so far
|
|
12936
|
+
// archivedAt: when the skill moved to state='archived' (NULL while active)
|
|
12937
|
+
createdBy: text("created_by").notNull().default("user"),
|
|
12938
|
+
// Which agent authored this skill (populated by the Tier-1 reflection pass).
|
|
12939
|
+
// NULL for user/system skills and curator umbrella skills (created_by_agent_id=null).
|
|
12940
|
+
createdByAgentId: uuid("created_by_agent_id").references(() => agents.id, {
|
|
12941
|
+
onDelete: "set null"
|
|
12942
|
+
}),
|
|
12943
|
+
state: text("state").notNull().default("active"),
|
|
12944
|
+
lastUsedAt: timestamp("last_used_at", { withTimezone: true }),
|
|
12945
|
+
patchCount: integer("patch_count").notNull().default(0),
|
|
12946
|
+
archivedAt: timestamp("archived_at", { withTimezone: true }),
|
|
12927
12947
|
createdAt: timestamp("created_at", { withTimezone: true }).defaultNow(),
|
|
12928
12948
|
updatedAt: timestamp("updated_at", { withTimezone: true }).defaultNow()
|
|
12929
12949
|
},
|
|
12930
12950
|
(table) => [
|
|
12931
12951
|
index("idx_agent_skills_entity_id").on(table.entityId),
|
|
12932
|
-
index("idx_skills_active").on(table.active, table.slug)
|
|
12952
|
+
index("idx_skills_active").on(table.active, table.slug),
|
|
12953
|
+
index("idx_agent_skills_is_community").on(table.isCommunity)
|
|
12933
12954
|
]
|
|
12934
12955
|
);
|
|
12935
12956
|
skillVersions = pgTable(
|
|
@@ -13022,46 +13043,6 @@ var init_schedules = __esm({
|
|
|
13022
13043
|
}
|
|
13023
13044
|
});
|
|
13024
13045
|
|
|
13025
|
-
// ../../packages/db/src/schema/runs.ts
|
|
13026
|
-
var agentRuns;
|
|
13027
|
-
var init_runs = __esm({
|
|
13028
|
-
"../../packages/db/src/schema/runs.ts"() {
|
|
13029
|
-
"use strict";
|
|
13030
|
-
init_pg_core();
|
|
13031
|
-
init_drizzle_orm();
|
|
13032
|
-
init_entities();
|
|
13033
|
-
init_agents();
|
|
13034
|
-
agentRuns = pgTable(
|
|
13035
|
-
"agent_runs",
|
|
13036
|
-
{
|
|
13037
|
-
id: uuid("id").primaryKey().defaultRandom(),
|
|
13038
|
-
entityId: uuid("entity_id").references(() => entities.id, { onDelete: "cascade" }),
|
|
13039
|
-
agentId: uuid("agent_id").references(() => agents.id, { onDelete: "cascade" }),
|
|
13040
|
-
task: text("task").notNull(),
|
|
13041
|
-
result: text("result"),
|
|
13042
|
-
success: boolean("success").default(true),
|
|
13043
|
-
toolsUsed: text("tools_used").array().default(sql`'{}'::text[]`),
|
|
13044
|
-
tokensUsed: integer("tokens_used"),
|
|
13045
|
-
inputTokens: integer("input_tokens"),
|
|
13046
|
-
outputTokens: integer("output_tokens"),
|
|
13047
|
-
durationMs: integer("duration_ms"),
|
|
13048
|
-
keySource: text("key_source"),
|
|
13049
|
-
createdAt: timestamp("created_at", { withTimezone: true }).defaultNow()
|
|
13050
|
-
},
|
|
13051
|
-
(table) => [
|
|
13052
|
-
index("idx_agent_runs_entity_id").on(table.entityId),
|
|
13053
|
-
index("idx_agent_runs_agent_created").on(table.agentId, sql`${table.createdAt} DESC`),
|
|
13054
|
-
index("idx_runs_agent").on(table.agentId, sql`${table.createdAt} DESC`),
|
|
13055
|
-
index("idx_runs_recent").on(sql`${table.createdAt} DESC`),
|
|
13056
|
-
check(
|
|
13057
|
-
"agent_runs_key_source_check",
|
|
13058
|
-
sql`${table.keySource} IN ('entity','operator') OR ${table.keySource} IS NULL`
|
|
13059
|
-
)
|
|
13060
|
-
]
|
|
13061
|
-
);
|
|
13062
|
-
}
|
|
13063
|
-
});
|
|
13064
|
-
|
|
13065
13046
|
// ../../packages/db/src/schema/mcp.ts
|
|
13066
13047
|
var mcpServers, agentMcpServers, mcpConnections;
|
|
13067
13048
|
var init_mcp = __esm({
|
|
@@ -13385,7 +13366,6 @@ __export(schema_exports, {
|
|
|
13385
13366
|
ORCHESTRATOR_MODES: () => ORCHESTRATOR_MODES,
|
|
13386
13367
|
PLUGIN_HOOKS: () => PLUGIN_HOOKS,
|
|
13387
13368
|
PLUGIN_TYPES: () => PLUGIN_TYPES,
|
|
13388
|
-
RUN_KEY_SOURCES: () => RUN_KEY_SOURCES,
|
|
13389
13369
|
SCHEDULE_LAST_STATUSES: () => SCHEDULE_LAST_STATUSES,
|
|
13390
13370
|
SCHEDULE_TYPES: () => SCHEDULE_TYPES,
|
|
13391
13371
|
TASK_PRIORITIES: () => TASK_PRIORITIES,
|
|
@@ -13398,7 +13378,6 @@ __export(schema_exports, {
|
|
|
13398
13378
|
agentMcpServers: () => agentMcpServers,
|
|
13399
13379
|
agentMemory: () => agentMemory,
|
|
13400
13380
|
agentPlugins: () => agentPlugins,
|
|
13401
|
-
agentRuns: () => agentRuns,
|
|
13402
13381
|
agentSchedules: () => agentSchedules,
|
|
13403
13382
|
agentSkillAssignments: () => agentSkillAssignments,
|
|
13404
13383
|
agentSkills: () => agentSkills,
|
|
@@ -13445,7 +13424,6 @@ var init_schema2 = __esm({
|
|
|
13445
13424
|
init_skills();
|
|
13446
13425
|
init_schedules();
|
|
13447
13426
|
init_llm_keys();
|
|
13448
|
-
init_runs();
|
|
13449
13427
|
init_mcp();
|
|
13450
13428
|
init_misc();
|
|
13451
13429
|
init_auth();
|
|
@@ -13527,6 +13505,14 @@ var init_skills2 = __esm({
|
|
|
13527
13505
|
}
|
|
13528
13506
|
});
|
|
13529
13507
|
|
|
13508
|
+
// ../../packages/db/src/repos/retention.ts
|
|
13509
|
+
var init_retention = __esm({
|
|
13510
|
+
"../../packages/db/src/repos/retention.ts"() {
|
|
13511
|
+
"use strict";
|
|
13512
|
+
init_schema2();
|
|
13513
|
+
}
|
|
13514
|
+
});
|
|
13515
|
+
|
|
13530
13516
|
// ../../packages/db/src/index.ts
|
|
13531
13517
|
var init_src4 = __esm({
|
|
13532
13518
|
"../../packages/db/src/index.ts"() {
|
|
@@ -13537,6 +13523,7 @@ var init_src4 = __esm({
|
|
|
13537
13523
|
init_credentials2();
|
|
13538
13524
|
init_agents2();
|
|
13539
13525
|
init_skills2();
|
|
13526
|
+
init_retention();
|
|
13540
13527
|
init_drizzle_orm();
|
|
13541
13528
|
}
|
|
13542
13529
|
});
|
|
@@ -13666,7 +13653,9 @@ function buildEnvForWeb(config, databaseUrl) {
|
|
|
13666
13653
|
const bind = config.bind === "loopback" ? "127.0.0.1" : "0.0.0.0";
|
|
13667
13654
|
const env = {
|
|
13668
13655
|
DATABASE_URL: databaseUrl,
|
|
13669
|
-
|
|
13656
|
+
// 127.0.0.1, not localhost: on Windows localhost prefers IPv6 (::1), letting a
|
|
13657
|
+
// foreign IPv6 server on the runner port silently steal the web→runner traffic.
|
|
13658
|
+
RUNNER_URL: `http://127.0.0.1:${config.ports.runner}`,
|
|
13670
13659
|
AUTH_MODE: authMode,
|
|
13671
13660
|
// Expose auth mode to the client so login/page.tsx can render the right form.
|
|
13672
13661
|
NEXT_PUBLIC_AUTH_MODE: authMode,
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
-- Community-installed skills (open Agent Skills / SKILL.md format).
|
|
2
|
+
-- is_community marks a skill installed at runtime from an external source (vs a
|
|
3
|
+
-- system-catalog skill or a user-authored custom skill). source records the
|
|
4
|
+
-- install origin (GitHub URL / skills.sh path) and doubles as the reinstall key.
|
|
5
|
+
-- installed_scripts lists the bundled scripts detected at install (.py/.sh/...)
|
|
6
|
+
-- — surfaced to the user as a warning, because the runtime does NOT execute
|
|
7
|
+
-- skill scripts (agents act through a controlled tool whitelist).
|
|
8
|
+
ALTER TABLE "agent_skills"
|
|
9
|
+
ADD COLUMN IF NOT EXISTS "is_community" boolean DEFAULT false NOT NULL,
|
|
10
|
+
ADD COLUMN IF NOT EXISTS "source" text,
|
|
11
|
+
ADD COLUMN IF NOT EXISTS "installed_scripts" jsonb;
|
|
12
|
+
|
|
13
|
+
CREATE INDEX IF NOT EXISTS "idx_agent_skills_is_community" ON "agent_skills" ("is_community");
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
-- Cache-aware token budget (Guard 1a). The cumulative per-job token budget now
|
|
2
|
+
-- counts EFFECTIVE (non-cached) input — inputTokens minus cachedInputTokens —
|
|
3
|
+
-- so a job that re-sends a prompt-cached history (cheap, ~10x via caching) is
|
|
4
|
+
-- no longer killed at the budget wall as if every re-send were fresh tokens.
|
|
5
|
+
-- This column persists the cumulative effective-input across self-chain resumes,
|
|
6
|
+
-- mirroring input_tokens / output_tokens.
|
|
7
|
+
ALTER TABLE "agent_jobs"
|
|
8
|
+
ADD COLUMN IF NOT EXISTS "effective_input_tokens" integer DEFAULT 0;
|
|
9
|
+
|
|
10
|
+
-- Backfill in-flight (resumable) jobs conservatively: seed effective from the
|
|
11
|
+
-- already-accumulated raw input so a resume AFTER this migration never
|
|
12
|
+
-- under-counts (treats prior raw as fully effective). Terminal jobs never
|
|
13
|
+
-- resume, so this only matters for jobs suspended in awaiting_* at upgrade time.
|
|
14
|
+
UPDATE "agent_jobs"
|
|
15
|
+
SET "effective_input_tokens" = COALESCE("input_tokens", 0)
|
|
16
|
+
WHERE COALESCE("effective_input_tokens", 0) = 0
|
|
17
|
+
AND COALESCE("input_tokens", 0) > 0
|
|
18
|
+
AND "completed_at" IS NULL;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
-- Real dollar cost budget (Guard 1e). Track what was ACTUALLY BILLED per job
|
|
2
|
+
-- (not token proxies) so the runner can enforce a hard dollar cap and the
|
|
3
|
+
-- dashboard can surface real $/job cost. Populated by OpenRouter when
|
|
4
|
+
-- `usage:{include:true}` is sent — `usage.cost` in the response lands in
|
|
5
|
+
-- providerMetadata.openrouter.usage.cost on the AI SDK result. NULL / 0 for
|
|
6
|
+
-- providers that don't report per-call cost (Anthropic, Ollama, etc.).
|
|
7
|
+
--
|
|
8
|
+
-- Stored as real (float4) — sub-cent values are common (e.g. $0.00056).
|
|
9
|
+
-- Default 0 so existing rows are valid without a backfill.
|
|
10
|
+
ALTER TABLE "agent_jobs"
|
|
11
|
+
ADD COLUMN IF NOT EXISTS "total_cost_usd" real DEFAULT 0;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
-- Served-upstream observability (P0-B). Tracks which upstream provider actually
|
|
2
|
+
-- handled a given job execution (e.g. 'DeepSeek' when routed via OpenRouter's
|
|
3
|
+
-- provider-order preference). Populated from providerMetadata.openrouter.provider
|
|
4
|
+
-- on each LLM call; only the LAST non-empty value is stored per job. NULL for
|
|
5
|
+
-- providers that don't report upstream identity (Anthropic, Ollama, etc.).
|
|
6
|
+
ALTER TABLE "agent_jobs"
|
|
7
|
+
ADD COLUMN IF NOT EXISTS "served_provider" text;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
-- Learning-loop columns for agent_skills (Phase A).
|
|
2
|
+
-- created_by: provenance — who created this skill ('user' | 'system' | 'agent').
|
|
3
|
+
-- Default 'user' for forward-compatibility; backfilled to 'system' for
|
|
4
|
+
-- community/bundled skills below.
|
|
5
|
+
-- state: lifecycle state — 'active' (default) | 'stale' | 'archived'.
|
|
6
|
+
-- No hard-delete path — skills are archived, never deleted.
|
|
7
|
+
-- last_used_at: fire-and-forget timestamp, bumped each time the skill is injected
|
|
8
|
+
-- into a job's system prompt. NULL = never used. Used to surface stale skills.
|
|
9
|
+
-- patch_count: how many agent-authored patches have been applied. Starts at 0.
|
|
10
|
+
-- archived_at: when the skill was moved to state='archived'. NULL while active.
|
|
11
|
+
|
|
12
|
+
ALTER TABLE "agent_skills"
|
|
13
|
+
ADD COLUMN IF NOT EXISTS "created_by" text NOT NULL DEFAULT 'user',
|
|
14
|
+
ADD COLUMN IF NOT EXISTS "state" text NOT NULL DEFAULT 'active',
|
|
15
|
+
ADD COLUMN IF NOT EXISTS "last_used_at" timestamptz,
|
|
16
|
+
ADD COLUMN IF NOT EXISTS "patch_count" integer NOT NULL DEFAULT 0,
|
|
17
|
+
ADD COLUMN IF NOT EXISTS "archived_at" timestamptz;
|
|
18
|
+
|
|
19
|
+
-- Backfill: community/bundled skills are 'system' provenance
|
|
20
|
+
UPDATE "agent_skills" SET "created_by" = 'system' WHERE "is_community" = true;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
-- Tier-2 CURATOR cadence tracker.
|
|
2
|
+
-- Per-entity timestamp of the last LLM consolidation pass. NULL = never run.
|
|
3
|
+
-- Used by run-curator.ts to gate the first-run-deferred pattern (skip first
|
|
4
|
+
-- run, set to now(), run on subsequent ticks beyond CURATOR_INTERVAL_DAYS).
|
|
5
|
+
|
|
6
|
+
ALTER TABLE "entities"
|
|
7
|
+
ADD COLUMN IF NOT EXISTS "last_curator_run_at" timestamptz;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
ALTER TABLE entities ADD COLUMN reflection_enabled boolean NOT NULL DEFAULT false;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
DROP TABLE IF EXISTS "agent_runs" CASCADE;
|