nodal-agents 0.7.8 → 0.7.95
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 +7 -6
- package/cli.js +73 -17
- package/migrations/0066_schedule_notify_channel.sql +19 -0
- package/migrations/0067_webhook_notify_channel.sql +12 -0
- package/migrations/meta/_journal.json +14 -0
- package/package.json +1 -1
- package/runner.js +407 -178
- package/web/.next/BUILD_ID +1 -1
- package/web/.next/app-path-routes-manifest.json +8 -8
- package/web/.next/build-manifest.json +2 -2
- package/web/.next/prerender-manifest.json +3 -3
- package/web/.next/required-server-files.json +1 -0
- package/web/.next/server/app/(dashboard)/agents/[id]/channels/page.js +2 -2
- package/web/.next/server/app/(dashboard)/agents/[id]/channels/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/agents/[id]/channels/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/agents/[id]/edit/page.js +5 -5
- 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 +1 -1
- 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)/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 -2
- package/web/.next/server/app/(dashboard)/learned-skills/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/learned-skills/page_client-reference-manifest.js +1 -1
- 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)/settings/root-context/page.js +2 -2
- package/web/.next/server/app/(dashboard)/settings/root-context/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/settings/root-context/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 +1 -1
- 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 +2 -2
- 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 +1 -1
- 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/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 +192 -192
- package/web/.next/server/app/onboarding/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app-paths-manifest.json +8 -8
- package/web/.next/server/chunks/1466.js +1 -0
- package/web/.next/server/chunks/1767.js +1 -0
- package/web/.next/server/chunks/3308.js +1 -0
- package/web/.next/server/chunks/4162.js +1 -1
- package/web/.next/server/chunks/4574.js +1 -1
- package/web/.next/server/chunks/5300.js +1 -0
- package/web/.next/server/chunks/6184.js +1 -0
- package/web/.next/server/chunks/6539.js +1 -0
- package/web/.next/server/chunks/7124.js +20 -20
- package/web/.next/server/chunks/8380.js +1 -0
- package/web/.next/server/chunks/9000.js +1 -0
- package/web/.next/server/chunks/9137.js +1 -0
- package/web/.next/server/chunks/{3847.js → 9507.js} +4 -4
- package/web/.next/server/chunks/9982.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/chunks/1498-d0d434749bb18cd2.js +1 -0
- package/web/.next/static/chunks/2406-66d8aa55b97d75c3.js +1 -0
- package/web/.next/static/chunks/{2491-cc8dee1fc55e1e38.js → 2491-b14243a2db419dd9.js} +1 -1
- package/web/.next/static/chunks/3966-679a4c07d6db8ee6.js +1 -0
- package/web/.next/static/chunks/4095-f76de40c53ae3d47.js +1 -0
- package/web/.next/static/chunks/4766-d80c537321cca448.js +1 -0
- package/web/.next/static/chunks/5876-4423499f49214575.js +1 -0
- package/web/.next/static/chunks/5953-54a29fc1e2d84c0c.js +1 -0
- package/web/.next/static/chunks/7829-78f753c50b408cde.js +1 -0
- package/web/.next/static/chunks/8542-ba178b7c68e14cf3.js +1 -0
- package/web/.next/static/chunks/8719-8ab59c5faa49c9ab.js +1 -0
- package/web/.next/static/chunks/9387-f5283e69fe4d4e83.js +1 -0
- package/web/.next/static/chunks/9567-db1512a42580d07c.js +1 -0
- package/web/.next/static/chunks/{8097-bad68cd78aa59a10.js → 9583-f93faba69d4c1f57.js} +1 -1
- package/web/.next/static/chunks/app/(dashboard)/agents/[id]/channels/page-d40d5db150472c4f.js +1 -0
- package/web/.next/static/chunks/app/(dashboard)/agents/[id]/edit/page-74934ff99c3b1261.js +6 -0
- package/web/.next/static/chunks/app/(dashboard)/agents/[id]/telegram/page-d40d5db150472c4f.js +1 -0
- package/web/.next/static/chunks/app/(dashboard)/agents/page-8ec50d6f48425813.js +1 -0
- package/web/.next/static/chunks/app/(dashboard)/approvals/page-d907a7c12917ab8a.js +1 -0
- package/web/.next/static/chunks/app/(dashboard)/automations/page-dd20cb7f04d22cca.js +1 -0
- package/web/.next/static/chunks/app/(dashboard)/chat/page-e9ffd3d09a46ad38.js +1 -0
- package/web/.next/static/chunks/app/(dashboard)/connectors/page-52828e317e7a63e6.js +1 -0
- package/web/.next/static/chunks/app/(dashboard)/credentials/page-f84a3f991cf69228.js +1 -0
- package/web/.next/static/chunks/app/(dashboard)/jobs/[id]/page-a0866da7952de417.js +1 -0
- package/web/.next/static/chunks/app/(dashboard)/jobs/page-aade90b389efb824.js +1 -0
- package/web/.next/static/chunks/app/(dashboard)/layout-10486dd8640fb6a0.js +1 -0
- package/web/.next/static/chunks/app/(dashboard)/learned-skills/page-e22d1e586ac8579c.js +1 -0
- package/web/.next/static/chunks/app/(dashboard)/llm-providers/page-46858f7d737ee49b.js +1 -0
- package/web/.next/static/chunks/app/(dashboard)/logs/page-17dd2080f6196b01.js +1 -0
- package/web/.next/static/chunks/app/(dashboard)/mcp/page-81e83a08c7b65719.js +1 -0
- package/web/.next/static/chunks/app/(dashboard)/memories/page-0336ba541b5ab006.js +1 -0
- package/web/.next/static/chunks/app/(dashboard)/page-3bf3a72ec95863d8.js +1 -0
- package/web/.next/static/chunks/app/(dashboard)/settings/page-0ee25e256bc3097f.js +1 -0
- package/web/.next/static/chunks/app/(dashboard)/settings/root-context/page-76653439bca06d8c.js +1 -0
- package/web/.next/static/chunks/app/(dashboard)/skills/[id]/edit/page-de1bf934a2c5e8b2.js +1 -0
- package/web/.next/static/chunks/app/(dashboard)/skills/new/page-a9640274b845190a.js +1 -0
- package/web/.next/static/chunks/app/(dashboard)/skills/page-928b6f005ba4dafb.js +1 -0
- package/web/.next/static/chunks/app/_global-error/page-d40d5db150472c4f.js +1 -0
- package/web/.next/static/chunks/app/_not-found/page-d40d5db150472c4f.js +1 -0
- package/web/.next/static/chunks/app/api/auth/[...all]/route-d40d5db150472c4f.js +1 -0
- package/web/.next/static/chunks/app/api/health/route-d40d5db150472c4f.js +1 -0
- package/web/.next/static/chunks/app/api/oauth/[provider]/callback/route-d40d5db150472c4f.js +1 -0
- package/web/.next/static/chunks/app/api/oauth/[provider]/start/route-d40d5db150472c4f.js +1 -0
- package/web/.next/static/chunks/app/auth/callback/route-d40d5db150472c4f.js +1 -0
- package/web/.next/static/chunks/app/error-ec052ef28a67f9b0.js +1 -0
- package/web/.next/static/chunks/app/login/page-97a658fa01e36c3f.js +1 -0
- package/web/.next/static/chunks/app/onboarding/page-d7c5a220f9244b45.js +26 -0
- package/web/.next/static/chunks/next/dist/client/components/builtin/app-error-d40d5db150472c4f.js +1 -0
- package/web/.next/static/chunks/next/dist/client/components/builtin/forbidden-d40d5db150472c4f.js +1 -0
- package/web/.next/static/chunks/next/dist/client/components/builtin/unauthorized-d40d5db150472c4f.js +1 -0
- package/web/.next/static/css/0f40c037c3aa9ff2.css +3 -0
- package/web/server.js +1 -1
- package/web/.next/server/chunks/6823.js +0 -1
- package/web/.next/server/chunks/715.js +0 -1
- package/web/.next/server/chunks/8308.js +0 -1
- package/web/.next/server/chunks/8430.js +0 -1
- package/web/.next/static/chunks/1361-5bc59efe9312f6ad.js +0 -1
- package/web/.next/static/chunks/2716-55970bc6e3910ccf.js +0 -1
- package/web/.next/static/chunks/3114-d846062bc8434b58.js +0 -1
- package/web/.next/static/chunks/370-554f47928c2648ee.js +0 -1
- package/web/.next/static/chunks/3763-2fa54c0e83122050.js +0 -1
- package/web/.next/static/chunks/3865-9aa6dedee678d08f.js +0 -1
- package/web/.next/static/chunks/8447-ec639f4e1d42d912.js +0 -1
- package/web/.next/static/chunks/9775-dad785c12d658539.js +0 -1
- package/web/.next/static/chunks/9836-5beba80ab70ed698.js +0 -1
- package/web/.next/static/chunks/app/(dashboard)/agents/[id]/channels/page-f2413d131f4e0bdf.js +0 -1
- package/web/.next/static/chunks/app/(dashboard)/agents/[id]/edit/page-5ab1dcbc58720645.js +0 -6
- package/web/.next/static/chunks/app/(dashboard)/agents/[id]/telegram/page-9397b9b7fccbb444.js +0 -1
- package/web/.next/static/chunks/app/(dashboard)/agents/page-6ac1ebd6598d7da7.js +0 -1
- package/web/.next/static/chunks/app/(dashboard)/approvals/page-76247d88c06bf203.js +0 -1
- package/web/.next/static/chunks/app/(dashboard)/automations/page-901227b6d047b2b7.js +0 -1
- package/web/.next/static/chunks/app/(dashboard)/chat/page-72f0688180411e7e.js +0 -1
- package/web/.next/static/chunks/app/(dashboard)/connectors/page-59b11d68fd1107c3.js +0 -1
- package/web/.next/static/chunks/app/(dashboard)/credentials/page-445228b74058e9c2.js +0 -1
- package/web/.next/static/chunks/app/(dashboard)/jobs/[id]/page-d7153b1b30dc6b78.js +0 -1
- package/web/.next/static/chunks/app/(dashboard)/jobs/page-65cb4b9970d04210.js +0 -1
- package/web/.next/static/chunks/app/(dashboard)/layout-16531dffd6974eb5.js +0 -1
- package/web/.next/static/chunks/app/(dashboard)/learned-skills/page-0211eb7caae5531d.js +0 -1
- package/web/.next/static/chunks/app/(dashboard)/llm-providers/page-c06f48cf0fbe5d63.js +0 -1
- package/web/.next/static/chunks/app/(dashboard)/logs/page-5080105f905f2d05.js +0 -1
- package/web/.next/static/chunks/app/(dashboard)/mcp/page-1aed0a1ab4459e69.js +0 -1
- package/web/.next/static/chunks/app/(dashboard)/memories/page-addb7eb81a34188b.js +0 -1
- package/web/.next/static/chunks/app/(dashboard)/page-5e99a1628397f82c.js +0 -1
- package/web/.next/static/chunks/app/(dashboard)/settings/page-ffff6582f6a33a65.js +0 -1
- package/web/.next/static/chunks/app/(dashboard)/settings/root-context/page-f42cc0aff627bd35.js +0 -1
- package/web/.next/static/chunks/app/(dashboard)/skills/[id]/edit/page-6022f41d61c64f4f.js +0 -1
- package/web/.next/static/chunks/app/(dashboard)/skills/new/page-a421b5020aa53715.js +0 -1
- package/web/.next/static/chunks/app/(dashboard)/skills/page-e8f83c423960e91d.js +0 -1
- package/web/.next/static/chunks/app/_global-error/page-9397b9b7fccbb444.js +0 -1
- package/web/.next/static/chunks/app/_not-found/page-9397b9b7fccbb444.js +0 -1
- package/web/.next/static/chunks/app/api/auth/[...all]/route-9397b9b7fccbb444.js +0 -1
- package/web/.next/static/chunks/app/api/health/route-9397b9b7fccbb444.js +0 -1
- package/web/.next/static/chunks/app/api/oauth/[provider]/callback/route-9397b9b7fccbb444.js +0 -1
- package/web/.next/static/chunks/app/api/oauth/[provider]/start/route-9397b9b7fccbb444.js +0 -1
- package/web/.next/static/chunks/app/auth/callback/route-9397b9b7fccbb444.js +0 -1
- package/web/.next/static/chunks/app/error-dc3b2db3bdb5b34e.js +0 -1
- package/web/.next/static/chunks/app/login/page-a6993d175f94d322.js +0 -1
- package/web/.next/static/chunks/app/onboarding/page-9619ad033b220394.js +0 -26
- package/web/.next/static/chunks/next/dist/client/components/builtin/app-error-9397b9b7fccbb444.js +0 -1
- package/web/.next/static/chunks/next/dist/client/components/builtin/forbidden-9397b9b7fccbb444.js +0 -1
- package/web/.next/static/chunks/next/dist/client/components/builtin/unauthorized-9397b9b7fccbb444.js +0 -1
- package/web/.next/static/css/637b48680bc0d57a.css +0 -3
- /package/web/.next/static/{29LavAHsyomtNE9YjHNlk → TWzSfBwiIIU81SgNxXcIw}/_buildManifest.js +0 -0
- /package/web/.next/static/{29LavAHsyomtNE9YjHNlk → TWzSfBwiIIU81SgNxXcIw}/_ssgManifest.js +0 -0
package/runner.js
CHANGED
|
@@ -1438,17 +1438,30 @@ var init_model_catalog = __esm({
|
|
|
1438
1438
|
contextWindow: 4e5
|
|
1439
1439
|
}
|
|
1440
1440
|
],
|
|
1441
|
+
// ─── Native Google (generativelanguage.googleapis.com) ──────────────────────
|
|
1442
|
+
// gemini-2.0-flash and gemini-2.5-pro were verified live (2026-07-12, real
|
|
1443
|
+
// key) to 404 / be shut down — dropped per product decision (family 3.x
|
|
1444
|
+
// only in the native catalog; gemini-2.5-flash deliberately NOT added).
|
|
1445
|
+
// Both entries below confirmed alive via ai.google.dev/gemini-api/docs/models
|
|
1446
|
+
// and openrouter.ai/google/… (2026-07-12): 1M-token context window, native
|
|
1447
|
+
// reasoning ("thinking") models, multimodal (text/image/video/audio/PDF).
|
|
1448
|
+
// forcedToolChoice:false — matches this file's reasoning-model convention
|
|
1449
|
+
// (MiniMax M3, Moonshot, GLM 5.2): don't force tool_choice on a thinking
|
|
1450
|
+
// model, let the runtime completion floor relax it to 'auto'. google.ts's
|
|
1451
|
+
// fetch shim injects generationConfig.thinkingConfig for these two entries
|
|
1452
|
+
// (reasoning:true gates it) so the API returns the chain-of-thought the
|
|
1453
|
+
// execute.ts round-trip needs across tool-call turns.
|
|
1441
1454
|
google: [
|
|
1442
1455
|
{
|
|
1443
|
-
modelId: "gemini-
|
|
1444
|
-
label: "Gemini
|
|
1445
|
-
capabilities: { tools: true, forcedToolChoice: true },
|
|
1456
|
+
modelId: "gemini-3.5-flash",
|
|
1457
|
+
label: "Gemini 3.5 Flash",
|
|
1458
|
+
capabilities: { tools: true, forcedToolChoice: false, reasoning: true },
|
|
1446
1459
|
contextWindow: 1048576
|
|
1447
1460
|
},
|
|
1448
1461
|
{
|
|
1449
|
-
modelId: "gemini-
|
|
1450
|
-
label: "Gemini
|
|
1451
|
-
capabilities: { tools: true, forcedToolChoice: true },
|
|
1462
|
+
modelId: "gemini-3.1-pro-preview",
|
|
1463
|
+
label: "Gemini 3.1 Pro (preview)",
|
|
1464
|
+
capabilities: { tools: true, forcedToolChoice: false, reasoning: true },
|
|
1452
1465
|
contextWindow: 1048576
|
|
1453
1466
|
}
|
|
1454
1467
|
],
|
|
@@ -1536,23 +1549,30 @@ var init_model_catalog = __esm({
|
|
|
1536
1549
|
contextWindow: 1048576,
|
|
1537
1550
|
providerOrder: ["deepseek"]
|
|
1538
1551
|
},
|
|
1539
|
-
// Google
|
|
1552
|
+
// Google — all three are thinking models on OpenRouter (supported_parameters
|
|
1553
|
+
// includes "reasoning", verified via openrouter.ai/google/… 2026-07-12).
|
|
1554
|
+
// reasoning:true makes the OpenRouter provider enable reasoning + round-trip
|
|
1555
|
+
// reasoning_details across tool-call turns. Unlike the M-series/Kimi/GLM
|
|
1556
|
+
// reasoning entries above, forcedToolChoice stays true here — no evidence
|
|
1557
|
+
// (live or documented) that OpenRouter's Gemini routes reject a forced
|
|
1558
|
+
// tool_choice, matching how deepseek/deepseek-v4-flash (also reasoning:true)
|
|
1559
|
+
// keeps forcedToolChoice:true in this file.
|
|
1540
1560
|
{
|
|
1541
1561
|
modelId: "google/gemini-3.1-flash-lite-preview",
|
|
1542
1562
|
label: "Gemini 3.1 Flash Lite (preview)",
|
|
1543
|
-
capabilities: { tools: true, forcedToolChoice: true },
|
|
1563
|
+
capabilities: { tools: true, forcedToolChoice: true, reasoning: true },
|
|
1544
1564
|
contextWindow: 1048576
|
|
1545
1565
|
},
|
|
1546
1566
|
{
|
|
1547
1567
|
modelId: "google/gemini-3.1-pro-preview",
|
|
1548
1568
|
label: "Gemini 3.1 Pro (preview)",
|
|
1549
|
-
capabilities: { tools: true, forcedToolChoice: true },
|
|
1569
|
+
capabilities: { tools: true, forcedToolChoice: true, reasoning: true },
|
|
1550
1570
|
contextWindow: 1048576
|
|
1551
1571
|
},
|
|
1552
1572
|
{
|
|
1553
1573
|
modelId: "google/gemini-3.5-flash",
|
|
1554
1574
|
label: "Gemini 3.5 Flash",
|
|
1555
|
-
capabilities: { tools: true, forcedToolChoice: true },
|
|
1575
|
+
capabilities: { tools: true, forcedToolChoice: true, reasoning: true },
|
|
1556
1576
|
contextWindow: 1048576
|
|
1557
1577
|
},
|
|
1558
1578
|
{
|
|
@@ -1630,8 +1650,8 @@ var init_model_catalog = __esm({
|
|
|
1630
1650
|
"claude-haiku-4-5-20251001",
|
|
1631
1651
|
"gpt-5",
|
|
1632
1652
|
"gpt-5-mini",
|
|
1633
|
-
"gemini-
|
|
1634
|
-
"gemini-
|
|
1653
|
+
"gemini-3.5-flash",
|
|
1654
|
+
"gemini-3.1-pro-preview",
|
|
1635
1655
|
"mistral-large-latest",
|
|
1636
1656
|
"MiniMax-M3",
|
|
1637
1657
|
"kimi-k2.6",
|
|
@@ -2352,6 +2372,17 @@ var init_schedules = __esm({
|
|
|
2352
2372
|
// forces the agent to send the user a success confirmation before finishing.
|
|
2353
2373
|
// Default false → the cron runs silently (the user must opt in per schedule).
|
|
2354
2374
|
notifyOnSuccess: boolean5("notify_on_success").notNull().default(false),
|
|
2375
|
+
// Explicit notify channel choice (B1, notify-channel-choice plan). One of
|
|
2376
|
+
// 'telegram'|'discord'|'slack'|'whatsapp', or NULL = auto (the historical
|
|
2377
|
+
// behavior: first active channel by CHANNEL_PRIORITY — see run-schedules.ts).
|
|
2378
|
+
// Choosing a channel here LINKS chatId resolution to it: the owner
|
|
2379
|
+
// conversation resolved at fire time is the owner's conversation ON THIS
|
|
2380
|
+
// CHANNEL, not whichever channel happened to win priority. 'whatsapp' is
|
|
2381
|
+
// accepted at the DB layer for forward-compat but the UI does not offer it
|
|
2382
|
+
// yet — no outbound send tool exists for whatsapp (TOOL_ONLY_DELIVERY_CHANNELS,
|
|
2383
|
+
// execute.ts), so a whatsapp notify would only ever reach the user through
|
|
2384
|
+
// deliver-results.ts's adapter-direct path, never a mid-run agent send.
|
|
2385
|
+
notifyChannel: text5("notify_channel"),
|
|
2355
2386
|
// Per-schedule daily cost ceiling in USD (Event Triggers, Brique 3). Rolled
|
|
2356
2387
|
// up against agent_jobs.total_cost_usd for this schedule since the start
|
|
2357
2388
|
// of its local day — see runScheduleTick (apps/runner/src/cron/run-schedules.ts).
|
|
@@ -2367,7 +2398,11 @@ var init_schedules = __esm({
|
|
|
2367
2398
|
check3("agent_schedules_type_check", sql3`${table.type} IN ('cron','heartbeat')`),
|
|
2368
2399
|
check3(
|
|
2369
2400
|
"agent_schedules_last_status_check",
|
|
2370
|
-
sql3`${table.lastStatus} IN ('success','failed','no_action','budget_exhausted') OR ${table.lastStatus} IS NULL`
|
|
2401
|
+
sql3`${table.lastStatus} IN ('success','failed','no_action','budget_exhausted','notify_unreachable') OR ${table.lastStatus} IS NULL`
|
|
2402
|
+
),
|
|
2403
|
+
check3(
|
|
2404
|
+
"agent_schedules_notify_channel_check",
|
|
2405
|
+
sql3`${table.notifyChannel} IN ('telegram','discord','slack','whatsapp') OR ${table.notifyChannel} IS NULL`
|
|
2371
2406
|
)
|
|
2372
2407
|
]
|
|
2373
2408
|
);
|
|
@@ -2898,7 +2933,17 @@ var init_memory2 = __esm({
|
|
|
2898
2933
|
});
|
|
2899
2934
|
|
|
2900
2935
|
// ../../packages/db/src/schema/webhooks.ts
|
|
2901
|
-
import {
|
|
2936
|
+
import {
|
|
2937
|
+
pgTable as pgTable13,
|
|
2938
|
+
text as text13,
|
|
2939
|
+
uuid as uuid13,
|
|
2940
|
+
boolean as boolean8,
|
|
2941
|
+
integer as integer7,
|
|
2942
|
+
timestamp as timestamp13,
|
|
2943
|
+
index as index12,
|
|
2944
|
+
check as check10
|
|
2945
|
+
} from "drizzle-orm/pg-core";
|
|
2946
|
+
import { sql as sql11 } from "drizzle-orm";
|
|
2902
2947
|
var webhookTriggers;
|
|
2903
2948
|
var init_webhooks = __esm({
|
|
2904
2949
|
"../../packages/db/src/schema/webhooks.ts"() {
|
|
@@ -2919,10 +2964,30 @@ var init_webhooks = __esm({
|
|
|
2919
2964
|
secret: text13("secret"),
|
|
2920
2965
|
lastTriggeredAt: timestamp13("last_triggered_at", { withTimezone: true }),
|
|
2921
2966
|
triggerCount: integer7("trigger_count").default(0),
|
|
2967
|
+
// B2 (notify-channel-choice plan): same pair of columns as
|
|
2968
|
+
// agent_schedules (see schedules.ts), same mechanic — the schedules
|
|
2969
|
+
// brique (B1) established the pattern, this just closes the gap the plan
|
|
2970
|
+
// identified: webhooks had no notify at all, not by design, just because
|
|
2971
|
+
// the original webhooks brique scoped delivery to the HTTP caller (202 +
|
|
2972
|
+
// jobId) and never to the owner. Default false → firing stays silent
|
|
2973
|
+
// unless opted in per trigger.
|
|
2974
|
+
notifyOnSuccess: boolean8("notify_on_success").notNull().default(false),
|
|
2975
|
+
// Explicit notify channel choice, NULL = auto (first active channel by
|
|
2976
|
+
// CHANNEL_PRIORITY — see routes/webhook.ts). Unlike agent_schedules,
|
|
2977
|
+
// there is no legacy webhook-notify behavior to preserve, so "auto" here
|
|
2978
|
+
// is a plain first-active-channel resolution from the start (no
|
|
2979
|
+
// telegram-only wrapper).
|
|
2980
|
+
notifyChannel: text13("notify_channel"),
|
|
2922
2981
|
createdAt: timestamp13("created_at", { withTimezone: true }).defaultNow(),
|
|
2923
2982
|
updatedAt: timestamp13("updated_at", { withTimezone: true }).defaultNow()
|
|
2924
2983
|
},
|
|
2925
|
-
(table) => [
|
|
2984
|
+
(table) => [
|
|
2985
|
+
index12("idx_webhook_triggers_entity_id").on(table.entityId),
|
|
2986
|
+
check10(
|
|
2987
|
+
"webhook_triggers_notify_channel_check",
|
|
2988
|
+
sql11`${table.notifyChannel} IN ('telegram','discord','slack','whatsapp') OR ${table.notifyChannel} IS NULL`
|
|
2989
|
+
)
|
|
2990
|
+
]
|
|
2926
2991
|
);
|
|
2927
2992
|
}
|
|
2928
2993
|
});
|
|
@@ -2939,7 +3004,7 @@ import {
|
|
|
2939
3004
|
index as index13,
|
|
2940
3005
|
unique as unique3
|
|
2941
3006
|
} from "drizzle-orm/pg-core";
|
|
2942
|
-
import { sql as
|
|
3007
|
+
import { sql as sql12 } from "drizzle-orm";
|
|
2943
3008
|
var agentSkills, skillVersions, skillConnectors, agentSkillAssignments;
|
|
2944
3009
|
var init_skills = __esm({
|
|
2945
3010
|
"../../packages/db/src/schema/skills.ts"() {
|
|
@@ -2959,9 +3024,9 @@ var init_skills = __esm({
|
|
|
2959
3024
|
description: text14("description"),
|
|
2960
3025
|
defaultContent: text14("default_content"),
|
|
2961
3026
|
contentOverridden: boolean9("content_overridden").default(false),
|
|
2962
|
-
requiredConfig: jsonb7("required_config").default(
|
|
2963
|
-
operations: jsonb7("operations").default(
|
|
2964
|
-
requiredBuiltins: text14("required_builtins").array().notNull().default(
|
|
3027
|
+
requiredConfig: jsonb7("required_config").default(sql12`'[]'::jsonb`),
|
|
3028
|
+
operations: jsonb7("operations").default(sql12`'[]'::jsonb`),
|
|
3029
|
+
requiredBuiltins: text14("required_builtins").array().notNull().default(sql12`'{}'::text[]`),
|
|
2965
3030
|
// ─── Community-installed skills (open Agent Skills / SKILL.md format) ───
|
|
2966
3031
|
// is_community = true for skills installed at runtime from an external
|
|
2967
3032
|
// source (vs system catalog or user-authored custom skills). source is the
|
|
@@ -3022,7 +3087,7 @@ var init_skills = __esm({
|
|
|
3022
3087
|
},
|
|
3023
3088
|
(table) => [
|
|
3024
3089
|
index13("idx_skill_versions_entity_id").on(table.entityId),
|
|
3025
|
-
index13("idx_skill_versions_skill_id").on(table.skillId,
|
|
3090
|
+
index13("idx_skill_versions_skill_id").on(table.skillId, sql12`${table.version} DESC`)
|
|
3026
3091
|
]
|
|
3027
3092
|
);
|
|
3028
3093
|
skillConnectors = pgTable14(
|
|
@@ -3044,7 +3109,7 @@ var init_skills = __esm({
|
|
|
3044
3109
|
entityId: uuid14("entity_id").notNull().references(() => entities.id, { onDelete: "cascade" }),
|
|
3045
3110
|
agentId: uuid14("agent_id").notNull().references(() => agents.id, { onDelete: "cascade" }),
|
|
3046
3111
|
skillId: uuid14("skill_id").notNull().references(() => agentSkills.id, { onDelete: "cascade" }),
|
|
3047
|
-
approvalOverrides: jsonb7("approval_overrides").default(
|
|
3112
|
+
approvalOverrides: jsonb7("approval_overrides").default(sql12`'{}'::jsonb`),
|
|
3048
3113
|
useCustomInstructions: boolean9("use_custom_instructions").notNull().default(false),
|
|
3049
3114
|
enabledOperations: text14("enabled_operations").array(),
|
|
3050
3115
|
// Per-skill × per-agent authorization to EXECUTE the skill's bundled scripts
|
|
@@ -3085,9 +3150,9 @@ import {
|
|
|
3085
3150
|
timestamp as timestamp15,
|
|
3086
3151
|
index as index14,
|
|
3087
3152
|
uniqueIndex as uniqueIndex2,
|
|
3088
|
-
check as
|
|
3153
|
+
check as check11
|
|
3089
3154
|
} from "drizzle-orm/pg-core";
|
|
3090
|
-
import { sql as
|
|
3155
|
+
import { sql as sql13 } from "drizzle-orm";
|
|
3091
3156
|
var mcpServers, agentMcpServers, mcpConnections;
|
|
3092
3157
|
var init_mcp = __esm({
|
|
3093
3158
|
"../../packages/db/src/schema/mcp.ts"() {
|
|
@@ -3104,8 +3169,8 @@ var init_mcp = __esm({
|
|
|
3104
3169
|
transport: text15("transport").notNull(),
|
|
3105
3170
|
url: text15("url"),
|
|
3106
3171
|
command: text15("command"),
|
|
3107
|
-
args: text15("args").array().default(
|
|
3108
|
-
envVars: jsonb8("env_vars").default(
|
|
3172
|
+
args: text15("args").array().default(sql13`'{}'::text[]`),
|
|
3173
|
+
envVars: jsonb8("env_vars").default(sql13`'{}'::jsonb`),
|
|
3109
3174
|
// Encrypted (enc:v1: blob) credential for HTTP MCP servers — same pattern
|
|
3110
3175
|
// as connectors.api_key. NULL for servers that need no auth.
|
|
3111
3176
|
apiKey: text15("api_key"),
|
|
@@ -3123,10 +3188,10 @@ var init_mcp = __esm({
|
|
|
3123
3188
|
updatedAt: timestamp15("updated_at", { withTimezone: true }).defaultNow()
|
|
3124
3189
|
},
|
|
3125
3190
|
(table) => [
|
|
3126
|
-
|
|
3127
|
-
|
|
3191
|
+
check11("mcp_servers_transport_check", sql13`${table.transport} IN ('http','stdio')`),
|
|
3192
|
+
check11(
|
|
3128
3193
|
"mcp_servers_auth_scheme_check",
|
|
3129
|
-
|
|
3194
|
+
sql13`${table.authScheme} IN ('header','query','bearer') OR ${table.authScheme} IS NULL`
|
|
3130
3195
|
)
|
|
3131
3196
|
// Multi-instance brique (migration 0017): the (entity_id, slug) UNIQUE
|
|
3132
3197
|
// index was dropped to allow multiple instances of the same MCP server
|
|
@@ -3159,7 +3224,7 @@ var init_mcp = __esm({
|
|
|
3159
3224
|
entityId: uuid15("entity_id").notNull().references(() => entities.id, { onDelete: "cascade" }),
|
|
3160
3225
|
slug: text15("slug").notNull(),
|
|
3161
3226
|
active: boolean10("active").notNull().default(true),
|
|
3162
|
-
toolConfig: jsonb8("tool_config").notNull().default(
|
|
3227
|
+
toolConfig: jsonb8("tool_config").notNull().default(sql13`'{}'::jsonb`),
|
|
3163
3228
|
createdAt: timestamp15("created_at", { withTimezone: true }).notNull().defaultNow(),
|
|
3164
3229
|
updatedAt: timestamp15("updated_at", { withTimezone: true }).notNull().defaultNow()
|
|
3165
3230
|
},
|
|
@@ -3185,10 +3250,10 @@ import {
|
|
|
3185
3250
|
jsonb as jsonb9,
|
|
3186
3251
|
timestamp as timestamp16,
|
|
3187
3252
|
index as index15,
|
|
3188
|
-
check as
|
|
3253
|
+
check as check12,
|
|
3189
3254
|
unique as unique4
|
|
3190
3255
|
} from "drizzle-orm/pg-core";
|
|
3191
|
-
import { sql as
|
|
3256
|
+
import { sql as sql14 } from "drizzle-orm";
|
|
3192
3257
|
var configuratorSessions, agentPlugins, rateLimits;
|
|
3193
3258
|
var init_misc = __esm({
|
|
3194
3259
|
"../../packages/db/src/schema/misc.ts"() {
|
|
@@ -3201,7 +3266,7 @@ var init_misc = __esm({
|
|
|
3201
3266
|
id: uuid16("id").primaryKey().defaultRandom(),
|
|
3202
3267
|
entityId: uuid16("entity_id").notNull().references(() => entities.id, { onDelete: "cascade" }),
|
|
3203
3268
|
agentId: uuid16("agent_id").references(() => agents.id, { onDelete: "cascade" }),
|
|
3204
|
-
messages: jsonb9("messages").notNull().default(
|
|
3269
|
+
messages: jsonb9("messages").notNull().default(sql14`'[]'::jsonb`),
|
|
3205
3270
|
status: text16("status").notNull().default("active"),
|
|
3206
3271
|
turnCount: integer9("turn_count").notNull().default(0),
|
|
3207
3272
|
createdAt: timestamp16("created_at", { withTimezone: true }).notNull().defaultNow(),
|
|
@@ -3221,7 +3286,7 @@ var init_misc = __esm({
|
|
|
3221
3286
|
slug: text16("slug").notNull(),
|
|
3222
3287
|
description: text16("description"),
|
|
3223
3288
|
pluginType: text16("plugin_type").notNull(),
|
|
3224
|
-
config: jsonb9("config").default(
|
|
3289
|
+
config: jsonb9("config").default(sql14`'{}'::jsonb`),
|
|
3225
3290
|
active: boolean11("active").default(true),
|
|
3226
3291
|
hook: text16("hook").notNull(),
|
|
3227
3292
|
webhookUrl: text16("webhook_url"),
|
|
@@ -3229,13 +3294,13 @@ var init_misc = __esm({
|
|
|
3229
3294
|
updatedAt: timestamp16("updated_at", { withTimezone: true }).defaultNow()
|
|
3230
3295
|
},
|
|
3231
3296
|
(table) => [
|
|
3232
|
-
|
|
3297
|
+
check12(
|
|
3233
3298
|
"agent_plugins_plugin_type_check",
|
|
3234
|
-
|
|
3299
|
+
sql14`${table.pluginType} IN ('webhook','transform','schedule')`
|
|
3235
3300
|
),
|
|
3236
|
-
|
|
3301
|
+
check12(
|
|
3237
3302
|
"agent_plugins_hook_check",
|
|
3238
|
-
|
|
3303
|
+
sql14`${table.hook} IN ('pre_task','post_task','pre_tool','post_tool','on_memory_save')`
|
|
3239
3304
|
),
|
|
3240
3305
|
// R5 (audit #2 follow-up): the pglite test DDL (packages/db/src/tests/
|
|
3241
3306
|
// helpers.ts) already assumed a per-entity unique slug here — same class
|
|
@@ -3365,8 +3430,8 @@ var init_agent_workspaces = __esm({
|
|
|
3365
3430
|
});
|
|
3366
3431
|
|
|
3367
3432
|
// ../../packages/db/src/schema/chat-messages.ts
|
|
3368
|
-
import { pgTable as pgTable20, text as text20, uuid as uuid20, timestamp as timestamp20, index as index18, check as
|
|
3369
|
-
import { sql as
|
|
3433
|
+
import { pgTable as pgTable20, text as text20, uuid as uuid20, timestamp as timestamp20, index as index18, check as check13 } from "drizzle-orm/pg-core";
|
|
3434
|
+
import { sql as sql15 } from "drizzle-orm";
|
|
3370
3435
|
var conversations, chatMessages;
|
|
3371
3436
|
var init_chat_messages = __esm({
|
|
3372
3437
|
"../../packages/db/src/schema/chat-messages.ts"() {
|
|
@@ -3392,7 +3457,7 @@ var init_chat_messages = __esm({
|
|
|
3392
3457
|
},
|
|
3393
3458
|
(table) => [
|
|
3394
3459
|
index18("idx_conversations_entity_agent").on(table.entityId, table.agentId, table.updatedAt),
|
|
3395
|
-
|
|
3460
|
+
check13("conversations_origin_check", sql15`${table.origin} IN ('user','onboarding')`)
|
|
3396
3461
|
]
|
|
3397
3462
|
);
|
|
3398
3463
|
chatMessages = pgTable20(
|
|
@@ -3413,7 +3478,7 @@ var init_chat_messages = __esm({
|
|
|
3413
3478
|
},
|
|
3414
3479
|
(table) => [
|
|
3415
3480
|
index18("idx_chat_messages_conversation").on(table.conversationId, table.createdAt),
|
|
3416
|
-
|
|
3481
|
+
check13("chat_messages_role_check", sql15`${table.role} IN ('user','assistant')`)
|
|
3417
3482
|
]
|
|
3418
3483
|
);
|
|
3419
3484
|
}
|
|
@@ -3451,11 +3516,11 @@ import {
|
|
|
3451
3516
|
uuid as uuid22,
|
|
3452
3517
|
timestamp as timestamp22,
|
|
3453
3518
|
index as index19,
|
|
3454
|
-
check as
|
|
3519
|
+
check as check14,
|
|
3455
3520
|
unique as unique6,
|
|
3456
3521
|
uniqueIndex as uniqueIndex4
|
|
3457
3522
|
} from "drizzle-orm/pg-core";
|
|
3458
|
-
import { sql as
|
|
3523
|
+
import { sql as sql16 } from "drizzle-orm";
|
|
3459
3524
|
var telegramAllowedChats;
|
|
3460
3525
|
var init_telegram_allowed_chats = __esm({
|
|
3461
3526
|
"../../packages/db/src/schema/telegram-allowed-chats.ts"() {
|
|
@@ -3484,8 +3549,8 @@ var init_telegram_allowed_chats = __esm({
|
|
|
3484
3549
|
unique6("telegram_allowed_chats_agent_chat_unique").on(table.agentId, table.chatId),
|
|
3485
3550
|
index19("idx_telegram_allowed_chats_agent").on(table.agentId),
|
|
3486
3551
|
index19("idx_telegram_allowed_chats_entity").on(table.entityId),
|
|
3487
|
-
|
|
3488
|
-
|
|
3552
|
+
check14("telegram_allowed_chats_role_check", sql16`${table.role} IN ('owner','member')`),
|
|
3553
|
+
check14("telegram_allowed_chats_status_check", sql16`${table.status} IN ('active','pending')`),
|
|
3489
3554
|
// F1 (audit #2 remediation follow-up, migration 0060): concurrent
|
|
3490
3555
|
// first-contact claims could each pass the "no owner yet" check before
|
|
3491
3556
|
// either row committed, creating two role='owner' rows for one agent —
|
|
@@ -3493,7 +3558,7 @@ var init_telegram_allowed_chats = __esm({
|
|
|
3493
3558
|
// resolveApprovalDeliveryTarget) does LIMIT 1 assuming uniqueness. A
|
|
3494
3559
|
// partial unique index (owner rows only; 'member' rows are unrestricted)
|
|
3495
3560
|
// closes the race at the DB level.
|
|
3496
|
-
uniqueIndex4("telegram_allowed_chats_single_owner").on(table.agentId).where(
|
|
3561
|
+
uniqueIndex4("telegram_allowed_chats_single_owner").on(table.agentId).where(sql16`${table.role} = 'owner'`)
|
|
3497
3562
|
]
|
|
3498
3563
|
);
|
|
3499
3564
|
}
|
|
@@ -3508,10 +3573,10 @@ import {
|
|
|
3508
3573
|
jsonb as jsonb10,
|
|
3509
3574
|
timestamp as timestamp23,
|
|
3510
3575
|
index as index20,
|
|
3511
|
-
check as
|
|
3576
|
+
check as check15,
|
|
3512
3577
|
unique as unique7
|
|
3513
3578
|
} from "drizzle-orm/pg-core";
|
|
3514
|
-
import { sql as
|
|
3579
|
+
import { sql as sql17 } from "drizzle-orm";
|
|
3515
3580
|
var channelBindings;
|
|
3516
3581
|
var init_channel_bindings = __esm({
|
|
3517
3582
|
"../../packages/db/src/schema/channel-bindings.ts"() {
|
|
@@ -3540,9 +3605,9 @@ var init_channel_bindings = __esm({
|
|
|
3540
3605
|
unique7("channel_bindings_agent_channel_unique").on(table.agentId, table.channel),
|
|
3541
3606
|
index20("idx_channel_bindings_agent").on(table.agentId),
|
|
3542
3607
|
index20("idx_channel_bindings_entity").on(table.entityId),
|
|
3543
|
-
|
|
3608
|
+
check15(
|
|
3544
3609
|
"channel_bindings_channel_check",
|
|
3545
|
-
|
|
3610
|
+
sql17`${table.channel} IN ('telegram','discord','slack','whatsapp')`
|
|
3546
3611
|
)
|
|
3547
3612
|
]
|
|
3548
3613
|
);
|
|
@@ -3556,11 +3621,11 @@ import {
|
|
|
3556
3621
|
uuid as uuid24,
|
|
3557
3622
|
timestamp as timestamp24,
|
|
3558
3623
|
index as index21,
|
|
3559
|
-
check as
|
|
3624
|
+
check as check16,
|
|
3560
3625
|
unique as unique8,
|
|
3561
3626
|
uniqueIndex as uniqueIndex5
|
|
3562
3627
|
} from "drizzle-orm/pg-core";
|
|
3563
|
-
import { sql as
|
|
3628
|
+
import { sql as sql18 } from "drizzle-orm";
|
|
3564
3629
|
var channelAllowedConversations;
|
|
3565
3630
|
var init_channel_allowed_conversations = __esm({
|
|
3566
3631
|
"../../packages/db/src/schema/channel-allowed-conversations.ts"() {
|
|
@@ -3596,24 +3661,24 @@ var init_channel_allowed_conversations = __esm({
|
|
|
3596
3661
|
),
|
|
3597
3662
|
index21("idx_channel_allowed_conversations_agent").on(table.agentId),
|
|
3598
3663
|
index21("idx_channel_allowed_conversations_entity").on(table.entityId),
|
|
3599
|
-
|
|
3664
|
+
check16(
|
|
3600
3665
|
"channel_allowed_conversations_channel_check",
|
|
3601
|
-
|
|
3666
|
+
sql18`${table.channel} IN ('telegram','discord','slack','whatsapp')`
|
|
3602
3667
|
),
|
|
3603
|
-
|
|
3668
|
+
check16(
|
|
3604
3669
|
"channel_allowed_conversations_kind_check",
|
|
3605
|
-
|
|
3670
|
+
sql18`${table.kind} IN ('private','group','channel','thread')`
|
|
3606
3671
|
),
|
|
3607
|
-
|
|
3608
|
-
|
|
3672
|
+
check16("channel_allowed_conversations_role_check", sql18`${table.role} IN ('owner','member')`),
|
|
3673
|
+
check16(
|
|
3609
3674
|
"channel_allowed_conversations_status_check",
|
|
3610
|
-
|
|
3675
|
+
sql18`${table.status} IN ('active','pending')`
|
|
3611
3676
|
),
|
|
3612
3677
|
// Mirrors telegram_allowed_chats_single_owner (migration 0060): at most one
|
|
3613
3678
|
// active-owner-authority row per (agent, channel) — same race this closes
|
|
3614
3679
|
// (concurrent first-contact claims), scoped so each channel gets its OWN
|
|
3615
3680
|
// owner rather than sharing one across an agent's whole multichannel surface.
|
|
3616
|
-
uniqueIndex5("channel_allowed_conversations_single_owner").on(table.agentId, table.channel).where(
|
|
3681
|
+
uniqueIndex5("channel_allowed_conversations_single_owner").on(table.agentId, table.channel).where(sql18`${table.role} = 'owner'`)
|
|
3617
3682
|
]
|
|
3618
3683
|
);
|
|
3619
3684
|
}
|
|
@@ -19064,12 +19129,12 @@ var require_formdata_parser = __commonJS({
|
|
|
19064
19129
|
return "failure";
|
|
19065
19130
|
}
|
|
19066
19131
|
if (bufferStartsWith(input, filenameBuffer, position)) {
|
|
19067
|
-
let
|
|
19068
|
-
if (input[
|
|
19132
|
+
let check17 = position.position + filenameBuffer.length;
|
|
19133
|
+
if (input[check17] === 42) {
|
|
19069
19134
|
position.position += 1;
|
|
19070
|
-
|
|
19135
|
+
check17 += 1;
|
|
19071
19136
|
}
|
|
19072
|
-
if (input[
|
|
19137
|
+
if (input[check17] !== 61 || input[check17 + 1] !== 34) {
|
|
19073
19138
|
return "failure";
|
|
19074
19139
|
}
|
|
19075
19140
|
position.position += 12;
|
|
@@ -46554,7 +46619,7 @@ var require_Util = __commonJS({
|
|
|
46554
46619
|
await client.rest.patch(route, { body: updatedItems, reason });
|
|
46555
46620
|
return updatedItems;
|
|
46556
46621
|
}
|
|
46557
|
-
function
|
|
46622
|
+
function basename5(path2, ext) {
|
|
46558
46623
|
const res = parse2(path2);
|
|
46559
46624
|
return ext && res.ext.startsWith(ext) ? res.name : res.base.split("?")[0];
|
|
46560
46625
|
}
|
|
@@ -46677,7 +46742,7 @@ var require_Util = __commonJS({
|
|
|
46677
46742
|
resolveColor,
|
|
46678
46743
|
discordSort,
|
|
46679
46744
|
setPosition,
|
|
46680
|
-
basename:
|
|
46745
|
+
basename: basename5,
|
|
46681
46746
|
cleanContent,
|
|
46682
46747
|
cleanCodeBlockContent,
|
|
46683
46748
|
parseWebhookURL,
|
|
@@ -65369,7 +65434,7 @@ var require_MessagePayload = __commonJS({
|
|
|
65369
65434
|
var { DiscordjsError: DiscordjsError2, DiscordjsRangeError: DiscordjsRangeError2, ErrorCodes: ErrorCodes2 } = require_errors2();
|
|
65370
65435
|
var { resolveFile } = require_DataResolver();
|
|
65371
65436
|
var MessageFlagsBitField = require_MessageFlagsBitField();
|
|
65372
|
-
var { basename:
|
|
65437
|
+
var { basename: basename5, verifyString, resolvePartialEmoji } = require_Util();
|
|
65373
65438
|
var getBaseInteraction = lazy(() => require_BaseInteraction());
|
|
65374
65439
|
var MessagePayload = class {
|
|
65375
65440
|
/**
|
|
@@ -65588,10 +65653,10 @@ var require_MessagePayload = __commonJS({
|
|
|
65588
65653
|
let name;
|
|
65589
65654
|
const findName = (thing) => {
|
|
65590
65655
|
if (typeof thing === "string") {
|
|
65591
|
-
return
|
|
65656
|
+
return basename5(thing);
|
|
65592
65657
|
}
|
|
65593
65658
|
if (thing.path) {
|
|
65594
|
-
return
|
|
65659
|
+
return basename5(thing.path);
|
|
65595
65660
|
}
|
|
65596
65661
|
return "file.jpg";
|
|
65597
65662
|
};
|
|
@@ -88043,7 +88108,7 @@ var require_EmbedBuilder = __commonJS({
|
|
|
88043
88108
|
var require_AttachmentBuilder = __commonJS({
|
|
88044
88109
|
"../../node_modules/.pnpm/discord.js@14.26.5/node_modules/discord.js/src/structures/AttachmentBuilder.js"(exports2, module2) {
|
|
88045
88110
|
"use strict";
|
|
88046
|
-
var { basename:
|
|
88111
|
+
var { basename: basename5, flatten } = require_Util();
|
|
88047
88112
|
var AttachmentBuilder = class _AttachmentBuilder {
|
|
88048
88113
|
/**
|
|
88049
88114
|
* @param {BufferResolvable|Stream} attachment The file
|
|
@@ -88103,7 +88168,7 @@ var require_AttachmentBuilder = __commonJS({
|
|
|
88103
88168
|
* @readonly
|
|
88104
88169
|
*/
|
|
88105
88170
|
get spoiler() {
|
|
88106
|
-
return
|
|
88171
|
+
return basename5(this.name).startsWith("SPOILER_");
|
|
88107
88172
|
}
|
|
88108
88173
|
toJSON() {
|
|
88109
88174
|
return flatten(this);
|
|
@@ -156710,7 +156775,7 @@ var require_wait2 = __commonJS({
|
|
|
156710
156775
|
return;
|
|
156711
156776
|
}
|
|
156712
156777
|
let prior = current;
|
|
156713
|
-
const
|
|
156778
|
+
const check17 = (backoff) => {
|
|
156714
156779
|
if (Date.now() > max2) {
|
|
156715
156780
|
done(null, "timed-out");
|
|
156716
156781
|
} else {
|
|
@@ -156718,7 +156783,7 @@ var require_wait2 = __commonJS({
|
|
|
156718
156783
|
prior = current;
|
|
156719
156784
|
current = Atomics.load(state, index22);
|
|
156720
156785
|
if (current === prior) {
|
|
156721
|
-
|
|
156786
|
+
check17(backoff >= MAX_TIMEOUT ? MAX_TIMEOUT : backoff * 2);
|
|
156722
156787
|
} else {
|
|
156723
156788
|
if (current === expected) done(null, "ok");
|
|
156724
156789
|
else done(null, "not-equal");
|
|
@@ -156726,7 +156791,7 @@ var require_wait2 = __commonJS({
|
|
|
156726
156791
|
}, backoff);
|
|
156727
156792
|
}
|
|
156728
156793
|
};
|
|
156729
|
-
|
|
156794
|
+
check17(1);
|
|
156730
156795
|
}
|
|
156731
156796
|
function waitDiff(state, index22, expected, timeout, done) {
|
|
156732
156797
|
const max2 = Date.now() + timeout;
|
|
@@ -156735,7 +156800,7 @@ var require_wait2 = __commonJS({
|
|
|
156735
156800
|
done(null, "ok");
|
|
156736
156801
|
return;
|
|
156737
156802
|
}
|
|
156738
|
-
const
|
|
156803
|
+
const check17 = (backoff) => {
|
|
156739
156804
|
if (Date.now() > max2) {
|
|
156740
156805
|
done(null, "timed-out");
|
|
156741
156806
|
} else {
|
|
@@ -156744,12 +156809,12 @@ var require_wait2 = __commonJS({
|
|
|
156744
156809
|
if (current !== expected) {
|
|
156745
156810
|
done(null, "ok");
|
|
156746
156811
|
} else {
|
|
156747
|
-
|
|
156812
|
+
check17(backoff >= MAX_TIMEOUT ? MAX_TIMEOUT : backoff * 2);
|
|
156748
156813
|
}
|
|
156749
156814
|
}, backoff);
|
|
156750
156815
|
}
|
|
156751
156816
|
};
|
|
156752
|
-
|
|
156817
|
+
check17(1);
|
|
156753
156818
|
}
|
|
156754
156819
|
module2.exports = { wait, waitDiff };
|
|
156755
156820
|
}
|
|
@@ -199107,7 +199172,7 @@ var require_view2 = __commonJS({
|
|
|
199107
199172
|
var path2 = __require("node:path");
|
|
199108
199173
|
var fs4 = __require("node:fs");
|
|
199109
199174
|
var dirname8 = path2.dirname;
|
|
199110
|
-
var
|
|
199175
|
+
var basename5 = path2.basename;
|
|
199111
199176
|
var extname2 = path2.extname;
|
|
199112
199177
|
var join16 = path2.join;
|
|
199113
199178
|
var resolve3 = path2.resolve;
|
|
@@ -199146,7 +199211,7 @@ var require_view2 = __commonJS({
|
|
|
199146
199211
|
var root = roots[i];
|
|
199147
199212
|
var loc = resolve3(root, name);
|
|
199148
199213
|
var dir = dirname8(loc);
|
|
199149
|
-
var file =
|
|
199214
|
+
var file = basename5(loc);
|
|
199150
199215
|
path3 = this.resolve(dir, file);
|
|
199151
199216
|
}
|
|
199152
199217
|
return path3;
|
|
@@ -199176,7 +199241,7 @@ var require_view2 = __commonJS({
|
|
|
199176
199241
|
if (stat11 && stat11.isFile()) {
|
|
199177
199242
|
return path3;
|
|
199178
199243
|
}
|
|
199179
|
-
path3 = join16(dir,
|
|
199244
|
+
path3 = join16(dir, basename5(file, ext), "index" + ext);
|
|
199180
199245
|
stat11 = tryStat(path3);
|
|
199181
199246
|
if (stat11 && stat11.isFile()) {
|
|
199182
199247
|
return path3;
|
|
@@ -202138,9 +202203,9 @@ var require_content_disposition = __commonJS({
|
|
|
202138
202203
|
if (typeof fallback === "string" && NON_LATIN1_REGEXP.test(fallback)) {
|
|
202139
202204
|
throw new TypeError("fallback must be ISO-8859-1 string");
|
|
202140
202205
|
}
|
|
202141
|
-
var name =
|
|
202206
|
+
var name = basename5(filename);
|
|
202142
202207
|
var isQuotedString = TEXT_REGEXP.test(name);
|
|
202143
|
-
var fallbackName = typeof fallback !== "string" ? fallback && getlatin1(name) :
|
|
202208
|
+
var fallbackName = typeof fallback !== "string" ? fallback && getlatin1(name) : basename5(fallback);
|
|
202144
202209
|
var hasFallback = typeof fallbackName === "string" && fallbackName !== name;
|
|
202145
202210
|
if (hasFallback || !isQuotedString || hasHexEscape(name)) {
|
|
202146
202211
|
params["filename*"] = name;
|
|
@@ -202260,7 +202325,7 @@ var require_content_disposition = __commonJS({
|
|
|
202260
202325
|
this.type = type;
|
|
202261
202326
|
this.parameters = parameters;
|
|
202262
202327
|
}
|
|
202263
|
-
function
|
|
202328
|
+
function basename5(path2) {
|
|
202264
202329
|
const normalized = path2.replaceAll("\\", "/");
|
|
202265
202330
|
let end = normalized.length;
|
|
202266
202331
|
while (end > 0 && normalized[end - 1] === "/") {
|
|
@@ -204667,8 +204732,6 @@ var envSchema = z.object({
|
|
|
204667
204732
|
EMBEDDING_PROVIDER: z.enum(["ollama", "openai", "keyword"]).default("keyword"),
|
|
204668
204733
|
EMBEDDING_MODEL: z.string().optional(),
|
|
204669
204734
|
EMBEDDING_BASE_URL: z.string().optional(),
|
|
204670
|
-
// Delivery
|
|
204671
|
-
TELEGRAM_BOT_TOKEN: z.string().optional(),
|
|
204672
204735
|
// Auth
|
|
204673
204736
|
AUTH_MODE: z.enum(["local-trust", "local-auth", "bearer-token"]).default("local-trust"),
|
|
204674
204737
|
WORKER_SECRET: z.string().default(""),
|
|
@@ -204695,8 +204758,6 @@ var envSchema = z.object({
|
|
|
204695
204758
|
// Enable reflection per entity via the dashboard toggle — NOT via this env var.
|
|
204696
204759
|
// The other knobs gate WHICH jobs qualify and bound the pass.
|
|
204697
204760
|
REFLECTION_ENABLED: z.string().default(""),
|
|
204698
|
-
// Minimum job turns before a completed job is "substantial" enough to reflect on.
|
|
204699
|
-
REFLECTION_MIN_TURNS: z.coerce.number().default(3),
|
|
204700
204761
|
// Per-entity rolling-hour cap on reflection passes (rate limit / cost guard).
|
|
204701
204762
|
REFLECTION_MAX_PER_HOUR: z.coerce.number().default(6),
|
|
204702
204763
|
// Max LLM turns inside a single reflection pass (the reflection loop itself).
|
|
@@ -204839,7 +204900,7 @@ init_schema();
|
|
|
204839
204900
|
|
|
204840
204901
|
// ../../packages/db/src/queries/credentials.ts
|
|
204841
204902
|
init_credentials();
|
|
204842
|
-
import { eq, sql as
|
|
204903
|
+
import { eq, sql as sql19 } from "drizzle-orm";
|
|
204843
204904
|
|
|
204844
204905
|
// ../../packages/secrets/src/index.ts
|
|
204845
204906
|
import { createCipheriv, createDecipheriv, randomBytes } from "node:crypto";
|
|
@@ -205031,7 +205092,7 @@ async function getDecryptedCredentialById(db, credentialId) {
|
|
|
205031
205092
|
if (provider?.supportsRefresh && payload.refreshToken) {
|
|
205032
205093
|
try {
|
|
205033
205094
|
payload = await db.transaction(async (tx) => {
|
|
205034
|
-
await tx.execute(
|
|
205095
|
+
await tx.execute(sql19`SELECT pg_advisory_xact_lock(hashtext(${credentialId}))`);
|
|
205035
205096
|
const [freshRow] = await tx.select().from(credentials).where(eq(credentials.id, credentialId));
|
|
205036
205097
|
if (!freshRow) return payload;
|
|
205037
205098
|
const freshPayload = decryptPayload(freshRow.payload);
|
|
@@ -205299,7 +205360,7 @@ async function attachAgentToOrchestrator(db, entityId, orchestratorId, agentSlug
|
|
|
205299
205360
|
// ../../packages/db/src/repos/skills.ts
|
|
205300
205361
|
init_agents();
|
|
205301
205362
|
init_skills();
|
|
205302
|
-
import { eq as eq4, and as and3, or as or3, inArray as inArray2, sql as
|
|
205363
|
+
import { eq as eq4, and as and3, or as or3, inArray as inArray2, sql as sql20 } from "drizzle-orm";
|
|
205303
205364
|
async function createSkillRepo(db, entityId, input, reservedSlugs = []) {
|
|
205304
205365
|
if (reservedSlugs.includes(input.slug)) {
|
|
205305
205366
|
return { error: "slug_reserved" };
|
|
@@ -205342,7 +205403,7 @@ async function updateSkillRepo(db, entityId, skillId, patch) {
|
|
|
205342
205403
|
}
|
|
205343
205404
|
if (patch.createdBy === "agent") {
|
|
205344
205405
|
set.createdBy = "agent";
|
|
205345
|
-
set.patchCount =
|
|
205406
|
+
set.patchCount = sql20`${agentSkills.patchCount} + 1`;
|
|
205346
205407
|
}
|
|
205347
205408
|
await db.update(agentSkills).set(set).where(eq4(agentSkills.id, skillId));
|
|
205348
205409
|
return { ok: true };
|
|
@@ -205378,7 +205439,7 @@ async function assignSkillRepo(db, entityId, input, systemSkillSlugs2) {
|
|
|
205378
205439
|
}
|
|
205379
205440
|
async function touchSkillsLastUsed(db, skillIds) {
|
|
205380
205441
|
if (skillIds.length === 0) return;
|
|
205381
|
-
await db.update(agentSkills).set({ lastUsedAt:
|
|
205442
|
+
await db.update(agentSkills).set({ lastUsedAt: sql20`now()` }).where(inArray2(agentSkills.id, skillIds));
|
|
205382
205443
|
}
|
|
205383
205444
|
async function transitionSkillLifecycle(db, thresholds) {
|
|
205384
205445
|
const now = /* @__PURE__ */ new Date();
|
|
@@ -205392,21 +205453,21 @@ async function transitionSkillLifecycle(db, thresholds) {
|
|
|
205392
205453
|
and3(
|
|
205393
205454
|
eq4(agentSkills.createdBy, "agent"),
|
|
205394
205455
|
eq4(agentSkills.state, "active"),
|
|
205395
|
-
|
|
205456
|
+
sql20`coalesce(${agentSkills.lastUsedAt}, ${agentSkills.createdAt}) < ${staleAt}`
|
|
205396
205457
|
)
|
|
205397
205458
|
).returning({ id: agentSkills.id });
|
|
205398
205459
|
const archivedRows = await db.update(agentSkills).set({ state: "archived", archivedAt: now, updatedAt: now }).where(
|
|
205399
205460
|
and3(
|
|
205400
205461
|
eq4(agentSkills.createdBy, "agent"),
|
|
205401
205462
|
eq4(agentSkills.state, "stale"),
|
|
205402
|
-
|
|
205463
|
+
sql20`coalesce(${agentSkills.lastUsedAt}, ${agentSkills.createdAt}) < ${archiveAt}`
|
|
205403
205464
|
)
|
|
205404
205465
|
).returning({ id: agentSkills.id });
|
|
205405
205466
|
const reactivatedRows = await db.update(agentSkills).set({ state: "active", updatedAt: now }).where(
|
|
205406
205467
|
and3(
|
|
205407
205468
|
eq4(agentSkills.createdBy, "agent"),
|
|
205408
205469
|
eq4(agentSkills.state, "stale"),
|
|
205409
|
-
|
|
205470
|
+
sql20`${agentSkills.lastUsedAt} >= ${staleAt}`
|
|
205410
205471
|
)
|
|
205411
205472
|
).returning({ id: agentSkills.id });
|
|
205412
205473
|
return {
|
|
@@ -205425,25 +205486,25 @@ async function archiveAgentSkill(db, entityId, skillId) {
|
|
|
205425
205486
|
|
|
205426
205487
|
// ../../packages/db/src/repos/retention.ts
|
|
205427
205488
|
init_schema();
|
|
205428
|
-
import { sql as
|
|
205489
|
+
import { sql as sql21, inArray as inArray3 } from "drizzle-orm";
|
|
205429
205490
|
async function pruneOldJobs(db, retentionDays, batchSize = 1e3) {
|
|
205430
205491
|
if (retentionDays <= 0) {
|
|
205431
205492
|
return { jobsDeleted: 0, toolCallsDeleted: 0 };
|
|
205432
205493
|
}
|
|
205433
|
-
const cutoffExpr =
|
|
205494
|
+
const cutoffExpr = sql21`now() - make_interval(days => ${retentionDays})`;
|
|
205434
205495
|
let jobsDeleted = 0;
|
|
205435
205496
|
let toolCallsDeleted = 0;
|
|
205436
205497
|
for (; ; ) {
|
|
205437
205498
|
const batch = await db.transaction(async (tx) => {
|
|
205438
205499
|
const prunableRows = await tx.select({ id: agentJobs.id }).from(agentJobs).where(
|
|
205439
|
-
|
|
205500
|
+
sql21`${agentJobs.status} IN ('completed','failed','cancelled')
|
|
205440
205501
|
AND ${agentJobs.completedAt} < ${cutoffExpr}`
|
|
205441
205502
|
).limit(batchSize);
|
|
205442
205503
|
if (prunableRows.length === 0) {
|
|
205443
205504
|
return null;
|
|
205444
205505
|
}
|
|
205445
205506
|
const jobIds = prunableRows.map((r) => r.id);
|
|
205446
|
-
const [tcCountRow] = await tx.select({ n:
|
|
205507
|
+
const [tcCountRow] = await tx.select({ n: sql21`count(*)::int` }).from(toolCalls).where(inArray3(toolCalls.jobId, jobIds));
|
|
205447
205508
|
const batchToolCallsDeleted = tcCountRow?.n ?? 0;
|
|
205448
205509
|
await tx.delete(agentJobs).where(inArray3(agentJobs.id, jobIds));
|
|
205449
205510
|
return { jobsDeleted: jobIds.length, toolCallsDeleted: batchToolCallsDeleted };
|
|
@@ -205458,7 +205519,7 @@ async function pruneOldJobs(db, retentionDays, batchSize = 1e3) {
|
|
|
205458
205519
|
|
|
205459
205520
|
// ../../packages/db/src/repos/app-settings.ts
|
|
205460
205521
|
init_schema();
|
|
205461
|
-
import { and as and4, eq as eq5, sql as
|
|
205522
|
+
import { and as and4, eq as eq5, sql as sql22 } from "drizzle-orm";
|
|
205462
205523
|
var INSTALL_NOTES_KEY = "install_notes";
|
|
205463
205524
|
async function getEntitySetting(db, entityId, key) {
|
|
205464
205525
|
const [row] = await db.select({ value: entitySettings.value }).from(entitySettings).where(and4(eq5(entitySettings.entityId, entityId), eq5(entitySettings.key, key))).limit(1);
|
|
@@ -205473,7 +205534,7 @@ import {
|
|
|
205473
205534
|
eq as eq6,
|
|
205474
205535
|
and as and5,
|
|
205475
205536
|
or as or4,
|
|
205476
|
-
sql as
|
|
205537
|
+
sql as sql23,
|
|
205477
205538
|
desc,
|
|
205478
205539
|
asc,
|
|
205479
205540
|
not,
|
|
@@ -206109,11 +206170,51 @@ function buildOpenAICompatibleModel(config) {
|
|
|
206109
206170
|
}
|
|
206110
206171
|
|
|
206111
206172
|
// ../../packages/llm/src/providers/google.ts
|
|
206173
|
+
init_src();
|
|
206112
206174
|
import { createGoogleGenerativeAI } from "@ai-sdk/google";
|
|
206175
|
+
var GOOGLE_HOSTS = /* @__PURE__ */ new Set(["generativelanguage.googleapis.com"]);
|
|
206176
|
+
function requestHost(input) {
|
|
206177
|
+
try {
|
|
206178
|
+
if (typeof input === "string") return new URL(input).host;
|
|
206179
|
+
if (input instanceof URL) return input.host;
|
|
206180
|
+
return new URL(input.url).host;
|
|
206181
|
+
} catch {
|
|
206182
|
+
return void 0;
|
|
206183
|
+
}
|
|
206184
|
+
}
|
|
206185
|
+
function injectGoogleThinking(body) {
|
|
206186
|
+
if (typeof body !== "object" || body === null) return body;
|
|
206187
|
+
const b = body;
|
|
206188
|
+
const generationConfig = typeof b["generationConfig"] === "object" && b["generationConfig"] !== null ? b["generationConfig"] : {};
|
|
206189
|
+
if (generationConfig["thinkingConfig"] === void 0) {
|
|
206190
|
+
generationConfig["thinkingConfig"] = { includeThoughts: true };
|
|
206191
|
+
}
|
|
206192
|
+
b["generationConfig"] = generationConfig;
|
|
206193
|
+
return body;
|
|
206194
|
+
}
|
|
206195
|
+
function createGoogleFetch(opts, baseFetch = globalThis.fetch) {
|
|
206196
|
+
return async (input, init2) => {
|
|
206197
|
+
const host = requestHost(input);
|
|
206198
|
+
if (!opts.injectThinking || !host || !GOOGLE_HOSTS.has(host) || !init2?.body) {
|
|
206199
|
+
return baseFetch(input, init2);
|
|
206200
|
+
}
|
|
206201
|
+
let patchedInit = init2;
|
|
206202
|
+
try {
|
|
206203
|
+
const rawBody = typeof init2.body === "string" ? init2.body : await new Response(init2.body).text();
|
|
206204
|
+
const patched = injectGoogleThinking(JSON.parse(rawBody));
|
|
206205
|
+
patchedInit = { ...init2, body: JSON.stringify(patched) };
|
|
206206
|
+
} catch {
|
|
206207
|
+
}
|
|
206208
|
+
return baseFetch(input, patchedInit);
|
|
206209
|
+
};
|
|
206210
|
+
}
|
|
206113
206211
|
function buildGoogleModel(config) {
|
|
206212
|
+
const entry = findModelCatalogEntry("google", config.model);
|
|
206213
|
+
const isReasoning = entry?.capabilities.reasoning === true;
|
|
206114
206214
|
const provider = createGoogleGenerativeAI({
|
|
206115
206215
|
apiKey: config.apiKey,
|
|
206116
|
-
...config.baseURL ? { baseURL: config.baseURL } : {}
|
|
206216
|
+
...config.baseURL ? { baseURL: config.baseURL } : {},
|
|
206217
|
+
fetch: createGoogleFetch({ injectThinking: isReasoning })
|
|
206117
206218
|
});
|
|
206118
206219
|
return provider(config.model);
|
|
206119
206220
|
}
|
|
@@ -206346,7 +206447,13 @@ var nodalToolCallMiddleware = createNativeToolCallMiddleware(nodalNativeParser);
|
|
|
206346
206447
|
// ../../packages/llm/src/providers/moonshot-schema.ts
|
|
206347
206448
|
var SCHEMA_MAP_KEYS = /* @__PURE__ */ new Set(["properties", "patternProperties", "$defs", "definitions"]);
|
|
206348
206449
|
var SCHEMA_LIST_KEYS = /* @__PURE__ */ new Set(["anyOf", "oneOf", "allOf", "prefixItems"]);
|
|
206349
|
-
var SCHEMA_NODE_KEYS = /* @__PURE__ */ new Set([
|
|
206450
|
+
var SCHEMA_NODE_KEYS = /* @__PURE__ */ new Set([
|
|
206451
|
+
"items",
|
|
206452
|
+
"contains",
|
|
206453
|
+
"not",
|
|
206454
|
+
"additionalProperties",
|
|
206455
|
+
"propertyNames"
|
|
206456
|
+
]);
|
|
206350
206457
|
function isPlainObject(value) {
|
|
206351
206458
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
206352
206459
|
}
|
|
@@ -206712,7 +206819,7 @@ function buildMiniMaxModel(config) {
|
|
|
206712
206819
|
init_src();
|
|
206713
206820
|
import { createOpenAICompatible as createOpenAICompatible2 } from "@ai-sdk/openai-compatible";
|
|
206714
206821
|
var MOONSHOT_HOSTS = /* @__PURE__ */ new Set(["api.moonshot.ai", "api.moonshot.cn"]);
|
|
206715
|
-
function
|
|
206822
|
+
function requestHost2(input) {
|
|
206716
206823
|
try {
|
|
206717
206824
|
if (typeof input === "string") return new URL(input).host;
|
|
206718
206825
|
if (input instanceof URL) return input.host;
|
|
@@ -206737,7 +206844,7 @@ function patchMoonshotRequestBody(body, opts) {
|
|
|
206737
206844
|
function createMoonshotFetch(opts, baseFetch = globalThis.fetch) {
|
|
206738
206845
|
const tolerant = createTolerantFetch(baseFetch);
|
|
206739
206846
|
return async (input, init2) => {
|
|
206740
|
-
const host =
|
|
206847
|
+
const host = requestHost2(input);
|
|
206741
206848
|
if (!host || !MOONSHOT_HOSTS.has(host) || !init2?.body) {
|
|
206742
206849
|
return tolerant(input, init2);
|
|
206743
206850
|
}
|
|
@@ -207544,8 +207651,8 @@ function rowToMemory(row) {
|
|
|
207544
207651
|
// ../../packages/memory/src/access-tracking.ts
|
|
207545
207652
|
async function touchMemory(db, id, entityId) {
|
|
207546
207653
|
await db.update(agentMemory).set({
|
|
207547
|
-
lastAccessedAt:
|
|
207548
|
-
accessCount:
|
|
207654
|
+
lastAccessedAt: sql23`now()`,
|
|
207655
|
+
accessCount: sql23`${agentMemory.accessCount} + 1`
|
|
207549
207656
|
}).where(and5(eq6(agentMemory.id, id), eq6(agentMemory.entityId, entityId)));
|
|
207550
207657
|
}
|
|
207551
207658
|
async function touchMemories(db, ids, entityId) {
|
|
@@ -207563,9 +207670,9 @@ async function keywordSearch(db, query, filters, sort = "importance") {
|
|
|
207563
207670
|
const conditions = buildWhereConditions({ entityId, agentId, skillTags, category });
|
|
207564
207671
|
const orderBy = keywordOrderBy(sort);
|
|
207565
207672
|
if (orTerms.length > 0) {
|
|
207566
|
-
const tsv =
|
|
207567
|
-
const tsq =
|
|
207568
|
-
const rows2 = await db.select().from(agentMemory).where(and5(...conditions,
|
|
207673
|
+
const tsv = sql23`"agent_memory"."search_tsv"`;
|
|
207674
|
+
const tsq = sql23`to_tsquery('english', ${orTerms.join(" | ")})`;
|
|
207675
|
+
const rows2 = await db.select().from(agentMemory).where(and5(...conditions, sql23`${tsv} @@ ${tsq}`)).orderBy(sql23`ts_rank(${tsv}, ${tsq}) DESC`, ...orderBy).limit(limit);
|
|
207569
207676
|
return rows2;
|
|
207570
207677
|
}
|
|
207571
207678
|
const rows = await db.select().from(agentMemory).where(and5(...conditions)).orderBy(...orderBy).limit(limit);
|
|
@@ -207610,10 +207717,10 @@ function buildWhereConditions(filters) {
|
|
|
207610
207717
|
if (skillTags && skillTags.length > 0) {
|
|
207611
207718
|
const tagLiteral = pgTextArray(skillTags);
|
|
207612
207719
|
conditions.push(
|
|
207613
|
-
|
|
207720
|
+
sql23`(
|
|
207614
207721
|
${agentMemory.skillTags} = '{}'::text[]
|
|
207615
207722
|
OR ${agentMemory.skillTags} IS NULL
|
|
207616
|
-
OR ${agentMemory.skillTags} && ${
|
|
207723
|
+
OR ${agentMemory.skillTags} && ${sql23.raw(tagLiteral)}::text[]
|
|
207617
207724
|
)`
|
|
207618
207725
|
);
|
|
207619
207726
|
}
|
|
@@ -207654,10 +207761,10 @@ async function transitionMemoryLifecycle(db, opts) {
|
|
|
207654
207761
|
const rows = await db.update(agentMemory).set({ archived: true, updatedAt: /* @__PURE__ */ new Date() }).where(
|
|
207655
207762
|
and5(
|
|
207656
207763
|
eq6(agentMemory.archived, false),
|
|
207657
|
-
|
|
207658
|
-
|
|
207659
|
-
|
|
207660
|
-
|
|
207764
|
+
sql23`${agentMemory.source} IN ('agent','reflection')`,
|
|
207765
|
+
sql23`${agentMemory.importance} <= ${opts.importanceMax}`,
|
|
207766
|
+
sql23`coalesce(${agentMemory.accessCount}, 0) = 0`,
|
|
207767
|
+
sql23`coalesce(${agentMemory.importanceLocked}, false) = false`,
|
|
207661
207768
|
lt(agentMemory.createdAt, cutoff)
|
|
207662
207769
|
)
|
|
207663
207770
|
).returning({ id: agentMemory.id });
|
|
@@ -207862,16 +207969,16 @@ async function selectMemoriesForInjection(db, opts) {
|
|
|
207862
207969
|
const baseConditions = and5(
|
|
207863
207970
|
eq6(agentMemory.entityId, opts.entityId),
|
|
207864
207971
|
eq6(agentMemory.archived, false),
|
|
207865
|
-
|
|
207972
|
+
sql23`(${agentMemory.validTo} IS NULL OR ${agentMemory.validTo} > now())`
|
|
207866
207973
|
);
|
|
207867
207974
|
const rawQuery = opts.query ?? "";
|
|
207868
207975
|
const tokens = tokenizeQuery(rawQuery);
|
|
207869
207976
|
let packed;
|
|
207870
207977
|
if (tokens.length > 0) {
|
|
207871
|
-
const tsv =
|
|
207872
|
-
const tsq =
|
|
207978
|
+
const tsv = sql23`"agent_memory"."search_tsv"`;
|
|
207979
|
+
const tsq = sql23`to_tsquery('english', ${tokens.join(" | ")})`;
|
|
207873
207980
|
const candidates = await db.select().from(agentMemory).where(baseConditions).orderBy(
|
|
207874
|
-
|
|
207981
|
+
sql23`ts_rank(${tsv}, ${tsq}) DESC`,
|
|
207875
207982
|
desc(agentMemory.importance),
|
|
207876
207983
|
desc(agentMemory.lastAccessedAt)
|
|
207877
207984
|
).limit(MAX_CANDIDATES);
|
|
@@ -207902,7 +208009,7 @@ async function findMemoriesByFactSubstring(db, entityId, substring, limit = 5) {
|
|
|
207902
208009
|
and5(
|
|
207903
208010
|
eq6(agentMemory.entityId, entityId),
|
|
207904
208011
|
eq6(agentMemory.archived, false),
|
|
207905
|
-
|
|
208012
|
+
sql23`(${agentMemory.validTo} IS NULL OR ${agentMemory.validTo} > now())`,
|
|
207906
208013
|
ilike2(agentMemory.fact, `%${substring}%`)
|
|
207907
208014
|
)
|
|
207908
208015
|
).limit(limit);
|
|
@@ -208029,16 +208136,16 @@ var searchHistoryTool = {
|
|
|
208029
208136
|
riskLevel: "read",
|
|
208030
208137
|
execute: async (input, ctx) => {
|
|
208031
208138
|
const limit = input.limit ?? 6;
|
|
208032
|
-
const tsq =
|
|
208033
|
-
const tsv =
|
|
208139
|
+
const tsq = sql23`plainto_tsquery('simple', ${input.query})`;
|
|
208140
|
+
const tsv = sql23`"agent_jobs"."search_tsv"`;
|
|
208034
208141
|
const rows = await ctx.db.select({
|
|
208035
208142
|
job_id: agentJobs.id,
|
|
208036
208143
|
agent: agents.slug,
|
|
208037
208144
|
channel: agentJobs.channel,
|
|
208038
208145
|
when: agentJobs.createdAt,
|
|
208039
208146
|
task: agentJobs.task,
|
|
208040
|
-
snippet:
|
|
208041
|
-
}).from(agentJobs).leftJoin(agents, eq6(agents.id, agentJobs.agentId)).where(and5(eq6(agentJobs.entityId, ctx.entityId),
|
|
208147
|
+
snippet: sql23`ts_headline('simple', coalesce(${agentJobs.searchText}, ${agentJobs.task}, ''), ${tsq}, 'StartSel=«, StopSel=», MaxFragments=2, MinWords=4, MaxWords=18, FragmentDelimiter= … ')`
|
|
208148
|
+
}).from(agentJobs).leftJoin(agents, eq6(agents.id, agentJobs.agentId)).where(and5(eq6(agentJobs.entityId, ctx.entityId), sql23`${tsv} @@ ${tsq}`)).orderBy(sql23`ts_rank(${tsv}, ${tsq}) DESC`, desc(agentJobs.createdAt)).limit(limit);
|
|
208042
208149
|
return rows.map((r) => ({
|
|
208043
208150
|
job_id: r.job_id,
|
|
208044
208151
|
agent: r.agent ?? null,
|
|
@@ -208255,7 +208362,7 @@ import { z as z29 } from "zod";
|
|
|
208255
208362
|
|
|
208256
208363
|
// ../../packages/tools/src/builtin/file-ops/workspace.ts
|
|
208257
208364
|
import { realpath, stat } from "node:fs/promises";
|
|
208258
|
-
import { resolve as resolvePath, sep, isAbsolute
|
|
208365
|
+
import { resolve as resolvePath, sep, isAbsolute } from "node:path";
|
|
208259
208366
|
var SHARED_WORKSPACE_LABEL = "shared";
|
|
208260
208367
|
var MAX_READ_BYTES = 1024 * 1024;
|
|
208261
208368
|
var MAX_READ_FILE_BYTES = 50 * 1024 * 1024;
|
|
@@ -208567,7 +208674,7 @@ var fileReadTool = {
|
|
|
208567
208674
|
|
|
208568
208675
|
// ../../packages/tools/src/builtin/file-ops/file-write.ts
|
|
208569
208676
|
import { writeFile, rename, mkdir, unlink } from "node:fs/promises";
|
|
208570
|
-
import { dirname as dirname2, basename
|
|
208677
|
+
import { dirname as dirname2, basename } from "node:path";
|
|
208571
208678
|
import { randomBytes as randomBytes2 } from "node:crypto";
|
|
208572
208679
|
import { z as z30 } from "zod";
|
|
208573
208680
|
var FileWriteInputSchema = z30.object({
|
|
@@ -208601,7 +208708,7 @@ var fileWriteTool = {
|
|
|
208601
208708
|
if (input.create_dirs) {
|
|
208602
208709
|
await mkdir(dir, { recursive: true });
|
|
208603
208710
|
}
|
|
208604
|
-
const tmp = `${dir}/.${
|
|
208711
|
+
const tmp = `${dir}/.${basename(path2)}.${randomBytes2(6).toString("hex")}.tmp`;
|
|
208605
208712
|
try {
|
|
208606
208713
|
await writeFile(tmp, input.content, "utf8");
|
|
208607
208714
|
await rename(tmp, path2);
|
|
@@ -208626,7 +208733,7 @@ var fileWriteTool = {
|
|
|
208626
208733
|
|
|
208627
208734
|
// ../../packages/tools/src/builtin/file-ops/file-edit.ts
|
|
208628
208735
|
import { readFile as readFile2, writeFile as writeFile2, rename as rename2, unlink as unlink2 } from "node:fs/promises";
|
|
208629
|
-
import { dirname as dirname3, basename as
|
|
208736
|
+
import { dirname as dirname3, basename as basename2 } from "node:path";
|
|
208630
208737
|
import { randomBytes as randomBytes3 } from "node:crypto";
|
|
208631
208738
|
import { z as z31 } from "zod";
|
|
208632
208739
|
var FileEditInputSchema = z31.object({
|
|
@@ -208684,7 +208791,7 @@ var fileEditTool = {
|
|
|
208684
208791
|
};
|
|
208685
208792
|
}
|
|
208686
208793
|
const dir = dirname3(path2);
|
|
208687
|
-
const tmp = `${dir}/.${
|
|
208794
|
+
const tmp = `${dir}/.${basename2(path2)}.${randomBytes3(6).toString("hex")}.tmp`;
|
|
208688
208795
|
try {
|
|
208689
208796
|
await writeFile2(tmp, updated, "utf8");
|
|
208690
208797
|
await rename2(tmp, path2);
|
|
@@ -208925,7 +209032,7 @@ import { z as z34 } from "zod";
|
|
|
208925
209032
|
// ../../packages/tools/src/builtin/office-ops/office-helpers.ts
|
|
208926
209033
|
var import_jszip = __toESM(require_lib3(), 1);
|
|
208927
209034
|
import { readFile as readFile4, writeFile as writeFile3, rename as rename3, unlink as unlink3, stat as stat5 } from "node:fs/promises";
|
|
208928
|
-
import { dirname as dirname4, basename as
|
|
209035
|
+
import { dirname as dirname4, basename as basename3 } from "node:path";
|
|
208929
209036
|
import { randomBytes as randomBytes4 } from "node:crypto";
|
|
208930
209037
|
var MAX_OFFICE_BYTES = 25 * 1024 * 1024;
|
|
208931
209038
|
var MAX_OFFICE_INFLATED_BYTES = 1024 * 1024 * 1024;
|
|
@@ -209039,7 +209146,7 @@ async function writeWorkspaceBinary(ctx, path2, buffer2, { overwrite = false } =
|
|
|
209039
209146
|
};
|
|
209040
209147
|
}
|
|
209041
209148
|
const dir = dirname4(resolvedPath);
|
|
209042
|
-
const tmp = `${dir}/.${
|
|
209149
|
+
const tmp = `${dir}/.${basename3(resolvedPath)}.${randomBytes4(6).toString("hex")}.tmp`;
|
|
209043
209150
|
try {
|
|
209044
209151
|
await writeFile3(tmp, buffer2);
|
|
209045
209152
|
await rename3(tmp, resolvedPath);
|
|
@@ -211673,8 +211780,8 @@ var createAgentTool = {
|
|
|
211673
211780
|
const { dbRole, orchestratorMode } = mapRole(input.role);
|
|
211674
211781
|
const resolved = await resolveAgentProvider(ctx.db, ctx.entityId, null);
|
|
211675
211782
|
if (resolved) {
|
|
211676
|
-
const
|
|
211677
|
-
if (!
|
|
211783
|
+
const check17 = validateModelForProvider(resolved.provider, input.model);
|
|
211784
|
+
if (!check17.ok) return check17;
|
|
211678
211785
|
}
|
|
211679
211786
|
let result;
|
|
211680
211787
|
try {
|
|
@@ -211746,8 +211853,8 @@ var updateAgentTool = {
|
|
|
211746
211853
|
if (input.model) {
|
|
211747
211854
|
const resolved = await resolveAgentProvider(ctx.db, ctx.entityId, agent.llmKeyId);
|
|
211748
211855
|
if (resolved) {
|
|
211749
|
-
const
|
|
211750
|
-
if (!
|
|
211856
|
+
const check17 = validateModelForProvider(resolved.provider, input.model);
|
|
211857
|
+
if (!check17.ok) return check17;
|
|
211751
211858
|
}
|
|
211752
211859
|
}
|
|
211753
211860
|
const patch = { updatedAt: /* @__PURE__ */ new Date() };
|
|
@@ -212490,13 +212597,15 @@ var runScheduleTool = {
|
|
|
212490
212597
|
task: agentSchedules.task,
|
|
212491
212598
|
chatId: agentSchedules.chatId,
|
|
212492
212599
|
notifyOnSuccess: agentSchedules.notifyOnSuccess,
|
|
212600
|
+
// B1 (notify-channel-choice): the schedule's explicit channel choice, if any.
|
|
212601
|
+
notifyChannel: agentSchedules.notifyChannel,
|
|
212493
212602
|
// Manual "run now": prevRunAt is still "when did this schedule last
|
|
212494
212603
|
// actually run" — this fire doesn't change that semantic.
|
|
212495
212604
|
lastRun: agentSchedules.lastRun
|
|
212496
212605
|
}).from(agentSchedules).where(and5(eq6(agentSchedules.entityId, ctx.entityId), eq6(agentSchedules.name, input.name))).limit(1);
|
|
212497
212606
|
if (!sched) return { ok: false, error: `No schedule named "${input.name}" in this workspace.` };
|
|
212498
212607
|
if (!sched.task) return { ok: false, error: `Schedule "${input.name}" has no task to run.` };
|
|
212499
|
-
const resolvedChatId = sched.notifyOnSuccess ? sched.chatId ?? await resolveOwnerChatId(ctx.db, sched.agentId) ?? null : null;
|
|
212608
|
+
const resolvedChatId = sched.notifyOnSuccess ? sched.notifyChannel ? sched.chatId ?? await resolveOwnerConversation(ctx.db, sched.agentId, sched.notifyChannel) : sched.chatId ?? await resolveOwnerChatId(ctx.db, sched.agentId) ?? null : null;
|
|
212500
212609
|
const [job] = await ctx.db.insert(agentJobs).values({
|
|
212501
212610
|
entityId: ctx.entityId,
|
|
212502
212611
|
agentId: sched.agentId,
|
|
@@ -212509,7 +212618,8 @@ var runScheduleTool = {
|
|
|
212509
212618
|
triggerContext: {
|
|
212510
212619
|
type: "cron",
|
|
212511
212620
|
scheduleName: input.name,
|
|
212512
|
-
prevRunAt: sched.lastRun ? sched.lastRun.toISOString() : null
|
|
212621
|
+
prevRunAt: sched.lastRun ? sched.lastRun.toISOString() : null,
|
|
212622
|
+
notifyChannel: sched.notifyChannel ?? null
|
|
212513
212623
|
}
|
|
212514
212624
|
}).returning({ id: agentJobs.id });
|
|
212515
212625
|
if (!job) return { ok: false, error: "Failed to queue the schedule run." };
|
|
@@ -320983,7 +321093,7 @@ var generateMessageIDV2 = (userId) => {
|
|
|
320983
321093
|
};
|
|
320984
321094
|
var generateMessageID = () => "3EB0" + randomBytes5(18).toString("hex").toUpperCase();
|
|
320985
321095
|
function bindWaitForEvent(ev, event) {
|
|
320986
|
-
return async (
|
|
321096
|
+
return async (check17, timeoutMs) => {
|
|
320987
321097
|
let listener;
|
|
320988
321098
|
let closeListener;
|
|
320989
321099
|
await promiseTimeout(timeoutMs, (resolve3, reject) => {
|
|
@@ -320994,7 +321104,7 @@ function bindWaitForEvent(ev, event) {
|
|
|
320994
321104
|
};
|
|
320995
321105
|
ev.on("connection.update", closeListener);
|
|
320996
321106
|
listener = async (update) => {
|
|
320997
|
-
if (await
|
|
321107
|
+
if (await check17(update)) {
|
|
320998
321108
|
resolve3();
|
|
320999
321109
|
}
|
|
321000
321110
|
};
|
|
@@ -335272,16 +335382,28 @@ function getAdapter3(channel2) {
|
|
|
335272
335382
|
}
|
|
335273
335383
|
|
|
335274
335384
|
// ../../packages/delivery/src/transport-channel.ts
|
|
335275
|
-
var
|
|
335276
|
-
|
|
335277
|
-
|
|
335278
|
-
"slack",
|
|
335279
|
-
"whatsapp"
|
|
335280
|
-
]);
|
|
335281
|
-
function resolveTransportChannel(channel2) {
|
|
335385
|
+
var CHANNEL_PRIORITY = ["telegram", "discord", "slack", "whatsapp"];
|
|
335386
|
+
var TRANSPORT_CHANNELS = new Set(CHANNEL_PRIORITY);
|
|
335387
|
+
function resolveTransportChannel(channel2, activeChannels) {
|
|
335282
335388
|
if (channel2 && TRANSPORT_CHANNELS.has(channel2)) return channel2;
|
|
335389
|
+
if (activeChannels && activeChannels.length > 0) {
|
|
335390
|
+
const active = new Set(activeChannels);
|
|
335391
|
+
const preferred = CHANNEL_PRIORITY.find((c) => active.has(c));
|
|
335392
|
+
if (preferred) return preferred;
|
|
335393
|
+
}
|
|
335283
335394
|
return "telegram";
|
|
335284
335395
|
}
|
|
335396
|
+
async function listActiveChannelsForAgent(db, agentId) {
|
|
335397
|
+
const [agentRow] = await db.select({ telegramBotToken: agents.telegramBotToken }).from(agents).where(eq6(agents.id, agentId)).limit(1);
|
|
335398
|
+
const bindings = await listChannelBindings(db, agentId);
|
|
335399
|
+
const enabled = new Set(bindings.filter((b) => b.enabled).map((b) => b.channel));
|
|
335400
|
+
const active = [];
|
|
335401
|
+
if (agentRow?.telegramBotToken) active.push("telegram");
|
|
335402
|
+
for (const channel2 of CHANNEL_PRIORITY) {
|
|
335403
|
+
if (channel2 !== "telegram" && enabled.has(channel2)) active.push(channel2);
|
|
335404
|
+
}
|
|
335405
|
+
return active;
|
|
335406
|
+
}
|
|
335285
335407
|
|
|
335286
335408
|
// ../../packages/tools/src/builtin/list-conversations.ts
|
|
335287
335409
|
var MAX_ROWS = 150;
|
|
@@ -335442,8 +335564,11 @@ import { z as z60 } from "zod";
|
|
|
335442
335564
|
import { realpath as realpath3 } from "node:fs/promises";
|
|
335443
335565
|
import { tmpdir as tmpdir3 } from "node:os";
|
|
335444
335566
|
import path from "node:path";
|
|
335567
|
+
function defaultChannelForJob(ctx) {
|
|
335568
|
+
return ctx.notifyChannelOverride ?? resolveTransportChannel(ctx.jobChannel, ctx.activeChannels);
|
|
335569
|
+
}
|
|
335445
335570
|
async function resolveChannelForJob(ctx, explicitChannel) {
|
|
335446
|
-
const jobChannel =
|
|
335571
|
+
const jobChannel = defaultChannelForJob(ctx);
|
|
335447
335572
|
if (explicitChannel === void 0 || explicitChannel === jobChannel) {
|
|
335448
335573
|
return jobChannel;
|
|
335449
335574
|
}
|
|
@@ -335489,7 +335614,7 @@ async function resolveRecipientChatId(explicitChatId, ctx, noRecipientErrorName,
|
|
|
335489
335614
|
throw err;
|
|
335490
335615
|
}
|
|
335491
335616
|
const channel2 = await resolveChannelForJob(ctx, explicitChannel);
|
|
335492
|
-
const crossChannel = explicitChannel !== void 0 && explicitChannel !==
|
|
335617
|
+
const crossChannel = explicitChannel !== void 0 && explicitChannel !== defaultChannelForJob(ctx);
|
|
335493
335618
|
let chatId = explicitChatId ?? (crossChannel ? null : ctx.jobChatId);
|
|
335494
335619
|
if (explicitChatId === void 0 && chatId === null) {
|
|
335495
335620
|
chatId = await resolveOwnerConversation(ctx.db, ctx.agentId, channel2);
|
|
@@ -335522,7 +335647,32 @@ async function resolveRecipientChatId(explicitChatId, ctx, noRecipientErrorName,
|
|
|
335522
335647
|
return chatId;
|
|
335523
335648
|
}
|
|
335524
335649
|
async function assertLocalSourceAllowed(source, ctx) {
|
|
335525
|
-
|
|
335650
|
+
let candidate = source;
|
|
335651
|
+
if (!path.isAbsolute(source)) {
|
|
335652
|
+
try {
|
|
335653
|
+
candidate = await resolveAndCheckPath(ctx, source);
|
|
335654
|
+
} catch (err) {
|
|
335655
|
+
if (err instanceof WorkspaceError) {
|
|
335656
|
+
const wrapped = new Error(`source_path_not_allowed: ${err.message}`);
|
|
335657
|
+
wrapped.name = "source_path_not_allowed";
|
|
335658
|
+
throw wrapped;
|
|
335659
|
+
}
|
|
335660
|
+
throw err;
|
|
335661
|
+
}
|
|
335662
|
+
}
|
|
335663
|
+
let real3;
|
|
335664
|
+
try {
|
|
335665
|
+
real3 = await realpath3(candidate);
|
|
335666
|
+
} catch (err) {
|
|
335667
|
+
if (err.code === "ENOENT") {
|
|
335668
|
+
const wrapped = new Error(
|
|
335669
|
+
path.isAbsolute(source) ? `source_path_not_allowed: no file found at "${source}".` : `source_path_not_allowed: no file found at workspace-relative path "${source}" (resolved to "${candidate}").`
|
|
335670
|
+
);
|
|
335671
|
+
wrapped.name = "source_path_not_allowed";
|
|
335672
|
+
throw wrapped;
|
|
335673
|
+
}
|
|
335674
|
+
throw err;
|
|
335675
|
+
}
|
|
335526
335676
|
const roots = [
|
|
335527
335677
|
...(ctx.workspaces ?? []).map((w) => w.path),
|
|
335528
335678
|
...ctx.skillStoreDir ? [ctx.skillStoreDir] : [],
|
|
@@ -336211,7 +336361,7 @@ async function healthRoute(c, deps) {
|
|
|
336211
336361
|
// LLM is not pinged on every health check (expensive)
|
|
336212
336362
|
};
|
|
336213
336363
|
try {
|
|
336214
|
-
await deps.db.execute(
|
|
336364
|
+
await deps.db.execute(sql23`SELECT 1`);
|
|
336215
336365
|
result.db = "ok";
|
|
336216
336366
|
} catch (err) {
|
|
336217
336367
|
console.error("[health] DB ping failed:", err instanceof Error ? err.message : err);
|
|
@@ -351608,7 +351758,9 @@ async function walkJobChainToRoot(db, jobId) {
|
|
|
351608
351758
|
async function resolveChannelApprovalDeliveryTarget(db, jobId) {
|
|
351609
351759
|
const chain = await walkJobChainToRoot(db, jobId);
|
|
351610
351760
|
if (!chain) return null;
|
|
351611
|
-
const
|
|
351761
|
+
const rootHop = chain[chain.length - 1];
|
|
351762
|
+
const activeChannels = await listActiveChannelsForAgent(db, rootHop.agentId);
|
|
351763
|
+
const rootChannel = resolveTransportChannel(rootHop.channel, activeChannels);
|
|
351612
351764
|
if (rootChannel === "telegram") {
|
|
351613
351765
|
const target = await resolveApprovalDeliveryTarget(db, jobId);
|
|
351614
351766
|
if (!target) return null;
|
|
@@ -351697,7 +351849,7 @@ import { join as join12 } from "node:path";
|
|
|
351697
351849
|
|
|
351698
351850
|
// src/skills/install.ts
|
|
351699
351851
|
import { cp, rm as rm2, mkdir as mkdir5, readFile as readFile11 } from "node:fs/promises";
|
|
351700
|
-
import { dirname as dirname7, join as join11, basename as
|
|
351852
|
+
import { dirname as dirname7, join as join11, basename as basename4, sep as sep5, resolve as resolve2 } from "node:path";
|
|
351701
351853
|
|
|
351702
351854
|
// src/skills/source.ts
|
|
351703
351855
|
var SkillSourceError = class extends Error {
|
|
@@ -352477,7 +352629,7 @@ async function pickManifest(extractRoot, subdir, skillName) {
|
|
|
352477
352629
|
}
|
|
352478
352630
|
}
|
|
352479
352631
|
if (byFrontmatter.length > 0) return byFrontmatter[0];
|
|
352480
|
-
const byFolder = manifests.filter((rel) =>
|
|
352632
|
+
const byFolder = manifests.filter((rel) => basename4(dirname7(rel)) === skillName);
|
|
352481
352633
|
if (byFolder.length > 0) return byFolder[0];
|
|
352482
352634
|
throw new SkillInstallError(
|
|
352483
352635
|
`Repository has multiple skills but none named "${skillName}". Found: ${manifests.map((m) => dirname7(m)).join(", ")}.`
|
|
@@ -353380,13 +353532,15 @@ async function runJob(jobId, deps, runnerEnv, opts) {
|
|
|
353380
353532
|
const canSeeImages = llmClient.capabilities.vision === true || modelCanSeeImages(llmClient.config.model);
|
|
353381
353533
|
const imageCache = /* @__PURE__ */ new Map();
|
|
353382
353534
|
const isOrchestrator = agent.role === "orchestrator";
|
|
353383
|
-
const
|
|
353535
|
+
const triggerWantsConfirmation = (job.channel === "cron" || job.channel === "webhook") && job.chatId != null;
|
|
353536
|
+
const jobTriggerContext = job.triggerContext;
|
|
353537
|
+
const notifyChannelOverride = jobTriggerContext?.type === "cron" || jobTriggerContext?.type === "webhook" ? jobTriggerContext.notifyChannel ?? void 0 : void 0;
|
|
353384
353538
|
const deployment = await getDeploymentContext(db, job.entityId ?? void 0);
|
|
353385
353539
|
const jobContext = {
|
|
353386
353540
|
origin: job.channel ?? "unknown",
|
|
353387
353541
|
...job.task ? { task: job.task } : {},
|
|
353388
353542
|
...job.chatId ? { telegramChatId: job.chatId } : {},
|
|
353389
|
-
...
|
|
353543
|
+
...triggerWantsConfirmation ? { notifyOnSuccess: true } : {},
|
|
353390
353544
|
...job.parentJobId ? { isDelegated: true } : {},
|
|
353391
353545
|
...job.triggerContext ? { triggerContext: job.triggerContext } : {},
|
|
353392
353546
|
deployment
|
|
@@ -353422,6 +353576,11 @@ async function runJob(jobId, deps, runnerEnv, opts) {
|
|
|
353422
353576
|
capabilityTools.push(createSendVoiceTool());
|
|
353423
353577
|
capabilityTools.push(createListConversationsTool());
|
|
353424
353578
|
}
|
|
353579
|
+
const activeChannels = [
|
|
353580
|
+
...deliveryBotToken ? ["telegram"] : [],
|
|
353581
|
+
...hasDiscordBinding ? ["discord"] : [],
|
|
353582
|
+
...hasSlackBinding ? ["slack"] : []
|
|
353583
|
+
];
|
|
353425
353584
|
const mcpClosers = [];
|
|
353426
353585
|
try {
|
|
353427
353586
|
const [rootEntityRow] = await db.select({
|
|
@@ -353511,7 +353670,10 @@ async function runJob(jobId, deps, runnerEnv, opts) {
|
|
|
353511
353670
|
decryptedEnv = Object.fromEntries(
|
|
353512
353671
|
Object.entries(rawEnv).map(([k, v]) => [k, decrypt(v)])
|
|
353513
353672
|
);
|
|
353514
|
-
} catch {
|
|
353673
|
+
} catch (err) {
|
|
353674
|
+
console.error(
|
|
353675
|
+
`[execute] MCP server '${ms.slug}' env vars failed to decrypt (tampered, or wrong/rotated master key): ${err instanceof Error ? err.message : String(err)}`
|
|
353676
|
+
);
|
|
353515
353677
|
continue;
|
|
353516
353678
|
}
|
|
353517
353679
|
const connectOpts = {
|
|
@@ -353625,8 +353787,8 @@ async function runJob(jobId, deps, runnerEnv, opts) {
|
|
|
353625
353787
|
return { status: "failed", error: errorCode };
|
|
353626
353788
|
}
|
|
353627
353789
|
const ruleRows = await db.select().from(approvalRules).where(eq6(approvalRules.entityId, job.entityId ?? "")).orderBy(
|
|
353628
|
-
|
|
353629
|
-
|
|
353790
|
+
sql23`${approvalRules.agentId} IS NULL`,
|
|
353791
|
+
sql23`${approvalRules.toolName} = '*'`,
|
|
353630
353792
|
approvalRules.id
|
|
353631
353793
|
);
|
|
353632
353794
|
let approvalRuleList = ruleRows.map((r) => ({
|
|
@@ -353745,6 +353907,8 @@ async function runJob(jobId, deps, runnerEnv, opts) {
|
|
|
353745
353907
|
db,
|
|
353746
353908
|
jobChatId: job.chatId ?? null,
|
|
353747
353909
|
jobChannel: job.channel,
|
|
353910
|
+
activeChannels,
|
|
353911
|
+
notifyChannelOverride,
|
|
353748
353912
|
resolvedTelegramBotToken: inheritedRootBotToken ?? void 0,
|
|
353749
353913
|
embeddingClient: deps.embeddingClient,
|
|
353750
353914
|
workspaces: agentWorkspacesList,
|
|
@@ -353846,7 +354010,7 @@ async function runJob(jobId, deps, runnerEnv, opts) {
|
|
|
353846
354010
|
const MAX_EMPTY_TURN_RETRIES = 2;
|
|
353847
354011
|
let emptyTurnRetries = 0;
|
|
353848
354012
|
let consecutiveDeliveryOnlyTurns = 0;
|
|
353849
|
-
const requiresToolDelivery = TOOL_ONLY_DELIVERY_CHANNELS.has(job.channel ?? "") ||
|
|
354013
|
+
const requiresToolDelivery = TOOL_ONLY_DELIVERY_CHANNELS.has(job.channel ?? "") || triggerWantsConfirmation;
|
|
353850
354014
|
const CHANNEL_DISPLAY_NAMES = {
|
|
353851
354015
|
telegram: "Telegram",
|
|
353852
354016
|
discord: "Discord",
|
|
@@ -354179,17 +354343,21 @@ ${notice}` : notice;
|
|
|
354179
354343
|
return part.providerMetadata != null && part.providerOptions == null ? { ...p, providerOptions: part.providerMetadata } : p;
|
|
354180
354344
|
});
|
|
354181
354345
|
const hasText = (response.text ?? "").trim().length > 0;
|
|
354346
|
+
const toolCallParts = rawToolCalls.map((tc) => {
|
|
354347
|
+
const base = {
|
|
354348
|
+
type: "tool-call",
|
|
354349
|
+
toolCallId: tc.toolCallId,
|
|
354350
|
+
toolName: tc.toolName,
|
|
354351
|
+
input: tc.input
|
|
354352
|
+
};
|
|
354353
|
+
return tc.providerMetadata != null ? { ...base, providerOptions: tc.providerMetadata } : base;
|
|
354354
|
+
});
|
|
354182
354355
|
const assistantMsg = {
|
|
354183
354356
|
role: "assistant",
|
|
354184
354357
|
content: rawToolCalls.length > 0 ? [
|
|
354185
354358
|
...reasoningParts,
|
|
354186
354359
|
...hasText ? [{ type: "text", text: response.text || "" }] : [],
|
|
354187
|
-
...
|
|
354188
|
-
type: "tool-call",
|
|
354189
|
-
toolCallId: tc.toolCallId,
|
|
354190
|
-
toolName: tc.toolName,
|
|
354191
|
-
input: tc.input
|
|
354192
|
-
}))
|
|
354360
|
+
...toolCallParts
|
|
354193
354361
|
] : reasoningParts.length > 0 ? [...reasoningParts, { type: "text", text: response.text || "" }] : response.text || ""
|
|
354194
354362
|
};
|
|
354195
354363
|
messages = [...messages, assistantMsg];
|
|
@@ -354293,6 +354461,8 @@ ${notice}` : notice;
|
|
|
354293
354461
|
db,
|
|
354294
354462
|
jobChatId: job.chatId ?? null,
|
|
354295
354463
|
jobChannel: job.channel,
|
|
354464
|
+
activeChannels,
|
|
354465
|
+
notifyChannelOverride,
|
|
354296
354466
|
resolvedTelegramBotToken: inheritedRootBotToken ?? void 0,
|
|
354297
354467
|
embeddingClient: deps.embeddingClient,
|
|
354298
354468
|
workspaces: agentWorkspacesList,
|
|
@@ -354481,6 +354651,8 @@ ${notice}` : notice;
|
|
|
354481
354651
|
db,
|
|
354482
354652
|
jobChatId: job.chatId ?? null,
|
|
354483
354653
|
jobChannel: job.channel,
|
|
354654
|
+
activeChannels,
|
|
354655
|
+
notifyChannelOverride,
|
|
354484
354656
|
resolvedTelegramBotToken: inheritedRootBotToken ?? void 0,
|
|
354485
354657
|
embeddingClient: deps.embeddingClient,
|
|
354486
354658
|
workspaces: agentWorkspacesList,
|
|
@@ -355637,7 +355809,8 @@ async function notifyBudgetExhausted(db, agentId, scheduleName, dailyBudgetUsd)
|
|
|
355637
355809
|
try {
|
|
355638
355810
|
const ownerChatId = await resolveOwnerChatId(db, agentId);
|
|
355639
355811
|
if (!ownerChatId) return;
|
|
355640
|
-
const
|
|
355812
|
+
const activeChannels = await listActiveChannelsForAgent(db, agentId);
|
|
355813
|
+
const channel2 = resolveTransportChannel("cron", activeChannels);
|
|
355641
355814
|
const creds = await getBindingCredentials(db, agentId, channel2);
|
|
355642
355815
|
if (!creds) return;
|
|
355643
355816
|
const adapter2 = getAdapter3(channel2);
|
|
@@ -355671,6 +355844,9 @@ async function runScheduleTick(db, deps, max2 = 5) {
|
|
|
355671
355844
|
notifyOnSuccess: agentSchedules.notifyOnSuccess,
|
|
355672
355845
|
// Explicit delivery target (e.g. "post to #team"), null for the common case.
|
|
355673
355846
|
chatId: agentSchedules.chatId,
|
|
355847
|
+
// Explicit notify channel choice (B1), null = auto (first active channel
|
|
355848
|
+
// by priority, the historical behavior — see the chatId resolution below).
|
|
355849
|
+
notifyChannel: agentSchedules.notifyChannel,
|
|
355674
355850
|
// Read BEFORE this tick's writes — "was it already budget_exhausted" is
|
|
355675
355851
|
// the transition check the notify-once-per-day dedup relies on below.
|
|
355676
355852
|
lastStatus: agentSchedules.lastStatus,
|
|
@@ -355683,6 +355859,7 @@ async function runScheduleTick(db, deps, max2 = 5) {
|
|
|
355683
355859
|
).limit(max2 * 2);
|
|
355684
355860
|
if (candidates.length === 0) return 0;
|
|
355685
355861
|
const fires = [];
|
|
355862
|
+
const notifyUnreachableScheduleIds = /* @__PURE__ */ new Set();
|
|
355686
355863
|
for (const sched of candidates.slice(0, max2)) {
|
|
355687
355864
|
if (!sched.task || !sched.entityId) continue;
|
|
355688
355865
|
const [liveJob] = await db.select({ id: agentJobs.id, createdAt: agentJobs.createdAt }).from(agentJobs).where(and5(eq6(agentJobs.scheduleId, sched.id), inArray4(agentJobs.status, LIVE_JOB_STATUSES))).orderBy(desc(agentJobs.createdAt)).limit(1);
|
|
@@ -355700,8 +355877,8 @@ async function runScheduleTick(db, deps, max2 = 5) {
|
|
|
355700
355877
|
continue;
|
|
355701
355878
|
}
|
|
355702
355879
|
const tz = resolveTimezone(sched.timezone);
|
|
355703
|
-
const [spentRow] = await db.select({ spent:
|
|
355704
|
-
|
|
355880
|
+
const [spentRow] = await db.select({ spent: sql23`COALESCE(SUM(${agentJobs.totalCostUsd}), 0)` }).from(agentJobs).where(
|
|
355881
|
+
sql23`${agentJobs.scheduleId} = ${sched.id} AND ${agentJobs.createdAt} >= (date_trunc('day', now() AT TIME ZONE ${tz}) AT TIME ZONE ${tz})`
|
|
355705
355882
|
);
|
|
355706
355883
|
const spentToday = Number(spentRow?.spent ?? 0);
|
|
355707
355884
|
if (spentToday >= sched.dailyBudgetUsd) {
|
|
@@ -355742,7 +355919,21 @@ async function runScheduleTick(db, deps, max2 = 5) {
|
|
|
355742
355919
|
)
|
|
355743
355920
|
).returning({ id: agentSchedules.id });
|
|
355744
355921
|
if (claimed.length === 0) continue;
|
|
355745
|
-
|
|
355922
|
+
let notifyChatId = null;
|
|
355923
|
+
if (sched.notifyOnSuccess) {
|
|
355924
|
+
if (sched.notifyChannel) {
|
|
355925
|
+
const channel2 = sched.notifyChannel;
|
|
355926
|
+
notifyChatId = sched.chatId ?? await resolveOwnerConversation(db, sched.agentId, channel2);
|
|
355927
|
+
if (!notifyChatId) {
|
|
355928
|
+
notifyUnreachableScheduleIds.add(sched.id);
|
|
355929
|
+
console.error(
|
|
355930
|
+
`[runScheduleTick] schedule "${sched.name}" (${sched.id}) chose notify channel '${channel2}' but has no owner conversation there yet (never DMed on that channel). Firing WITHOUT a delivery target \u2014 not falling back to another channel. lastStatus will read 'notify_unreachable'.`
|
|
355931
|
+
);
|
|
355932
|
+
}
|
|
355933
|
+
} else {
|
|
355934
|
+
notifyChatId = sched.chatId ?? await resolveOwnerChatId(db, sched.agentId) ?? null;
|
|
355935
|
+
}
|
|
355936
|
+
}
|
|
355746
355937
|
const [job] = await db.insert(agentJobs).values({
|
|
355747
355938
|
entityId: sched.entityId,
|
|
355748
355939
|
agentId: sched.agentId,
|
|
@@ -355755,7 +355946,8 @@ async function runScheduleTick(db, deps, max2 = 5) {
|
|
|
355755
355946
|
triggerContext: {
|
|
355756
355947
|
type: "cron",
|
|
355757
355948
|
scheduleName: sched.name,
|
|
355758
|
-
prevRunAt: sched.lastRun ? sched.lastRun.toISOString() : null
|
|
355949
|
+
prevRunAt: sched.lastRun ? sched.lastRun.toISOString() : null,
|
|
355950
|
+
notifyChannel: sched.notifyChannel ?? null
|
|
355759
355951
|
}
|
|
355760
355952
|
}).returning({ id: agentJobs.id });
|
|
355761
355953
|
if (!job) {
|
|
@@ -355784,7 +355976,9 @@ async function runScheduleTick(db, deps, max2 = 5) {
|
|
|
355784
355976
|
if (settled.status === "rejected") continue;
|
|
355785
355977
|
const { fire, result } = settled.value;
|
|
355786
355978
|
let lastStatus;
|
|
355787
|
-
if (
|
|
355979
|
+
if (notifyUnreachableScheduleIds.has(fire.scheduleId)) {
|
|
355980
|
+
lastStatus = "notify_unreachable";
|
|
355981
|
+
} else if (result.status === "completed") lastStatus = "success";
|
|
355788
355982
|
else if (result.status === "failed") lastStatus = "failed";
|
|
355789
355983
|
else if (result.status === "cancelled") lastStatus = "failed";
|
|
355790
355984
|
else lastStatus = "no_action";
|
|
@@ -355818,7 +356012,8 @@ async function deliverCompletedRoots(db) {
|
|
|
355818
356012
|
chatId: agentJobs.chatId,
|
|
355819
356013
|
agentId: agentJobs.agentId,
|
|
355820
356014
|
entityId: agentJobs.entityId,
|
|
355821
|
-
task: agentJobs.task
|
|
356015
|
+
task: agentJobs.task,
|
|
356016
|
+
triggerContext: agentJobs.triggerContext
|
|
355822
356017
|
}).from(agentJobs).where(eq6(agentJobs.id, rootJobId)).limit(1);
|
|
355823
356018
|
const rootJob = rootJobRows[0];
|
|
355824
356019
|
if (!rootJob) continue;
|
|
@@ -355863,7 +356058,10 @@ async function deliverCompletedRoots(db) {
|
|
|
355863
356058
|
}
|
|
355864
356059
|
if (rootJob.chatId && rootJob.agentId && compiledResult.trim()) {
|
|
355865
356060
|
try {
|
|
355866
|
-
const
|
|
356061
|
+
const activeChannels = await listActiveChannelsForAgent(db, rootJob.agentId);
|
|
356062
|
+
const triggerContext = rootJob.triggerContext;
|
|
356063
|
+
const notifyChannelOverride = triggerContext?.type === "cron" || triggerContext?.type === "webhook" ? triggerContext.notifyChannel ?? void 0 : void 0;
|
|
356064
|
+
const channel2 = notifyChannelOverride ?? resolveTransportChannel(rootJob.channel, activeChannels);
|
|
355867
356065
|
const allowed = rootJob.entityId !== null && await isConversationAllowed(db, {
|
|
355868
356066
|
entityId: rootJob.entityId,
|
|
355869
356067
|
agentId: rootJob.agentId,
|
|
@@ -356376,12 +356574,12 @@ async function runCuratorTick(db, _deps, runnerEnv) {
|
|
|
356376
356574
|
eq6(agentSkills.state, "active"),
|
|
356377
356575
|
eq6(entities.reflectionEnabled, true)
|
|
356378
356576
|
)
|
|
356379
|
-
).groupBy(agentSkills.entityId).having(
|
|
356577
|
+
).groupBy(agentSkills.entityId).having(sql23`count(${agentSkills.id}) >= ${e2.CURATOR_MIN_SKILLS}`);
|
|
356380
356578
|
for (const c of skillCandidates) if (c.entityId) skillSet.add(c.entityId);
|
|
356381
356579
|
}
|
|
356382
356580
|
const memorySet = /* @__PURE__ */ new Set();
|
|
356383
356581
|
if (e2.MEMORY_CURATION_ENABLED !== "false") {
|
|
356384
|
-
const memoryCandidates = await db.select({ entityId: agentMemory.entityId }).from(agentMemory).innerJoin(entities, eq6(entities.id, agentMemory.entityId)).where(and5(eq6(agentMemory.archived, false), eq6(entities.memoryCurationEnabled, true))).groupBy(agentMemory.entityId).having(
|
|
356582
|
+
const memoryCandidates = await db.select({ entityId: agentMemory.entityId }).from(agentMemory).innerJoin(entities, eq6(entities.id, agentMemory.entityId)).where(and5(eq6(agentMemory.archived, false), eq6(entities.memoryCurationEnabled, true))).groupBy(agentMemory.entityId).having(sql23`count(${agentMemory.id}) >= ${e2.CURATOR_MEMORY_MIN}`);
|
|
356385
356583
|
for (const c of memoryCandidates) if (c.entityId) memorySet.add(c.entityId);
|
|
356386
356584
|
}
|
|
356387
356585
|
if (skillSet.size === 0 && memorySet.size === 0) {
|
|
@@ -357024,18 +357222,38 @@ async function webhookRoute(c, deps, runnerEnv) {
|
|
|
357024
357222
|
const triggeredAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
357025
357223
|
const interpolated = interpolateTemplate(trigger.taskTemplate, bodyResult.value);
|
|
357026
357224
|
const task = buildWebhookEnvelope(trigger.name, triggeredAt, interpolated);
|
|
357225
|
+
let notifyChatId = null;
|
|
357226
|
+
let notifyChannel = null;
|
|
357227
|
+
if (trigger.notifyOnSuccess) {
|
|
357228
|
+
if (trigger.notifyChannel) {
|
|
357229
|
+
notifyChannel = trigger.notifyChannel;
|
|
357230
|
+
} else {
|
|
357231
|
+
const activeChannels = (await listActiveChannelsForAgent(deps.db, agentId)).filter(
|
|
357232
|
+
(c2) => c2 !== "whatsapp"
|
|
357233
|
+
);
|
|
357234
|
+
notifyChannel = resolveTransportChannel("webhook", activeChannels);
|
|
357235
|
+
}
|
|
357236
|
+
notifyChatId = await resolveOwnerConversation(deps.db, agentId, notifyChannel);
|
|
357237
|
+
if (!notifyChatId) {
|
|
357238
|
+
console.error(
|
|
357239
|
+
`[webhook] trigger "${trigger.name}" (${trigger.slug}) chose notify channel '${notifyChannel}' but has no owner conversation there yet (never DMed on that channel). Firing WITHOUT a delivery target \u2014 not falling back to another channel.`
|
|
357240
|
+
);
|
|
357241
|
+
}
|
|
357242
|
+
}
|
|
357027
357243
|
const [job] = await deps.db.insert(agentJobs).values({
|
|
357028
357244
|
entityId: trigger.entityId ?? void 0,
|
|
357029
357245
|
agentId,
|
|
357030
357246
|
channel: "webhook",
|
|
357031
357247
|
task,
|
|
357032
357248
|
status: "pending",
|
|
357249
|
+
chatId: notifyChatId,
|
|
357033
357250
|
messages: [{ role: "user", content: task }],
|
|
357034
357251
|
triggerContext: {
|
|
357035
357252
|
type: "webhook",
|
|
357036
357253
|
webhookName: trigger.name,
|
|
357037
357254
|
slug: trigger.slug,
|
|
357038
|
-
triggeredAt
|
|
357255
|
+
triggeredAt,
|
|
357256
|
+
notifyChannel
|
|
357039
357257
|
}
|
|
357040
357258
|
}).returning({ id: agentJobs.id });
|
|
357041
357259
|
if (!job) {
|
|
@@ -359351,7 +359569,18 @@ function startSlackSocket(opts) {
|
|
|
359351
359569
|
);
|
|
359352
359570
|
});
|
|
359353
359571
|
});
|
|
359354
|
-
void app.start().
|
|
359572
|
+
void app.start().then(async () => {
|
|
359573
|
+
try {
|
|
359574
|
+
const identity = await app.client.auth.test();
|
|
359575
|
+
console.warn(
|
|
359576
|
+
`[slack-socket agent=${agentId}] connected (socket mode) as ${identity.user ?? "unknown"} (team=${identity.team ?? "unknown"})`
|
|
359577
|
+
);
|
|
359578
|
+
} catch (err) {
|
|
359579
|
+
console.warn(
|
|
359580
|
+
`[slack-socket agent=${agentId}] connected (socket mode), but auth.test failed: ${err instanceof Error ? err.message : String(err)}`
|
|
359581
|
+
);
|
|
359582
|
+
}
|
|
359583
|
+
}).catch((err) => {
|
|
359355
359584
|
console.warn(
|
|
359356
359585
|
`[slack-socket agent=${agentId}] start failed (invalid token(s)?): ${err instanceof Error ? err.message : String(err)}; will retry on the manager's next refresh`
|
|
359357
359586
|
);
|