nodal-agents 0.4.2 → 0.4.3

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.
Files changed (131) hide show
  1. package/README.md +6 -10
  2. package/package.json +2 -1
  3. package/runner.js +91 -16
  4. package/web/.next/BUILD_ID +1 -1
  5. package/web/.next/app-path-routes-manifest.json +1 -1
  6. package/web/.next/build-manifest.json +2 -2
  7. package/web/.next/prerender-manifest.json +3 -3
  8. package/web/.next/server/app/(dashboard)/agents/[id]/edit/page.js +3 -3
  9. package/web/.next/server/app/(dashboard)/agents/[id]/edit/page.js.nft.json +1 -1
  10. package/web/.next/server/app/(dashboard)/agents/[id]/edit/page_client-reference-manifest.js +1 -1
  11. package/web/.next/server/app/(dashboard)/agents/[id]/telegram/page.js +1 -1
  12. package/web/.next/server/app/(dashboard)/agents/[id]/telegram/page_client-reference-manifest.js +1 -1
  13. package/web/.next/server/app/(dashboard)/agents/page.js +2 -2
  14. package/web/.next/server/app/(dashboard)/agents/page_client-reference-manifest.js +1 -1
  15. package/web/.next/server/app/(dashboard)/approvals/page.js +2 -2
  16. package/web/.next/server/app/(dashboard)/approvals/page.js.nft.json +1 -1
  17. package/web/.next/server/app/(dashboard)/approvals/page_client-reference-manifest.js +1 -1
  18. package/web/.next/server/app/(dashboard)/automations/page.js +2 -2
  19. package/web/.next/server/app/(dashboard)/automations/page_client-reference-manifest.js +1 -1
  20. package/web/.next/server/app/(dashboard)/billing/page.js +1 -1
  21. package/web/.next/server/app/(dashboard)/billing/page_client-reference-manifest.js +1 -1
  22. package/web/.next/server/app/(dashboard)/chat/page.js +1 -1
  23. package/web/.next/server/app/(dashboard)/chat/page_client-reference-manifest.js +1 -1
  24. package/web/.next/server/app/(dashboard)/connectors/page.js +1 -1
  25. package/web/.next/server/app/(dashboard)/connectors/page.js.nft.json +1 -1
  26. package/web/.next/server/app/(dashboard)/connectors/page_client-reference-manifest.js +1 -1
  27. package/web/.next/server/app/(dashboard)/credentials/page.js +1 -1
  28. package/web/.next/server/app/(dashboard)/credentials/page.js.nft.json +1 -1
  29. package/web/.next/server/app/(dashboard)/credentials/page_client-reference-manifest.js +1 -1
  30. package/web/.next/server/app/(dashboard)/jobs/[id]/page.js +2 -2
  31. package/web/.next/server/app/(dashboard)/jobs/[id]/page_client-reference-manifest.js +1 -1
  32. package/web/.next/server/app/(dashboard)/jobs/page.js +2 -2
  33. package/web/.next/server/app/(dashboard)/jobs/page.js.nft.json +1 -1
  34. package/web/.next/server/app/(dashboard)/jobs/page_client-reference-manifest.js +1 -1
  35. package/web/.next/server/app/(dashboard)/llm-providers/page.js +2 -2
  36. package/web/.next/server/app/(dashboard)/llm-providers/page_client-reference-manifest.js +1 -1
  37. package/web/.next/server/app/(dashboard)/logs/page.js +1 -1
  38. package/web/.next/server/app/(dashboard)/logs/page_client-reference-manifest.js +1 -1
  39. package/web/.next/server/app/(dashboard)/mcp/page.js +1 -1
  40. package/web/.next/server/app/(dashboard)/mcp/page_client-reference-manifest.js +1 -1
  41. package/web/.next/server/app/(dashboard)/memories/page.js +2 -2
  42. package/web/.next/server/app/(dashboard)/memories/page_client-reference-manifest.js +1 -1
  43. package/web/.next/server/app/(dashboard)/page.js +3 -3
  44. package/web/.next/server/app/(dashboard)/page.js.nft.json +1 -1
  45. package/web/.next/server/app/(dashboard)/page_client-reference-manifest.js +1 -1
  46. package/web/.next/server/app/(dashboard)/settings/page.js +2 -2
  47. package/web/.next/server/app/(dashboard)/settings/page_client-reference-manifest.js +1 -1
  48. package/web/.next/server/app/(dashboard)/skills/[id]/edit/page.js +1 -1
  49. package/web/.next/server/app/(dashboard)/skills/[id]/edit/page.js.nft.json +1 -1
  50. package/web/.next/server/app/(dashboard)/skills/[id]/edit/page_client-reference-manifest.js +1 -1
  51. package/web/.next/server/app/(dashboard)/skills/new/page.js +2 -2
  52. package/web/.next/server/app/(dashboard)/skills/new/page.js.nft.json +1 -1
  53. package/web/.next/server/app/(dashboard)/skills/new/page_client-reference-manifest.js +1 -1
  54. package/web/.next/server/app/(dashboard)/skills/page.js +1 -1
  55. package/web/.next/server/app/(dashboard)/skills/page_client-reference-manifest.js +1 -1
  56. package/web/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  57. package/web/.next/server/app/_global-error.html +1 -1
  58. package/web/.next/server/app/_global-error.rsc +2 -2
  59. package/web/.next/server/app/_global-error.segments/_full.segment.rsc +2 -2
  60. package/web/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  61. package/web/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  62. package/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  63. package/web/.next/server/app/_global-error.segments/_index.segment.rsc +2 -2
  64. package/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  65. package/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  66. package/web/.next/server/app/_not-found.html +1 -1
  67. package/web/.next/server/app/_not-found.rsc +2 -2
  68. package/web/.next/server/app/_not-found.segments/_full.segment.rsc +2 -2
  69. package/web/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  70. package/web/.next/server/app/_not-found.segments/_index.segment.rsc +2 -2
  71. package/web/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +2 -2
  72. package/web/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  73. package/web/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  74. package/web/.next/server/app/api/oauth/[provider]/callback/route.js +1 -1
  75. package/web/.next/server/app/login/page_client-reference-manifest.js +1 -1
  76. package/web/.next/server/app/onboarding/page_client-reference-manifest.js +1 -1
  77. package/web/.next/server/app/onboarding.html +1 -1
  78. package/web/.next/server/app/onboarding.rsc +2 -2
  79. package/web/.next/server/app/onboarding.segments/_full.segment.rsc +2 -2
  80. package/web/.next/server/app/onboarding.segments/_head.segment.rsc +1 -1
  81. package/web/.next/server/app/onboarding.segments/_index.segment.rsc +2 -2
  82. package/web/.next/server/app/onboarding.segments/_tree.segment.rsc +1 -1
  83. package/web/.next/server/app/onboarding.segments/onboarding/__PAGE__.segment.rsc +1 -1
  84. package/web/.next/server/app/onboarding.segments/onboarding.segment.rsc +1 -1
  85. package/web/.next/server/app-paths-manifest.json +1 -1
  86. package/web/.next/server/chunks/3233.js +1 -1
  87. package/web/.next/server/chunks/7741.js +1 -1
  88. package/web/.next/server/chunks/8052.js +1 -0
  89. package/web/.next/server/chunks/8766.js +1 -0
  90. package/web/.next/server/chunks/{4839.js → 8782.js} +1 -1
  91. package/web/.next/server/chunks/{1945.js → 9084.js} +1 -1
  92. package/web/.next/server/middleware-build-manifest.js +1 -1
  93. package/web/.next/server/pages/404.html +1 -1
  94. package/web/.next/server/pages/500.html +1 -1
  95. package/web/.next/server/server-reference-manifest.js +1 -1
  96. package/web/.next/server/server-reference-manifest.json +1 -1
  97. package/web/.next/static/chunks/{9123-20653d928e33410a.js → 9123-5c5ad180c831baa4.js} +1 -1
  98. package/web/.next/static/chunks/app/(dashboard)/agents/[id]/edit/page-de6c8fc7cb73a3de.js +2 -0
  99. package/web/.next/static/chunks/app/(dashboard)/agents/[id]/telegram/page-6d4161f1e0b19885.js +1 -0
  100. package/web/.next/static/chunks/app/(dashboard)/agents/{page-b258b8975ac6450b.js → page-50005050a3304bee.js} +1 -1
  101. package/web/.next/static/chunks/app/(dashboard)/approvals/{page-79dea6e91956eeba.js → page-7f4314908d1024f6.js} +1 -1
  102. package/web/.next/static/chunks/app/(dashboard)/automations/page-7693601b49363371.js +1 -0
  103. package/web/.next/static/chunks/app/(dashboard)/chat/page-839128f211f63728.js +1 -0
  104. package/web/.next/static/chunks/app/(dashboard)/connectors/{page-4a437ba82f4086da.js → page-a6a1d8f0a33d2faf.js} +1 -1
  105. package/web/.next/static/chunks/app/(dashboard)/jobs/[id]/page-4fc570c6c1e39edb.js +1 -0
  106. package/web/.next/static/chunks/app/(dashboard)/jobs/{page-94a311f688a255d8.js → page-cf861b235dc54ced.js} +1 -1
  107. package/web/.next/static/chunks/app/(dashboard)/{layout-e1b0d4fad2926646.js → layout-769de8a52528194a.js} +1 -1
  108. package/web/.next/static/chunks/app/(dashboard)/llm-providers/page-99eab754716f9071.js +1 -0
  109. package/web/.next/static/chunks/app/(dashboard)/mcp/{page-c071c54f76273ac4.js → page-082442b4f9ac0f91.js} +1 -1
  110. package/web/.next/static/chunks/app/(dashboard)/memories/page-e201633b4bbbdf73.js +1 -0
  111. package/web/.next/static/chunks/app/(dashboard)/page-a42d880f7036e866.js +1 -0
  112. package/web/.next/static/chunks/app/(dashboard)/settings/page-d85cac3728506241.js +1 -0
  113. package/web/.next/static/chunks/app/(dashboard)/skills/[id]/edit/page-ecaf3520da303237.js +1 -0
  114. package/web/.next/static/chunks/app/(dashboard)/skills/new/page-cdbc2aada2be0bfc.js +1 -0
  115. package/web/.next/static/chunks/app/(dashboard)/skills/page-234553540bef945b.js +1 -0
  116. package/web/.next/server/chunks/8206.js +0 -1
  117. package/web/.next/server/chunks/8398.js +0 -1
  118. package/web/.next/static/chunks/app/(dashboard)/agents/[id]/edit/page-a8e293c54c818084.js +0 -2
  119. package/web/.next/static/chunks/app/(dashboard)/agents/[id]/telegram/page-7a94ae67b2c3c9c3.js +0 -1
  120. package/web/.next/static/chunks/app/(dashboard)/automations/page-3b863b7af8e2c1a3.js +0 -1
  121. package/web/.next/static/chunks/app/(dashboard)/chat/page-4d965bb7ee3732db.js +0 -1
  122. package/web/.next/static/chunks/app/(dashboard)/jobs/[id]/page-be20dcbf25c8f3ce.js +0 -1
  123. package/web/.next/static/chunks/app/(dashboard)/llm-providers/page-e5e2c4e2b783d37f.js +0 -1
  124. package/web/.next/static/chunks/app/(dashboard)/memories/page-8ca0b34ad35eb1fa.js +0 -1
  125. package/web/.next/static/chunks/app/(dashboard)/page-fb50e1576a3ab2e4.js +0 -1
  126. package/web/.next/static/chunks/app/(dashboard)/settings/page-7b256e9c462e97f8.js +0 -1
  127. package/web/.next/static/chunks/app/(dashboard)/skills/[id]/edit/page-12930816795e8b20.js +0 -1
  128. package/web/.next/static/chunks/app/(dashboard)/skills/new/page-e3a19abaf7468db9.js +0 -1
  129. package/web/.next/static/chunks/app/(dashboard)/skills/page-43f1475a0bc9c45f.js +0 -1
  130. /package/web/.next/static/{ZuUX-HBTQOhLf0tFI6JQI → n6jP_zB4kqJScKY_T2ciu}/_buildManifest.js +0 -0
  131. /package/web/.next/static/{ZuUX-HBTQOhLf0tFI6JQI → n6jP_zB4kqJScKY_T2ciu}/_ssgManifest.js +0 -0
package/README.md CHANGED
@@ -16,12 +16,6 @@ connectors, and delegate to each other to get the job done.
16
16
  to install, runs on any machine with Node 22+ (Mac, PC, Linux), and works
17
17
  with **any LLM** — frontier or local, paid or free.
18
18
 
19
- > **Run the models others choke on.** DeepSeek V4 works out of the box —
20
- > including the cheap, fast OpenRouter routes — because the runtime quietly
21
- > handles its quirks (non-standard tool-call payloads) instead of failing.
22
- > Mix the right model per agent: a frontier model where judgment matters, a
23
- > near-free one where it doesn't.
24
-
25
19
  ---
26
20
 
27
21
  ## Why Nodal-Agents
@@ -29,7 +23,7 @@ with **any LLM** — frontier or local, paid or free.
29
23
  | | |
30
24
  | --- | --- |
31
25
  | 🏠  **Local-first** | Single binary, embedded Postgres, zero cloud dependency. Your conversations, memory, and credentials stay on your machine. |
32
- | 🔌  **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) are handled automatically. |
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. |
33
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). |
34
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). |
35
29
  | 🤝  **Orchestrators that finish** | Router and planner orchestrators delegate to specialist sub-agents, then resume on completion to wrap up the answer. |
@@ -90,7 +84,7 @@ When a newer version is available, `nodal-agents up` also prints a one-line
90
84
  notice:
91
85
 
92
86
  ```
93
- ℹ v0.4.2 available — run `nodal-agents update`
87
+ ℹ v0.4.3 available — run `nodal-agents update`
94
88
  ```
95
89
 
96
90
  ### Build from source
@@ -218,7 +212,7 @@ pnpm deps:check # runs locally and in CI before every release
218
212
 
219
213
  ## Status
220
214
 
221
- **Current release:** `0.4.2` on npm `latest`. Used daily by the
215
+ **Current release:** `0.4.3` on npm `latest`. Used daily by the
222
216
  maintainer, stable enough for personal production. Pre-1.0 — breaking
223
217
  changes are still possible between minors.
224
218
 
@@ -227,7 +221,9 @@ changes are still possible between minors.
227
221
  - Multi-LLM, **per-agent model selection** — provider setup is just an API key
228
222
  (one per provider); each agent chooses its own model on top. Frontier and
229
223
  local providers, including **DeepSeek V4** (non-spec tool-call args normalized
230
- automatically), plus native tool-call parsing for Kimi K2 / Qwen3-Coder / GLM
224
+ automatically) and **reasoning models like MiniMax M3** (their hidden
225
+ chain-of-thought is round-tripped across tool calls so they keep reasoning on
226
+ multi-turn tasks), plus native tool-call parsing for Kimi K2 / Qwen3-Coder / GLM
231
227
  - **Provider failover** — an opt-in ordered key chain per agent; on a 5xx /
232
228
  timeout / quota mid-job the runner fails over to the next key, and fails loud
233
229
  (`all_providers_failed`) only when the whole chain is exhausted
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nodal-agents",
3
- "version": "0.4.2",
3
+ "version": "0.4.3",
4
4
  "description": "Local-first AI agent platform with a web dashboard — install in one command.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -46,6 +46,7 @@
46
46
  "@ai-sdk/openai": "^3.0.63",
47
47
  "@ai-sdk/openai-compatible": "^2.0.47",
48
48
  "@ai-sdk/provider": "^3.0.10",
49
+ "@openrouter/ai-sdk-provider": "^2.9.0",
49
50
  "ollama-ai-provider-v2": "^3.5.0",
50
51
  "googleapis": "^171.4.0",
51
52
  "@notionhq/client": "^2.3.0",
package/runner.js CHANGED
@@ -1164,7 +1164,9 @@ var init_model_catalog = __esm({
1164
1164
  ],
1165
1165
  // OpenRouter models are namespaced by sub-vendor (anthropic/, deepseek/, …).
1166
1166
  // The UI groups them by that vendor (see modelGroupLabel). Tested + working
1167
- // routes; all accept a forced tool_choice.
1167
+ // routes. `forcedToolChoice` is per-model: most accept tool_choice:'required';
1168
+ // MiniMax M3 does not (some of its OpenRouter endpoints reject the forced
1169
+ // value), so it runs on 'auto' + the runtime floor.
1168
1170
  openrouter: [
1169
1171
  // Anthropic
1170
1172
  {
@@ -1233,6 +1235,16 @@ var init_model_catalog = __esm({
1233
1235
  modelId: "google/gemma-4-31b-it",
1234
1236
  label: "Gemma 4 31B-IT",
1235
1237
  capabilities: { tools: true, forcedToolChoice: true }
1238
+ },
1239
+ // MiniMax
1240
+ {
1241
+ modelId: "minimax/minimax-m3",
1242
+ label: "MiniMax M3",
1243
+ // A reasoning model. Some of its OpenRouter endpoints reject a FORCED
1244
+ // tool_choice ('required') → we send 'auto' (forcedToolChoice:false).
1245
+ // reasoning:true makes the provider return reasoning_details so the runner
1246
+ // can round-trip them across tool-call turns.
1247
+ capabilities: { tools: true, forcedToolChoice: false, reasoning: true }
1236
1248
  }
1237
1249
  ]
1238
1250
  };
@@ -10946,7 +10958,8 @@ function buildGroqModel(config) {
10946
10958
  }
10947
10959
 
10948
10960
  // ../../packages/llm/src/providers/openrouter.ts
10949
- import { createOpenAICompatible as createOpenAICompatible2 } from "@ai-sdk/openai-compatible";
10961
+ init_src();
10962
+ import { createOpenRouter } from "@openrouter/ai-sdk-provider";
10950
10963
  import { wrapLanguageModel } from "ai";
10951
10964
 
10952
10965
  // ../../packages/llm/src/providers/parsers.ts
@@ -11174,15 +11187,21 @@ function buildOpenRouterModel(config) {
11174
11187
  throw new ProviderConfigError("openrouter provider requires an apiKey");
11175
11188
  }
11176
11189
  const baseURL = config.baseURL ?? PROVIDER_PRESETS.openrouter.defaultBaseURL;
11177
- const provider = createOpenAICompatible2({
11178
- name: "openrouter",
11179
- baseURL,
11190
+ const provider = createOpenRouter({
11180
11191
  apiKey: config.apiKey,
11192
+ baseURL,
11193
+ // 'strict' is the documented mode for the first-party OpenRouter API
11194
+ // ('compatible' is for 3rd-party proxies). We hit openrouter.ai directly.
11195
+ compatibility: "strict",
11181
11196
  // Normalise non-spec responses (e.g. DeepSeek V4 returning function.arguments
11182
- // as an object instead of a JSON string) before AI SDK's Zod schema sees them.
11197
+ // as an object instead of a JSON string) before the SDK's Zod schema sees them.
11183
11198
  fetch: createTolerantFetch()
11184
11199
  });
11185
- const base = provider(config.model);
11200
+ const isReasoning = findModelCatalogEntry("openrouter", config.model)?.capabilities.reasoning;
11201
+ const base = provider.chat(
11202
+ config.model,
11203
+ isReasoning ? { extraBody: { reasoning: { enabled: true } } } : void 0
11204
+ );
11186
11205
  const middleware = middlewareForFamily(detectAgenticFamily(config.model));
11187
11206
  if (middleware) {
11188
11207
  return wrapLanguageModel({ model: base, middleware });
@@ -28158,14 +28177,18 @@ async function executeJob(jobId, deps, _runnerEnv) {
28158
28177
  await failJob(db, jobId, "delivery_spam_guard", runStats());
28159
28178
  return { status: "failed", error: "delivery_spam_guard" };
28160
28179
  }
28180
+ const reasoningParts = response.reasoning ?? [];
28161
28181
  const assistantMsg = {
28162
28182
  role: "assistant",
28163
- content: rawToolCalls.length > 0 ? rawToolCalls.map((tc) => ({
28164
- type: "tool-call",
28165
- toolCallId: tc.toolCallId,
28166
- toolName: tc.toolName,
28167
- input: tc.input
28168
- })) : response.text || ""
28183
+ content: rawToolCalls.length > 0 ? [
28184
+ ...reasoningParts,
28185
+ ...rawToolCalls.map((tc) => ({
28186
+ type: "tool-call",
28187
+ toolCallId: tc.toolCallId,
28188
+ toolName: tc.toolName,
28189
+ input: tc.input
28190
+ }))
28191
+ ] : reasoningParts.length > 0 ? [...reasoningParts, { type: "text", text: response.text || "" }] : response.text || ""
28169
28192
  };
28170
28193
  messages = [...messages, assistantMsg];
28171
28194
  const returnResultCall = rawToolCalls.find((tc) => tc.toolName === "return_result");
@@ -29208,6 +29231,7 @@ var CHAT_TOOLS = {
29208
29231
  inputSchema: z89.object({ instruction: z89.string().min(1).max(4e3) })
29209
29232
  }
29210
29233
  };
29234
+ var ESCALATION_RECHECK = "Re-read your previous reply. If it committed to performing an action \u2014 running, launching, sending, fetching, creating, configuring, delegating, or any task or tool use \u2014 then your text ALONE did nothing: call the run_task tool NOW with a clear, self-contained instruction. If your reply was pure conversation, a question, or simply recalling a fact, do not call any tool \u2014 the conversation is complete.";
29211
29235
  async function runChatTurn(opts) {
29212
29236
  const { deps, entityId, agentId, conversationId, message } = opts;
29213
29237
  const db = deps.db;
@@ -29249,8 +29273,43 @@ async function runChatTurn(opts) {
29249
29273
  origin: "dashboard",
29250
29274
  surface: "chat"
29251
29275
  });
29252
- const rows = await db.select({ role: chatMessages.role, content: chatMessages.content }).from(chatMessages).where(eq4(chatMessages.conversationId, conversationId)).orderBy(desc(chatMessages.createdAt)).limit(HISTORY_LIMIT);
29253
- const messages = rows.reverse().map((r) => ({ role: r.role, content: r.content }));
29276
+ const rows = await db.select({
29277
+ role: chatMessages.role,
29278
+ content: chatMessages.content,
29279
+ jobId: chatMessages.jobId,
29280
+ jobTask: agentJobs.task
29281
+ }).from(chatMessages).leftJoin(agentJobs, eq4(chatMessages.jobId, agentJobs.id)).where(eq4(chatMessages.conversationId, conversationId)).orderBy(desc(chatMessages.createdAt)).limit(HISTORY_LIMIT);
29282
+ const messages = [];
29283
+ for (const r of rows.reverse()) {
29284
+ if (r.role === "assistant" && r.jobId) {
29285
+ const toolCallId = `hist-${r.jobId}`;
29286
+ messages.push({
29287
+ role: "assistant",
29288
+ content: [
29289
+ ...r.content ? [{ type: "text", text: r.content }] : [],
29290
+ {
29291
+ type: "tool-call",
29292
+ toolCallId,
29293
+ toolName: "run_task",
29294
+ input: { instruction: r.jobTask ?? "" }
29295
+ }
29296
+ ]
29297
+ });
29298
+ messages.push({
29299
+ role: "tool",
29300
+ content: [
29301
+ {
29302
+ type: "tool-result",
29303
+ toolCallId,
29304
+ toolName: "run_task",
29305
+ output: { type: "text", value: "Task dispatched." }
29306
+ }
29307
+ ]
29308
+ });
29309
+ } else {
29310
+ messages.push({ role: r.role, content: r.content });
29311
+ }
29312
+ }
29254
29313
  let text22 = "";
29255
29314
  let runTask;
29256
29315
  try {
@@ -29261,7 +29320,23 @@ async function runChatTurn(opts) {
29261
29320
  });
29262
29321
  text22 = (response.text ?? "").trim();
29263
29322
  runTask = (response.toolCalls ?? []).find((tc) => tc.toolName === "run_task");
29264
- } catch {
29323
+ } catch (err) {
29324
+ console.warn(`[run-chat-turn] tools call failed (${agentRow.slug}):`, err.message);
29325
+ }
29326
+ if (!runTask && text22) {
29327
+ try {
29328
+ const recheck = await llmClient.generateText({
29329
+ system: systemPrompt,
29330
+ messages: [
29331
+ ...messages,
29332
+ { role: "assistant", content: text22 },
29333
+ { role: "user", content: ESCALATION_RECHECK }
29334
+ ],
29335
+ tools: CHAT_TOOLS
29336
+ });
29337
+ runTask = (recheck.toolCalls ?? []).find((tc) => tc.toolName === "run_task");
29338
+ } catch {
29339
+ }
29265
29340
  }
29266
29341
  if (runTask) {
29267
29342
  const instruction = String(runTask.input?.instruction ?? "").trim() || message;
@@ -1 +1 @@
1
- ZuUX-HBTQOhLf0tFI6JQI
1
+ n6jP_zB4kqJScKY_T2ciu
@@ -13,8 +13,8 @@
13
13
  "/(dashboard)/agents/[id]/edit/page": "/agents/[id]/edit",
14
14
  "/(dashboard)/agents/[id]/telegram/page": "/agents/[id]/telegram",
15
15
  "/(dashboard)/agents/page": "/agents",
16
- "/(dashboard)/automations/page": "/automations",
17
16
  "/(dashboard)/approvals/page": "/approvals",
17
+ "/(dashboard)/automations/page": "/automations",
18
18
  "/(dashboard)/chat/page": "/chat",
19
19
  "/(dashboard)/connectors/page": "/connectors",
20
20
  "/(dashboard)/credentials/page": "/credentials",
@@ -4,8 +4,8 @@
4
4
  ],
5
5
  "devFiles": [],
6
6
  "lowPriorityFiles": [
7
- "static/ZuUX-HBTQOhLf0tFI6JQI/_buildManifest.js",
8
- "static/ZuUX-HBTQOhLf0tFI6JQI/_ssgManifest.js"
7
+ "static/n6jP_zB4kqJScKY_T2ciu/_buildManifest.js",
8
+ "static/n6jP_zB4kqJScKY_T2ciu/_ssgManifest.js"
9
9
  ],
10
10
  "rootMainFiles": [
11
11
  "static/chunks/webpack-3741bf0a7636d65e.js",
@@ -78,8 +78,8 @@
78
78
  "dynamicRoutes": {},
79
79
  "notFoundRoutes": [],
80
80
  "preview": {
81
- "previewModeId": "3ee52df782a2df2a4ee50789902ca7be",
82
- "previewModeSigningKey": "89ca14b4b6d0a92f00c85b444ae7555c09e000f7447bbab9332647fa03c9e2ae",
83
- "previewModeEncryptionKey": "c5e0ed4849dcf791d73cc1bb97004c7e4b13127cb4b820419f39aa7aea22021e"
81
+ "previewModeId": "98616a9865e16bddc6a1143b769ee98e",
82
+ "previewModeSigningKey": "ee3ee89f46a6815ae05eb06949ae794c6962a52e9a6f58e3dfbcf1c6614ff841",
83
+ "previewModeEncryptionKey": "c4c6b207c2e3329b64d6c383809a95a2f5f1f3ecd6c68005de252da1d057c7bb"
84
84
  }
85
85
  }